diff --git a/app/JsonRpc/OrderService.php b/app/JsonRpc/OrderService.php index 0e662a1..1a1b47b 100644 --- a/app/JsonRpc/OrderService.php +++ b/app/JsonRpc/OrderService.php @@ -8,10 +8,14 @@ use App\Constants\v3\LogLabel; use App\Constants\v3\OrderState; use App\Exception\ErrorCodeException; use App\Model\v3\Order; +use App\Model\v3\OrderGoods; use App\Model\v3\OrderMain; use App\Service\v3\Interfaces\OrderOnlineServiceInterface; use App\Service\v3\Interfaces\SeparateAccountsServiceInterface; +use EasyWeChat\Factory; +use EasyWeChat\Kernel\Exceptions\InvalidConfigException; use Hyperf\DbConnection\Db; +use Hyperf\Guzzle\CoroutineHandler; use Hyperf\RpcServer\Annotation\RpcService; use Hyperf\Di\Annotation\Inject; use function AlibabaCloud\Client\json; @@ -107,53 +111,142 @@ class OrderService implements OrderServiceInterface * 退2元商品时,退款金额为 * 红包 :(2/(98+2))*10 = 0.2 * 退款:2-0.2=1.8元 - * @param $user_id *用户ID + * @param $user_id *用户ID * @param $global_order_id *全局总订单ID - * @param $child_order_id *主订单ID, + * @param $order_child_id *主订单ID, * @param $order_goods_id *订单商品ID * @param $note + * @throws InvalidConfigException */ - public function onlineSingleRefund($user_id, $note, $global_order_id, $child_order_id=null, $order_goods_id=null) + public function onlineSingleRefund($user_id, $note, $global_order_id, $order_child_id=null, $order_goods_id=null) { + + $params = [ + 'user_id' => $user_id, + 'note' => $note, + 'global_order_id' => $global_order_id, + 'order_child_id' => $order_child_id, + 'order_goods_id' => $order_goods_id, + ]; + if (!$user_id || !$global_order_id || !$note) { $this->log->event(LogLabel::ORDER_REFUND_LOG, [ 'jsonrpc_order_service_exception_onlineSingleRefund' => '参数不对', - 'params' => json([$global_order_id, $user_id, $note]) + 'params' => json_encode($params) ]); throw new ErrorCodeException(ErrorCode::ORDER_REFUND_FAIL); } // 主订单 $orderMain = OrderMain::query() - ->where(['global_order_id' => $global_order_id]) + ->where(['global_order_id' => $global_order_id, 'user_id' => $user_id]) ->whereIn('state', OrderState::CAN_REFUND_DIRECT) ->first(); - if (empty($orderMain)) { + if (is_null($orderMain)) { $this->log->event(LogLabel::ORDER_REFUND_LOG, [ 'jsonrpc_order_service_exception_onlineSingleRefund' => '订单不存在', - 'params' => json([$global_order_id, $user_id, $note]) + 'params' => json_encode($params) ]); throw new ErrorCodeException(ErrorCode::ORDER_REFUND_FAIL); } // 子订单 - if ($child_order_id) { - $orderChild = Order::query()->where(['order_main_id' => $orderMain->global_order_id])->first(); + $orderChild = null; + if ($order_child_id) { + $orderChild = Order::query()->where(['order_main_id' => $orderMain->global_order_id, 'id' => $order_child_id])->first(); } - // 单商品退 + // 订单商品 + $orderGoods = null; if ($order_goods_id) { - if (!$child_order_id) { + if (!$order_child_id || is_null($orderChild)) { $this->log->event(LogLabel::ORDER_REFUND_LOG, [ - 'jsonrpc_order_service_exception_onlineSingleRefund' => '参数不对[单品]', - 'params' => json([$global_order_id, $user_id, $note, $child_order_id]) + 'jsonrpc_order_service_exception_onlineSingleRefund' => '子订单参数异常[单品]', + 'params' => json_encode($params) ]); throw new ErrorCodeException(ErrorCode::ORDER_REFUND_FAIL); } + $orderGoods = OrderGoods::query()->where(['order_id' => $orderChild->id, 'id' => $order_goods_id])->first(); + + if (is_null($orderGoods)) { + $this->log->event(LogLabel::ORDER_REFUND_LOG, [ + 'jsonrpc_order_service_exception_onlineSingleRefund' => '订单商品参数异常[单品]', + 'params' => json_encode($params) + ]); + throw new ErrorCodeException(ErrorCode::ORDER_REFUND_FAIL); + } + + } + + $totalAmount = $orderMain->total_money; // 订单可退款金额,总订单金额不含配送费和服务费 + $preRefundAmount = 0; // 预退款金额 + $refundAmount = 0; // 实际退款金额 + $refundType = 'Main'; // 退款类型, Main整单 Sub子单 Goods单品 + if ($orderGoods) { // 1. 如果订单商品存在则说明要退单品 + $preRefundAmount = bcmul($orderGoods->price, $orderGoods->number, 2); + $refundType = 'Goods'; + } elseif ($orderChild) { // 2. 否则如果存在子订单说明退子订单 + $preRefundAmount = $orderChild->money; + $refundType = 'Sub'; + } else { // 3. 再则如果存在主订单说明退主订单 + $preRefundAmount = $orderMain->total_money; + $refundType = 'Main'; + } + + // 占订单金额的比例 + $rate = bcdiv($preRefundAmount, $totalAmount, 6); + // 计算优惠券所占金额 + $couponMoney = bcmul($orderMain->coupon_money, $rate, 6); + // 计算本次退款实际退款金额 + $refundAmount = bcsub($preRefundAmount, $couponMoney, 2); + + if ($refundAmount <= 0) { + $this->log->event(LogLabel::ORDER_REFUND_LOG, [ + 'jsonrpc_order_service_exception_onlineSingleRefund' => '没有可退款金额[实际退款金额]', + 'params' => json_encode($params) + ]); + throw new ErrorCodeException(ErrorCode::ORDER_REFUND_FAIL); + } + // 开始退款 + $config = config('wxpay'); + $app = Factory::payment($config); + $app['guzzle_handler'] = CoroutineHandler::class; + $result = $app->refund->byOutTradeNumber( + $orderMain->global_order_id, + $orderMain->global_order_id, + bcmul($orderMain->money, 100, 0), + bcmul($refundAmount, 100, 0), + [ + 'refund_desc' => '订单协商退款['.$refundType.']', + 'notify_url' => config('wechat.notify_url.refund_single'), + ] + ); + + if ($result['return_code'] == 'FAIL') { + $this->log->event(LogLabel::ORDER_REFUND_LOG, [ + 'jsonrpc_order_service_exception_onlineSingleRefund' => $result['return_msg'].'[微信退款失败]', + 'params' => json_encode($result) + ]); + throw new ErrorCodeException(ErrorCode::ORDER_REFUND_FAIL); } + if ($result['result_code'] == 'FAIL') { + $this->log->event(LogLabel::ORDER_REFUND_LOG, [ + 'jsonrpc_order_service_exception_onlineSingleRefund' => $result['err_code_des'].'[微信退款失败]'.$result['err_code'], + 'params' => json_encode($result) + ]); + throw new ErrorCodeException(ErrorCode::ORDER_REFUND_FAIL); + } + + // 退款申请成功,查询退款状态 + $refundResult = $app->refund->queryByRefundId($result['refund_id']); + $this->log->event(LogLabel::ORDER_REFUND_LOG, [ + 'jsonrpc_order_service_exception_onlineSingleRefund' => '[微信退款查询]', + 'params' => json_encode($refundResult) + ]); + } } \ No newline at end of file diff --git a/app/Model/v3/OrderMain.php b/app/Model/v3/OrderMain.php index 01134a4..c3abfc8 100644 --- a/app/Model/v3/OrderMain.php +++ b/app/Model/v3/OrderMain.php @@ -72,6 +72,12 @@ class OrderMain extends Model public function getStateTextAttribute() { + if ($this->attributes['state'] == 3) { + if (!$this->attributes['horseman_id']) { + return '已接单'; + } + } + return OrderState::getMessage($this->attributes['state']); }