MiniExpressService.php 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443
  1. <?php
  2. namespace bizGhs\express\services;
  3. //小程序 即使配送相关接口 lqh 2021.2.4
  4. use bizHd\wx\classes\WxOpenClass;
  5. use biz\express\classes\ExpressClass;
  6. use common\components\miniUtil;
  7. use common\components\util;
  8. class MiniExpressService
  9. {
  10. //订单取消原因
  11. public static $cancelOrderReasonMap = [
  12. 1=>'暂时不需要邮寄',
  13. 2=>'价格不合适',
  14. 3=>'订单信息有误,重新下单',
  15. 4=>'骑手取货不及时',
  16. 5=>'骑手配送不及时',
  17. 6=>'其他原因', //如果选择6,需要填写取消原因,否则不需要填写
  18. ];
  19. //order_status 枚举值
  20. /*
  21. * 最终状态包括成功状态302,失败状态: 103,203,204,205,401,501,502。
  22. 当状态更新时,我们会在关键节点给收件用户推送服务通知,告知配送状态,
  23. 同一配送单常态下会收到三条通知,即【骑手已接单】、【骑手已取货,配送中】、【配送已完成】,
  24. 配送异常时会下发【配送异常】服务通知。
  25. 骑手已接单 102
  26. 骑手已取货,配送中 202或301
  27. 配送已完成 302
  28. 配送异常 203、204、205、303、304、305、501、502
  29. */
  30. public static $orderStatusMap = [
  31. 101=>'等待分配骑手',//配送公司接单阶段——等待分配骑手,即初始状态
  32. 102=>'骑手已接单',//配送公司接单阶段——分配骑手成功
  33. 103=>'商家取消订单',//配送公司接单阶段——商家取消订单, 订单结束
  34. 201=>'骑手到店开始取货',//骑手取货阶段——骑手到店开始取货
  35. 202=>'取货成功',//骑手取货阶段——取货成功
  36. 203=>'取货失败,商家取消订单',//骑手取货阶段——取货失败,商家取消订单, 订单结束
  37. 204=>'取货失败,骑手因自身原因取消订单',//骑手取货阶段——取货失败,骑手因自身原因取消订单, 订单结束
  38. 205=>'取货失败,骑手因商家原因取消订单',//骑手取货阶段——取货失败,骑手因商家原因取消订单, 订单结束
  39. 301=>'配送中',//骑手配送阶段——配送中
  40. 302=>'配送成功',//骑手配送阶段——配送成功, 订单结束
  41. 303=>'商家取消订单,配送物品开始返还商家',//骑手配送阶段——商家取消订单,配送物品开始返还商家
  42. 304=>'无法联系收货人,配送物品开始返还商家',//骑手配送阶段——无法联系收货人,配送物品开始返还商家
  43. 305=>'收货人拒收,配送物品开始返还商家',//骑手配送阶段——收货人拒收,配送物品开始返还商家
  44. 401=>'货品返还商户成功',//骑手返回配送货品阶段——货品返还商户成功, 订单结束
  45. 501=>'因运力系统原因取消, 订单结束',//因运力系统原因取消, 订单结束
  46. 502=>'因不可抗拒因素取消,订单结束',//因不可抗拒因素(天气,道路管制等原因)取消,订单结束
  47. ];
  48. //获取已支持的配送公司列表接口(改为查 数据库 xhExpress)
  49. /*
  50. * [{"delivery_id":"SFTC","delivery_name":"顺丰同城急送"},{"delivery_id":"SS","delivery_name":"闪送"},{"delivery_id":"MTPS","delivery_name":"美团配送"},{"delivery_id":"DADA","delivery_name":"达达"}]
  51. */
  52. public static function getAllImmeDelivery($select='*',$where=[])
  53. {
  54. // $merchant = self::getGhsWxInfo();
  55. // $res = miniUtil::getAllImmeDelivery($merchant,2);
  56. // self::handleReturn($res);
  57. // return $res;
  58. $res = ExpressClass::getExpressAll($select,$where);
  59. return $res;
  60. }
  61. //下单
  62. /**
  63. * @param int $expressId 哪家快递 xhExpress 主键ID
  64. * @param string $shopNo 门店ID(商家ID)
  65. * @param string $orderSn 订单号
  66. * @param string $openId 下单用户的openid
  67. * @param array $sender 发件人信息,顺丰同城急送必须填写,美团配送、达达、闪送,若传了shop_no的值可不填该字段
  68. * @param array $receiver 收件人信息
  69. * @param array $cargo 货物信息
  70. * @param array $orderInfo 订单信息
  71. * @param array $shop 商品信息,会展示到物流通知消息中
  72. * @param string $subBizId 子商户id,区分小程序内部多个子商户
  73. * @return mixed
  74. */
  75. /*
  76. * https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/immediate-delivery/by-business/immediateDelivery.addOrder.html
  77. * 'sender'=>[
  78. 'name'=>'test', //必填:姓名,最长不超过256个字符
  79. 'city'=>'厦门市', //必填:城市名称,如广州市
  80. 'address'=>'思明区', //必填:地址(街道、小区、大厦等,用于定位)
  81. 'address_detail'=>'软件园二期', //必填:地址详情(楼号、单元号、层号)
  82. 'phone'=>'19959271111', //必填:电话/手机号,最长不超过64个字符
  83. 'lng'=>118.134343, //必填:经度(火星坐标或百度坐标,和 coordinate_type 字段配合使用,确到小数点后6位
  84. 'lat'=>24.483566, //必填:纬度(火星坐标或百度坐标,和 coordinate_type 字段配合使用,精确到小数点后6位)
  85. 'coordinate_type'=>0, //非必填:坐标类型,0:火星坐标(高德,腾讯地图均采用火星坐标) 1:百度坐标
  86. ],
  87. 'receiver'=>[
  88. 'name'=>'test', //必填:姓名,最长不超过256个字符
  89. 'city'=>'厦门市', //必填:城市名称,如广州市
  90. 'address'=>'思明区', //必填:地址(街道、小区、大厦等,用于定位)
  91. 'address_detail'=>'软件园二期', //必填:地址详情(楼号、单元号、层号)
  92. 'phone'=>'19959271111', //必填:电话/手机号,最长不超过64个字符
  93. 'lng'=>118.134343, //必填:经度(火星坐标或百度坐标,和 coordinate_type 字段配合使用,确到小数点后6位
  94. 'lat'=>24.483566, //必填:纬度(火星坐标或百度坐标,和 coordinate_type 字段配合使用,精确到小数点后6位)
  95. 'coordinate_type'=>0, //非必填:坐标类型,0:火星坐标(高德,腾讯地图均采用火星坐标) 1:百度坐标
  96. ],
  97. 'cargo'=>[
  98. 'goods_value'=>1, //必填:货物价格,单位为元,精确到小数点后两位(如果小数点后位数多于两位,则四舍五入保留两位小数),范围为(0-5000]
  99. 'goods_weight'=>0.1 //必填: 货物重量,单位为kg,精确到小数点后两位(如果小数点后位数多于两位,则四舍五入保留两位小数),范围为(0-50]
  100. 'goods_height'=>0.1,//非必填: 货物高度,单位为cm,精确到小数点后两位(如果小数点后位数多于两位,则四舍五入保留两位小数),范围为(0-45]
  101. 'goods_length'=>0.1,//非必填: 货物长度,单位为cm,精确到小数点后两位(如果小数点后位数多于两位,则四舍五入保留两位小数),范围为(0-65]
  102. 'goods_with'=>0.1,//非必填: 货物宽度,单位为cm,精确到小数点后两位(如果小数点后位数多于两位,则四舍五入保留两位小数),范围为(0-50]
  103. 'goods_pickup_info'=>'', //非必填: 货物取货信息,用于骑手到店取货,最长不超过100个字符
  104. 'goods_delivery_info'=>'', //非必填: 货物交付信息,最长不超过100个字符
  105. 'cargo_first_class'=>'鲜花', //可以固定写死
  106. 'cargo_second_class'=>'鲜花',//可以固定写死
  107. 'goods_detail'=>[ //非必填:货物详情
  108. 'goods'=>[
  109. [
  110. 'good_count'=>1, //必填:货物数量
  111. 'good_name'=>'', //必填:货品名称
  112. 'good_price'=>1, //非必填:货品单价,精确到小数点后两位(如果小数点后位数多于两位,则四舍五入保留两位小数)
  113. 'good_unit'=>'', //非必填:货品单位,最长不超过20个字符
  114. ],
  115. ]
  116. ],
  117. ],
  118. 'order_info'=>[ //可以不填?
  119. ],
  120. 'shop'=>[
  121. 'wxa_path'=>'/shop',
  122. 'img_url'=>'http://www.baidu.com/test.png',
  123. 'goods_name'=>'test',
  124. 'goods_count'=>1,
  125. ],
  126. */
  127. public static function addOrder(int $expressId,string $shopNo,string $orderSn,string $openId,array $sender,array $receiver,array $cargo,array $orderInfo,array $shop, string $subBizId='')
  128. {
  129. $merchant = self::getGhsWxInfo();
  130. //通过 $expressId, 获取 appKey, appSecret
  131. $expressData = self::getExpressInfo($expressId);
  132. $shopId = $expressData['appKey']; //app_key
  133. $shopOrderId = $orderSn;
  134. $appSecret = $expressData['appSecret'];//app_secrect
  135. $delivery_id = $expressData['deliveryId'];
  136. $delivery_sign = self::getDeliverySign($shopId,$appSecret,$shopOrderId);
  137. $data = [
  138. 'shopid'=>$shopId,
  139. 'shop_order_id'=>$orderSn,
  140. 'shop_no'=>$shopNo,
  141. 'delivery_sign'=>$delivery_sign, //delivery_sign=SHA1(shopid + shop_order_id + AppSecret)
  142. 'delivery_id'=>$delivery_id,
  143. 'openid'=>$openId,
  144. 'sender'=>$sender,
  145. 'receiver'=>$receiver,
  146. 'cargo'=>$cargo,
  147. 'order_info'=>$orderInfo,
  148. 'shop'=>$shop,
  149. ];
  150. if(empty($orderInfo)) {
  151. unset($data['order_info']);
  152. }
  153. $res = miniUtil::addOrder($data,$merchant, 2);
  154. self::handleReturn($res);
  155. return $res;
  156. }
  157. //增加小费
  158. /*
  159. * "shopid": "123456",
  160. "shop_order_id": "123456",
  161. "waybill_id": "123456",
  162. "tips": 5,
  163. "remark": "gogogo",
  164. "delivery_sign": "123456",
  165. "shop_no": "shop_no_111"
  166. */
  167. /**
  168. * @param int $expressId xhExpressLocal 主键ID
  169. * @param string $orderSn 订单号
  170. * @param string $waybillId 快递方的订单号
  171. * @param string $shopNo 店铺ID
  172. * @param float $tips 小费
  173. * @param string $remark 备注说明
  174. * @return mixed
  175. */
  176. public static function addTip(int $expressId,string $orderSn, string $waybillId, string $shopNo, float $tips,string $remark='')
  177. {
  178. $merchant = self::getGhsWxInfo();
  179. $expressData = self::getExpressInfo($expressId);
  180. $data = [
  181. 'shopid'=>$expressData['appKey'],
  182. 'shop_order_id'=>$orderSn,
  183. 'waybill_id'=>$waybillId,
  184. 'tips'=>$tips,
  185. 'remark'=>$remark,
  186. 'shop_no'=>$shopNo,
  187. 'delivery_sign'=>self::getDeliverySign($expressData['appKey'],$expressData['appSecret'],$orderSn),
  188. ];
  189. $res = miniUtil::addOrder($data,$merchant, 2);
  190. self::handleReturn($res);
  191. return $res;
  192. }
  193. //取消订单
  194. /*
  195. * {
  196. "shopid": "123456",
  197. "shop_order_id": "123456",
  198. "waybill_id": "123456",
  199. "delivery_id": "123456",
  200. "cancel_reason_id": 1,
  201. "cancel_reason": "",
  202. "delivery_sign": "123456",
  203. "shop_no": "shop_no_111"
  204. }
  205. */
  206. public static function cancelOrder(int $expressId,string $orderSn,string $waybillId, string $shopNo,int $reasonId,string $reason='')
  207. {
  208. $merchant = self::getGhsWxInfo();
  209. $expressData = self::getExpressInfo($expressId);
  210. $data = [
  211. 'shopid'=>$expressData['appKey'],
  212. 'shop_order_id'=>$orderSn,
  213. 'waybill_id'=>$waybillId,
  214. 'delivery_id'=>$expressData['deliveryId'],
  215. 'cancel_reason_id'=>$reasonId,
  216. 'cancel_reason'=>$reason,
  217. 'shop_no'=>$shopNo,
  218. 'delivery_sign'=>self::getDeliverySign($expressData['appKey'],$expressData['appSecret'],$orderSn),
  219. ];
  220. $res = miniUtil::cancelOrder($data,$merchant,2);
  221. self::handleReturn($res);
  222. return $res;
  223. }
  224. //获取运单数据
  225. /*
  226. 'shopid'=>'',
  227. 'shop_order_id'=>'',
  228. 'shop_no'=>'',
  229. 返回数据:
  230. (
  231. [resultcode] => 0
  232. [resultmsg] => ok
  233. [order_status] => 302
  234. [agent_info] => Array
  235. (
  236. )
  237. [waybill_id] => test_waybill_id
  238. [rider_name] => 我是小哥
  239. [rider_phone] => 13712345678
  240. [order_token] => NsXweKCKhSyAEIhAdnX3TYZsVDES0-t-tymHDONG0MpRsF31dQvVxiP_JJvLFaKS-kwXuOG3D0hzKkl7o-gzew
  241. )
  242. */
  243. /**
  244. * @param int $expressId
  245. * @param string $orderSn
  246. * @param string $shopNo
  247. * @return mixed
  248. */
  249. public static function getOrder(int $expressId,string $orderSn,string $shopNo)
  250. {
  251. $merchant = self::getGhsWxInfo();
  252. $expressData = self::getExpressInfo($expressId);
  253. $data =[
  254. 'shopid'=>$expressData['appKey'],
  255. 'shop_order_id'=>$orderSn,
  256. 'shop_no'=>$shopNo,
  257. ];
  258. $res = miniUtil::getOrder($data,$merchant,2);
  259. self::handleReturn($res);
  260. return $res;
  261. }
  262. //更新快递状态(沙箱)
  263. /*
  264. * {
  265. "shopid": "test_shop_id",
  266. "shop_order_id": "xxxxxxxxxxx",
  267. "action_time": 12345678,
  268. "order_status": 101,
  269. "action_msg": "",
  270. }
  271. */
  272. /**
  273. * @param int $expressId 快递ID
  274. * @param string $orderSn 唯一标识订单的 ID,由商户生成
  275. * @param int $orderStatus 配送状态
  276. * @param string $actionMsg 附加信息
  277. * @return mixed
  278. */
  279. /*
  280. * 返回数据:
  281. * {
  282. "resultcode": 0,
  283. "resultmsg": "ok"
  284. }
  285. */
  286. public static function mockUpdateOrder(int $expressId,string $orderSn,int $orderStatus,string $actionMsg='')
  287. {
  288. $merchant = self::getGhsWxInfo();
  289. $expressData = self::getExpressInfo($expressId);
  290. $data =[
  291. 'shopid'=>$expressData['appKey'],
  292. 'shop_order_id'=>$orderSn,
  293. 'action_time'=>time(),
  294. 'order_status'=>$orderStatus,
  295. 'action_msg'=>$actionMsg,
  296. ];
  297. $res = miniUtil::mockUpdateOrder($data,$merchant,2);
  298. self::handleReturn($res);
  299. return $res;
  300. }
  301. //预下配送单接口 (参数跟下单一样)
  302. /*
  303. 返回数据:
  304. {
  305. "resultcode": 0,
  306. "resultmsg": "ok",
  307. "fee": 10,
  308. "deliverfee": 10,
  309. "couponfee": 0,
  310. "tips": 0,
  311. "insurancfee": 0,
  312. "distance": 1000,
  313. "dispatch_duration": 300,
  314. "delivery_token": "1111111"
  315. }
  316. */
  317. public static function preAddOrder(int $expressId,string $shopNo,string $orderSn,string $openId,array $sender,array $receiver,array $cargo,array $orderInfo,array $shop, string $subBizId='')
  318. {
  319. $merchant = self::getGhsWxInfo();
  320. //通过 $expressId, 获取 appKey, appSecret
  321. $expressData = self::getExpressInfo($expressId);
  322. $shopId = $expressData['appKey']; //app_key
  323. $shopOrderId = $orderSn;
  324. $appSecret = $expressData['appSecret'];//app_secrect
  325. $delivery_id = $expressData['deliveryId'];
  326. $delivery_sign = self::getDeliverySign($shopId,$appSecret,$shopOrderId);
  327. if(!$shopNo){
  328. //$shopNo = $expressData['shopNo'];
  329. }
  330. $data = [
  331. 'shopid'=>(string)$shopId,
  332. 'shop_order_id'=>$orderSn,
  333. 'shop_no'=>$shopNo,
  334. 'delivery_sign'=>$delivery_sign, //delivery_sign=SHA1(shopid + shop_order_id + AppSecret)
  335. 'delivery_id'=>$delivery_id,
  336. 'openid'=>$openId,
  337. 'sender'=>$sender,
  338. 'receiver'=>$receiver,
  339. 'cargo'=>$cargo,
  340. 'order_info'=>$orderInfo,
  341. 'shop'=>$shop,
  342. ];
  343. if(empty($orderInfo)) {
  344. unset($data['order_info']);
  345. }
  346. $res = miniUtil::preAddOrder($data,$merchant, 2);
  347. self::handleReturn($res);
  348. return $res;
  349. }
  350. //预取消配送单接口
  351. /*
  352. * {
  353. "shopid": "123456",
  354. "shop_order_id": "123456",
  355. "waybill_id": "123456",
  356. "delivery_id": "123456",
  357. "cancel_reason_id": 1,
  358. "cancel_reason": "",
  359. "delivery_sign": "123456",
  360. "shop_no": "shop_no_111"
  361. }
  362. 返回数据:
  363. {
  364. "resultcode": 0,
  365. "resultmsg": "ok",
  366. "deduct_fee": 5,
  367. "desc": "blabla"
  368. }
  369. */
  370. public static function preCancelOrder(int $expressId,string $orderSn,string $waybillId, string $shopNo,int $reasonId,string $reason='')
  371. {
  372. $merchant = self::getGhsWxInfo();
  373. $expressData = self::getExpressInfo($expressId);
  374. $data = [
  375. 'shopid'=>$expressData['appKey'],
  376. 'shop_order_id'=>$orderSn,
  377. 'waybill_id'=>$waybillId,
  378. 'delivery_id'=>$expressData['deliveryId'],
  379. 'cancel_reason_id'=>$reasonId,
  380. 'cancel_reason'=>$reason,
  381. 'shop_no'=>$shopNo,
  382. 'delivery_sign'=>self::getDeliverySign($expressData['appKey'],$expressData['appSecret'],$orderSn),
  383. ];
  384. $res = miniUtil::preCancelOrder($data,$merchant,2);
  385. self::handleReturn($res);
  386. return $res;
  387. }
  388. //重新下单(暂不支持。可以先取消,再下单)
  389. //运力签名 lqh 2021.2.3
  390. public static function getDeliverySign($shopId,$appSecret,$shopOrderId)
  391. {
  392. return sha1($shopId.$shopOrderId.$appSecret);
  393. }
  394. public static function getGhsWxInfo()
  395. {
  396. return WxOpenClass::getGhsWxInfo();
  397. }
  398. public static function getExpressInfo($expressId)
  399. {
  400. return ExpressClass::getExpressInfo($expressId);
  401. }
  402. public static function handleReturn($res)
  403. {
  404. if(isset($res['errcode'])){
  405. util::fail($res['errmsg']);
  406. }
  407. if($res['resultcode'] != 0 ){
  408. if (getenv('YII_ENV', 'local') == 'production') {
  409. util::fail('出错啦!请联系客服');
  410. }
  411. util::fail($res['resultmsg']);
  412. }
  413. }
  414. }