From 2089e7a60bc778e6476c281bc38d0bece1e6d2c0 Mon Sep 17 00:00:00 2001 From: elf <360197197@qq.com> Date: Fri, 4 Aug 2023 01:26:53 +0800 Subject: [PATCH] yh --- app/Controller/Payment/NotifyController.php | 50 +++++++- app/Controller/Payment/PayController.php | 4 +- app/Helper/StringHelper.php | 2 + app/Model/Order.php | 4 + app/Model/OrderSplitInfo.php | 10 ++ app/Model/User.php | 4 + app/Service/PaymentService.php | 134 +++++++++++++++++--- payment.sql | 14 +- 8 files changed, 201 insertions(+), 21 deletions(-) create mode 100644 app/Model/OrderSplitInfo.php diff --git a/app/Controller/Payment/NotifyController.php b/app/Controller/Payment/NotifyController.php index 0b98f99..af337b2 100644 --- a/app/Controller/Payment/NotifyController.php +++ b/app/Controller/Payment/NotifyController.php @@ -65,10 +65,10 @@ class NotifyController extends AbstractController $requestLog = $this->requestService->getRequestLogByToken($token); $params = $request->all(); - Log::info('registerNotifyParams:', $params); + Log::info('bindCardNotifyParams:', $params); $baofu = new Baofu(); - if (!$baofu->notifyVerify($params, 'register')) { - Log::info('registerNotifyVerifyFail: ' . $params); + if (!$baofu->notifyVerify($params, 'bindCard')) { + Log::info('bindCardNotifyVerifyFail: ' . $params); return $baofu->notifySuccess(); } @@ -89,6 +89,50 @@ class NotifyController extends AbstractController $baofu->notifySuccess(); } + public function payment(RequestInterface $request) + { + $token = $request->route('token'); + $requestLog = $this->requestService->getRequestLogByToken($token); + + $params = $request->all(); + Log::info('paymentNotifyParams:', $params); + $baofu = new Baofu(); + if (!$baofu->notifyVerify($params, 'payment')) { + Log::info('paymentNotifyVerifyFail: ' . $params); + return $baofu->notifySuccess(); + } + + $info = [ + 'member_id' => $params['loginId'], + 'order_no' => $params['orderId'], + 'third_order_no' => $params['tradeId'], + 'status' => $params['orderStatus'], + 'amount' => $params['orderMoney'], + 'finished_at' => $params['finishTime'], + 'error_message' => $params['errorMsg'], + 'transaction_id' => $params['transactionId'], + 'out_transaction_id' => $params['outTransactionId'], + ]; + $order = $this->paymentService->updateOrder($info); + if (empty($order)) { + return $baofu->notifySuccess(); + } + + $result = $this->notify( + $requestLog->getDataValue('notify_url'), + $requestLog->app, + [ + 'status' => $order->status, + 'userId' => $order->user_id, + 'orderNo' => $order->order_no, + 'outOrderNo' => $order->out_order_no, + 'finishTime' => $order->finished_at, + ] + ); + + $baofu->notifySuccess(); + } + protected function notify($url, $app, $data) { if (empty($url)) { diff --git a/app/Controller/Payment/PayController.php b/app/Controller/Payment/PayController.php index b824a57..1f8e541 100644 --- a/app/Controller/Payment/PayController.php +++ b/app/Controller/Payment/PayController.php @@ -42,7 +42,9 @@ class PayController extends AbstractController public function bindCardPay(RequestInterface $request) { - + $requestLog = Context::get('requestLog'); + $data = $this->paymentService->bindCardPay($request->all(), $requestLog->request_token); + return $this->success($data); } public function protocolPayConfirm(RequestInterface $request) diff --git a/app/Helper/StringHelper.php b/app/Helper/StringHelper.php index 82b6795..c4ed468 100644 --- a/app/Helper/StringHelper.php +++ b/app/Helper/StringHelper.php @@ -6,6 +6,8 @@ namespace App\Helper; class StringHelper { + const ORDER_NO_TYPE_PAY = 'pay'; + const ORDER_NO_TYPE_PAY_SPLIT = 'pay_split'; const ORDER_NO_TYPE_UNBIND_CARD = 'unbind_card'; const ORDER_NO_TYPE_QUERY_CUSTOMER_INFO = 'query_customer_info'; diff --git a/app/Model/Order.php b/app/Model/Order.php index 3ae6a71..b5bd6aa 100644 --- a/app/Model/Order.php +++ b/app/Model/Order.php @@ -23,4 +23,8 @@ class Order extends Model ]; return $statusMap[$this->status]; } + + public function getExpiresIn() { + return strtotime($this->expired_at) - time(); + } } \ No newline at end of file diff --git a/app/Model/OrderSplitInfo.php b/app/Model/OrderSplitInfo.php new file mode 100644 index 0000000..713d989 --- /dev/null +++ b/app/Model/OrderSplitInfo.php @@ -0,0 +1,10 @@ +first(); + } } \ No newline at end of file diff --git a/app/Service/PaymentService.php b/app/Service/PaymentService.php index 90b0f24..46fc1f4 100644 --- a/app/Service/PaymentService.php +++ b/app/Service/PaymentService.php @@ -4,6 +4,7 @@ declare(strict_types=1); namespace App\Service; +use App\Exception\BasicException; use App\Exception\BusinessException; use App\Helper\Baofu\Baofu; use App\Helper\Efps\Api; @@ -13,6 +14,7 @@ use App\Helper\StringHelper; use App\Model\App; use App\Model\BankCard; use App\Model\Order; +use App\Model\OrderSplitInfo; use App\Model\PrePayLog; use App\Model\RefundOrder; use App\Model\User; @@ -25,6 +27,7 @@ use App\Request\ProtocolPayPreRequest; use App\Request\RefundQueryRequest; use App\Request\RefundRequest; use App\Request\UnBindCardRequest; +use Exception; class PaymentService extends AbstractService { @@ -44,28 +47,127 @@ class PaymentService extends AbstractService if ($user) { throw new BusinessException('用户已存在'); } - $baofu = new Baofu(); - $baofu->paymentSplit([ - 'loginNo' => $user->member_id, - 'outOrderNo' => '', - 'amount' => $user->member_id, - 'paidType' => 'CARD', - 'agreementNo' => $reqData[''], - 'pwdPayExpTime' => $reqData[''], - 'notifyUrl' => '', - ], $token); + $order = Order::where('app_id', $app->app_id)->where('out_order_no', $reqData['outOrderNo'])->first(); + if ($order) { + throw new BusinessException('订单号重复'); + } + [$order, $orderSplitInfos] = $this->createOrder($app, $reqData, $user); + + $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'], + ]; + } + + $baofu = new Baofu(); + try { + $url = $baofu->paymentSplit([ + 'loginNo' => $user->member_id, + 'outOrderNo' => $order->order_no, + 'amount' => $user->member_id, + 'paidType' => 'CARD', + 'agreementNo' => $order->agreement_no, + 'pwdPayExpTime' => $order->getExpiresIn(), + 'splitInfoList' => $splitInfoList, + 'notifyUrl' => '', + ], $token); + $order->status = 'APPLY_SUCCESS'; + $order->applied_at = date('Y-m-d H:i:s'); + $order->pay_url = $url; + return $url; + } catch (BasicException $e) { + $order->status = 'APPLY_FAILED'; + $order->applied_at = date('Y-m-d H:i:s'); + $order->error_code = $e->getCode(); + $order->error_message = $e->getMessage(); + $order->save(); + throw $e; + } } - public function createOrder(App $app, array $params, $user) { + public function createOrder(App $app, array $params, User $user) { + $expiresIn = $params['expiresIn'] ?: 15 * 60; $order = new Order(); $order->app_id = $app->app_id; + $order->user_id = $user->user_id; $order->member_id = $user->member_id; - $order->out_member_id = $params['outMemberId'] ?? ''; - $order->out_order_no = $params['outOrderNo'] ?? ''; - $order->amount = $params['payAmount'] ?? 0; - $order->notify_url = $params['notifyUrl'] ?? ''; - $order->order_info = json_encode($params['orderInfo'] ?? [], JSON_UNESCAPED_UNICODE); + $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->save(); + + $fee = floor($order->amount * 0.007); + $orderSplitInfos = []; + $splitUserIds = array_column($params['splitInfoList'], 'userId'); + $users = User::where('app_id', $app->app_id)->whereIn('user_id', $splitUserIds)->get()->keyBy('user_id'); + $platformAccount = User::getPlatformAccount(); + foreach ($params['splitInfoList'] as $splitInfo) { + $splitUser = $users[$splitInfo['userId']]; + $splitAmount = $splitInfo['sellerFlag'] == 1 ? ($splitInfo['amount'] - $fee): $splitInfo['amount']; + $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['userId'], + '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_FAILED')->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; } diff --git a/payment.sql b/payment.sql index d10092d..8e2873a 100644 --- a/payment.sql +++ b/payment.sql @@ -14,6 +14,7 @@ CREATE TABLE `users` ( `certificate_no` varchar(20) NOT NULL DEFAULT '', `user_type` varchar(20) NOt NULL, `apply_no` varchar(32) NOT NULL DEFAULT '', + `is_platform_account` tinyint(1) not null DEFAULT 0, `updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`) USING BTREE, @@ -57,12 +58,22 @@ CREATE TABLE `orders` ( `order_no` varchar(32) NOT NULL, `out_order_no` varchar(32) NOT NULL, `amount` int(11) NOT NULL DEFAULT 0, - `pay_type` varchar(10) NOT NULL, + `pay_channel` varchar(20) NOT NULL, + `pay_method` varchar(20) NOT NULL, + `pay_type` varchar(20) NOT NULL, `agreement_no` varchar(32) NOT NULL DEFAULT '', `expired_at` datetime DEFAULT NULL, + `applied_at` datetime DEFAULT NULL, `notify_url` varchar(255) NOT NULL DEFAULT '', `return_url` varchar(255) NOT NULL DEFAULT '', + `pay_url` varchar(255) NOT NULL DEFAULT '', `status` varchar(16) NOT NULL DEFAULT '', + `error_code` varchar(20) NOT NULL DEFAULT '', + `error_message` varchar(120) NOT NULL DEFAULT '', + `finished_at` datetime DEFAULT NULL, + `third_order_no` varchar(32) NOT NULL DEFAULT '', + `transaction_id` varchar(32) NOT NULL DEFAULT '', + `out_transaction_id` varchar(32) NOT NULL DEFAULT '', `updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`) USING BTREE, @@ -78,6 +89,7 @@ CREATE TABLE `order_split_infos` ( `user_id` varchar(32) NOT NULL, `split_member_id` varchar(32) NOT NULL, `split_user_id` varchar(32) NOT NULL, + `split_user_type` varchar(20) NOT NULL, `order_no` varchar(32) NOT NULL, `out_order_no` varchar(32) NOT NULL, `sub_order_no` varchar(32) NOT NULL,