| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820 |
- <?php
- /**
- * 1688分销严选采购解决方案 - 订单服务类
- *
- * 提供预下单、下单、订单查询等功能
- *
- * @author: yourname
- * @day: 2026/04/28
- */
- namespace app\services\ThirdParty\AlibabaAgent;
- use app\entity\data\store\StoreOrderEntity;
- use app\entity\data\store\StoreOrderStatusEntity;
- use think\facade\Db;
- use think\facade\Log;
- class OrderService extends AlibabaAgentBaseService
- {
- /**
- * API命名空间
- */
- const NAMESPACE = 'com.alibaba.trade';
- /**
- * 物流API命名空间
- */
- const LOGISTICS_NAMESPACE = 'com.alibaba.logistics';
- const REFUND_GOOD_STATUS = [
- // 售中等待卖家发货
- 'waitsellersend' => 'refundWaitSellerSend',
- // 售中等待买家收货
- 'waitbuyerreceive'=>'refundWaitBuyerReceive',
- // // 售中已收货(未确认完成交易)
- // 'BuyerReceived'=>'refundBuyerReceived',
- // // 售后未收货
- // 'saleBuyerNotReceived'=>'aftersaleBuyerNotReceived',
- // // 售后已收到货
- // 'saleBuyerReceived'=>'aftersaleBuyerReceived',
- ];
- /**
- * 预下单
- *
- * API: com.alibaba.trade:alibaba.createOrder.preview-1
- *
- * 接口文档: https://open.1688.com/api/apidocdetail.htm?id=com.alibaba.trade%3Aalibaba.createOrder.preview-1
- *
- * 请求参数格式:
- * - flow: 流程标识(saleproxy=分销采购, general=普通下单)
- * - productList: 商品列表JSON数组,每个商品包含 offerId, quantity, specId
- * - addressParam: 地址参数JSON对象,包含 fullName, mobile, provinceText, cityText, areaText, address
- * - totalAmount: 总金额(单位:分,可选)
- * - message: 买家留言(可选)
- *
- * @param array $params 预下单参数
- * @return array|false
- */
- public function previewOrder(array $params = [])
- {
- $businessParams = [];
- // --- productList(商品列表,JSON字符串) ---
- // 直接传入已格式化的数组,由方法转为JSON
- if (!empty($params['cargoParamList'])) {
- $businessParams['cargoParamList'] = is_array($params['cargoParamList'])
- ? json_encode($params['cargoParamList'], JSON_UNESCAPED_UNICODE)
- : $params['cargoParamList'];
- }
- // --- addressParam(地址参数,JSON字符串) ---
- // 直接传入已格式化的数组,由方法转为JSON
- if (!empty($params['addressParam'])) {
- $businessParams['addressParam'] = is_array($params['addressParam'])
- ? json_encode($params['addressParam'], JSON_UNESCAPED_UNICODE)
- : $params['addressParam'];
- }
- // --- 调用API ---
- $result = $this->executeParam2(
- self::NAMESPACE,
- 'alibaba.createOrder.preview',
- 1,
- $businessParams
- );
- if ($result === false) {
- Log::channel('alibaba')->error('[预下单] API请求失败', $businessParams);
- return false;
- }
- Log::channel('alibaba')->info('[预下单] API请求成功', ['result' => json_encode($result)]);
- return $this->formatPreviewResult($result);
- }
- /**
- * 格式化预下单返回结果
- *
- * 实际返回结构:
- * {
- * "orderPreviewResuslt": [{
- * "tradeModeNameList": ["assureTrade"],
- * "status": true,
- * "sumPayment": 370, // 总支付金额(单位:分)
- * "sumCarriage": 300, // 总运费(单位:分)
- * "sumPaymentNoCarriage": 70, // 商品总金额(不含运费,单位:分)
- * "flowFlag": "fenxiaonew",
- * "cargoList": [{ // 商品列表
- * "amount": 0.7,
- * "finalUnitPrice": 0.7,
- * "specId": "...",
- * "skuId": 6148579878582,
- * "offerId": 678279922176,
- * "openOfferId": "...",
- * "cargoPromotionList": []
- * }],
- * "tradeModelList": [{"name":"担保交易","tradeType":"assureTrade","opSupport":true}],
- * "payChannelInfos": [{"name":"alipay"}],
- * "orderGroup": "79d4f82d...",
- * "canUseOfficialSolution": false
- * }],
- * "success": true,
- * "unsupportedCrossBorderPayOfferList": []
- * }
- *
- * @param array $result API原始返回数据
- * @return array
- */
- protected function formatPreviewResult(array $result): array
- {
- $success = $result['success'] ?? false;
- $previewList = $result['orderPreviewResuslt'] ?? [];
- if (empty($previewList) || !is_array($previewList)) {
- return [
- 'success' => $success,
- 'preview' => null,
- 'list' => [],
- ];
- }
- $formattedList = [];
- foreach ($previewList as $item) {
- $formattedList[] = [
- 'sumPayment' => $item['sumPayment'] ?? 0,
- 'sumCarriage' => $item['sumCarriage'] ?? 0,
- 'sumPaymentNoCarriage' => $item['sumPaymentNoCarriage'] ?? 0,
- 'flowFlag' => $item['flowFlag'] ?? '',
- // 'orderGroup' => $item['orderGroup'] ?? '',
- // 'status' => $item['status'] ?? false,
- // 'cargoList' => $item['cargoList'] ?? [],
- // 'tradeModeNameList' => $item['tradeModeNameList'] ?? [],
- // 'tradeModelList' => $item['tradeModelList'] ?? [],
- // 'payChannelInfos' => $item['payChannelInfos'] ?? [],
- // 'shopPromotionList' => $item['shopPromotionList'] ?? [],
- // 'tradeServiceList' => $item['tradeServiceList'] ?? [],
- // 'taoSampleSinglePromotion' => $item['taoSampleSinglePromotion'] ?? false,
- // 'canUseOfficialSolution' => $item['canUseOfficialSolution'] ?? false,
- ];
- }
- return [
- // 'success' => $success,
- 'preview' => $formattedList[0] ?? null,
- // 'list' => $formattedList,
- // 'unsupportedCrossBorderPayOfferList' => $result['unsupportedCrossBorderPayOfferList'] ?? [],
- ];
- }
- /**
- * 快速创建订单
- *
- * API: com.alibaba.trade:alibaba.trade.fastCreateOrder-1
- *
- * 接口文档: https://open.1688.com/api/apidocdetail.htm?id=com.alibaba.trade%3Aalibaba.trade.fastCreateOrder-1
- *
- * 请求参数:
- * - flow: 流程标识(saleproxy=分销采购, general=普通下单)
- * - cargoParamList: 商品列表JSON数组(alibaba.trade.fast.cargo[]),每个商品包含 offerId, quantity, specId
- * - addressParam: 地址参数JSON对象,包含 fullName, mobile, provinceText, cityText, areaText, address
- * - totalAmount: 总金额(单位:分,可选)
- * - message: 买家留言(可选)
- * - orderGroup: 订单分组标识(从预下单返回的 orderGroup 字段获取,可选)
- *
- * @param array $params 创建订单参数
- * @return array|false
- */
- public function fastCreateOrder(array $params = [])
- {
- $businessParams = [];
- // --- flow(流程标识) ---
- $businessParams['flow'] = $params['flow'] ?? 'general';
- // --- cargoParamList(商品列表,JSON字符串) ---
- if (!empty($params['cargoParamList'])) {
- $businessParams['cargoParamList'] = is_array($params['cargoParamList'])
- ? json_encode($params['cargoParamList'], JSON_UNESCAPED_UNICODE)
- : $params['cargoParamList'];
- }
- // --- addressParam(地址参数,JSON字符串) ---
- if (!empty($params['addressParam'])) {
- $businessParams['addressParam'] = is_array($params['addressParam'])
- ? json_encode($params['addressParam'], JSON_UNESCAPED_UNICODE)
- : $params['addressParam'];
- }
- // --- 调用API ---
- $result = $this->executeParam2(
- self::NAMESPACE,
- 'alibaba.trade.fastCreateOrder',
- 1,
- $businessParams
- );
- if ($result === false) {
- Log::channel('alibaba')->error('[创建订单] API请求失败', $businessParams);
- return false;
- }
- Log::channel('alibaba')->info('[创建订单] API请求成功', ['result' => json_encode($result)]);
- return $this->formatCreateOrderResult($result);
- }
- /**
- * @param StoreOrderEntity[] $storeOrderEntityList
- * @return bool
- * @author 史晨
- * @date 2026/4/30 09:44
- * 支付成功通知1688
- */
- public function paySuccess(array $storeOrderEntityList): bool
- {
- foreach ($storeOrderEntityList as $storeOrderEntity) {
- $alibabaOrderId = $storeOrderEntity->getAlibabaOrderId();
- if (empty($alibabaOrderId)) {
- Log::channel('alibaba')->error($storeOrderEntity->getOrderSn() . '不是1688订单,不需要调取1688支付成功接口');
- continue;
- }
- $res = $this->prepareProtocolPay(['orderId' => $alibabaOrderId]);
- if ($res['success'] === false) {
- return false;
- }
- }
- return true;
- }
- /**
- * 免密支付准备
- *
- * API: com.alibaba.trade:alibaba.trade.pay.protocolPay.preparePay-1
- *
- * 接口文档: https://open.1688.com/api/apidocdetail.htm?id=com.alibaba.trade%3Aalibaba.trade.pay.protocolPay.preparePay-1
- *
- * 请求参数说明(接口文档定义):
- * - tradeWithholdPreparePayParam: 必填,类型 message:alibaba.trade.pay.withhold.preparePayParam
- * preparePayParam 结构:
- * - orderId: 订单ID(Long,必填)
- *
- * 调用示例:
- * $orderService->prepareProtocolPay([
- * 'orderId' => 123456789,
- * ]);
- *
- * @param array $params 免密支付参数(orderId)
- * @return array|false
- */
- public function prepareProtocolPay(array $params = [])
- {
- // --- 参数校验 ---
- if (empty($params['orderId'])) {
- Log::channel('alibaba')->error('[免密支付] orderId不能为空');
- return false;
- }
- // --- 构建 tradeWithholdPreparePayParam(message类型需序列化为JSON字符串) ---
- $businessParams = [
- 'tradeWithholdPreparePayParam' => json_encode([
- 'orderId' => (int)$params['orderId'],
- ], JSON_UNESCAPED_UNICODE),
- ];
- // --- 调用API ---
- $result = $this->executeParam2(
- self::NAMESPACE,
- 'alibaba.trade.pay.protocolPay.preparePay',
- 1,
- $businessParams
- );
- if ($result === false) {
- Log::channel('alibaba')->error('[免密支付] API请求失败', $businessParams);
- return false;
- }
- Log::channel('alibaba')->info('[免密支付] API请求成功', ['result' => json_encode($result)]);
- return $this->formatProtocolPayResult($result);
- }
- /**
- * 格式化免密支付准备返回结果
- *
- * @param array $result API原始返回数据
- * @return array
- */
- protected function formatProtocolPayResult(array $result): array
- {
- // 返回结构: { "result": { ... }, "success": true }
- $data = $result['result'] ?? $result;
- $success = $result['success'] ?? false;
- Log::channel('alibaba')->info('[免密支付] 返回结果', [
- 'success' => $success,
- 'data' => $data,
- ]);
- return [
- 'success' => $success,
- 'data' => $data,
- 'rawData' => $result,
- ];
- }
- /**
- * 格式化创建订单返回结果
- *
- * @param array $result API原始返回数据
- * @return array
- */
- protected function formatCreateOrderResult(array $result): array
- {
- // 创建订单成功返回: { "result": { "orderId": "123456", "totalAmount": 370 }, "success": true }
- $data = $result['result'] ?? $result;
- $success = $result['success'] ?? false;
- return [
- 'success' => $success,
- 'orderId' => $data['orderId'] ?? 0,
- 'totalAmount' => $data['totalAmount'] ?? 0,
- 'rawData' => $data,
- ];
- }
- /**
- * 构建商品列表参数(便捷方法)
- *
- * @param array $items 商品列表 [['offerId' => 123, 'quantity' => 2, 'skuId' => 456], ...]
- * @return array
- */
- public function buildProductList(array $items): array
- {
- $productList = [];
- foreach ($items as $item) {
- $product = [
- 'offerId' => (int)($item['offerId'] ?? $item['productId'] ?? 0),
- 'quantity' => (int)($item['quantity'] ?? 1),
- ];
- if (!empty($item['skuId'])) {
- $product['skuId'] = (int)$item['skuId'];
- }
- if (!empty($item['price'])) {
- $product['price'] = (int)$item['price']; // 单位:分
- }
- if (!empty($item['productUnit'])) {
- $product['productUnit'] = $item['productUnit'];
- }
- $productList[] = $product;
- }
- return $productList;
- }
- /**
- * 构建地址参数(便捷方法)
- *
- * @param int $addressId 地址ID
- * @return array
- */
- public function buildAddressParam(int $addressId): array
- {
- return [
- 'addressId' => $addressId,
- ];
- }
- /**
- * 构建完整地址参数(使用系统地址数据格式)
- *
- * 适配系统 user_address 表字段:
- * address_id, real_name, phone, province, city, district, detail, post_code, code_list
- *
- * @param array $address 地址信息(系统user_address表数据)
- * @return array
- */
- public function buildFullAddressParam(array $address): array
- {
- // 解析地区编码列表: "1,67449,35,493"
- $codeList = $address['code_list'] ?? '';
- $codes = explode(',', $codeList);
- $districtCode = $codes[1] ?? $codes[0] ?? '';
- return [
- 'fullName' => $address['real_name'] ?? $address['fullName'] ?? '',
- 'mobile' => $address['phone'] ?? $address['mobile'] ?? '',
- 'phone' => $address['phone'] ?? $address['phone'] ?? '',
- 'postCode' => $address['post_code'] ?? $address['postCode'] ?? '',
- 'cityText' => $address['city'] ?? $address['cityText'] ?? '',
- 'provinceText' => $address['province'] ?? $address['provinceText'] ?? '',
- 'areaText' => $address['district'] ?? $address['areaText'] ?? '',
- 'townText' => $address['village'] ?? $address['townText'] ?? '',
- 'address' => $address['detail'] ?? $address['address'] ?? '',
- 'districtCode' => $districtCode,
- ];
- }
- /**
- * 获取交易订单的物流信息(买家视角)
- *
- * API: com.alibaba.trade:alibaba.trade.get.logisticsInfos.buyerView-1
- *
- * 接口文档: https://open.1688.com/api/apidocdetail.htm?id=com.alibaba.trade%3Aalibaba.trade.get.logisticsInfos.buyerView-1
- *
- * 请求参数:
- * - orderId: 1688订单ID(必填)
- * - webSite: 1688站点(可选,默认"1688")
- *
- * 返回示例:
- * {
- * "result": {
- * "logisticsItems": [{
- * "logisticsId": "LP001",
- * "logisticsCode": "SF1234567890", // 物流单号
- * "logisticsName": "顺丰速运", // 物流公司名称
- * "logisticsCompany": "shunfeng", // 物流公司编码
- * "status": "accept", // 物流状态
- * "gmtCreate": "2018-05-30 19:34:27"
- * }]
- * },
- * "success": true
- * }
- *
- * @param array $params 请求参数(orderId 必填)
- * @return array|false
- */
- public function getLogisticsInfosBuyerView(array $params = [])
- {
- // --- 参数校验 ---
- if (empty($params['orderId'])) {
- Log::channel('alibaba')->error('[获取物流信息] orderId不能为空');
- return false;
- }
- $businessParams = [
- 'orderId' => (string)$params['orderId'],
- 'webSite' => $params['webSite'] ?? '1688',
- ];
- // --- 调用API ---
- $result = $this->executeParam2(
- self::LOGISTICS_NAMESPACE,
- 'alibaba.trade.getLogisticsInfos.buyerView',
- 1,
- $businessParams
- );
- if ($result === false) {
- Log::channel('alibaba')->error('[获取物流信息] API请求失败, params:' . json_encode($businessParams, JSON_UNESCAPED_UNICODE));
- return false;
- }
- Log::channel('alibaba')->info('[获取物流信息] API请求成功, result:' . json_encode($result, JSON_UNESCAPED_UNICODE));
- return $this->formatLogisticsInfosResult($result);
- }
- /**
- * 格式化物流信息返回结果
- *
- * 实际返回数据结构(result为数组):
- * {
- * "result": [{
- * "logisticsId": "LP00815917141701",
- * "logisticsBillNo": "YT7619307479079", // 物流单号
- * "logisticsCompanyName": "圆通速递(YTO)", // 物流公司名称
- * "logisticsCompanyNo": "YTO", // 物流公司编码
- * "status": "SIGN",
- * ...
- * }],
- * "success": true
- * }
- *
- * @param array $result API原始返回数据
- * @return array
- */
- protected function formatLogisticsInfosResult(array $result): array
- {
- $success = $result['success'] ?? false;
- $logisticsItems = [];
- // result 是数组,每个元素是一条物流信息
- if (isset($result['result']) && is_array($result['result'])) {
- foreach ($result['result'] as $item) {
- $logisticsItems[] = [
- 'logisticsId' => $item['logisticsId'] ?? '',
- 'logisticsBillNo' => $item['logisticsBillNo'] ?? '', // 物流单号
- 'logisticsName' => $item['logisticsCompanyName'] ?? '', // 物流公司名称
- 'logisticsCompany' => $item['logisticsCompanyNo'] ?? '', // 物流公司编码
- 'status' => $item['status'] ?? '',
- 'orderEntryIds' => $item['orderEntryIds'] ?? '',
- ];
- }
- }
- return [
- 'success' => $success,
- 'logisticsItems' => $logisticsItems,
- 'rawData' => $result,
- ];
- }
- /**
- * 获取订单详情(买家视角)
- *
- * API: com.alibaba.trade:alibaba.trade.get.buyerView-1
- *
- * @param string $orderId 1688订单号
- * @return array|false
- */
- public function getOrderDetailBuyerView(string $orderId)
- {
- if (empty($orderId)) {
- Log::channel('alibaba')->error('[获取订单详情] orderId不能为空');
- return false;
- }
- $businessParams = [
- 'orderId' => $orderId,
- 'webSite' => 1688,
- ];
- $result = $this->executeParam2(
- self::NAMESPACE,
- 'alibaba.trade.get.buyerView',
- 1,
- $businessParams
- );
- if ($result === false) {
- Log::channel('alibaba')->error('[获取订单详情] API请求失败, orderId:' . $orderId);
- return false;
- }
- Log::channel('alibaba')->info('[获取订单详情] API请求成功, orderId:' . $orderId . ', result:' . json_encode($result, JSON_UNESCAPED_UNICODE));
- return $result;
- }
- /**
- * 查询退款退货原因列表
- *
- * 流程:
- * 1. 先调用 alibaba.trade.get.buyerView 获取订单详情
- * 2. 从订单详情中提取子订单号(orderEntryIds)、货物状态、可退款金额、可退运费
- * 3. 再调用 alibaba.trade.getRefundReasonList 获取退款原因
- *
- * API: com.alibaba.trade:alibaba.trade.getRefundReasonList-1
- *
- * @param array $params 请求参数(orderId 必填)
- * @return array|false
- */
- public function getRefundReasonList(array $params = [])
- {
- // --- 参数校验 ---
- if (empty($params['orderId'])) {
- Log::channel('alibaba')->error('[获取退款原因] orderId不能为空');
- return false;
- }
- $orderId = (string)$params['orderId'];
- // 1. 先获取订单详情,提取子订单号和货物状态
- $orderDetail = $this->getOrderDetailBuyerView($orderId);
- if ($orderDetail === false) {
- Log::channel('alibaba')->error('[获取退款原因] 获取订单详情失败, orderId:' . $orderId);
- return false;
- }
- // 从订单详情中提取子订单ID列表
- $orderEntryIds = $orderDetail['result']['productItems'][0]['subItemID'] ?: '';
- $goodsStatus = self::REFUND_GOOD_STATUS[$orderDetail['result']['productItems'][0]['status']] ?: '';
- if (!$goodsStatus) {
- Log::channel('alibaba')->error('[获取退款原因] 获取货物状态失败, orderId:' . $orderId);
- return false;
- }
- // 提取可退款金额和可退运费(从订单详情中)
- // totalSuccessAmount: 实付款(分),carriage: 运费(分)
- $applyPayment = (string)$orderDetail['result']['baseInfo']['totalAmount'] ?? 0;
- $applyCarriage = (string)$orderDetail['result']['baseInfo']['shippingFee'] ?? 0;
- // 2. 调用退款原因查询API
- $businessParams = [
- 'orderId' => $orderId,
- 'orderEntryIds' => '[' . $orderEntryIds . ']',
- 'goodsStatus' => $goodsStatus,
- ];
- Log::channel('alibaba')->info('[获取退款原因] 准备请求, orderId:' . $orderId . ', orderEntryIds:' . json_encode($orderEntryIds) . ', goodsStatus:' . $goodsStatus);
- // --- 调用API ---
- $result = $this->executeParam2(
- self::NAMESPACE,
- 'alibaba.trade.getRefundReasonList',
- 1,
- $businessParams
- );
- if ($result === false) {
- Log::channel('alibaba')->error('[获取退款原因] API请求失败, params:' . json_encode($businessParams, JSON_UNESCAPED_UNICODE));
- return false;
- }
- Log::channel('alibaba')->info('[获取退款原因] API请求成功, result:' . json_encode($result, JSON_UNESCAPED_UNICODE));
- return $this->formatRefundReasonListResult($result, $orderId, $orderEntryIds, $goodsStatus, $applyPayment, $applyCarriage);
- }
- /**
- * 格式化退款退货原因列表返回结果
- *
- * 实际返回数据结构:
- * {
- * "result": {
- * "result": {
- * "reasons": [
- * {"id": 20006, "name": "不想买了", "needVoucher": false, "noRefundCarriage": false, "tip": ""}
- * ]
- * },
- * "success": true
- * }
- * }
- *
- * @param array $result API原始返回数据
- * @param string $orderId 1688订单号
- * @param string $orderEntryIds 子订单ID列表
- * @param string $goodsStatus 货物状态
- * @param int $applyPayment 可退款金额(分)
- * @param int $applyCarriage 可退运费(分)
- * @return array
- */
- protected function formatRefundReasonListResult(array $result, string $orderId = '', string $orderEntryIds = '', string $goodsStatus = '', string $applyPayment = '0', string $applyCarriage = '0'): array
- {
- $reasons = [];
- if (isset($result['result']['result']['reasons']) && is_array($result['result']['result']['reasons'])) {
- foreach ($result['result']['result']['reasons'] as $reason) {
- $reasons[] = [
- 'id' => $reason['id'] ?? '',
- 'name' => $reason['name'] ?? '',
- ];
- }
- }
- return [
- 'orderId' => $orderId,
- 'orderEntryIds' => $orderEntryIds,
- 'goodsStatus' => $goodsStatus,
- 'applyPayment' => $applyPayment,
- 'applyCarriage' => $applyCarriage,
- 'reasons' => $reasons,
- ];
- }
- /**
- * 提交售后申请
- *
- * API: com.alibaba.trade:alibaba.trade.createRefund-1
- *
- * 接口文档: https://open.1688.com/api/apidocdetail.htm?id=com.alibaba.trade%3Aalibaba.trade.createRefund-1
- *
- * 请求参数:
- * - orderId: 主订单ID(必填)
- * - orderEntryIds: 子订单ID列表,格式 "[123,456]"(必填)
- * - disputeReasonId: 退款原因ID(必填,从 getRefundReasonList 获取)
- * - description: 退款说明(必填)
- * - goodsStatus: 货物状态(必填)
- * - applyPayment: 退款金额,单位分(必填)
- * - applyCarriage: 退运费,单位分(可选,默认0)
- * - voucher: 凭证图片列表,格式 "[{url:'http://...'}]"(可选)
- * - applyReason: 退款原因描述(可选)
- *
- * 返回示例:
- * {
- * "result": {
- * "result": {
- * "refundId": "RF123456",
- * "status": "refundWaitSellerSend"
- * },
- * "success": true
- * }
- * }
- *
- * @param array $params 请求参数
- * @return array|false
- */
- public function createRefund(array $params = [])
- {
- // --- 参数校验 ---
- $requiredFields = ['orderId', 'orderEntryIds', 'disputeReasonId', 'description', 'goodsStatus', 'applyPayment', 'applyCarriage', 'applyReasonId'];
- foreach ($requiredFields as $field) {
- if (!isset($params[$field])) {
- Log::channel('alibaba')->error('[提交售后申请] 缺少必填参数: ' . $field);
- return [
- 'success' => false,
- 'refundId' => '',
- 'status' => 'param_missing',
- 'rawData' => ['error' => '缺少必填参数: ' . $field],
- ];
- }
- }
- $businessParams = [
- 'orderId' => (string)$params['orderId'],
- 'orderEntryIds' => $params['orderEntryIds'],
- 'disputeRequest' => (string)$params['disputeReasonId'],
- 'applyPayment' => (string)$params['applyPayment'],
- 'applyCarriage' => (string)$params['applyCarriage'],
- 'applyReasonId' => (string)$params['applyReasonId'],
- 'description' => (string)$params['description'],
- 'goodsStatus' => (string)$params['goodsStatus'],
- ];
- // 可选参数
- if (!empty($params['voucher'])) {
- $businessParams['voucher'] = $params['voucher'];
- }
- Log::channel('alibaba')->info('[提交售后申请] 准备请求, params:' . json_encode($businessParams, JSON_UNESCAPED_UNICODE));
- // --- 调用API ---
- $result = $this->executeParam2(
- self::NAMESPACE,
- 'alibaba.trade.createRefund',
- 1,
- $businessParams
- );
- // 不管API调用是否成功,都返回格式化的结果(包含原始数据)
- if ($result === false) {
- Log::channel('alibaba')->error('[提交售后申请] API请求失败, params:' . json_encode($businessParams, JSON_UNESCAPED_UNICODE));
- return [
- 'success' => false,
- 'refundId' => '',
- 'status' => 'api_failed',
- 'rawData' => ['error' => 'API请求失败'],
- ];
- }
- Log::channel('alibaba')->info('[提交售后申请] API请求成功, result:' . json_encode($result, JSON_UNESCAPED_UNICODE));
- return $this->formatCreateRefundResult($result);
- }
- /**
- * 格式化提交售后申请返回结果
- *
- * 成功返回数据结构:
- * {
- * "result": {
- * "result": {
- * "refundId": "RF123456",
- * "status": "refundWaitSellerSend"
- * },
- * "success": true
- * }
- * }
- *
- * 失败返回数据结构:
- * {
- * "result": {
- * "code": "5000",
- * "message": "错误描述",
- * "success": false
- * }
- * }
- *
- * @param array $result API原始返回数据
- * @return array
- */
- protected function formatCreateRefundResult(array $result): array
- {
- // 检查 result 层是否存在
- $resultData = $result['result'] ?? $result;
- $success = $resultData['success'] ?? false;
- if ($success) {
- // 成功:result.result 中包含 refundId 和 status
- $refundResult = $resultData['result'] ?? [];
- return [
- 'success' => true,
- 'refundId' => $refundResult['refundId'] ?? '',
- 'status' => $refundResult['status'] ?? '',
- 'rawData' => $result,
- ];
- }
- // 失败:result 中包含 code 和 message
- return [
- 'success' => false,
- 'refundId' => '',
- 'status' => $resultData['message'] ?? ($resultData['code'] ?? 'api_error'),
- 'rawData' => $result,
- ];
- }
- }
|