|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+<?php
|
|
|
2
|
+/**
|
|
|
3
|
+ * 1688分销严选采购解决方案 - 订单服务类
|
|
|
4
|
+ *
|
|
|
5
|
+ * 提供预下单、下单、订单查询等功能
|
|
|
6
|
+ *
|
|
|
7
|
+ * @author: yourname
|
|
|
8
|
+ * @day: 2026/04/28
|
|
|
9
|
+ */
|
|
|
10
|
+
|
|
|
11
|
+namespace app\services\ThirdParty\AlibabaAgent;
|
|
|
12
|
+
|
|
|
13
|
+use think\facade\Db;
|
|
|
14
|
+use think\facade\Log;
|
|
|
15
|
+
|
|
|
16
|
+class OrderService extends AlibabaAgentBaseService
|
|
|
17
|
+{
|
|
|
18
|
+ /**
|
|
|
19
|
+ * API命名空间
|
|
|
20
|
+ */
|
|
|
21
|
+ const NAMESPACE = 'com.alibaba.trade';
|
|
|
22
|
+
|
|
|
23
|
+ /**
|
|
|
24
|
+ * 预下单
|
|
|
25
|
+ *
|
|
|
26
|
+ * API: com.alibaba.trade:alibaba.createOrder.preview-1
|
|
|
27
|
+ *
|
|
|
28
|
+ * 接口文档: https://open.1688.com/api/apidocdetail.htm?id=com.alibaba.trade%3Aalibaba.createOrder.preview-1
|
|
|
29
|
+ *
|
|
|
30
|
+ * 请求参数格式:
|
|
|
31
|
+ * - flow: 流程标识(saleproxy=分销采购, general=普通下单)
|
|
|
32
|
+ * - productList: 商品列表JSON数组,每个商品包含 offerId, quantity, specId
|
|
|
33
|
+ * - addressParam: 地址参数JSON对象,包含 fullName, mobile, provinceText, cityText, areaText, address
|
|
|
34
|
+ * - totalAmount: 总金额(单位:分,可选)
|
|
|
35
|
+ * - message: 买家留言(可选)
|
|
|
36
|
+ *
|
|
|
37
|
+ * @param array $params 预下单参数
|
|
|
38
|
+ * @return array|false
|
|
|
39
|
+ */
|
|
|
40
|
+ public function previewOrder(array $params = [])
|
|
|
41
|
+ {
|
|
|
42
|
+ $businessParams = [];
|
|
|
43
|
+
|
|
|
44
|
+ // --- productList(商品列表,JSON字符串) ---
|
|
|
45
|
+ // 直接传入已格式化的数组,由方法转为JSON
|
|
|
46
|
+ if (!empty($params['cargoParamList'])) {
|
|
|
47
|
+ $businessParams['cargoParamList'] = is_array($params['cargoParamList'])
|
|
|
48
|
+ ? json_encode($params['cargoParamList'], JSON_UNESCAPED_UNICODE)
|
|
|
49
|
+ : $params['cargoParamList'];
|
|
|
50
|
+ }
|
|
|
51
|
+
|
|
|
52
|
+ // --- addressParam(地址参数,JSON字符串) ---
|
|
|
53
|
+ // 直接传入已格式化的数组,由方法转为JSON
|
|
|
54
|
+ if (!empty($params['addressParam'])) {
|
|
|
55
|
+ $businessParams['addressParam'] = is_array($params['addressParam'])
|
|
|
56
|
+ ? json_encode($params['addressParam'], JSON_UNESCAPED_UNICODE)
|
|
|
57
|
+ : $params['addressParam'];
|
|
|
58
|
+ }
|
|
|
59
|
+ // --- 调用API ---
|
|
|
60
|
+ $result = $this->executeParam2(
|
|
|
61
|
+ self::NAMESPACE,
|
|
|
62
|
+ 'alibaba.createOrder.preview',
|
|
|
63
|
+ 1,
|
|
|
64
|
+ $businessParams
|
|
|
65
|
+ );
|
|
|
66
|
+
|
|
|
67
|
+ if ($result === false) {
|
|
|
68
|
+ Log::channel('alibaba')->error('[预下单] API请求失败', $businessParams);
|
|
|
69
|
+ return false;
|
|
|
70
|
+ }
|
|
|
71
|
+
|
|
|
72
|
+ return $this->formatPreviewResult($result);
|
|
|
73
|
+ }
|
|
|
74
|
+
|
|
|
75
|
+ /**
|
|
|
76
|
+ * 格式化预下单返回结果
|
|
|
77
|
+ *
|
|
|
78
|
+ * 实际返回结构:
|
|
|
79
|
+ * {
|
|
|
80
|
+ * "orderPreviewResuslt": [{
|
|
|
81
|
+ * "tradeModeNameList": ["assureTrade"],
|
|
|
82
|
+ * "status": true,
|
|
|
83
|
+ * "sumPayment": 370, // 总支付金额(单位:分)
|
|
|
84
|
+ * "sumCarriage": 300, // 总运费(单位:分)
|
|
|
85
|
+ * "sumPaymentNoCarriage": 70, // 商品总金额(不含运费,单位:分)
|
|
|
86
|
+ * "flowFlag": "fenxiaonew",
|
|
|
87
|
+ * "cargoList": [{ // 商品列表
|
|
|
88
|
+ * "amount": 0.7,
|
|
|
89
|
+ * "finalUnitPrice": 0.7,
|
|
|
90
|
+ * "specId": "...",
|
|
|
91
|
+ * "skuId": 6148579878582,
|
|
|
92
|
+ * "offerId": 678279922176,
|
|
|
93
|
+ * "openOfferId": "...",
|
|
|
94
|
+ * "cargoPromotionList": []
|
|
|
95
|
+ * }],
|
|
|
96
|
+ * "tradeModelList": [{"name":"担保交易","tradeType":"assureTrade","opSupport":true}],
|
|
|
97
|
+ * "payChannelInfos": [{"name":"alipay"}],
|
|
|
98
|
+ * "orderGroup": "79d4f82d...",
|
|
|
99
|
+ * "canUseOfficialSolution": false
|
|
|
100
|
+ * }],
|
|
|
101
|
+ * "success": true,
|
|
|
102
|
+ * "unsupportedCrossBorderPayOfferList": []
|
|
|
103
|
+ * }
|
|
|
104
|
+ *
|
|
|
105
|
+ * @param array $result API原始返回数据
|
|
|
106
|
+ * @return array
|
|
|
107
|
+ */
|
|
|
108
|
+ protected function formatPreviewResult(array $result): array
|
|
|
109
|
+ {
|
|
|
110
|
+ $success = $result['success'] ?? false;
|
|
|
111
|
+ $previewList = $result['orderPreviewResuslt'] ?? [];
|
|
|
112
|
+
|
|
|
113
|
+ if (empty($previewList) || !is_array($previewList)) {
|
|
|
114
|
+ return [
|
|
|
115
|
+ 'success' => $success,
|
|
|
116
|
+ 'preview' => null,
|
|
|
117
|
+ 'list' => [],
|
|
|
118
|
+ ];
|
|
|
119
|
+ }
|
|
|
120
|
+
|
|
|
121
|
+ $formattedList = [];
|
|
|
122
|
+ foreach ($previewList as $item) {
|
|
|
123
|
+ $formattedList[] = [
|
|
|
124
|
+ 'sumPayment' => $item['sumPayment'] ?? 0,
|
|
|
125
|
+ 'sumCarriage' => $item['sumCarriage'] ?? 0,
|
|
|
126
|
+ 'sumPaymentNoCarriage' => $item['sumPaymentNoCarriage'] ?? 0,
|
|
|
127
|
+ 'flowFlag' => $item['flowFlag'] ?? '',
|
|
|
128
|
+ // 'orderGroup' => $item['orderGroup'] ?? '',
|
|
|
129
|
+ // 'status' => $item['status'] ?? false,
|
|
|
130
|
+ // 'cargoList' => $item['cargoList'] ?? [],
|
|
|
131
|
+ // 'tradeModeNameList' => $item['tradeModeNameList'] ?? [],
|
|
|
132
|
+ // 'tradeModelList' => $item['tradeModelList'] ?? [],
|
|
|
133
|
+ // 'payChannelInfos' => $item['payChannelInfos'] ?? [],
|
|
|
134
|
+ // 'shopPromotionList' => $item['shopPromotionList'] ?? [],
|
|
|
135
|
+ // 'tradeServiceList' => $item['tradeServiceList'] ?? [],
|
|
|
136
|
+ // 'taoSampleSinglePromotion' => $item['taoSampleSinglePromotion'] ?? false,
|
|
|
137
|
+ // 'canUseOfficialSolution' => $item['canUseOfficialSolution'] ?? false,
|
|
|
138
|
+ ];
|
|
|
139
|
+ }
|
|
|
140
|
+
|
|
|
141
|
+ return [
|
|
|
142
|
+ // 'success' => $success,
|
|
|
143
|
+ 'preview' => $formattedList[0] ?? null,
|
|
|
144
|
+ // 'list' => $formattedList,
|
|
|
145
|
+ // 'unsupportedCrossBorderPayOfferList' => $result['unsupportedCrossBorderPayOfferList'] ?? [],
|
|
|
146
|
+ ];
|
|
|
147
|
+ }
|
|
|
148
|
+
|
|
|
149
|
+ /**
|
|
|
150
|
+ * 构建商品列表参数(便捷方法)
|
|
|
151
|
+ *
|
|
|
152
|
+ * @param array $items 商品列表 [['offerId' => 123, 'quantity' => 2, 'skuId' => 456], ...]
|
|
|
153
|
+ * @return array
|
|
|
154
|
+ */
|
|
|
155
|
+ public function buildProductList(array $items): array
|
|
|
156
|
+ {
|
|
|
157
|
+ $productList = [];
|
|
|
158
|
+ foreach ($items as $item) {
|
|
|
159
|
+ $product = [
|
|
|
160
|
+ 'offerId' => (int)($item['offerId'] ?? $item['productId'] ?? 0),
|
|
|
161
|
+ 'quantity' => (int)($item['quantity'] ?? 1),
|
|
|
162
|
+ ];
|
|
|
163
|
+ if (!empty($item['skuId'])) {
|
|
|
164
|
+ $product['skuId'] = (int)$item['skuId'];
|
|
|
165
|
+ }
|
|
|
166
|
+ if (!empty($item['price'])) {
|
|
|
167
|
+ $product['price'] = (int)$item['price']; // 单位:分
|
|
|
168
|
+ }
|
|
|
169
|
+ if (!empty($item['productUnit'])) {
|
|
|
170
|
+ $product['productUnit'] = $item['productUnit'];
|
|
|
171
|
+ }
|
|
|
172
|
+ $productList[] = $product;
|
|
|
173
|
+ }
|
|
|
174
|
+ return $productList;
|
|
|
175
|
+ }
|
|
|
176
|
+
|
|
|
177
|
+ /**
|
|
|
178
|
+ * 构建地址参数(便捷方法)
|
|
|
179
|
+ *
|
|
|
180
|
+ * @param int $addressId 地址ID
|
|
|
181
|
+ * @return array
|
|
|
182
|
+ */
|
|
|
183
|
+ public function buildAddressParam(int $addressId): array
|
|
|
184
|
+ {
|
|
|
185
|
+ return [
|
|
|
186
|
+ 'addressId' => $addressId,
|
|
|
187
|
+ ];
|
|
|
188
|
+ }
|
|
|
189
|
+
|
|
|
190
|
+ /**
|
|
|
191
|
+ * 构建完整地址参数(使用系统地址数据格式)
|
|
|
192
|
+ *
|
|
|
193
|
+ * 适配系统 user_address 表字段:
|
|
|
194
|
+ * address_id, real_name, phone, province, city, district, detail, post_code, code_list
|
|
|
195
|
+ *
|
|
|
196
|
+ * @param array $address 地址信息(系统user_address表数据)
|
|
|
197
|
+ * @return array
|
|
|
198
|
+ */
|
|
|
199
|
+ public function buildFullAddressParam(array $address): array
|
|
|
200
|
+ {
|
|
|
201
|
+ // 解析地区编码列表: "1,67449,35,493"
|
|
|
202
|
+ $codeList = $address['code_list'] ?? '';
|
|
|
203
|
+ $codes = explode(',', $codeList);
|
|
|
204
|
+ $districtCode = $codes[1] ?? $codes[0] ?? '';
|
|
|
205
|
+
|
|
|
206
|
+ return [
|
|
|
207
|
+ 'fullName' => $address['real_name'] ?? $address['fullName'] ?? '',
|
|
|
208
|
+ 'mobile' => $address['phone'] ?? $address['mobile'] ?? '',
|
|
|
209
|
+ 'phone' => $address['phone'] ?? $address['phone'] ?? '',
|
|
|
210
|
+ 'postCode' => $address['post_code'] ?? $address['postCode'] ?? '',
|
|
|
211
|
+ 'cityText' => $address['city'] ?? $address['cityText'] ?? '',
|
|
|
212
|
+ 'provinceText' => $address['province'] ?? $address['provinceText'] ?? '',
|
|
|
213
|
+ 'areaText' => $address['district'] ?? $address['areaText'] ?? '',
|
|
|
214
|
+ 'townText' => $address['village'] ?? $address['townText'] ?? '',
|
|
|
215
|
+ 'address' => $address['detail'] ?? $address['address'] ?? '',
|
|
|
216
|
+ 'districtCode' => $districtCode,
|
|
|
217
|
+ ];
|
|
|
218
|
+ }
|
|
|
219
|
+}
|