小程序支付

This commit is contained in:
liu
2026-09-03 20:36:09 +08:00
parent d190bdaade
commit 1370926780
7 changed files with 874 additions and 21 deletions
@@ -6,6 +6,7 @@ use App\Exceptions\RepositoryException;
use App\Models\PaymentModel;
use App\Services\OnlinePaymentService;
use App\Services\WangpuPayService;
use App\Services\WechatPayService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
@@ -15,11 +16,11 @@ use Modules\AnnoRoute\Attribute\RequestAttribute;
use Throwable;
/**
* 小程序在线支付(旺铺网关 JSAPI)
* 小程序在线支付(渠道二选一:旺铺网关 JSAPI / 微信官方支付 APIv3
*
* 链路:POST /mini/payment/online 下单(返回调起支付参数)
* → 小程序 wx.requestPayment 完成支付
* → 网关 POST /mini/payment/notify 后台通知(验签 + 幂等结账
* → 渠道后台通知(旺铺 /mini/payment/notify;微信 /mini/payment/wechat-notify验签 + 幂等结账
* → 小程序 GET /mini/payment/online/{paymentNo}/query 主动同步支付结果(回调兜底)
*/
#[RequestAttribute('/mini', 'mini', authGuard: 'users')]
@@ -28,6 +29,7 @@ class OnlinePaymentController extends BaseMiniController
public function __construct(
protected OnlinePaymentService $onlinePayment,
protected WangpuPayService $wangpu,
protected WechatPayService $wxpay,
) {}
/**
@@ -123,6 +125,43 @@ class OnlinePaymentController extends BaseMiniController
return $this->notifyAck(WangpuPayService::NOTIFY_ACK_OK, '成功');
}
/**
* 微信支付结果后台通知(公开路由,验签 + AES-GCM 解密后幂等结账)
*
* 应答 {"code":"SUCCESS","message":"成功"} 视为通知成功,否则微信按阶梯间隔重推;
* 重复通知必须幂等(settle 内部行锁 + 状态判断)。
*/
#[PostRoute('/payment/wechat-notify', authorize: false)]
public function wechatNotify(Request $request): JsonResponse
{
try {
$params = $this->wxpay->decryptNotify($request);
} catch (Throwable $e) {
Log::warning('微信支付通知验签/解密失败', ['error' => $e->getMessage()]);
return $this->wechatNotifyAck(WechatPayService::NOTIFY_ACK_FAIL, '报文验签解密失败');
}
try {
$this->onlinePayment->settleByWechatNotify($params);
} catch (Throwable $e) {
Log::error('微信支付通知处理失败', ['params' => $params, 'error' => $e->getMessage()]);
return $this->wechatNotifyAck(WechatPayService::NOTIFY_ACK_FAIL, $e->getMessage());
}
return $this->wechatNotifyAck(WechatPayService::NOTIFY_ACK_OK, '成功');
}
/**
* 微信通知应答报文(微信约定格式)
*/
protected function wechatNotifyAck(string $code, string $msg): JsonResponse
{
return response()->json([
'code' => $code,
'message' => mb_substr($msg, 0, 64),
], $code === WechatPayService::NOTIFY_ACK_OK ? 200 : 500);
}
/**
* 通知应答报文(网关约定格式,timestampyyyyMMddHHmmssSSS
*/