app_id)->where('user_id', $data['userId'])->first(); if (empty($user)) { throw new BusinessException('用户不存在'); } $order = Order::where('app_id', $app->app_id)->where('out_order_no', $data['outOrderNo'])->first(); if ($order) { throw new BusinessException('订单号重复'); } [$order, $orderSplitInfos] = $this->createOrder($app, $data, $user); $splitInfoList = $this->buildSplitInfoList($orderSplitInfos); return $this->paymentSplit($order, $user, $splitInfoList, $token); } private function buildSplitInfoList($orderSplitInfos) { $splitInfoList = []; foreach ($orderSplitInfos as $splitInfo) { $splitInfoList[] = [ 'subOutOrderNo' => $splitInfo['sub_order_no'], 'contractNo' => $splitInfo['contract_no'], 'customerType' => $splitInfo['split_user_type'], 'splitAmount' => $splitInfo['split_amount'], 'sellerFlag' => $splitInfo['seller_flag'], ]; } return $splitInfoList; } private function paymentSplit(Order $order, User $user, array $splitInfoList, string $token) { try { $baofu = new Baofu(); $url = $baofu->paymentSplit([ 'loginNo' => $user->member_id, 'outOrderNo' => $order->order_no, 'amount' => $order->amount, 'paidType' => 'CARD', 'agreementNo' => $order->agreement_no, 'pwdPayExpTime' => strtotime($order->expired_at), 'splitInfoList' => $splitInfoList, ], $token); $order->status = 'APPLY_SUCCESS'; $order->applied_at = date('Y-m-d H:i:s'); $order->pay_url = $url; $order->save(); return $url; } catch (ApiException $e) { $order->status = 'APPLY_FAILED'; $order->applied_at = date('Y-m-d H:i:s'); $order->error_code = $e->getErrorCode(); $order->error_message = $e->getMessage(); $order->save(); throw $e; } } public function createOrder(App $app, array $params, User $user) { $expiresIn = $params['expiresIn'] ?? 10 * 60; $order = new Order(); $order->app_id = $app->app_id; $order->user_id = $user->user_id; $order->member_id = $user->member_id; $order->order_no = StringHelper::generateOrderNo(StringHelper::ORDER_NO_TYPE_PAY); $order->out_order_no = $params['outOrderNo']; $order->amount = $params['amount']; $order->notify_url = $params['notifyUrl']; $order->return_url = $params['returnUrl']; $order->agreement_no = $params['agreementNo'] ?: ''; $order->status = 'PREPARE'; $order->pay_channel = 'BAOFU'; $order->pay_method = 'paymentSplit'; $order->pay_type = 'CARD'; $order->expired_at = date('Y-m-d H:i:s', $expiresIn); $order->org_split_info_list = $params['splitInfoList']; $order->save(); $platformAccount = User::getPlatformAccount(); $fee = $platformAccount ? floor($order->amount * 0.01) : 0; $orderSplitInfos = []; $splitUserIds = array_column($params['splitInfoList'], 'splitUserId'); $users = User::where('app_id', $app->app_id)->whereIn('user_id', $splitUserIds)->get()->keyBy('user_id'); foreach ($params['splitInfoList'] as $splitInfo) { $splitUser = $users[$splitInfo['splitUserId']]; $splitAmount = $splitInfo['sellerFlag'] == 1 ? ($splitInfo['splitAmount'] - $fee): $splitInfo['splitAmount']; $orderSplitInfos[] = [ 'app_id' => $app->app_id, 'user_id' => $user->user_id, 'member_id' => $user->member_id, 'split_member_id' => $splitUser->member_id, 'split_user_id' => $splitInfo['splitUserId'], 'split_user_type' => $splitUser->user_type, 'order_no' => $order->order_no, 'out_order_no' => $order->out_order_no, 'sub_order_no' => StringHelper::generateOrderNo(StringHelper::ORDER_NO_TYPE_PAY_SPLIT), 'sub_out_order_no' => $splitInfo['subOutOrderNo'], 'split_amount' => $splitAmount, 'contract_no' => $splitUser->contract_no, 'seller_flag' => $splitInfo['sellerFlag'], ]; } if ($fee) { $feeSubOrderNo = StringHelper::generateOrderNo(StringHelper::ORDER_NO_TYPE_PAY_SPLIT); $orderSplitInfos[] = [ 'app_id' => $app->app_id, 'user_id' => $user->user_id, 'member_id' => $user->member_id, 'split_member_id' => $platformAccount->member_id, 'split_user_id' => $platformAccount->user_id, 'split_user_type' => $platformAccount->user_type, 'order_no' => $order->order_no, 'out_order_no' => $order->out_order_no, 'sub_order_no' => $feeSubOrderNo, 'sub_out_order_no' => $feeSubOrderNo, 'split_amount' => $fee, 'contract_no' => $platformAccount->contract_no, 'seller_flag' => 0, ]; } OrderSplitInfo::insert($orderSplitInfos); return [$order, $orderSplitInfos]; } public function updateOrder($params) { $order = Order::where('order_no', $params['order_no'])->where('status', 'APPLY_SUCCESS')->first(); if (empty($order)) { return null; } $order->third_order_no = $params['third_order_no']; $order->status = $params['status']; $order->finished_at = date('Y-m-d H:i:s', strtotime($params['finished_at'])); $order->error_message = $params['error_message']; $order->transaction_id = $params['transaction_id']; $order->out_transaction_id = $params['out_transaction_id']; $order->save(); return $order; } public function refundApply(array $data, App $app) { $user = User::where('app_id', $app->app_id)->where('user_id', $data['userId'])->first(); if (!$user) { throw new BusinessException('用户不存在'); } $order = Order::where('app_id', $app->app_id)->where('out_order_no', $data['outOrderNo'])->first(); if (empty($order)) { throw new BusinessException('订单号不存在'); } if ($order->status != 'SUCCESS') { throw new BusinessException('该订单状态不能发起退款'); } $refund = Refund::where('app_id', $app->app_id)->where('out_refund_no', $data['outRefundNo'])->first(); if ($refund) { throw new BusinessException('该退款单已经存在'); } $refund = new Refund(); $refund->app_id = $app->app_id; $refund->user_id = $user->user_id; $refund->member_id = $user->member_id; $refund->order_no = $order->order_no; $refund->out_order_no = $order->out_order_no; $refund->refund_no = StringHelper::generateOrderNo(StringHelper::ORDER_NO_TYPE_REFUND); $refund->out_refund_no = $data['outRefundNo']; $refund->refund_amount = $data['refundAmount']; $refund->refund_reason = $data['refundReason']; $refund->notify_url = $data['notifyUrl'] ?? ''; $refund->org_refund_split_info_list = $data['refundSplitInfoList'] ?? []; $refund->remark = $data['remark'] ?? ''; $refund->applied_at = date('Y-m-d H:i:s'); $refundSplitInfoList = []; $refundSplitInfos = []; foreach ($order->orderSplitInfos as $splitInfo) { $refundSplitInfoList[] = [ 'orgSubOutOrderNo' => $splitInfo->sub_order_no, 'refundAmount' => (string)$splitInfo->split_amount, ]; $refundSplitInfos[$splitInfo->sub_order_no] = [ 'app_id' => $splitInfo->user_id, 'user_id' => $splitInfo->user_id, 'member_id' => $splitInfo->member_id, 'user_id' => $splitInfo->user_id, 'split_member_id' => $splitInfo->split_member_id, 'split_user_id' => $splitInfo->split_user_id, 'refund_no' => $refund->refund_no, 'out_refund_no' => $refund->out_refund_no, 'order_no' => $splitInfo->order_no, 'out_order_no' => $splitInfo->out_order_no, 'sub_order_no' => $splitInfo->sub_order_no, 'sub_out_order_no' => $splitInfo->sub_out_order_no, 'refund_amount' => $splitInfo->split_amount, 'status' => Refund::STATUS_PREPARE, 'message' => '', ]; } try { $baofu = new Baofu(); $result = $baofu->profitShareRefundApply([ 'loginNo' => $user->member_id, 'refundTradeId' => $refund->refund_no, 'refundTradeType' => 'REFUND_APPLY', 'orgTradeId' => $refund->order_no, 'refundAmount' => $refund->refund_amount, 'refundReason' => $refund->refund_reason, 'refundSplitInfoList' => $refundSplitInfoList, ]); $refund->status = 'APPLY_SUCCESS'; $refund->real_refund_amount = $result['refundAmount']; foreach ($result['refundSplitResultList'] as $refundSplitResult) { $subOrderNo = $refundSplitResult['orgSubOutOrderNo']; $refundSplitInfos[$subOrderNo]['status'] = Refund::getStatusByShortStatus($refundSplitResult['status']); $refundSplitInfos[$subOrderNo]['message'] = $refundSplitResult['message'] ?: ''; } RefundSplitInfo::insert($refundSplitInfos); $refund->save(); } catch (BasicException $e) { $refund->status = 'APPLY_FAILED'; $refund->error_code = $e->getCode(); $refund->error_message = $e->getMessage(); foreach ($refundSplitInfos as $key => $refundSplitInfo) { $refundSplitInfos[$key]['status'] = 'APPLY_FAILED'; $refundSplitInfos[$key]['message'] = $e->getMessage(); } RefundSplitInfo::insert($refundSplitInfos); $refund->save(); throw $e; } } public function refundConfirm(array $data, App $app, string $token) { $user = User::where('app_id', $app->app_id)->where('user_id', $data['userId'])->first(); if (!$user) { throw new BusinessException('用户不存在'); } $order = Order::where('app_id', $app->app_id)->where('out_order_no', $data['outOrderNo'])->first(); if (empty($order)) { throw new BusinessException('订单号不存在'); } if ($order->status != 'SUCCESS') { throw new BusinessException('该订单状态不能发起退款'); } $refund = Refund::where('app_id', $app->app_id)->where('out_refund_no', $data['outRefundNo'])->first(); if (empty($refund)) { throw new BusinessException('退款申请不存在'); } if ($refund->status != Refund::STATUS_APPLY_SUCCESS || $refund->status != Refund::STATUS_CONFIRM_FAILED) { throw new BusinessException('该退款单未申请成功'); } try { $baofu = new Baofu(); $result = $baofu->profitShareRefundConfirm([ 'loginNo' => $user->member_id, 'refundTradeId' => $refund->refund_no, 'refundTradeType' => 'REFUND_APPLY', 'orgTradeId' => $refund->order_no, 'refundAmount' => $refund->refund_amount, 'notifyUrl' => $data['notifyUrl'], ], $token); $refund->status = Refund::getStatusByShortStatus($result['refundStatus']); $refund->third_refund_no = $result['refundOrderId']; $refund->save(); } catch (ApiException $e) { $refund->status = Refund::STATUS_CONFIRM_FAILED; $refund->error_code = $e->getCode(); $refund->error_message = $e->getMessage(); $refund->save(); throw $e; } } public function updateRefund($params) { $refund = Refund::where('refund_no', $params['refund_no'])->where('status', 'APPLY_FAILED')->first(); if (empty($refund)) { return null; } $refund->third_refund_no = $params['third_refund_no']; $refund->status = Refund::getStatusByShortStatus($params['status']); $refund->refund_success_at = date('Y-m-d H:i:s', strtotime($params['refund_success_at'])); $refund->error_message = $params['error_message']; $refund->save(); return $refund; } }