6
0
Fork 0
jiqu-library-server/app/Services/Payment/WxpayService.php

169 lines
4.4 KiB
PHP

<?php
namespace App\Services\Payment;
use App\Enums\WxpayTradeType;
use App\Exceptions\WeChatPayException;
use EasyWeChat\Factory;
use EasyWeChat\Payment\Application;
use Illuminate\Support\Arr;
class WxpayService
{
/**
* @var array<string, \EasyWeChat\Payment\Application>
*/
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'])) {
$path = route('wxpay.paid_notify', ['payment' => $payment ?: 'default'], false);
$params['notify_url'] = url($path, [], true);
}
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 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) {
$params['sub_openid'] = Arr::pull($params, 'openid');
$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);
}
}
}