core_pay_service = new CorePayService(); } /** * 去支付 * @param string $type * @param string $trade_type * @param int $trade_id * @param string $return_url * @param string $quit_url * @param string $buyer_id * @return mixed * @throws DataNotFoundException * @throws DbException * @throws ModelNotFoundException */ public function pay(string $type, string $trade_type, int $trade_id, string $return_url = '', string $quit_url = '', string $buyer_id = '', string $voucher = '', string $openid = ''){ $member = (new CoreMemberService())->getInfoByMemberId($this->member_id); switch ($this->channel) { case ChannelDict::WECHAT://公众号 $openid = $openid ? $openid : $member['wx_openid'] ?? ''; break; case ChannelDict::WEAPP://微信小程序 $openid = $openid ? $openid : $member['weapp_openid'] ?? ''; break; } return $this->core_pay_service->pay($trade_type, $trade_id, $type, $this->channel, $openid, $return_url, $quit_url, $buyer_id, $voucher, $this->member_id); } /** * 关闭支付 * @param string $type * @param string $out_trade_no * @return null */ public function close(string $type, string $out_trade_no){ return $this->core_pay_service->close($out_trade_no); } /** * 支付异步通知 * @param string $channel * @param string $type * @param string $action * @return void|null */ public function notify(string $channel, string $type, string $action){ return $this->core_pay_service->notify($channel, $type, $action); } /** * 通过交易流水号查询支付信息以及支付方式 * @param $out_trade_no * @return array */ public function getInfoByOutTradeNo($out_trade_no){ return $this->core_pay_service->getInfoByOutTradeNo($out_trade_no, $this->channel); } public function getInfoByTrade(string $trade_type, int $trade_id, array $data){ return $this->core_pay_service->getInfoByTrade($trade_type, $trade_id, $this->channel, $data['scene']); } /** * 获取找朋友帮忙付支付信息 * @param string $trade_type * @param int $trade_id * @return array */ public function getFriendspayInfoByTrade($trade_type, $trade_id){ $from_pay_info = ( new Pay() )->field('id')->where([ [ 'trade_type', '=', $trade_type ], [ 'trade_id', '=', $trade_id ] ])->findOrEmpty()->toArray();//查询发起交易所属的站点id if (empty($from_pay_info)) throw new ApiException('TRADE_NOT_EXIST'); $pay_info = $this->core_pay_service->getInfoByTrade($trade_type, $trade_id, $this->channel, PaySceneDict::FRIENDSPAY); if (!empty($pay_info)) { //todo 查询订单交易信息,其它插件可实现该钩子 $trade_info = array_values(array_filter(event('PayTradeInfo',[ 'trade_type' => $trade_type, 'trade_id' => $trade_id ])))[0] ?? []; $pay_info['trade_info'] = $trade_info; if ($pay_info['from_main_id'] != $this->member_id) { $pay_info['is_self'] = false; } else { $pay_info['is_self'] = true; } //海报 $poster = ( new Poster() )->field('id')->where([ [ 'type', '=', 'friendspay' ], [ 'status', '=', 1 ], [ 'is_default', '=', 1 ] ])->findOrEmpty()->toArray(); if (!empty($poster)) { $pay_info['poster_id'] = $poster['id']; } //发起帮付会员信息 $member = ( new Member() )->field('member_id,nickname,headimg')->where([ [ 'member_id', '=', $pay_info['from_main_id'] ] ])->findOrEmpty()->toArray(); $pay_info['member'] = $member; } return $pay_info; } /** * 获取支付方法 * @param string $trade_type * @return array|array[] * @throws DataNotFoundException * @throws DbException * @throws ModelNotFoundException */ public function getPayTypeByTrade(string $trade_type){ return $this->core_pay_service->getPayTypeByTrade($trade_type, $this->channel); } /** * 二维码支付回调 */ public function qrcodeNotify($data,$order_id) { Log::debug('qrcodeNotify',$data); $order = new OrderTable(); $order_info = $order->where(['id' => $order_id])->find(); if($order_info['order_status'] == 'pending' and !empty($order_info['ipv3'])){ $resource = $data['resource']; $decrypted = decryptWechatPayNotify( $resource['ciphertext'], $resource['nonce'], $resource['associated_data'], $order_info['ipv3'] ); $info = json_decode($decrypted, true); $order->where(['payment_id' => $info['out_trade_no']]) ->update(['order_status' => 'paid','payment_time' => date("Y-m-d H:i:s")]); $payModel = new Pay(); $payModel->where(['trade_id' => $order_id])->update([ 'status' => 2, 'pay_time' => time() ]); (new OrderTableService())->handlePaymentSuccess($order_info->toArray()); } } /** * 小程序支付(绕过 CorePayService,直接使用 return_pay_config) * @param array $data * @return array * @throws \Exception */ public function weappPay(array $data) { $order_id = $data['order_id']; $openid = $data['openid']; // 获取订单信息 $order = new OrderTable(); $order_info = $order->where(['id' => $order_id])->find(); if (!$order_info) { throw new \Exception('订单不存在'); } if ($order_info['order_status'] != 'pending') { throw new \Exception('订单状态不正确'); } // 获取校区支付配置 $config = return_pay_config($order_info['campus_id'], $order_id); // 生成支付流水号 $out_trade_no = 'WEAPP' . date("YmdHis") . $order_id; // 构建支付参数 $params = [ 'out_trade_no' => $out_trade_no, 'body' => '订单支付:' . $out_trade_no, 'money' => $order_info['order_amount'] * 100, // 转换为分 'openid' => $openid ]; // 使用 PayLoader 调用微信小程序支付 $pay = new \core\pay\PayLoader('Wechatpay', $config); $result = $pay->mini($params); // 更新订单支付流水号和密钥 $order->where(['id' => $order_id])->update([ 'payment_id' => $out_trade_no, 'ipv3' => $config['mch_secret_key'] ]); // 记录支付信息到 pay 表 $payModel = new Pay(); $payModel->insert([ 'main_id' => $order_info['student_id'], 'from_main_id' => $order_info['student_id'], 'out_trade_no' => $out_trade_no, 'trade_type' => 'school_order_table', 'trade_id' => $order_id, 'trade_no' => $out_trade_no, 'body' => '小程序支付', 'money' => $order_info['order_amount'], 'status' => 1, // 支付中 'create_time' => time(), 'type' => 'wechatpay', 'main_type' => 'wechatpay', 'channel' => 'weapp' ]); return $result; } /** * 小程序支付回调处理 * @param array $data * @param int $order_id * @return void */ public function weappNotify($data, $order_id) { Log::debug('weappNotify', $data); $order = new OrderTable(); $order_info = $order->where(['id' => $order_id])->find(); if (!$order_info) { Log::error('订单不存在: ' . $order_id); return; } if ($order_info['order_status'] == 'pending' && !empty($order_info['ipv3'])) { $resource = $data['resource']; // 解密微信支付回调数据 $decrypted = decryptWechatPayNotify( $resource['ciphertext'], $resource['nonce'], $resource['associated_data'], $order_info['ipv3'] ); $info = json_decode($decrypted, true); Log::info('小程序支付回调解密数据', $info); // 更新订单状态 $order->where(['payment_id' => $info['out_trade_no']]) ->update([ 'order_status' => 'paid', 'payment_time' => date("Y-m-d H:i:s") ]); // 更新支付记录状态 $payModel = new Pay(); $payModel->where(['trade_id' => $order_id])->update([ 'status' => 2, // 已支付 'pay_time' => time() ]); // 处理支付成功后的业务逻辑 (new OrderTableService())->handlePaymentSuccess($order_info->toArray()); Log::info('小程序支付成功处理完成: 订单ID ' . $order_id); } } }