| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436 |
- <?php
- namespace addons\WechatVideoShop\common\service;
- use addons\WechatVideoShop\common\expand\sdk\weixin\src\enums\RefundEnum;
- use addons\WechatVideoShop\common\expand\sdk\weixin\src\model\basic\GetMediaModel;
- use addons\WechatVideoShop\common\expand\sdk\weixin\src\model\refund\RefundInfoModel;
- use addons\WechatVideoShop\common\expand\sdk\weixin\src\request\basic\GetMediaRequest;
- use addons\WechatVideoShop\common\expand\sdk\weixin\src\request\refund\RefundInfoRequest;
- use addons\WechatVideoShop\common\helper\WechatRequestHelper;
- use addons\WechatVideoShop\common\models\WechatVideoShop;
- use addons\WechatVideoShop\common\models\WechatVideoShopExpressCompany;
- use addons\WechatVideoShop\common\models\WechatVideoShopOrder;
- use addons\WechatVideoShop\common\models\WechatVideoShopRefund;
- use common\enums\OrderStatusEnum;
- use common\enums\RefundStatusEnum;
- use common\events\order\OrderRefundEvent;
- use common\helpers\FormatHelper;
- use common\logic\order\OrderRefundLogic;
- use common\models\goods\Goods;
- use common\models\order\Order;
- use common\models\order\OrderDetail;
- use common\models\order\OrderRefund;
- use common\models\order\OrderRefundStep;
- use common\models\user\UserInfo;
- use Yii;
- use yii\helpers\Json;
- class RefundCallbackService extends AbstractService
- {
- /**
- * 这边退款不需要退钱
- * @param array $event
- * @return void
- * @throws \Exception
- */
- public function update(array $event)
- {
- $resp = $this->getRefundDetail($event['finder_shop_aftersale_status_update']['after_sale_order_id']);
- // 判断是否有同步当前退款,没有的话那么就需要记录
- $status = $resp['after_sale_order']['status'] ?? null;
- switch ($status) {
- case RefundEnum::AFTER_SALE_STATUS_USER_CANCELD: // 用户取消申请
- $refund = $this->cancel($resp['after_sale_order'] ?? []);
- break;
- case RefundEnum::AFTER_SALE_STATUS_MERCHANT_PROCESSING: // 商家受理中
- // $this->create($resp['after_sale_order'] ?? []);
- break;
- case RefundEnum::AFTER_SALE_STATUS_MERCHANT_REJECT_REFUND: // 商家拒绝退款
- $refund = $this->reject($resp['after_sale_order'] ?? []);
- break;
- case RefundEnum::AFTER_SALE_STATUS_MERCHANT_REJECT_RETURN: // 商家拒绝退货退款
- $refund = $this->reject($resp['after_sale_order'] ?? []);
- break;
- case RefundEnum::AFTER_SALE_STATUS_USER_WAIT_RETURN: // 待买家退货
- $refund = $this->agree($resp['after_sale_order'] ?? []);
- break;
- case RefundEnum::AFTER_SALE_STATUS_RETURN_CLOSED: // 退货退款关闭
- $refund = $this->cancel($resp['after_sale_order'] ?? []);
- break;
- case RefundEnum::AFTER_SALE_STATUS_MERCHANT_WAIT_RECEIPT: // 待商家收货
- $refund = $this->buyerShip($resp['after_sale_order'] ?? []);
- break;
- case RefundEnum::AFTER_SALE_STATUS_MERCHANT_OVERDUE_REFUND: // 商家逾期未退款
- break;
- case RefundEnum::AFTER_SALE_STATUS_MERCHANT_REFUND_SUCCESS: // 退款完成
- break;
- case RefundEnum::AFTER_SALE_STATUS_MERCHANT_RETURN_SUCCESS: // 退货退款完成
- break;
- case RefundEnum::AFTER_SALE_STATUS_PLATFORM_REFUNDING: // 平台退款中
- break;
- case RefundEnum::AFTER_SALE_STATUS_PLATFORM_REFUND_FAIL: // 平台退款失败
- break;
- case RefundEnum::AFTER_SALE_STATUS_USER_WAIT_CONFIRM: // 待用户确认
- break;
- case RefundEnum::AFTER_SALE_STATUS_MERCHANT_REFUND_RETRY_FAIL: // 商家打款失败,客服关闭售后
- $refund = $this->cancel($resp['after_sale_order'] ?? []);
- break;
- case RefundEnum::AFTER_SALE_STATUS_MERCHANT_FAIL: // 售后关闭
- $refund = $this->cancel($resp['after_sale_order'] ?? []);
- break;
- }
- if (!empty($refund)) {
- $refund->content = $resp['after_sale_order'];
- if (!$refund->save()) { // 修改数据
- throw new \Exception($refund->getErrorMessage());
- }
- }
- }
- /**
- * 申请售后
- * @return void
- * @throws \Exception
- */
- protected function create(array $resp)
- {
- if (empty($resp)) throw new \Exception("售后订单数据为空");
- // 取出订单
- $user_id = UserInfo::find()->where(['mall_id' => $this->mall_id])
- ->andWhere(['openid' => $resp['openid']])->select('user_id')->scalar();
- if (empty($user_id)) throw new \Exception("用户不存在: {$resp['openid']}");
- // $order_ids = WechatVideoShopOrder::find()
- // ->where(['third_order_id' => $resp['order_id']])->select('order_id')->column();
- // if (empty($order_ids)) throw new \Exception("订单不存在: {$resp['order_id']}");
- $orders = WechatVideoShopOrder::lists([
- 'where' => [
- ['third_order_id' => $resp['order_id']]
- ],
- 'index' => 'order_id',
- 'select'=> 'order_id, content'
- ]);
- // SKU ID 不一致
- if (empty($orders)) throw new \Exception("订单不存在: {$resp['order_id']}");
- $order_id = 0;
- $sku_id = 0;
- foreach ($orders as $key => $order) {
- $content = Json::decode($order['content']);
- // 找出包含 $resp['product_info']['sku_id'] 的那一行数据
- $product_infos = $content['order_detail']['product_infos'];
- $tmp_skus = array_column($product_infos, "out_sku_id", "sku_id");
- if (!empty($tmp_skus[$resp['product_info']['sku_id']])) {
- $order_id = $key;
- $sku_id = $tmp_skus[$resp['product_info']['sku_id']];
- }
- }
- if (empty($order_id)) throw new \Exception("未找到相关SKU: {$resp['product_info']['sku_id']}");
- // 取出订单商品ID
- $orderDetail = OrderDetail::getOne([
- ['order_id' => $order_id],
- ['goods_attr_id' => $sku_id],
- ['user_id' => $user_id]
- ]);
- if (empty($orderDetail)) throw new \Exception("订单详情不存在: $sku_id");
- // order_detail_id, shipping_status, pic_list, reason, refund_price, remark, type
- // 获取media
- $pic_list = [];
- if (!empty($resp['details']['media_id_list'])) {
- foreach ($resp['details']['media_id_list'] as $mediaId) {
- $mediaModel = new GetMediaModel();
- $mediaModel->media_id = $mediaId;
- $pic_list[] = WechatRequestHelper::accessTokenAndToArray(new GetMediaRequest([]), $mediaModel);
- }
- }
- $params['user_id'] = $user_id;
- $params['mall_id'] = $this->mall_id;
- $params['order_detail_id'] = $orderDetail->id;
- $params['pic_list'] = Json::encode($pic_list);
- $params['refund_price'] = bcmul($resp['refund_info']['amount'], 0.01, 2);
- $params['reason'] = $resp['reason_text'] ?? '未知理由';
- $params['shipping_status'] = $orderDetail->order_status == OrderStatusEnum::PAY ? 0 : 1; // 是否已经发货
- $params['type'] = $resp['type'] == 'REFUND' ? 1 : 2; // 售后类型:1=仅退款,2=退货退款,3=换货 // 售后类型。REFUND:退款;RETURN:退货退款。
- $params['remark'] = "{$resp['details']['desc']}, 联系电话: [{$resp['details']['tel_number']}]";
- // 退货数量
- // 退款金额
- $where = [
- ['=', 'order_detail_id', $params['order_detail_id']],
- ['=', 'user_id', $user_id],
- ['=', 'mall_id', $this->mall_id],
- ['>', 'step_status', 0],
- ['<>', 'refund_status', RefundStatusEnum::REVOKE]
- ];
- $order_refund_model = OrderRefund::getOne($where, true);
- if ($order_refund_model) throw new \Exception('该订单商品已经申请过售后');
- $res = OrderRefund::feedback($params);
- if (!$res) throw new \Exception(OrderRefund::getStaticError());
- // 这里需要怎么处理呢?
- $refundModel = new WechatVideoShopRefund();
- $refundModel->mall_id = $this->mall_id;
- $refundModel->shop_id = $this->shop_id;
- $refundModel->user_id = $user_id;
- $refundModel->order_id = $orderDetail->order_id;
- $refundModel->third_refund_id = $resp['after_sale_order_id'];
- $refundModel->third_order_id = $resp['order_id'];
- $refundModel->refund_id = $res->id;
- $refundModel->content = $resp;
- $refundModel->refund_certificates = !empty($resp['details']['media_id_list']) ? $resp['details']['media_id_list'] : [];
- $refundModel->refund_desc = $resp['details']['desc'];
- if (!$refundModel->save()) {
- throw new \Exception($refundModel->getErrorMessage());
- }
- // 触发事件
- $event = new OrderRefundEvent();
- $event->mall_id = $this->mall_id;
- $order_detail['order_detail_id'] = $params['order_detail_id'];
- $order_detail['id'] = $res->id;
- $order_detail['operator_id'] = 0;
- $order_detail['operator_name'] = OrderCallbackService::OPERATOR_NAME;
- Yii::$app->services->events->dispatch($event, $order_detail, $event->listeners);
- }
- /**
- * @param $third_refund_id
- * @return WechatVideoShopRefund
- * @throws \Exception
- */
- protected function getLocalRefund($third_refund_id)
- {
- $refund = WechatVideoShopRefund::getOne([
- ['third_refund_id' => $third_refund_id]
- ]);
- if (empty($refund)) throw new \Exception("退款单号不存在: {$third_refund_id}");
- return $refund;
- }
- /**
- * 取消售后
- * @return WechatVideoShopRefund
- * @throws \Exception
- */
- protected function cancel(array $resp)
- {
- $refund = $this->getLocalRefund($resp['after_sale_order_id']);
- $params['mall_id'] = $this->mall_id;
- $params['user_id'] = $refund->user_id;
- $params['id'] = $refund->refund_id;
- $res = OrderRefund::cancelRefund($params);
- if ($res === false) throw new \Exception(OrderRefund::getStaticError());
- return $refund;
- }
- /**
- * 买家发货
- * @return WechatVideoShopRefund
- * @throws \Exception
- */
- protected function buyerShip(array $resp)
- {
- $refund = $this->getLocalRefund($resp['after_sale_order_id']);
- $params['mall_id'] = $this->mall_id;
- $params['user_id'] = $refund->user_id;
- // 快递公司
- $company = WechatVideoShopExpressCompany::getOne([
- ['delivery_id' => $resp['return_info']['delivery_id']]
- ]);
- $params['express'] = !empty($company) ? $company->delivery_name : "其他"; // 默认其他快递
- $params['express_id'] = !empty($company) ? $company->company_id : 10000; // 默认其他快递
- // 快递单号
- $params['express_no'] = $resp['return_info']['waybill_id'];
- $params['id'] = $refund->refund_id;
- $res = OrderRefundStep::refundSend($params);
- if ($res === false) throw new \Exception(OrderRefundStep::getStaticError());
- return $refund;
- }
- /**
- * 买家收货 - 买家不需要收货
- * @return WechatVideoShopRefund
- * @throws \Exception
- */
- protected function buyerSing(array $resp)
- {
- $refund = $this->getLocalRefund($resp['after_sale_order_id']);
- $params['mall_id'] = $this->mall_id;
- $params['user_id'] = $refund->user_id;
- $params['id'] = $refund->refund_id;
- $res = OrderRefundStep::refundTakeDelivery($params);
- if ($res === false) throw new \Exception(OrderRefundStep::getStaticError());
- return $refund;
- }
- /**
- * 卖家发货 - 卖家不需要发货
- * @return WechatVideoShopRefund
- * @throws \Exception
- */
- protected function sellerShip(array $resp)
- {
- // 卖家发货
- $refund = $this->getLocalRefund($resp['after_sale_order_id']);
- $this->handle([
- 'id' => $refund->refund_id,
- 'step_status' => -1
- ]);
- return $refund;
- }
- /**
- * 同意售后
- * @return WechatVideoShopRefund
- * @throws \Exception
- */
- protected function agree(array $resp)
- {
- $refund = $this->getLocalRefund($resp['after_sale_order_id']);
- $params = [];
- switch ($resp['type']) {
- case 'REFUND':
- // id: 108
- // step_status: 6
- $params['step_status'] = RefundStatusEnum::STEP_6;
- $params['id'] = $refund->refund_id;
- break;
- case 'RETURN':
- // address_type: 1
- // consignee: 林锦豪
- // mobile: 13246824705
- // address: 广州市白云区永平街永泰学山塘街81号A2栋618
- // express_id:
- // saler_express:
- // saler_express_no:
- // customer_name:
- // id: 105
- // step_status: 2
- $shop = WechatVideoShop::getOne([
- ['id' => $refund->shop_id]
- ]);
- $params = [
- 'address_type' => 2,
- 'consignee' => $shop->contact_person,
- 'mobile' => $shop->phone,
- 'address' => "{$shop->province}{$shop->city}{$shop->district}{$shop->address}",
- 'id' => $refund->refund_id,
- 'step_status' => RefundStatusEnum::STEP_2, // 第几步,如果是仅退款是第几步,如果是退货退款那么是第几步
- ];
- break;
- }
- if (empty($params)) throw new \Exception("退款类型未找到: {$resp['type']}");
- $this->handle($params);
- return $refund;
- }
- /**
- * 拒绝售后
- * @return WechatVideoShopRefund
- * @throws \Exception
- */
- protected function reject(array $resp)
- {
- // id: 106
- // step_status: -1
- $refund = $this->getLocalRefund($resp['after_sale_order_id']);
- $this->handle([
- 'id' => $refund->refund_id,
- 'step_status' => RefundStatusEnum::REFUSE
- ]);
- return $refund;
- }
- /**
- * @param array $params
- * @return void
- * @throws \Exception
- */
- protected function handle(array $params)
- {
- // 退货地址
- $address = ['consignee' => $params['consignee'] ?? '','mobile' => $params['mobile'] ?? '','address' => $params['address'] ?? ''];
- // 换货物流信息
- $express = ['saler_express' => $params['saler_express'] ?? '',
- 'saler_express_no' => $params['saler_express_no'] ?? '', 'customer_name' => $params['customer_name'] ?? ''];
- $data = [
- 'id' => $params['id'],
- 'step_status' => $params['step_status'], // 在这里处理
- 'address' => $address,
- 'express' => $express,
- 'is_async' => true, // 不退钱
- 'is_trigger_update_event' => true,
- ];
- $logic = new OrderRefundLogic();
- $res = $logic->execute($this->mall_id, $data);
- if (!$res) throw new \Exception($logic->getError());
- }
-
- /**
- * 卖家收货
- * @return WechatVideoShopRefund
- * @throws \Exception
- */
- protected function sellerSing(array $resp)
- {
- $refund = $this->getLocalRefund($resp['after_sale_order_id']);
- $this->handle([
- 'id' => $refund->refund_id,
- 'step_status' => 4
- ]);
- return $refund;
- }
- /**
- * @param $after_sale_order_id
- * @param array $config
- * @return array
- * @throws \Exception
- */
- public function getRefundDetail($after_sale_order_id, array $config = [])
- {
- $refundInfoModel = new RefundInfoModel();
- $refundInfoModel->after_sale_order_id = $after_sale_order_id;
- $resp = WechatRequestHelper::accessTokenAndToArray(new RefundInfoRequest(!empty($config) ? $config : $this->config), $refundInfoModel);
- if (empty($resp['after_sale_order'])) throw new \Exception('获取售后详情失败');
- return $resp;
- }
- /**
- * @param array $config
- * @return void
- * @throws \Exception
- */
- public function syncCreate(array $config)
- {
- try {
- $this->mall_id = $config['mall_id'];
- $this->shop_id = $config['id'];
- $resp = $this->getRefundDetail($config['after_sale_order_id'], $config);
- $this->create($resp['after_sale_order'] ?? []);
- } catch (\Exception $e) {
- \Yii::error(FormatHelper::exception($e, __METHOD__));
- }
- }
- }
|