*/ protected $payments = []; /** * 支付 * * @param array $params * @param string|null $payment * @return array */ public function pay(array $params, ?string $payment = null): array { if (! isset($params['notify_url'])) { $params['notify_url'] = route('wxpay.paid_notify', ['payment' => $payment ?: 'default']); } if (! isset($params['trade_type'])) { $params['trade_type'] = WxpayTradeType::App->value; } $app = $this->payment($payment); // 服务商模式 (子商户) $appId = config('wechat.payment.sub.app_id'); $mchId = config('wechat.payment.sub.mch_id'); if ($appId && $mchId) { $params['sub_openid'] = Arr::pull($params, 'openid'); } $result = $app->order->unify($params); $this->validateResult($result, $params); return match ($params['trade_type']) { WxpayTradeType::App->value => $app->jssdk->appConfig($result['prepay_id']), WxpayTradeType::H5->value => Arr::only($result, ['mweb_url']), default => $app->jssdk->bridgeConfig($result['prepay_id'], false), }; } /** * 微信企业付款到零钱 * * @param array $params * @return array * @throws WeChatPayException */ public function transfer(array $params) { $config = config('wechat.payment.transfer'); $debug = config('app.debug'); if (!isset($params['openid']) && $debug) { $params['openid'] = 'oU7xS5UspzVvpPEBqKZuW6N9WXDg'; } if ($debug) { $params['amount'] = 100; } $app = Factory::payment($config); /* 'partner_trade_no' => '1233455', // 商户订单号,需保持唯一性(只能是字母或者数字,不能包含有符号) 'openid' => 'oxTWIuGaIt6gTKsQRLau2M0yL16E', 'check_name' => 'FORCE_CHECK', // NO_CHECK:不校验真实姓名, FORCE_CHECK:强校验真实姓名 're_user_name' => '王小帅', // 如果 check_name 设置为FORCE_CHECK,则必填用户真实姓名 'amount' => 10000, // 企业付款金额,单位为分 'desc' => '理赔', // 企业付款操作说明信息。必填 */ $result = $app->transfer->toBalance($params); $this->validateResult($result); return $result; } /** * 查询 微信企业付款到零钱 的订单 * * @param string $no 商户订单号 * @return array */ public function queryTransfer($no) { $config = config('wechat.payment.transfer'); $app = Factory::payment($config); $result = $app->transfer->queryBalanceOrder($no); $this->validateResult($result); return $result; } /** * 微信支付-单次分账 * * @param $order_sn string 商户订单号 * @param $share_sn string 分账订单号 * @param $receivers array 接收方{} * @return mixed */ public function share(string $order_sn, string $share_sn, array $receivers): mixed { $app = $this->payment(); // 服务商模式 (子商户) $appId = config('wechat.payment.sub.app_id'); $mchId = config('wechat.payment.sub.mch_id'); if ($appId && $mchId) { $app->setSubMerchant($mchId, $appId); } // 添加分账接收方 foreach ($receivers as $receiver) { $app->profit_sharing->addReceiver([ "type" => $receiver['type'], "account" => $receiver['account'], "relation_type" => "DISTRIBUTOR" ]); } $result = $app->profit_sharing->share($order_sn, $share_sn, $receivers); $this->validateResult($result); return $result; } /** * 微信支付-查询分账结果 * * @param string $transaction_id * @param string $share_sn * @return mixed */ public function queryShare(string $transaction_id, string $share_sn) { $app = $this->payment(); // 服务商模式 (子商户) $appId = config('wechat.payment.sub.app_id'); $mchId = config('wechat.payment.sub.mch_id'); if ($appId && $mchId) { $app->setSubMerchant($mchId, $appId); } return $app->profit_sharing->query($transaction_id, $share_sn); } /** * 微信支付-完结分账, 解冻订单剩余资金 * * @param string $transaction_id 微信支付流水号 * @param string $out_trade_sn 分账订单号, 自动生成 * @return mixed */ public function finishShare(string $transaction_id, string $out_trade_sn) { $app = $this->payment(); // 服务商模式 (子商户) $appId = config('wechat.payment.sub.app_id'); $mchId = config('wechat.payment.sub.mch_id'); if ($appId && $mchId) { $app->setSubMerchant($mchId, $appId); } return $app->profit_sharing->markOrderAsFinished([ 'transaction_id' => $transaction_id, 'out_order_no' => $out_trade_sn, 'description' => '订单分账完结, 解冻资金' ]); } /** * 根据商户订单号退款 * * @param string $number * @param string $refundNumber * @param int $totalFee * @param int $refundFee * @param array $optional * @return array */ public function refundByOutTradeNumber(array $params, ?string $payment = null) { $optional = Arr::get($params, 'optional', []); if (! is_array($optional)) { $optional = []; } if (! isset($optional['notify_url'])) { $path = route('wxpay.order_refund_notify', [ 'payment' => $payment ?: 'default', ], false); $optional['notify_url'] = url($path, [], true); } $result = $this->payment($payment)->refund->byOutTradeNumber( $params['number'], $params['refund_number'], $params['total_fee'], $params['refund_fee'], $optional, ); $this->validateResult($result, $params); return $result; } /** * @param string|null $name * @return \EasyWeChat\Payment\Application */ public function payment(?string $name = null): Application { $name = $name ?: 'default'; return $this->payments[$name] = $this->get($name); } /** * @param string $name * @return \EasyWeChat\Payment\Application */ protected function get(string $name): Application { return $this->payments[$name] ?? $this->resolve($name); } /** * @param string $name * @return \EasyWeChat\Payment\Application * * @throws \App\Exceptions\WeChatPayException */ protected function resolve(string $name): Application { $config = config("wechat.payment.{$name}"); if (empty($config)) { throw new WeChatPayException("支付 [{$name}] 配置未找到"); } $app = Factory::payment($config); // 服务商模式 (子商户) $appId = config('wechat.payment.sub.app_id'); $mchId = config('wechat.payment.sub.mch_id'); if ($appId && $mchId) { $app->setSubMerchant($mchId, $appId); } return $app; } /** * 校验响应结果 * * @param array $result * @param array $raw * @return void * * @throws \App\Exceptions\WeChatPayException */ protected function validateResult(array $result, array $raw = []) { if (Arr::get($result, 'return_code') !== 'SUCCESS') { throw new WeChatPayException(Arr::get($result, 'return_msg', '请求失败'), $raw); } if (Arr::get($result, 'result_code') !== 'SUCCESS') { throw new WeChatPayException(sprintf( '[%s] %s', Arr::get($result, 'err_code', '-1'), Arr::get($result, 'err_code_des', '交易失败') ), $raw); } } }