terminal = $terminal; $this->config = WeChatConfigService::getPayConfigByTerminal($terminal); $this->app = new Application($this->config); if ($userId !== null) { $this->auth = UserAuth::where(['user_id' => $userId, 'terminal' => $terminal])->findOrEmpty(); } } /** * @notes 发起微信支付统一下单 * @param $from * @param $order * @return array|false|string * @author 段誉 * @date 2021/8/4 15:05 */ public function pay($order_type,$from, $order) { try { switch ($this->terminal) { case UserTerminalEnum::WECHAT_MMP: $config = WeChatConfigService::getMnpConfig(); $result = $this->jsapiPay($order_type,$from, $order, $config['app_id']); break; case UserTerminalEnum::WECHAT_OA: $config = WeChatConfigService::getOaConfig(); $result = $this->jsapiPay($from, $order, $config['app_id']); break; case UserTerminalEnum::IOS: case UserTerminalEnum::ANDROID: $config = WeChatConfigService::getOpConfig(); $result = $this->appPay($from, $order, $config['app_id']); break; case UserTerminalEnum::H5: $config = WeChatConfigService::getOaConfig(); $result = $this->mwebPay($from, $order, $config['app_id']); break; case UserTerminalEnum::PC: $config = WeChatConfigService::getOaConfig(); $result = $this->nativePay($from, $order, $config['app_id']); break; default: throw new \Exception('支付方式错误'); } return [ 'config' => $result, 'pay_way' => PayEnum::WECHAT_PAY ]; } catch (\Exception $e) { $this->setError($e->getMessage()); return false; } } /** * @notes jsapiPay * @param $from * @param $order * @param $appId * @return mixed * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException * @author 段誉 * @date 2023/2/28 12:12 */ public function jsapiPay($order_type,$from, $order, $appId) { $response = $this->app->getClient()->postJson("v3/pay/transactions/jsapi", [ "appid" => $appId, "mchid" => $this->config['mch_id'], "description" => $this->payDesc($from), "out_trade_no" => $order['pay_sn'], "notify_url" => $this->config['notify_url'], "amount" => [ "total" => intval($order['order_amount'] * 100), ], "payer" => [ "openid" => $this->auth['openid'] ], 'attach' => json_encode([ 'order_type' => $order_type, 'from' => $from ]) ]); $result = $response->toArray(false); $this->checkResultFail($result); return $this->getPrepayConfig($result['prepay_id'], $appId); } /** * @notes 网站native * @param $from * @param $order * @param $appId * @return mixed * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException * @author 段誉 * @date 2023/2/28 12:12 */ public function nativePay($from, $order, $appId) { $response = $this->app->getClient()->postJson('v3/pay/transactions/native', [ 'appid' => $appId, 'mchid' => $this->config['mch_id'], 'description' => $this->payDesc($from), 'out_trade_no' => $order['pay_sn'], 'notify_url' => $this->config['notify_url'], 'amount' => [ 'total' => intval($order['order_amount'] * 100), ], 'attach' => $from ]); $result = $response->toArray(false); $this->checkResultFail($result); return $result['code_url']; } /** * @notes appPay * @param $from * @param $order * @param $appId * @return mixed * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException * @author 段誉 * @date 2023/2/28 12:12 */ public function appPay($from, $order, $appId) { $response = $this->app->getClient()->postJson('v3/pay/transactions/app', [ 'appid' => $appId, 'mchid' => $this->config['mch_id'], 'description' => $this->payDesc($from), 'out_trade_no' => $order['pay_sn'], 'notify_url' => $this->config['notify_url'], 'amount' => [ 'total' => intval($order['order_amount'] * 100), ], 'attach' => $from ]); $result = $response->toArray(false); $this->checkResultFail($result); return $result['prepay_id']; } /** * @notes h5 * @param $from * @param $order * @param $appId * @param $redirectUrl * @return mixed * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException * @author 段誉 * @date 2023/2/28 12:13 */ public function mwebPay($from, $order, $appId) { $ip = request()->ip(); if (!empty(env('project.test_web_ip')) && env('APP_DEBUG')) { $ip = env('project.test_web_ip'); } $response = $this->app->getClient()->postJson('v3/pay/transactions/h5', [ 'appid' => $appId, 'mchid' => $this->config['mch_id'], 'description' => $this->payDesc($from), 'out_trade_no' => $order['pay_sn'], 'notify_url' => $this->config['notify_url'], 'amount' => [ 'total' => intval(strval($order['order_amount'] * 100)), ], 'attach' => $from, 'scene_info' => [ 'payer_client_ip' => $ip, 'h5_info' => [ 'type' => 'Wap', ] ] ]); $result = $response->toArray(false); $this->checkResultFail($result); $domain = request()->domain(); if (!empty(env('project.test_web_domain')) && env('APP_DEBUG')) { $domain = env('project.test_web_domain'); } $redirectUrl = $domain . '/mobile'. $order['redirect_url'] .'?id=' . $order['id'] . '&from='. $from . '&checkPay=true'; return $result['h5_url'] . '&redirect_url=' . urlencode($redirectUrl); } /** * @notes 退款 * @param array $refundData * @return mixed * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException * @author 段誉 * @date 2023/2/28 16:53 */ public function refund(array $refundData) { $response = $this->app->getClient()->postJson('v3/refund/domestic/refunds', [ 'transaction_id' => $refundData['transaction_id'], 'out_refund_no' => $refundData['refund_sn'], "notify_url" =>$refundData['notify_url'], 'amount' => [ 'refund' => intval($refundData['total_amount'] * 100), 'total' => intval($refundData['total_amount'] * 100), 'currency' => 'CNY', ] ]); $result = $response->toArray(false); $this->checkResultFail($result); return $result; } /** * @notes 查询退款 * @param $refundSn * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException * @author 段誉 * @date 2023/3/1 11:16 */ public function queryRefund($refundSn) { $response = $this->app->getClient()->get("v3/refund/domestic/refunds/{$refundSn}"); return $response->toArray(false); } /** * @notes 支付描述 * @param $from * @return string * @author 段誉 * @date 2023/2/27 17:54 */ public function payDesc($from) { $desc = [ 'order' => '商品', 'recharge' => '充值', ]; return $desc[$from] ?? '商品'; } /** * @notes 捕获错误 * @param $result * @throws \Exception * @author 段誉 * @date 2023/2/28 12:09 */ public function checkResultFail($result) { if (!empty($result['code']) || !empty($result['message'])) { throw new \Exception('微信:'. $result['code'] . '-' . $result['message']); } } /** * @notes 预支付配置 * @param $prepayId * @param $appId * @return mixed[] * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException * @author 段誉 * @date 2023/2/28 17:38 */ public function getPrepayConfig($prepayId, $appId) { return $this->app->getUtils()->buildBridgeConfig($prepayId, $appId); } public function notifyRefundMnp(){ return true; } /** * @notes 支付回调 * @return \Psr\Http\Message\ResponseInterface * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException * @throws \EasyWeChat\Kernel\Exceptions\RuntimeException * @throws \ReflectionException * @throws \Throwable * @author 段誉 * @date 2023/2/28 14:20 */ public function notify() { $server = $this->app->getServer(); // 支付通知 Log::write("支付日志",'2222222222222222222222222222222'); $server->handlePaid(function (Message $message) { if ($message['trade_state'] === 'SUCCESS') { $extra['transaction_id'] = $message['transaction_id']; $attach = json_decode($message['attach'],true); $message['out_trade_no'] = mb_substr($message['out_trade_no'], 0, 18); switch ($attach['from']) { case 'recharge': $order = RechargeOrder::where(['order_sn' => $message['out_trade_no']])->findOrEmpty(); if($order->isEmpty() || $order->pay_status == PayEnum::ISPAID) { return true; } PayNotifyLogic::handle('recharge', $message['out_trade_no'], $extra); break; case 'wx': $name = ""; if($attach['order_type'] == 0){ $order = Order::where("order_sn",$message['out_trade_no'])->findOrEmpty(); $name = "order"; }elseif($attach['order_type'] == 1){ $order = OrderStore::where("order_sn",$message['out_trade_no'])->findOrEmpty(); $name = "orderStore"; }elseif($attach['order_type'] == 2) { $order = OrderGroup::where("order_sn", $message['out_trade_no'])->findOrEmpty(); $name = "orderGroup"; }elseif($attach['order_type'] == 3){ $order = OrderMember::where("order_sn", $message['out_trade_no'])->findOrEmpty(); $name = "orderMember"; }elseif($attach['order_type'] == 7){ $order = OrderStoreRenew::where("order_sn", $message['out_trade_no'])->findOrEmpty(); $name = "orderStoreRenew"; }elseif($attach['order_type'] == 9){ $order = OrderStoreRecharge::where("order_sn", $message['out_trade_no'])->findOrEmpty(); $name = "OrderStoreRecharge"; }elseif($attach['order_type'] == 10){ $order = OrderTeamaster::where("order_sn", $message['out_trade_no'])->findOrEmpty(); $name = "orderTeamaster"; }elseif($attach['order_type'] == 11){ Log::write("支付日志",'33333333'); $order = OrderTeamasterRenew::where("order_sn", $message['out_trade_no'])->findOrEmpty(); $name = "orderTeamaRenw"; } if($order->isEmpty() || $order->pay_status == PayEnum::ISPAID) { return true; } if($name != ""){ PayNotifyLogic::handle($name, $message['out_trade_no'], $extra); } break; } } return true; }); // 退款通知 $server->handleRefunded(function (Message $message) { if($message['refund_status']=='SUCCESS'){ Log::write("回调参数",json_encode($message['out_trade_no'])); $message['out_trade_no'] = mb_substr($message['out_trade_no'], 0, 18); $extra['transaction_id'] = $message['transaction_id']; $refund_record = RefundRecord::where("source_sn",$message['out_trade_no'])->find(); if($refund_record['order_type'] == 5){ $order = OrderGroup::where("order_sn",$refund_record['source_sn'])->findOrEmpty(); $name = "refundOrderGroup"; } if($refund_record['order_type'] == 1){ $order = OrderStore::where("order_sn",$refund_record['source_sn'])->findOrEmpty(); $name = "refundOrderStore"; }if($refund_record['order_type'] == 10){ $order = OrderTeamaster::where("order_sn",$refund_record['source_sn'])->findOrEmpty(); $name = "teamasterOrderRefund"; } if($order->isEmpty() || $order->pay_status == 6) { return true; } if($name != ""){ PayNotifyLogic::handle($name, $message['out_trade_no'], $extra); } } return true; }); return $server->serve(); } }