CallBackNotify.php 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. <?php
  2. namespace common\components\delivery\platform\fengniao;
  3. use biz\common\classes\GhsNotifyClass;
  4. use biz\common\classes\HdNotifyClass;
  5. use bizGhs\express\classes\DeliveryAuthTokenClass;
  6. use bizGhs\express\classes\GhsDeliveryOrderClass;
  7. use bizGhs\order\classes\OrderClass;
  8. use bizHd\express\classes\HdDeliveryOrderClass;
  9. use bizHd\order\classes\OrderClass as HdOrderClass;
  10. use bizHd\purchase\classes\PurchaseClass;
  11. use common\components\noticeUtil;
  12. use common\components\util;
  13. use Yii;
  14. //回调业务类型
  15. const TYPE_ORDER_STATUS_NOTIFY = 'orderStatusNotify'; //订单状态回调
  16. const TYPE_ABNORMAL_REPORT_NOTIFY = 'abnormalReportNotify'; //异常报备回调
  17. const TYPE_COOKING_FINISH_NOTIFY = 'cookingFinishNotify'; //商户出餐回调
  18. const TYPE_CHAINSTORE_STATUS_NOTIFY = 'chainstoreStatusNotify'; //门店状态变更回调
  19. const TYPE_CHAINSTORE_SERVICE_STATUS_NOTIFY = 'chainstoreServiceStatusNotify'; //门店采购服务变更回调
  20. const TYPE_CHAINSTORE_BUSINESS_TIME_NOTIFY = 'chainstoreBusinessTimeNotify'; //门店营业时间变更回调
  21. /**
  22. * Class OrderStatusNotify
  23. * @package common\components\delivery\platform\fengniao
  24. * 各回调业务类型处理
  25. */
  26. class CallBackNotify
  27. {
  28. public function handle($type, $data)
  29. {
  30. switch ($type) {
  31. case TYPE_ORDER_STATUS_NOTIFY:
  32. return self::handleOrderStatusNotify($data);
  33. case TYPE_ABNORMAL_REPORT_NOTIFY:
  34. return self::handleAbnormalReportNotify($data);
  35. case TYPE_COOKING_FINISH_NOTIFY:
  36. return self::handleCookingFinishNotify($data);
  37. case TYPE_CHAINSTORE_STATUS_NOTIFY:
  38. return self::handleChainstoreStatusNotify($data);
  39. case TYPE_CHAINSTORE_SERVICE_STATUS_NOTIFY:
  40. return self::handleChainstoreServiceStatusNotify($data);
  41. case TYPE_CHAINSTORE_BUSINESS_TIME_NOTIFY:
  42. return self::handleChainstoreBusinessTimeNotify($data);
  43. default:
  44. throw new \Exception('不支持的回调业务类型: ' . $type);
  45. }
  46. }
  47. /**
  48. * 处理订单状态回调
  49. * @param array $data 回调数据
  50. * @return bool 处理结果
  51. */
  52. private function handleOrderStatusNotify($data)
  53. {
  54. $deliveryOrder = $this->getDeliveryOrder($data['order_id']);
  55. // 将蜂鸟平台的订单状态转换为系统内的 orderStatus
  56. $sendStatus = SendStatusUtil::convertOrderStatus($data['order_status']);
  57. $deliveryOrder->orderStatus = $sendStatus;
  58. $deliveryOrder->save();
  59. $orderStatus = OrderStatusUtil::convertStatus($data['order_status']);
  60. if($sendStatus == -1){
  61. noticeUtil::push('蜂鸟跑腿产生订单取消回调');
  62. }
  63. if(isset($deliveryOrder->ghsOrderId)){ // 批发
  64. util::checkRepeatCommit('ghs_pt_'.$deliveryOrder->ghsOrderId.'_'.$data['order_status'], 2); // 防止重复回调
  65. $order = OrderClass::getById($deliveryOrder->ghsOrderId, true, 'id,sendType,sendStatus,deliveryId,purchaseId,customId,status');
  66. $cg = PurchaseClass::getById($order->purchaseId, true, 'id,status,sendStatus');
  67. // 确认送达或取消订单,更新主订单状态
  68. if ($sendStatus == 5) {
  69. if($cg->status == 3){
  70. OrderClass::confirmReach($order, ['staffId' => 0, 'staffName' => '']);
  71. }else{
  72. Yii::warning('进行确认送达时,采购单状态不为3,无法进行确认送达。orderId='.$order->id);
  73. noticeUtil::push('进行确认送达时,采购单状态不为3,无法进行确认送达。orderId='.$order->id.', purchaseId='.$cg->id);
  74. }
  75. }
  76. if (!in_array($order->sendStatus, [-2, -1]) && ($sendStatus == -1 || $sendStatus == -2)) {
  77. OrderClass::cancelOrderSend($order, ['staffId' => 0, 'staffName' => '']);
  78. $event = $this->cancelFrom($sendStatus, $data);
  79. GhsNotifyClass::ptErrorNotify($order->id, $event);
  80. }
  81. $cg->sendStatus = $sendStatus;
  82. $cg->save();
  83. $order->sendStatus = $sendStatus;
  84. $order->status = $orderStatus;
  85. $order->save();
  86. }elseif(isset($deliveryOrder->hdOrderId)){ // 零售
  87. util::checkRepeatCommit('hd_pt_'.$deliveryOrder->hdOrderId.'_'.$data['order_status'], 2); // 防止重复回调
  88. $order = HdOrderClass::getById($deliveryOrder->hdOrderId, true, 'id,sendType,sendStatus,deliveryId,customId,status');
  89. if (!in_array($order->sendStatus, [-2, -1]) && ($sendStatus == -1 || $sendStatus == -2)) {
  90. $event = $this->cancelFrom($sendStatus, $data);
  91. HdNotifyClass::ptErrorNotify($order->id, $event);
  92. }
  93. $order->sendStatus = $sendStatus;
  94. $order->status = $orderStatus;
  95. $order->save();
  96. }
  97. return true;
  98. }
  99. /**
  100. * 处理异常报备回调
  101. * @param array $data 回调数据
  102. * @return bool 处理结果
  103. */
  104. private function handleAbnormalReportNotify($data)
  105. {
  106. Yii::info('蜂鸟异常报备回调: ' . json_encode($data, JSON_UNESCAPED_UNICODE), 'fengniao');
  107. return $data;
  108. }
  109. /**
  110. * 处理商户出餐回调
  111. * @param array $data 回调数据
  112. * @return bool 处理结果
  113. */
  114. private function handleCookingFinishNotify($data)
  115. {
  116. Yii::info('蜂鸟商户出餐回调: ' . json_encode($data, JSON_UNESCAPED_UNICODE), 'fengniao');
  117. return $data;
  118. }
  119. /**
  120. * 处理门店状态变更回调
  121. * @param array $data 回调数据
  122. * @return bool 处理结果
  123. */
  124. private function handleChainstoreStatusNotify($data)
  125. {
  126. Yii::info('蜂鸟门店状态变更回调: ' . json_encode($data, JSON_UNESCAPED_UNICODE), 'fengniao');
  127. $statusMap = [
  128. 10 => '上架审核中',
  129. 20 => '正常(已上架)',
  130. 30 => '上架审核失败',
  131. 40 => '已冻结',
  132. 50 => '已下架',
  133. ];
  134. $modifyStatusMap = [
  135. 0 => '无修改',
  136. 10 => '资料修改审核中',
  137. 20 => '审核通过',
  138. 30 => '审核驳回',
  139. ];
  140. $merchantId = $data['merchant_id'];
  141. $chainStoreId = $data['chain_store_id'];
  142. $outShopCode = $data['out_shop_code'];
  143. $status = isset($data['status']) ? (int)$data['status'] : null;
  144. $modifyStatus = isset($data['modify_status']) ? (int)$data['modify_status'] : null;
  145. $remark = $data['remark'] ?? '';
  146. $normalizedPayload = [
  147. 'merchant_id' => $merchantId,
  148. 'chain_store_id' => $chainStoreId,
  149. 'out_shop_code' => $outShopCode,
  150. 'status' => [
  151. 'code' => $status,
  152. 'desc' => $status !== null ? ($statusMap[$status] ?? '未知状态') : '',
  153. ],
  154. 'modify_status' => [
  155. 'code' => $modifyStatus,
  156. 'desc' => $modifyStatus !== null ? ($modifyStatusMap[$modifyStatus] ?? '未知状态') : '',
  157. ],
  158. 'remark' => $remark,
  159. ];
  160. $condition = ['mainId' => $outShopCode, 'platform' => 'fengniao'];
  161. $tokenModel = DeliveryAuthTokenClass::getByCondition($condition, true);
  162. if (!$tokenModel) {
  163. Yii::warning('蜂鸟门店状态回调未匹配到授权记录: ' . json_encode($condition, JSON_UNESCAPED_UNICODE), 'fengniao');
  164. return false;
  165. }
  166. $tokenModel->callBack = json_encode($normalizedPayload, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
  167. $tokenModel->merchantId = $merchantId;
  168. $tokenModel->shopId = $chainStoreId;
  169. if ($tokenModel->save() === false) {
  170. Yii::error('蜂鸟门店状态回调保存失败: ' . json_encode($tokenModel->getErrors(), JSON_UNESCAPED_UNICODE), 'fengniao');
  171. return false;
  172. }
  173. return true;
  174. }
  175. /**
  176. * 处理门店采购服务变更回调
  177. * @param array $data 回调数据
  178. * @return bool 处理结果
  179. */
  180. private function handleChainstoreServiceStatusNotify($data)
  181. {
  182. Yii::info('蜂鸟门店采购服务变更回调: ' . json_encode($data, JSON_UNESCAPED_UNICODE), 'fengniao');
  183. return $data;
  184. }
  185. /**
  186. * 处理门店营业时间变更回调
  187. * @param array $data 回调数据
  188. * @return bool 处理结果
  189. */
  190. private function handleChainstoreBusinessTimeNotify($data)
  191. {
  192. Yii::info('蜂鸟门店营业时间变更回调: ' . json_encode($data, JSON_UNESCAPED_UNICODE), 'fengniao');
  193. return $data;
  194. }
  195. /**
  196. * 根据订单号查找配送订单
  197. *
  198. * @param string $orderId
  199. * @return object|null
  200. */
  201. private function getDeliveryOrder($orderId)
  202. {
  203. // 查找批发配送订单
  204. $deliveryOrder = GhsDeliveryOrderClass::getByCondition([
  205. 'deliveryId' => 'fengniao',
  206. 'orderId' => $orderId
  207. ], true);
  208. if ($deliveryOrder) {
  209. return $deliveryOrder;
  210. }
  211. // 查找零售配送订单
  212. return HdDeliveryOrderClass::getByCondition([
  213. 'deliveryId' => 'fengniao',
  214. 'orderId' => $orderId
  215. ], true);
  216. }
  217. private function cancelFrom($sendStatus, $data)
  218. {
  219. if($sendStatus == -1){
  220. return $data['description'] ?? '取消';
  221. }
  222. if($sendStatus == -2){
  223. $errorScene =[
  224. 'ORDER_INFORMATION_INCORRECT' => '商户推单信息有误,创建蜂鸟运单失败',
  225. 'OUT_OF_DELIVERY_SERVICE' => '超出配送服务能力,创建蜂鸟运单失败',
  226. 'MERCHANT_STORE_ERROR' => '因商户原因导致无法继续配送',
  227. 'CUSTOMER_ERROR' => '因用户原因导致无法继续配送',
  228. 'CARRIER_ERROR' => '因运力原因导致无法继续配送',
  229. 'ELE_SYSTEM_ERROR' => '蜂鸟系统异常',
  230. 'UNKNOW_ERROR' => '其他未知错误'
  231. ];
  232. //return "异常code={$data['error_code']}, 异常描述:{$errorScene[$data['error_scene']]}";
  233. return "{$data['detail_description']} -- {$data['description']}";
  234. }
  235. }
  236. }