paymentService = $paymentService; } public function getMemberInfo(RequestInterface $request) { [$app, $prePayLog] = $this->checkToken($request->input('stoken', '')); $outMemberId = $prePayLog->out_member_id; $user = User::where('app_id', $app->app_id)->where('out_member_id', $outMemberId)->first(); $bankCard = null; $userInfo = null; if ($user) { $bankCard = BankCard::where('app_id', $app->app_id)->where('out_member_id', $outMemberId)->where('status', BankCard::STATUS_ACTIVE)->first(); $userInfo = [ 'name' => $user->real_name ?? '', 'cardNo' => $user->card_no ?? '', 'mobile' => $user->mobile ?? '', 'bankCardNo' => $bankCard->bank_card_no ?? '', ]; } return $this->success([ 'user' => $userInfo, 'amount' => intval($prePayLog->amount / 100), ]); } public function recharge(RequestInterface $request) { [$app, $prePayLog] = $this->checkToken($request->input('stoken', '')); $name = $request->input('name'); if (empty($name)) { throw new BusinessException('请输入姓名'); } $amount = $request->input('amount'); if ($prePayLog->amount == 0) { $amount = $request->input('amount'); if (empty($amount)) { throw new BusinessException('请输入金额'); } if (!is_numeric($amount)) { throw new BusinessException('请输入金额'); } if ($amount <= 0) { throw new BusinessException('金额需大于0'); } } $cardNo = $request->input('cardNo'); if (empty($cardNo)) { throw new BusinessException('请输入身份证号'); } $mobile = $request->input('mobile'); if (empty($mobile)) { throw new BusinessException('请输入手机号'); } $bankCardNo = $request->input('bankCardNo'); if (empty($bankCardNo)) { throw new BusinessException('请输入银行卡号'); } $outMemberId = $prePayLog->out_member_id; $user = User::where('app_id', $app->app_id)->where('out_member_id', $outMemberId)->first(); $bankCard = null; if ($user) { $bankCard = BankCard::where('app_id', $app->app_id) ->where('out_member_id', $outMemberId) ->where('bank_card_no', $bankCardNo) ->where('status', BankCard::STATUS_ACTIVE)->first(); $mobile = $user->mobile; $cardNo = $user->cardNo; $name = $user->real_name; } if ($bankCard) { $outOrderNo = $prePayLog->out_order_no; $nextStep = 'confirm-pay'; $amount = $prePayLog->amount > 0 ? $prePayLog->amount : intval($amount * 100); $bizData = $this->paymentService->protocolPayPreRequest($this->buildPrepayParams($outMemberId, $outOrderNo, $bankCard->protocol, $amount, $prePayLog->notify_url, $app)); } else { $mchOrderNo = StringHelper::generateBankCardOrderNo(); $nextStep = 'confirm-bind'; $bizData = $this->paymentService->bindCard($this->buildBindCardParams( $mchOrderNo, $outMemberId, $name, $cardNo, $mobile, $bankCardNo, $app )); } return $this->success([ 'nextStep' => $nextStep, 'outMemberId' => $outMemberId, 'bizData' => $bizData ]); } public function confirmBindCard(RequestInterface $request) { [$app, $prePayLog] = $this->checkToken($request->input('stoken', '')); $smsNo = $request->input('smsNo'); $smsCode = $request->input('smsCode'); $bizData = $this->paymentService->bindCardConfirm($this->buildComfirmBindCardParams($prePayLog->out_member_id, $smsNo, $smsCode, $app)); return $this->success([ 'outMemberId' => $prePayLog->out_member_id, 'bizData' => $bizData ]); } public function confirmBindCardAndPay(RequestInterface $request) { [$app, $prePayLog] = $this->checkToken($request->input('stoken', '')); $amount = $request->input('amount'); if ($prePayLog->amount == 0) { $amount = $request->input('amount'); if (empty($amount)) { throw new BusinessException('请输入金额'); } if (!is_numeric($amount)) { throw new BusinessException('请输入金额'); } if ($amount <= 0) { throw new BusinessException('金额需大于0'); } } $outMemberId = $prePayLog->out_member_id; $outOrderNo = $prePayLog->out_order_no; $notifyUrl = $prePayLog->notify_url; $amount = $prePayLog->amount > 0 ? $prePayLog->amount : intval($amount * 100); $smsNo = $request->input('smsNo'); $smsCode = $request->input('smsCode'); $this->paymentService->protocolPayPreRequest($this->buildConfirmBindAndPay($outMemberId, $outOrderNo, $smsNo, $smsCode, $amount, $notifyUrl, $app)); return $this->success([ 'outMemberId' => $prePayLog->out_member_id, 'bizData' => ['outOrderNo' => $prePayLog->out_order_no] ]); } public function confirmPay(RequestInterface $request) { [$app, $prePayLog] = $this->checkToken($request->input('stoken', '')); $token = $request->input('token'); $protocol = $request->input('protocol'); $smsCode = $request->input('smsCode'); $this->paymentService->protocolPayConfirm($this->buildConfirmPayParams($token, $protocol, $smsCode, $app)); return $this->success([ 'outMemberId' => $prePayLog->out_member_id, 'bizData' => ['outOrderNo' => $prePayLog->out_order_no] ]); } private function buildBindCardParams($mchOrderNo, $outMemberId, $name, $cardNo, $mobile, $bankCardNo, $app) { $params = [ 'app_id' => $app->app_id, 'timestamp' => time(), 'nonce_str' => StringHelper::getRandomString(32), 'data' => json_encode([ 'mchtOrderNo' => $mchOrderNo, 'outMemberId' => $outMemberId, 'userName' => $name, 'phoneNum' => $mobile, 'bankCardNo' => $bankCardNo, 'bankCardType' => 'debit', 'certificatesNo' => $cardNo, ]), ]; $sign = \App\Helper\Platform\Signer::sign($params, $app->app_key); $params['sign'] = $sign; return $params; } private function buildPrepayParams($outMemberId, $outOrderNo, $protocol, $amount, $notifyUrl, $app) { $params = [ 'app_id' => $app->app_id, 'timestamp' => time(), 'nonce_str' => StringHelper::getRandomString(32), 'data' => json_encode([ 'outMemberId' => $outMemberId, 'outOrderNo' => $outOrderNo, 'protocol' => $protocol, 'payAmount' => $amount, 'notifyUrl' => $notifyUrl, ]), ]; $sign = \App\Helper\Platform\Signer::sign($params, $app->app_key); $params['sign'] = $sign; return $params; } private function buildConfirmBindAndPay($outMemberId, $outOrderNo, $smsNo, $smsCode, $amount, $notifyUrl, $app) { $params = [ 'app_id' => $app->app_id, 'timestamp' => time(), 'nonce_str' => StringHelper::getRandomString(32), 'data' => json_encode([ 'outMemberId' => $outMemberId, 'outOrderNo' => $outOrderNo, 'payAmount' => $amount, 'notifyUrl' => $notifyUrl, 'smsNo' => $smsNo, 'smsCode' => $smsCode, ]), ]; $sign = \App\Helper\Platform\Signer::sign($params, $app->app_key); $params['sign'] = $sign; return $params; } private function buildConfirmPayParams($token, $protocol, $smsCode, $app) { $params = [ 'app_id' => $app->app_id, 'timestamp' => time(), 'nonce_str' => StringHelper::getRandomString(32), 'data' => json_encode([ 'token' => $token, 'protocol' => $protocol, 'smsCode' => $smsCode, ]), ]; $sign = \App\Helper\Platform\Signer::sign($params, $app->app_key); $params['sign'] = $sign; return $params; } private function buildComfirmBindCardParams($outMemberId, $smsNo, $smsCode, $app) { $params = [ 'app_id' => $app->app_id, 'timestamp' => time(), 'nonce_str' => StringHelper::getRandomString(32), 'data' => json_encode([ 'outMemberId' => $outMemberId, 'smsNo' => $smsNo, 'smsCode' => $smsCode, ]), ]; $sign = \App\Helper\Platform\Signer::sign($params, $app->app_key); $params['sign'] = $sign; return $params; } public function orders(RequestInterface $request) { $page = $request->input('page', 1); $pageSize = $request->input('pageSize', 20); $status = $request->input('status', 0); $timeRange = $request->input('timeRange', null); $token = $request->input('token'); $mobile = $request->input('mobile', ''); $cardNo = $request->input('cardNo', ''); $orderNo = $request->input('orderNo', ''); $outOrderNo = $request->input('outOrderNo', ''); $bankCardNo = $request->input('bankCardNo', ''); $appId = Redis::get('token:' . $token); if (empty($appId)) { throw new UnauthorizedException(); } if ($appId == 'all') { $appIds = App::all()->pluck('app_id')->toArray(); } else { $appIds = explode(',', $appId); } $offset = ($page - 1) * $pageSize; $query = Order::query()->whereIn('app_id', $appIds); if ($status) { $query->where('status', $status); } if ($mobile) { $memberIds = User::whereIn('app_id', $appIds)->where('mobile', $mobile)->get(['member_id'])->pluck('member_id')->toArray(); $query->whereIn('member_id', $memberIds); } if ($cardNo) { $memberIds = User::whereIn('app_id', $appIds)->where('card_no', $cardNo)->get(['member_id'])->pluck('member_id')->toArray(); $query->whereIn('member_id', $memberIds); } if ($bankCardNo) { $protocols = BankCard::whereIn('app_id', $appIds)->where('bank_card_no', $bankCardNo)->get(['protocol'])->pluck('protocol')->toArray(); $query->whereIn('protocol', $protocols); } if ($orderNo) { $query->where('order_no', $orderNo); } if ($outOrderNo) { $query->where('out_order_no', $outOrderNo); } if ($timeRange) { $timeRange[0] .= ' 00:00:00'; $timeRange[1] .= ' 23:59:59'; $query->whereBetween('created_at', $timeRange); } $countQuery = clone $query; $sumQuery = clone $query; $orders = $query->orderBy('id', 'desc')->offset($offset)->limit($pageSize)->get(); $protocols = $orders->pluck('protocol'); $bankCards = BankCard::whereIn('app_id', $appIds)->whereIn('protocol', $protocols)->get(); $bankCards = $bankCards->keyBy('protocol'); $records = []; foreach ($orders as $order) { $bankCard = $order->protocol ? ($bankCards[$order->protocol] ?? null) : null; $records[] = [ 'out_order_no' => $order->out_order_no, 'payed_at' => $order->payed_at, 'status' => $order->status, 'amount' => number_format($order->amount / 100, 2, '.', ''), 'real_name' => $bankCard ? $bankCard->real_name : '', 'bank_card_no' => $bankCard ? $bankCard->bank_card_no : '', 'mobile' => $bankCard ? $bankCard->mobile : '', 'card_no' => $bankCard ? $bankCard->card_no : '', 'status_text' => $order->getStatusText(), ]; } $total = $countQuery->count(); $amount = $sumQuery->sum('amount'); return $this->success([ 'records' => $records, 'total' => $total, 'amount' => $amount / 100, ]); } public function login(RequestInterface $request) { $username = $request->input('username'); $password = $request->input('password'); if (empty($username) || empty($password)) { throw new BusinessException('账号或密码错误'); } $user = $this->getUser($username); if (!$user) { throw new BusinessException('账号或密码错误'); } if ($user['password'] !== $password) { throw new BusinessException('账号或密码错误'); } $token = md5(microtime() . $username . $password); Redis::set('token:' . $token, $user['app_id']); Redis::expire('token:' . $token, 60*60); return $this->success(['token' => $token]); } private function getUser($username) { $users = [ 'owx0tlx' => ['password' => 'lSoLW28NxtMlxUazC8p', 'app_id' => 'all'], 'ioexlp2' => ['password' => 'wwU8Ir3Xp0rxXssA9NV', 'app_id' => '202305270000001'], 'lix73nxIN' => ['password' => 'a01@lWl3dfNmT', 'app_id' => '202306140000001'], 'xtIxt2x3L' => ['password' => 'sd3@xxgNtxxJipOmT', 'app_id' => '202306200000001'], 'ni2Nx2M9T' => ['password' => 'x5sN!xlNoiQxpVbs', 'app_id' => '202306260000001'], 'Nx28OpjmL' => ['password' => 'xny3MU26MRxwqStM', 'app_id' => '202306260000002'], ]; return $users[$username] ?? null; } private function checkToken($token) { if (empty($token)) { throw new BusinessException('token异常'); } $log = PrePayLog::where('token', $token)->first(); if (empty($log)) { throw new BusinessException('预支付记录不存在'); } if ($log->created_at->timestamp < time() - 5*60) { throw new BusinessException('支付超时,请重新请求'); } $app = App::where('app_id', $log->app_id)->first(); if (empty($app)) { throw new BusinessException('应用异常'); } return [$app, $log]; } }