123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839 |
- <?php
- // +----------------------------------------------------------------------
- // | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
- // +----------------------------------------------------------------------
- // | Copyright (c) 2016~2020 https://www.crmeb.com All rights reserved.
- // +----------------------------------------------------------------------
- // | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
- // +----------------------------------------------------------------------
- // | Author: CRMEB Team <admin@crmeb.com>
- // +----------------------------------------------------------------------
- declare (strict_types=1);
- namespace app\services\erp;
- use app\jobs\order\OrderSyncJob;
- use app\services\order\StoreOrderCartInfoServices;
- use app\services\order\StoreOrderCreateServices;
- use app\services\order\StoreOrderDeliveryServices;
- use app\services\order\StoreOrderRefundServices;
- use app\services\order\StoreOrderServices;
- use crmeb\exceptions\AdminException;
- use crmeb\services\erp\Erp as erpServices;
- use think\facade\Log;
- /**
- * Class OrderServices
- * @package app\services\erp
- */
- class OrderServices
- {
- protected $services;
- /**
- * OrderServices constructor.
- * @param erpServices $services
- */
- public function __construct(erpServices $services)
- {
- $this->services = $services;
- }
- /**
- * 订单上传
- * @param int $oid
- * @return bool
- * @throws \Exception
- */
- public function upload(int $oid): bool
- {
- /** @var StoreOrderServices $orderServices */
- $orderServices = app()->make(StoreOrderServices::class);
- $order = $orderServices->get($oid, ['*'], ['store']);
- if ($order['id'] < 1) {
- throw new AdminException('订单信息不能为空!');
- }
- // 过滤已退款订单和虚拟商品
- if ($order['refund_status'] == 2 || $order['product_type'] > 0) {
- return true;
- }
- $biz = [
- 'shop_id' => $this->getShopId($order->store->erp_shop_id ?? 0), // 店铺编号
- 'so_id' => $this->getErpOrderId($order['order_id'], $order['erp_order_id']), // 线上订单号, 长度 <= 50
- 'shop_status' => 'WAIT_SELLER_SEND_GOODS', // 订单状态 待发货
- 'buyer_message' => $order['mark'], // 买家留言
- 'shop_buyer_id' => (string)$order['uid'], // 买家帐号
- 'receiver_name' => $order['real_name'], // 收件人
- 'receiver_mobile' => $order['user_phone'], // 联系手机
- 'pay_amount' => (float)$order['pay_price'], // 应付金额,保留两位小数,单位元)
- 'freight' => (float)$order['freight_price'], // 运费
- 'order_date' => date('Y-m-d H:i:s', $order['add_time']), // 订单日期
- 'shop_modified' => date('Y-m-d H:i:s', $order['add_time']), // 订单修改日期
- 'items' => $this->getItems($oid, (int)$order['uid'], $order['unique']),
- 'pay' => [
- 'outer_pay_id' => 'xxx', // 外部支付单号,最大50
- 'pay_date' => date('Y-m-d H:i:s', $order['pay_time']), // 支付日期
- 'payment' => $order['pay_type'], // 支付方式,最大20
- 'seller_account' => 'seller', // 卖家支付账号,最大 50
- 'buyer_account' => 'buyer', // 买家支付账号,最大 200
- 'amount' => (float)$order['pay_price'] // 支付总额
- ]
- ];
- $biz = array_merge($biz, $this->getAddress($order['user_address']));
- $num = 3;
- for ($i = $num; $i >= 0; $i--) {
- if ($i <= 0) {
- Log::error(['msg' => 'ERP订单上传失败,调用均为异常', 'oid' => $oid]);
- return false;
- }
- try {
- $result = $this->services->serviceDriver('order')->ordersUpload([$biz]);
- if ($result['datas'][0]['issuccess'] && $order['erp_order_id'] != $biz['so_id']) {
- $order->save(['erp_id' => $result['datas'][0]['o_id'], 'erp_order_id' => $biz['so_id']]);
- }
- break;
- } catch (\Exception $e) {
- usleep(1000 * 50);
- Log::error('ERP订单上传失败,原因:' . $e->getMessage());
- }
- }
- return true;
- }
- /**
- * 收货地址
- * @param string $userAddress
- * @return array
- */
- public function getAddress(string $userAddress): array
- {
- $receiver_state = $receiver_city = $receiver_district = $receiver_address = '';
- if (!empty($userAddress)) {
- $address = explode(' ', $userAddress);
- $receiver_state = $address[0] ?? ''; // 收货省份
- $receiver_city = $address[1] ?? ''; // 收货市
- $receiver_district = $address[2] ?? ''; // 收货区
- $receiver_address = $address[3] ?? ''; // 收货街道
- $receiver_address .= $address[4] ?? ''; // 街道
- }
- return compact('receiver_state', 'receiver_city', 'receiver_district', 'receiver_address');
- }
- /**
- * 获取erp指定订单商品详情
- * @param int $oid
- * @param int $uid
- * @param string $unique
- * @return array
- */
- public function getItems(int $oid, int $uid, string $unique): array
- {
- /** @var StoreOrderCartInfoServices $storeOrderCartInfoServices */
- $storeOrderCartInfoServices = app()->make(StoreOrderCartInfoServices::class);
- $cartInfo = $storeOrderCartInfoServices->getOrderCartInfo($oid);
- if (empty($cartInfo)) {
- /** @var StoreOrderServices $orderServices */
- $orderServices = app()->make(StoreOrderServices::class);
- //同步查询订单商品为查询到 查询缓存信息
- $orderInfo = $orderServices->getCacheOrderInfo($uid, $unique);
- $cartInfo = $orderInfo['cartInfo'] ?? [];
- }
- $items = [];
- foreach ($cartInfo as $cart) {
- $cart = $cart['cart_info'] ?? $cart;
- $attrInfo = $cart['productInfo']['attrInfo'];
- $items[] = [
- 'sku_id' => $attrInfo['code'],
- 'shop_sku_id' => $attrInfo['code'],
- 'base_price' => (float)bcdiv((string)$cart['truePrice'], (string)$cart['cart_num'], 2),
- 'amount' => (float)$cart['truePrice'],
- 'qty' => $cart['cart_num'],
- 'pic' => $cart['productInfo']['image'],
- 'name' => $cart['productInfo']['store_name'],
- 'properties_value' => $attrInfo['suk'],
- 'outer_oi_id' => $cart['product_attr_unique'],
- ];
- }
- return $items;
- }
- /**
- * 取消回调
- * @param array $cancel
- * @return bool
- * @throws \Psr\SimpleCache\InvalidArgumentException
- */
- public function cancelCallback(array $cancel): bool
- {
- try {
- /** @var StoreOrderServices $orderServices */
- $orderServices = app()->make(StoreOrderServices::class);
- $orders = explode('_', $cancel['so_id']);
- $cancel['order_id'] = $orders[0] ?? '';
- $order = $orderServices->getOne(['order_id' => $cancel['order_id']], '*');
- if (!$order) {
- throw new AdminException('订单信息不能为空!');
- }
- $order = is_object($order) ? $order->toArray() : $order;
- $ids = [$order['erp_order_id']];
- // 获取子订单号
- $orders = $orderServices->getColumn(['pid' => $order['id']], 'erp_order_id', 'id');
- if ($orders) {
- $ids = array_values(array_unique(array_filter(array_merge($ids, $orders))));
- }
- $result = $this->services->serviceDriver('order')->ordersSingleQuery(['so_ids' => $ids]);
- // 取消申请退货
- $this->checkRefundApply((int)$order['id']);
- // 部分退货
- if (count($result['orders']) > 1) {
- $this->applyPartRefund($cancel, $order, $result['orders'], $orderServices);
- } else {
- $this->applyRefund($cancel, $order, $orderServices);
- }
- } catch (\Exception $e) {
- Log::error(['msg' => '订单取消失败,原因:' . $e->getMessage(), 'data' => $cancel]);
- }
- return true;
- }
- /**
- * 订单申请退款
- * @param array $cancel
- * @param array $order
- * @param StoreOrderServices $orderServices
- * @return void
- */
- protected function applyRefund(array $cancel, array $order, StoreOrderServices $orderServices)
- {
- try {
- $data['refund_reason_wap_explain'] = $cancel['remark'];
- $data['order_id'] = $cancel['order_id'];
- /** @var StoreOrderRefundServices $storeOrderRefundServices */
- $storeOrderRefundServices = app()->make(StoreOrderRefundServices::class);
- if ($storeOrderRefundServices->count(['store_order_id' => $order['id'], 'refund_type' => [0, 1, 2, 4, 5], 'is_cancel' => 0, 'is_del' => 1])) {
- throw new AdminException('请先处理售后申请!');
- }
- //0元退款
- if ($order['pay_price'] == 0 && in_array($order['refund_status'], [0, 1])) {
- $refund_price = 0;
- } else {
- if ($order['pay_price'] == $order['refund_price']) {
- throw new AdminException('已退完支付金额!不能再退款了!');
- }
- $refund_price = bcsub((string)$order['pay_price'], $order['refund_price'], 2);
- }
- $data['refund_status'] = 2;
- $data['refund_type'] = 6;
- $refund_data['pay_price'] = $order['pay_price'];
- $refund_data['refund_price'] = $refund_price;
- if ($order['refund_price'] > 0) {
- mt_srand();
- $refund_data['refund_id'] = $order['order_id'] . rand(100, 999);
- }
- /** @var StoreOrderCreateServices $service */
- $storeOrderCreateServices = app()->make(StoreOrderCreateServices::class);
- //生成退款订单
- $refundOrderData['uid'] = $order['uid'];
- $refundOrderData['store_id'] = $order['store_id'];
- $refundOrderData['store_order_id'] = $order['id'];
- $refundOrderData['refund_num'] = $order['total_num'];
- $refundOrderData['refund_type'] = $data['refund_type'];
- $refundOrderData['refund_price'] = $order['pay_price'];
- $refundOrderData['refunded_price'] = $refund_price;
- $refundOrderData['refund_reason'] = $cancel['remark'];
- $refundOrderData['order_id'] = $storeOrderCreateServices->getNewOrderId('');
- $refundOrderData['refunded_time'] = time();
- $refundOrderData['add_time'] = time();
- /** @var StoreOrderCartInfoServices $orderInfoServices */
- $storeOrderCartInfoServices = app()->make(StoreOrderCartInfoServices::class);
- $cartInfos = $storeOrderCartInfoServices->getCartColunm(['oid' => $order['id']], 'id,cart_id,cart_num,cart_info');
- foreach ($cartInfos as &$cartInfo) {
- $cartInfo['cart_info'] = is_string($cartInfo['cart_info']) ? json_decode($cartInfo['cart_info'], true) : $cartInfo['cart_info'];
- }
- $refundOrderData['cart_info'] = json_encode(array_column($cartInfos, 'cart_info'));
- $res = $storeOrderRefundServices->save($refundOrderData);
- //修改订单退款状态
- if ($storeOrderRefundServices->agreeRefund((int)$res->id, $refund_data)) {
- //主动退款清楚原本退款单
- $storeOrderRefundServices->delete(['store_order_id' => $order['id']]);
- $orderServices->update($order['id'], $data);
- } else {
- $storeOrderRefundServices->storeProductOrderRefundYFasle((int)$order['id'], $refund_price);
- }
- } catch (\Exception $e) {
- Log::error('订单申请退款失败,原因:' . $e->getMessage());
- }
- }
- /**
- * 部分退款申请
- * @param array $cancel
- * @param array $order
- * @param array $orders
- * @param StoreOrderServices $orderServices
- * @return bool|void
- * @throws \Psr\SimpleCache\InvalidArgumentException
- */
- protected function applyPartRefund(array $cancel, array $order, array $orders, StoreOrderServices $orderServices)
- {
- try {
- $cartWhere = ['oid' => $order['id']];
- // 获取拆单信息
- if ($order['pid'] < 0) {
- $oIds = $orderServices->Value([['pid', '=', $order['id']], ['refund_status', '<', 2], ['status', '=', 0]], 'GROUP_CONCAT(id)');
- if (!empty($oIds)) {
- $oIds = array_filter(explode(',', $oIds));
- }
- $cartWhere = ['oid' => $oIds, 'split_status' => [0, 1]];
- }
- /** @var StoreOrderCartInfoServices $orderInfoServices */
- $storeOrderCartInfoServices = app()->make(StoreOrderCartInfoServices::class);
- $cartInfos = $storeOrderCartInfoServices->getCartColunm($cartWhere, 'id,oid,cart_id,cart_num,split_surplus_num,cart_info');
- foreach ($cartInfos as &$cartInfo) {
- $cartInfo['cart_info'] = is_string($cartInfo['cart_info']) ? json_decode($cartInfo['cart_info'], true) : $cartInfo['cart_info'];
- }
- // 过滤已退商品
- $cancelled = $this->filter($orders, $order['id']);
- if (empty($cancelled)) {
- return true;
- }
- $cartOid = 0;
- $cartIds = [];
- foreach ($cartInfos as $cart) {
- $num = $cancelled[$cart['cart_info']['productInfo']['attrInfo']['code']] ?? 0;
- if ($num > 0) {
- $allow = $num <= $cart['split_surplus_num'] ? $num : $num - $cart['split_surplus_num'];
- $cartId = (string)$cart['cart_id'];
- if (isset($cartIds[$cartId])) {
- $cartIds[$cartId]['cart_num'] += $allow;
- } else {
- $cartIds[$cartId] = ['cart_id' => $cartId, 'cart_num' => $allow, 'oid' => $cart['oid']];
- $cartOid = $cart['oid'];
- }
- }
- }
- if ($order['pid'] < 0) {
- $oid = $orderServices->Value([['pid', '=', $order['id']], ['refund_status', '<', 2], ['status', '=', 0]], 'id');
- if ($oid < 1) {
- return true;
- }
- $order = $orderServices->getOne(['id' => $oid], '*');
- if (!$order) {
- throw new AdminException('订单信息不能为空!');
- }
- }
- /** @var StoreOrderRefundServices $storeOrderRefundServices */
- $storeOrderRefundServices = app()->make(StoreOrderRefundServices::class);
- $refundData = ['refund_reason' => $cancel['remark'], 'refund_explain' => 'ERP取消订单', 'refund_img' => json_encode([])];
- $refundId = $storeOrderRefundServices->applyRefund($cartOid, $order['uid'], $order, array_values($cartIds), 1, 0.00, $refundData, 1, false);
- if ($refundId) {
- $refund = $storeOrderRefundServices->get($refundId);
- // 立即退款
- $this->receivedCallback(['outer_as_id' => $refund['order_id']], 1);
- }
- } catch (\Exception $e) {
- Log::error('订单部分退款申请失败,原因:' . $e->getMessage());
- }
- }
- /**
- * 订单发货
- * @param array $data
- * @return bool
- */
- public function deliverCallback(array $data): bool
- {
- try {
- /** @var StoreOrderServices $orderServices */
- $orderServices = app()->make(StoreOrderServices::class);
- /** @var StoreOrderDeliveryServices $orderDeliveryServices */
- $orderDeliveryServices = app()->make(StoreOrderDeliveryServices::class);
- $order = $orderServices->getOne(['erp_id' => $data['o_id'], 'status' => 0], '*');
- $deliver = [
- "type" => 1, // 订单统一使用快递配送
- "delivery_name" => $data['logistics_company'], // 快递公司名称
- "delivery_id" => $data['l_id'], // 快递公司单号
- "delivery_code" => $data['lc_id'], // 快递公司编码
- "express_record_type" => "1", // 快递
- 'express_temp_id' => '',
- 'expressTemp' => [],
- "to_name" => '',
- "to_tel" => '',
- "to_addr" => '',
- "sh_delivery_name" => "",
- "sh_delivery_id" => "",
- "sh_delivery_uid" => "",
- "fictitious_content" => "",
- "export_open" => true,
- 'erp_id' => (int)$data['o_id'] // 内部订单编号
- ];
- // 单个订单发货
- if (!empty($order)) {
- // 取消申请退货
- $this->checkRefundApply($order['id']);
- $other = ["to_name" => $order['real_name'], "to_tel" => $order['user_phone'], "to_addr" => $order['user_address']];
- $orderDeliveryServices->delivery($order['id'], array_merge($deliver, $other));
- return true;
- }
- // 根据订单ID查找为空则订单异常
- $order = $orderServices->getOne(['erp_order_id' => $data['so_id']], '*');
- if (!$order) {
- throw new AdminException('订单信息获取异常,不能进行自动发货!');
- }
- // 拆单发货
- /** @var StoreOrderCartInfoServices $cartInfoServices */
- $cartInfoServices = app()->make(StoreOrderCartInfoServices::class);
- $list = $cartInfoServices->getSplitCartList($order['id']);
- if ($order['pid'] < 0 && empty($list)) {
- $oIds = $orderServices->Value([['pid', '=', $order['id']], ['status', '=', 0], ['refund_status', '<', 2]], 'GROUP_CONCAT(id)');
- if ($oIds) {
- $oIds = array_filter(explode(',', $oIds));
- // 获取拆单信息进行匹配是否拆单
- $cartWhere = ['oid' => $oIds, 'split_status' => [0, 1]];
- $list = $cartInfoServices->getCartColunm($cartWhere, 'id,oid,cart_id,cart_num,split_surplus_num,cart_info');
- foreach ($list as &$cartInfo) {
- $cartInfo['cart_info'] = is_string($cartInfo['cart_info']) ? json_decode($cartInfo['cart_info'], true) : $cartInfo['cart_info'];
- }
- }
- }
- // 获取发货数据
- [$deliver['cart_ids'], $oid] = $this->generateCart($data['items'], $list);
- if (empty($deliver['cart_ids'])) {
- return true;
- }
- // 取消申请退货
- $this->checkRefundApply($oid);
- $other = ["to_name" => $order['real_name'], "to_tel" => $order['user_phone'], "to_addr" => $order['user_address']];
- $orderDeliveryServices->splitDelivery($oid, array_merge($deliver, $other));
- } catch (\Exception $e) {
- Log::error('发货回调失败, 原因:' . $e->getMessage());
- }
- return true;
- }
- /**
- * 订单拆分后的数据
- * @param array $items
- * @param array $list
- * @return array
- * @throws Exception
- */
- public function generateCart(array $items, array $list): array
- {
- $carts = [];
- $oid = 0;
- foreach ($items as $item) {
- foreach ($list as $cart) {
- if ($item['sku_id'] == $cart['cart_info']['productInfo']['attrInfo']['code']) {
- $carts[] = ['cart_id' => $cart['cart_id'], 'cart_num' => (int)$item['qty']];
- $oid = $cart['oid'];
- }
- }
- }
- return [$carts, $oid];
- }
- /**
- * 售后单上传
- * @param array $refundIds
- * @return bool
- */
- public function refundOrderUpload(array $refundIds, string $shopStatus = 'WAIT_SELLER_CONFIRM_GOODS')
- {
- try {
- /** @var StoreOrderServices $orderServices */
- $orderServices = app()->make(StoreOrderServices::class);
- /** @var StoreOrderRefundServices $storeOrderRefundServices */
- $storeOrderRefundServices = app()->make(StoreOrderRefundServices::class);
- $list = [];
- foreach ($refundIds as $refundId) {
- $refund = $storeOrderRefundServices->getOne(['id' => $refundId], '*', ['order']);
- if ($refund->order['pid'] > 0) {
- $order = $orderServices->get($refund->order['pid']);
- if (!$order) {
- throw new AdminException('父级订单信息不能为空!');
- }
- $soId = $order->erp_order_id;
- } else {
- $soId = $refund->order->erp_order_id;
- }
- $refundData = [
- 'shop_id' => $this->getShopId($refund->order->store->erp_shop_id ?? 0), // 店铺编号
- 'outer_as_id' => $refund['order_id'], // 退货退款单号,平台唯一
- 'so_id' => $soId, // 平台订单号
- 'type' => '普通退货', // 售后类型
- 'shop_status' => $shopStatus, // WAIT_SELLER_CONFIRM_GOODS:等待卖家确认收货 CLOSED:退款关闭
- 'good_status' => 'BUYER_RETURNED_GOODS', // 买家已退货
- 'question_type' => null,
- 'remark' => $refund['refund_reason'], // 问题类型
- 'total_amount' => (float)$refund->order['pay_price'], // 原单据总金额
- 'refund' => (float)$refund['refund_price'], // 卖家应退金额
- 'payment' => 0.00 // 买家应补偿金额
- ];
- $items = [];
- foreach ($refund['cart_info'] as $cart) {
- $items[] = [
- 'sku_id' => $cart['productInfo']['attrInfo']['code'], // 商家商品编码
- 'qty' => (int)$cart['cart_num'], // 退货数量
- 'amount' => bcadd(bcmul((string)($cart['truePrice'] ?? 0), (string)$cart['cart_num'], 4), (string)($cart['postage_price'] ?? 0), 2), // SKU退款金额
- 'type' => '退货',
- 'pic' => $cart['productInfo']['attrInfo']['image']
- ];
- }
- $refundData['items'] = $items;
- $list[] = $refundData;
- }
- $result = $this->services->serviceDriver('order')->afterSaleUpload($list);
- if ($result['datas'][0]['issuccess'] != true) {
- Log::error('退货单:' . implode(',', $refundIds) . ' 发送失败,原因:' . $result['datas'][0]['msg']);
- }
- } catch (\Exception $e) {
- Log::error(['msg' => '售后单上传失败,原因:' . $e->getMessage(), 'data' => ['refundIds' => $refundIds, 'shopStatus' => $shopStatus]]);
- }
- }
- /**
- * 获取店铺编号
- * @param int $erpShopId
- * @return int
- */
- public function getShopId(int $erpShopId): int
- {
- if ($erpShopId < 1) {
- $erpShopId = sys_config('jst_default_shopid');
- }
- return (int)$erpShopId;
- }
- /**
- * ERP订单取消
- * @param string $orderId
- * @param array $erpOrderId
- * @return void
- */
- public function cancelOrder(string $orderId, array $erpOrderId = [])
- {
- $erpOrderId[] = $orderId;
- $result = $this->services->serviceDriver('order')->ordersSingleQuery(['so_ids' => array_filter($erpOrderId), 'status' => 'WaitConfirm']);
- if (!$erpIds = array_column($result['orders'], 'o_id')) {
- Log::error(['msg' => 'ERP订单取消失败,原因:未找到待发货订单', 'data' => [$orderId, $erpOrderId]]);
- return false;
- }
- $cancelData = ['o_ids' => $erpIds, 'cancel_type' => '用户申请退货, 重新生成订单'];
- $num = 3;
- for ($i = $num; $i >= 0; $i--) {
- if ($i <= 0) {
- Log::error(['msg' => 'ERP订单取消失败,调用均为异常', 'data' => [$orderId, $erpOrderId]]);
- return false;
- }
- try {
- $this->services->serviceDriver('order')->orderByOIdCancel($cancelData);
- return true;
- } catch (\Exception $e) {
- usleep(1000 * 50);
- Log::error('ERP订单取消失败,原因:' . $e->getMessage());
- }
- }
- return false;
- }
- /**
- * 售后收货回调
- * @param array $refund
- * @param int $type
- * @param bool $isUpload
- * @return void
- */
- public function receivedCallback(array $refund, int $type = 1, bool $isUpload = false)
- {
- try {
- /** @var StoreOrderServices $orderServices */
- $orderServices = app()->make(StoreOrderServices::class);
- /** @var StoreOrderRefundServices $orderRefundServices */
- $orderRefundServices = app()->make(StoreOrderRefundServices::class);
- $data = [
- 'refund_type' => 6, // 已退款
- 'refunded_time' => time()
- ];
- if ($type == 1) {
- $data['refund_status'] = 2;
- $data['refund_type'] = 6;
- } else if ($type == 2) {
- $data['refund_status'] = 0;
- $data['refund_type'] = 3;
- }
- $orderRefund = $orderRefundServices->getOne(['order_id' => $refund['outer_as_id']]);
- if (!$orderRefund) {
- throw new AdminException('Data does not exist!');
- }
- $id = (int)$orderRefund['id'];
- if ($type == 2) {
- $refundData = [
- 'refuse_reason' => 'ERP订单发货取消',
- 'refund_type' => 3,
- 'refunded_time' => time()
- ];
- $orderRefundServices->refuseRefund($id, $refundData, $orderRefund);
- } else {
- if ($orderRefund['is_cancel'] == 1) {
- throw new AdminException('用户已取消申请!');
- }
- $order = $orderServices->get((int)$orderRefund['store_order_id']);
- if (!$order) {
- throw new AdminException('Data does not exist!');
- }
- if (!in_array($orderRefund['refund_type'], [1, 2, 5])) {
- throw new AdminException('售后订单状态不支持该操作');
- }
- // 0元退款
- if ($orderRefund['refund_price'] == 0) {
- $refund_price = 0;
- } else {
- $refund_price = $orderRefund['refund_price'];
- if ($orderRefund['refund_price'] == $orderRefund['refunded_price']) {
- throw new AdminException('已退完支付金额!不能再退款了');
- }
- $data['refunded_price'] = bcadd($refund_price, $orderRefund['refunded_price'], 2);
- $bj = bccomp((string)$orderRefund['refund_price'], $data['refunded_price'], 2);
- if ($bj < 0) {
- throw new AdminException('退款金额大于支付金额,请修改退款金额');
- }
- }
- $refund_data['pay_price'] = $order['pay_price'];
- $refund_data['refund_price'] = $refund_price;
- if ($order['refund_price'] > 0) {
- mt_srand();
- $refund_data['refund_id'] = $order['order_id'] . rand(100, 999);
- }
- // 修改订单退款状态
- unset($data['refund_price']);
- if ($orderRefundServices->agreeRefund($id, $refund_data)) {
- $orderRefundServices->update($id, $data);
- } else {
- $orderRefundServices->storeProductOrderRefundYFasle($id, $refund_price);
- throw new AdminException('退货单退款失败');
- }
- // 重新上传订单
- if ($type && $isUpload) {
- $orders = explode('_', $refund['so_id']);
- $order = $orderServices->getOne(['order_id' => $orders[0] ?? ''], 'id, pid, status, refund_status, erp_order_id');
- if (!$order) {
- throw new AdminException('订单不存在');
- }
- $erpOrderId = [];
- $oid = (int)$order['id'];
- $status = (int)$order['status'];
- if ($order['pid'] < 0) {
- $childOrder = $orderServices->getOne([['pid', '=', $order['id']], ['status', '=', 0], ['refund_status', '=', 0]], 'id, pid, status, refund_status, erp_order_id');
- $refundChild = $orderServices->getColumn([['pid', '=', $order['id']], ['status', '=', 0], ['refund_status', '=', 2]], 'erp_order_id');
- if (!empty($refundChild)) {
- $erpOrderId = array_unique($refundChild);
- }
- if ($childOrder) {
- $oid = (int)$childOrder['id'];
- $erpOrderId[] = $childOrder['erp_order_id'];
- $status = (int)$childOrder['status'];
- }
- }
- if ($oid > 0) {
- !in_array($status, [2, 4]) && OrderSyncJob::dispatchDo('reorderOrder', [$order['erp_order_id'], $erpOrderId, $oid]);
- } else {
- Log::error(['msg' => '售后收货回调没有需要取消的订单', 'data' => $refund]);
- }
- }
- }
- } catch (\Exception $e) {
- Log::error(['msg' => '售后收货回调失败,原因:' . $e->getMessage(), 'data' => ['refund' => $refund, 'type' => $type, 'isUpload' => $isUpload]]);
- }
- }
- /**
- * 过滤ERP不可退订单
- * @param array $orders
- * @param int $oid
- * @return array
- */
- protected function filter(array $orders, int $oid): array
- {
- $cancelled = $waitConfirm = [];
- foreach ($orders as $cartOrder) {
- if (in_array($cartOrder['status'], ['WaitConfirm', 'Sent'])) {
- foreach ($cartOrder['items'] as $item) {
- if (!isset($waitConfirm[$item['sku_id']])) {
- $waitConfirm[$item['sku_id']] = $item['qty'];
- } else {
- $waitConfirm[$item['sku_id']] += $item['qty'];
- }
- }
- }
- }
- /** @var StoreOrderCartInfoServices $storeOrderCartInfoServices */
- $storeOrderCartInfoServices = app()->make(StoreOrderCartInfoServices::class);
- $cartInfo = $storeOrderCartInfoServices->getOrderCartInfo($oid);
- foreach ($cartInfo as $cart) {
- $attrInfo = $cart['cart_info']['productInfo']['attrInfo'];
- $cancelled[$attrInfo['code']] = $cart['cart_info']['cart_num'];
- if (isset($waitConfirm[$attrInfo['code']])) {
- $cancelled[$attrInfo['code']] -= $waitConfirm[$attrInfo['code']];
- if ($cancelled[$attrInfo['code']] < 1) {
- unset($cancelled[$attrInfo['code']]);
- }
- }
- }
- $refundData = $this->getOrderRefund($oid);
- foreach ($refundData as $key => $item) {
- $num = $cancelled[$key] ?? 0;
- if ($num > 0) {
- $cancelled[$key] -= $item;
- if ($cancelled[$key] < 1) {
- unset($cancelled[$key]);
- }
- }
- }
- return $cancelled;
- }
- /**
- * 累计订单已退数量
- * @param int $oid
- * @return array
- */
- public function getOrderRefund(int $oid): array
- {
- $attrData = [];
- $refunds = $this->orderRefundList($oid);
- foreach ($refunds as $refund) {
- foreach ($refund['cart_info'] as $item) {
- if (!isset($attrData[$item['productInfo']['attrInfo']['code']])) {
- $attrData[$item['productInfo']['attrInfo']['code']] = $item['cart_num'];
- } else {
- $attrData[$item['productInfo']['attrInfo']['code']] += $item['cart_num'];
- }
- }
- }
- return $attrData;
- }
- /**
- * 存在申请退货单则关闭
- * @param int $oid
- * @return bool
- */
- public function checkRefundApply(int $oid): bool
- {
- $refunds = $this->orderRefundList($oid, 1);
- if (!empty($refunds)) {
- $refundIds = [];
- foreach ($refunds as $refund) {
- $refundIds[] = $refund['id'];
- $this->receivedCallback(['outer_as_id' => $refund['order_id']], 2);
- }
- // 关闭 ERP 退货单
- $this->refundOrderUpload($refundIds, 'CLOSED');
- }
- return true;
- }
- /**
- * 订单退货单相关信息
- * @param int $id
- * @param int $refundType
- * @return array
- */
- public function orderRefundList(int $id, int $refundType = 4): array
- {
- /** @var StoreOrderRefundServices $storeOrderRefundServices */
- $storeOrderRefundServices = app()->make(StoreOrderRefundServices::class);
- $refunds = $storeOrderRefundServices->getRefundList(['store_order_id' => $id, 'refundTypes' => $refundType], 'id, store_order_id, store_id, order_id, uid, cart_info');
- /** @var StoreOrderServices $orderServices */
- $orderServices = app()->make(StoreOrderServices::class);
- $ids = $orderServices->Value(['pid' => $id], 'GROUP_CONCAT(id)');
- if ($ids) {
- $ids = array_filter(explode(',', $ids));
- $list = $storeOrderRefundServices->getRefundList(['store_order_id' => $ids, 'refundTypes' => $refundType], 'id, store_order_id, store_id, order_id, uid, cart_info');
- $refunds = array_merge($refunds, $list);
- }
- return $refunds;
- }
- /**
- * ERP订单号
- * @return string $orderId
- * @return string $erpOrderId
- */
- public function getErpOrderId(string $orderId, string $erpOrderId = ''): string
- {
- if (!empty($erpOrderId)) {
- $arr = explode('_', $erpOrderId);
- if (count($arr) == 1) {
- return $erpOrderId . '_1';
- }
- $num = end($arr);
- return $arr[0] . '_' . ++$num;
- }
- return $orderId;
- }
- }
|