IntraCityExpress.php 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667
  1. <?php
  2. namespace common\components;
  3. use hd\models\IntraCity\StoreFeeForm;
  4. use yii\helpers\Json;
  5. //use linslin\yii2\curl;
  6. use bizHd\wx\classes\WxOpenClass;
  7. use phpseclib\Crypt\RSA;
  8. class IntraCityExpress
  9. {
  10. /**
  11. * 获取 access_token
  12. * @param $merchant
  13. * @param int $ptStyle
  14. * @return string
  15. */
  16. public static function getAccessToken($merchant, $ptStyle = 0)
  17. {
  18. if ($ptStyle == 0) {
  19. $ptStyle = dict::getDict('ptStyle', 'hd');
  20. }
  21. // 直接复用 miniUtil 的获取小程序 access_token 方法
  22. return miniUtil::getMiniProgramAccessToken($merchant, $ptStyle);
  23. }
  24. public static function getMerchant()
  25. {
  26. $merchant = WxOpenClass::getWxInfo();
  27. return $merchant;
  28. }
  29. /**
  30. * 使用 WxApi 方式生成微信API签名
  31. * @param string $url 请求URL
  32. * @param string $appId 小程序AppID
  33. * @param int $timestamp 时间戳
  34. * @param string $reqData 请求体JSON字符串
  35. * @return string 签名字符串
  36. */
  37. private static function generateWxApiSignature($url, $appId, $timestamp, $reqData)
  38. {
  39. // 获取私钥
  40. $env = getenv('YII_ENV') == 'production' ? 'production' : 'dev';
  41. $privateKeyPath = __DIR__ . '/wxapi/' . $env . '/rsa-private-key.txt';
  42. if (!file_exists($privateKeyPath)) {
  43. throw new \Exception("私钥文件不存在: {$privateKeyPath}");
  44. }
  45. $privateKey = file_get_contents($privateKeyPath);
  46. if (!$privateKey) {
  47. throw new \Exception('无法获取私钥文件');
  48. }
  49. // 构建签名载荷,格式:$url\n$appId\n$timestamp\n$reqData
  50. $payload = "$url\n$appId\n$timestamp\n$reqData";
  51. // 方案一: 使用 OpenSSL(推荐方式,与微信官方示例一致)
  52. // $signature = '';
  53. // $result = openssl_sign($payload, $signature, $privateKey, OPENSSL_ALGO_SHA256);
  54. // if (!$result) {
  55. // throw new \Exception('OpenSSL签名失败: ' . openssl_error_string());
  56. // }
  57. // $base64Signature = base64_encode($signature);
  58. // \Yii::info("生成的签名: " . $base64Signature, 'intracity_signature');
  59. // return $base64Signature;
  60. // 方案二:使用 RSA SHA256签名
  61. try {
  62. // 使用RSA SHA256签名
  63. $rsa = new RSA();
  64. $rsa->loadKey($privateKey);
  65. $rsa->setHash("sha256");
  66. $rsa->setMGFHash("sha256");
  67. $signature = $rsa->sign($payload);
  68. // $rsa = new RSA();
  69. // $rsa->loadKey($privateKey);
  70. // $rsa->setSignatureMode(RSA::SIGNATURE_PKCS1); // 明确使用PKCS#1 v1.5
  71. // $rsa->setHash("sha256");
  72. // 不要设置MGF,PKCS#1 v1.5不使用MGF
  73. // $signature = $rsa->sign($payload);
  74. $base64Signature = base64_encode($signature);
  75. \Yii::info("phpseclib生成的签名: " . $base64Signature, 'intracity_signature');
  76. return $base64Signature;
  77. } catch (\Exception $e) {
  78. \Yii::error("所有签名方法都失败 - OpenSSL: " . $e->getMessage() . " phpseclib: " . $e->getMessage(), 'intracity_signature');
  79. throw new \Exception('签名生成失败: OpenSSL和phpseclib都失败');
  80. }
  81. }
  82. /**
  83. * 发送HTTP请求
  84. * @param string $url 请求URL
  85. * @param array $data 请求数据
  86. * @param string $accessToken access_token
  87. * @return array
  88. */
  89. public static function sendRequest($url, $data, $accessToken)
  90. {
  91. // ================ 选择哪个 appId =================
  92. // 微信开放平台 appId
  93. $open = \biz\wx\classes\WxOpenClass::getByCondition(['style' => dict::getDict('ptStyle', 'hd')]);
  94. if (empty($open)) {
  95. util::fail('没有找到平台信息');
  96. }
  97. $component_app_id = $open['appId'];
  98. $appId = $component_app_id;
  99. // 当前小程序的 appId
  100. //$appId = $merchant['miniAppId'] ?? util::fail('app-id 出错');
  101. // 方式一: 使用WxApi方式处理请求 ============================
  102. try {
  103. $wxApi = new \common\components\wxapi\WxApi($appId, $accessToken);
  104. $result = $wxApi->request($url, $data);
  105. return $result;
  106. } catch (\Exception $e) {
  107. // 如果WxApi方式失败,回退到简单方式
  108. util::fail('error');
  109. }
  110. // 添加access_token到URL
  111. $urlWithToken = $url . (strpos($url, '?') !== false ? '&' : '?') . 'access_token=' . $accessToken;
  112. $timestamp = time();
  113. $body = Json::encode($data);
  114. if ($body === '[]') {
  115. $body = '{}';
  116. }
  117. // 方式二: 自己处理请求 =========== 失败,不使用(可删除)
  118. // $signature = self::generateWxApiSignature($url, $appId, $timestamp, $body);
  119. // 构建请求头,包含微信API签名所需的头部
  120. // $headers = [
  121. // 'Content-Type: application/json',
  122. // 'Accept: application/json',
  123. // 'Wechatmp-Appid: ' . $appId,
  124. // 'Wechatmp-TimeStamp: ' . $timestamp,
  125. // 'Wechatmp-Signature: ' . $signature
  126. // ];
  127. // $curl = new curl\Curl();
  128. // $response = $curl->setOption(CURLOPT_POSTFIELDS, $body)
  129. // ->setOption(CURLOPT_HTTPHEADER, $headers)
  130. // ->post($urlWithToken);
  131. // if (is_array($response)) {
  132. // return $response;
  133. // }
  134. // return Json::decode($response, true);
  135. }
  136. // ==================== API URL常量 ====================
  137. const API_BASE_URL = 'https://api.weixin.qq.com/cgi-bin/express/intracity';
  138. // 门店管理
  139. const API_CREATE_STORE = self::API_BASE_URL . '/createstore';
  140. const API_UPDATE_STORE = self::API_BASE_URL . '/updatestore';
  141. const API_QUERY_STORE = self::API_BASE_URL . '/querystore';
  142. // 开通门店权限
  143. const API_APPLY_STORE = self::API_BASE_URL . '/apply';
  144. // 订单管理
  145. const API_ADD_ORDER = self::API_BASE_URL . '/addorder';
  146. const API_CANCEL_ORDER = self::API_BASE_URL . '/cancelorder';
  147. const API_GET_ORDER = self::API_BASE_URL . '/queryorder';
  148. // 预下单
  149. const API_PRE_ADD_ORDER = self::API_BASE_URL . '/preaddorder';
  150. // 资金管理
  151. const API_BALANCE_QUERY = self::API_BASE_URL . '/balancequery';
  152. const API_STORE_CHARGE = self::API_BASE_URL . '/storecharge';
  153. const API_STORE_REFUND = self::API_BASE_URL . '/storerefund';
  154. const API_CHARGE_RECORD = self::API_BASE_URL . '/queryflow';
  155. // 测试接口
  156. const API_MOCK_NOTIFY = self::API_BASE_URL . '/mocknotify';
  157. // ==================== 门店管理接口 ====================
  158. /**
  159. * 创建门店
  160. * @param array $storeData 门店信息
  161. * @param string $merchant 商户信息
  162. * @param int $ptStyle
  163. * @return array
  164. */
  165. public static function createStore($storeData, $merchant = null, $ptStyle = 0)
  166. {
  167. if ($merchant === null) {
  168. $merchant = self::getMerchant();
  169. }
  170. $accessToken = self::getAccessToken($merchant, $ptStyle);
  171. $data = [
  172. 'out_store_id' => $storeData['out_store_id'],
  173. 'store_name' => $storeData['store_name'],
  174. 'order_pattern' => 1,
  175. "address_info" => $storeData['address_info']
  176. ];
  177. return self::sendRequest(self::API_CREATE_STORE, $data, $accessToken);
  178. }
  179. /**
  180. * 更新门店
  181. * @param array $storeData 门店信息
  182. * @param string $merchant 商户信息
  183. * @param int $ptStyle
  184. * @return array
  185. */
  186. public static function updateStore($storeData, $merchant = null, $ptStyle = 0)
  187. {
  188. if ($merchant === null) {
  189. $merchant = self::getMerchant();
  190. }
  191. $accessToken = self::getAccessToken($merchant, $ptStyle);
  192. $data = $storeData;
  193. return self::sendRequest(self::API_UPDATE_STORE, $data, $accessToken);
  194. }
  195. /**
  196. * 查询门店
  197. * @param string $outStoreId 门店ID
  198. * @param string $merchant 商户信息
  199. * @param int $ptStyle
  200. * @return array
  201. */
  202. public static function getStore($outStoreId, $merchant = null, $ptStyle = 0)
  203. {
  204. if ($merchant === null) {
  205. $merchant = self::getMerchant();
  206. }
  207. $accessToken = self::getAccessToken($merchant, $ptStyle);
  208. $data = [
  209. 'out_store_id' => $outStoreId,
  210. ];
  211. return self::sendRequest(self::API_QUERY_STORE, $data, $accessToken);
  212. }
  213. /**
  214. * 开通门店权限
  215. * @param null $merchant
  216. * @param int $ptStyle
  217. * @return array
  218. */
  219. public static function applyStore($merchant = null, $ptStyle = 0)
  220. {
  221. if ($merchant === null) {
  222. $merchant = self::getMerchant();
  223. }
  224. $accessToken = self::getAccessToken($merchant, $ptStyle);
  225. return self::sendRequest(self::API_APPLY_STORE, [], $accessToken);
  226. }
  227. // ==================== 订单管理接口 ====================
  228. /**
  229. * 创建订单
  230. * @param array $orderData 订单信息
  231. * @param string $merchant 商户信息
  232. * @param int $ptStyle
  233. * @return array
  234. */
  235. public static function createOrder($orderData, $merchant = null, $ptStyle = 0)
  236. {
  237. if ($merchant === null) {
  238. $merchant = self::getMerchant();
  239. }
  240. $accessToken = self::getAccessToken($merchant, $ptStyle);
  241. $data = $orderData;
  242. return self::sendRequest(self::API_ADD_ORDER, $data, $accessToken);
  243. }
  244. /**
  245. * 预下单(查询运费)
  246. * @param array $orderData
  247. * @param null $merchant
  248. * @param int $ptStyle
  249. * @return array
  250. */
  251. public static function preAddOrder($orderData, $merchant = null, $ptStyle = 0)
  252. {
  253. // 创建表单验证模型
  254. $form = new StoreFeeForm();
  255. $form->setScenario('query_fee');
  256. $form->load($orderData, ''); // 直接从 post 数据加载,不使用模型名作为前缀
  257. // 执行表单验证
  258. $form->validateForm();
  259. if ($merchant === null) {
  260. $merchant = self::getMerchant();
  261. }
  262. $accessToken = self::getAccessToken($merchant, $ptStyle);
  263. // 请求体
  264. $data = $orderData;
  265. return self::sendRequest(self::API_PRE_ADD_ORDER, $data, $accessToken);
  266. }
  267. /**
  268. * 取消订单
  269. * @param string $wxOrderId 微信订单号
  270. * @param string $storeOrderId 商户订单号
  271. * @param string $wxStoreId 门店ID
  272. * @param string $merchant 商户信息
  273. * @param int $ptStyle
  274. * @return array
  275. */
  276. public static function cancelOrder($wxOrderId = '', $storeOrderId = '', $wxStoreId = '', $merchant = null, $ptStyle = 0)
  277. {
  278. if ($merchant === null) {
  279. $merchant = self::getMerchant();
  280. }
  281. $accessToken = self::getAccessToken($merchant, $ptStyle);
  282. $data = [];
  283. if (!empty($wxOrderId)) {
  284. $data['wx_order_id'] = $wxOrderId;
  285. }
  286. if (!empty($storeOrderId)) {
  287. $data['store_order_id'] = $storeOrderId;
  288. }
  289. if (!empty($wxStoreId)) {
  290. $data['wx_store_id'] = $wxStoreId;
  291. }
  292. $cancelReasons = []; // 1:不需要了 2:信息填错 3:无人接单 99:其他
  293. $data['cancel_reason_id'] = 1;
  294. return self::sendRequest(self::API_CANCEL_ORDER, $data, $accessToken);
  295. }
  296. /**
  297. * 查询订单
  298. * @param string $wxOrderId 微信订单号
  299. * @param string $outOrderId 商户订单号
  300. * @param string $outStoreId 门店ID
  301. * @param string $merchant 商户信息
  302. * @param int $ptStyle
  303. * @return array
  304. */
  305. public static function queryOrder($wxStoreId, $storeOrderId='', $wxOrderId='', $merchant = null, $ptStyle = 0)
  306. {
  307. if ($merchant === null) {
  308. $merchant = self::getMerchant();
  309. }
  310. $accessToken = self::getAccessToken($merchant, $ptStyle);
  311. if (empty($wxOrderId) && (empty($storeOrderId) || empty($wxStoreId))) {
  312. util::fail("参数不足:wx_order_id 或 (store_order_id + wx_store_id) 必须提供一组");
  313. }
  314. $data = [];
  315. if ($wxStoreId != '') {
  316. $data['wx_order_id'] = $wxOrderId;
  317. }
  318. $data['store_order_id'] = $storeOrderId;
  319. $data['wx_store_id'] = $wxStoreId;
  320. return self::sendRequest(self::API_GET_ORDER, $data, $accessToken);
  321. }
  322. // ==================== 资金管理接口 ====================
  323. /**
  324. * 查询门店余额
  325. * @param string $wxStoreId
  326. * @param null $merchant
  327. * @param int $ptStyle
  328. * @return array
  329. */
  330. public static function getBalance($wxStoreId, $merchant = null, $ptStyle = 0)
  331. {
  332. if ($merchant === null) {
  333. $merchant = self::getMerchant();
  334. }
  335. $accessToken = self::getAccessToken($merchant, $ptStyle);
  336. $data = ['wx_store_id' => $wxStoreId]; //'out_store_id' => $outStoreId,
  337. return self::sendRequest(self::API_BALANCE_QUERY, $data, $accessToken);
  338. }
  339. /**
  340. * 门店充值
  341. * @param string $wxStoreId
  342. * @param string $outChargeId
  343. * @param int $amount
  344. * @param null $merchant
  345. * @param int $ptStyle
  346. * @return array
  347. */
  348. public static function storeCharge($wxStoreId, $chargeId, $amount, $merchant = null, $ptStyle = 0)
  349. {
  350. if ($merchant === null) {
  351. $merchant = self::getMerchant();
  352. }
  353. $accessToken = self::getAccessToken($merchant, $ptStyle);
  354. $data = [
  355. 'wx_store_id' => $wxStoreId,
  356. 'service_trans_id' => $chargeId,
  357. 'amount' => $amount,
  358. ];
  359. return self::sendRequest(self::API_STORE_CHARGE, $data, $accessToken);
  360. }
  361. /**
  362. * 门店退款
  363. * @param string $wxStoreId
  364. * @param string $payMode
  365. * @param string $transId
  366. * @param null $merchant
  367. * @param int $ptStyle
  368. * @return array
  369. */
  370. public static function storeFund($wxStoreId, $payMode, $transId, $merchant = null, $ptStyle = 0)
  371. {
  372. if ($merchant === null) {
  373. $merchant = self::getMerchant();
  374. }
  375. $accessToken = self::getAccessToken($merchant, $ptStyle);
  376. $data = [
  377. 'wx_store_id' => $wxStoreId,
  378. 'pay_mode' => $payMode,
  379. 'service_trans_id' => $transId,
  380. ];
  381. return self::sendRequest(self::API_STORE_REFUND, $data, $accessToken);
  382. }
  383. /**
  384. * 查询充值记录
  385. * @param string $outChargeId
  386. * @param null $merchant
  387. * @param int $ptStyle
  388. * @return array
  389. */
  390. public static function getChargeRecord($outChargeId, $merchant = null, $ptStyle = 0)
  391. {
  392. if ($merchant === null) {
  393. $merchant = self::getMerchant();
  394. }
  395. $accessToken = self::getAccessToken($merchant, $ptStyle);
  396. $data = ['out_charge_id' => $outChargeId];
  397. return self::sendRequest(self::API_CHARGE_RECORD, $data, $accessToken);
  398. }
  399. // ==================== 测试接口 ====================
  400. /**
  401. * 模拟回调接口
  402. * @param string $wxOrderId 微信订单号
  403. * @param string $outStoreId 门店ID
  404. * @param string $outOrderId 商户订单号
  405. * @param int $orderStatus 订单状态
  406. * @param string $merchant 商户信息
  407. * @param int $ptStyle
  408. * @return array
  409. */
  410. public static function mockNotify($orderStatus, $wxOrderId = '', $outStoreId = '', $outOrderId = '', $merchant = null, $ptStyle = 0)
  411. {
  412. if ($merchant === null) {
  413. $merchant = self::getMerchant();
  414. }
  415. $accessToken = self::getAccessToken($merchant, $ptStyle);
  416. $data = [
  417. 'order_status' => $orderStatus,
  418. ];
  419. if (!empty($wxOrderId)) {
  420. $data['wx_order_id'] = $wxOrderId;
  421. }
  422. // 注意:文档中模拟回调使用的是 wx_store_id 和 store_order_id
  423. if (!empty($outStoreId) && !empty($outOrderId)) {
  424. $data['wx_store_id'] = $outStoreId;
  425. $data['store_order_id'] = $outOrderId;
  426. }
  427. return self::sendRequest(self::API_MOCK_NOTIFY, $data, $accessToken);
  428. }
  429. /**
  430. * 生成回调签名
  431. * @param array $params 回调参数
  432. * @param string $token 安全token
  433. * @return string
  434. */
  435. public static function generateCallbackSignature($params, $token)
  436. {
  437. // 1. 筛选出参与签名的字段
  438. $signParams = [];
  439. $fieldsToSign = ['appid', 'order_status', 'service_trans_id', 'status_change_time', 'store_order_id', 'timestamp', 'wx_order_id', 'wx_store_id'];
  440. foreach ($fieldsToSign as $field) {
  441. if (isset($params[$field])) {
  442. $signParams[$field] = $params[$field];
  443. }
  444. }
  445. // 2. 按字典序排序参数
  446. ksort($signParams);
  447. // 3. 拼接参数字符串
  448. $signStr = '';
  449. foreach ($signParams as $key => $value) {
  450. $signStr .= $key . '=' . $value . '&';
  451. }
  452. $signStr .= 'token=' . $token;
  453. // 4. 计算MD5并转为小写
  454. return strtolower(md5($signStr));
  455. }
  456. // ==================== 回调验证接口 ====================
  457. /**
  458. * 验证回调签名
  459. * @param array $params 回调参数
  460. * @param string $token 安全token
  461. * @return bool
  462. */
  463. public static function verifyCallback($params, $token)
  464. {
  465. if (!isset($params['sign'])) {
  466. return false;
  467. }
  468. $receivedSign = $params['sign'];
  469. unset($params['sign']);
  470. $calculatedSign = self::generateCallbackSignature($params, $token);
  471. return $receivedSign === $calculatedSign;
  472. }
  473. /**
  474. * 处理订单状态回调
  475. * @param array $callbackData 回调数据
  476. * @param string $token 安全token
  477. * @return array
  478. */
  479. public static function handleOrderCallback($callbackData, $token)
  480. {
  481. // 验证签名
  482. if (!self::verifyCallback($callbackData, $token)) {
  483. return [
  484. 'return_code' => 1,
  485. 'return_msg' => '签名验证失败'
  486. ];
  487. }
  488. // 处理订单状态变化
  489. $orderStatus = $callbackData['order_status'];
  490. $wxOrderId = $callbackData['wx_order_id'];
  491. $outOrderId = $callbackData['store_order_id'] ?? '';
  492. $outStoreId = $callbackData['wx_store_id'] ?? '';
  493. // 这里可以添加具体的业务逻辑处理
  494. // 例如:更新数据库中的订单状态、发送通知等
  495. // 伪代码示例:
  496. /*
  497. switch ($orderStatus) {
  498. case 10000: // 订单创建成功
  499. // 处理订单创建成功逻辑
  500. break;
  501. case 30000: // 配送员接单
  502. // 处理配送员接单逻辑
  503. break;
  504. case 40000: // 配送员到店
  505. // 处理配送员到店逻辑
  506. break;
  507. case 50000: // 配送中
  508. // 处理配送中逻辑
  509. break;
  510. case 70000: // 配送完成
  511. // 处理配送完成逻辑
  512. break;
  513. case 20000: // 商家取消订单
  514. case 20001: // 配送方取消订单
  515. case 60000: // 配送员撤单
  516. // 处理订单取消逻辑
  517. break;
  518. case 90000: // 配送异常
  519. // 处理配送异常逻辑
  520. break;
  521. }
  522. */
  523. return [
  524. 'return_code' => 0,
  525. 'return_msg' => 'OK'
  526. ];
  527. }
  528. // ==================== 常量定义 ====================
  529. /**
  530. * 订单状态常量
  531. */
  532. const ORDER_STATUS_CREATED = 10000; // 订单创建成功
  533. const ORDER_STATUS_CANCELED_BY_MERCHANT = 20000; // 商家取消订单
  534. const ORDER_STATUS_CANCELED_BY_DELIVERY = 20001; // 配送方取消订单
  535. const ORDER_STATUS_ACCEPTED = 30000; // 配送员接单
  536. const ORDER_STATUS_ARRIVED = 40000; // 配送员到店
  537. const ORDER_STATUS_DELIVERING = 50000; // 配送中
  538. const ORDER_STATUS_WITHDRAWN = 60000; // 配送员撤单
  539. const ORDER_STATUS_COMPLETED = 70000; // 配送完成
  540. const ORDER_STATUS_EXCEPTION = 90000; // 配送异常
  541. /**
  542. * 物品类型常量
  543. */
  544. const GOODS_TYPE_FAST_FOOD = 1; // 快餐
  545. const GOODS_TYPE_MEDICINE = 2; // 药品
  546. const GOODS_TYPE_GENERAL = 3; // 百货
  547. const GOODS_TYPE_FRESH = 6; // 生鲜
  548. const GOODS_TYPE_WINE = 8; // 酒品
  549. const GOODS_TYPE_DOCUMENT = 12; // 文件
  550. const GOODS_TYPE_CAKE = 13; // 蛋糕
  551. const GOODS_TYPE_FLOWER = 14; // 鲜花
  552. const GOODS_TYPE_DIGITAL = 15; // 数码
  553. const GOODS_TYPE_CLOTHING = 16; // 服装
  554. const GOODS_TYPE_AUTO_PARTS = 17; // 汽配
  555. const GOODS_TYPE_JEWELRY = 18; // 珠宝
  556. const GOODS_TYPE_DRINK = 32; // 饮料
  557. const GOODS_TYPE_LICENSE = 36; // 证照
  558. const GOODS_TYPE_PET = 55; // 宠物用品
  559. const GOODS_TYPE_MATERNITY = 56; // 母婴用品
  560. const GOODS_TYPE_COSMETICS = 57; // 美妆用品
  561. const GOODS_TYPE_HOME = 58; // 家居建材
  562. const GOODS_TYPE_OTHER = 99; // 其他
  563. /**
  564. * 运力常量
  565. */
  566. const DELIVERY_DADA = 'DADA'; // 达达
  567. const DELIVERY_SFTC = 'SFTC'; // 顺丰同城
  568. }