From d46793f072211805cc41b601d80c825e8731846e Mon Sep 17 00:00:00 2001 From: erio Date: Fri, 6 Mar 2026 18:04:11 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=94=AF=E4=BB=98=E5=AE=9D=E7=9B=B4?= =?UTF-8?q?=E8=BF=9E=20H5=20=E7=AB=AF=E4=BD=BF=E7=94=A8=20wap.pay=20?= =?UTF-8?q?=E5=94=A4=E8=B5=B7=E6=94=AF=E4=BB=98=E5=AE=9D=20APP?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 前端传递 is_mobile 参数,AlipayProvider 根据设备类型选择: - PC: alipay.trade.page.pay (FAST_INSTANT_TRADE_PAY) - H5: alipay.trade.wap.pay (QUICK_WAP_WAY) Co-Authored-By: Claude Opus 4.6 --- src/app/api/orders/route.ts | 4 +++- src/app/pay/page.tsx | 1 + src/lib/alipay/client.ts | 8 ++++---- src/lib/alipay/provider.ts | 6 +++++- src/lib/order/service.ts | 2 ++ src/lib/payment/types.ts | 2 ++ 6 files changed, 17 insertions(+), 6 deletions(-) diff --git a/src/app/api/orders/route.ts b/src/app/api/orders/route.ts index 25b3537..e0678d6 100644 --- a/src/app/api/orders/route.ts +++ b/src/app/api/orders/route.ts @@ -10,6 +10,7 @@ const createOrderSchema = z.object({ payment_type: z.string().min(1), src_host: z.string().max(253).optional(), src_url: z.string().max(2048).optional(), + is_mobile: z.boolean().optional(), }); export async function POST(request: NextRequest) { @@ -23,7 +24,7 @@ export async function POST(request: NextRequest) { return NextResponse.json({ error: '参数错误', details: parsed.error.flatten().fieldErrors }, { status: 400 }); } - const { user_id, amount, payment_type, src_host, src_url } = parsed.data; + const { user_id, amount, payment_type, src_host, src_url, is_mobile } = parsed.data; // Validate amount range if (amount < env.MIN_RECHARGE_AMOUNT || amount > env.MAX_RECHARGE_AMOUNT) { @@ -48,6 +49,7 @@ export async function POST(request: NextRequest) { clientIp, srcHost: src_host, srcUrl: src_url, + isMobile: is_mobile, }); // 不向客户端暴露 userName / userBalance 等隐私字段 diff --git a/src/app/pay/page.tsx b/src/app/pay/page.tsx index 24f6e85..60923ae 100644 --- a/src/app/pay/page.tsx +++ b/src/app/pay/page.tsx @@ -255,6 +255,7 @@ function PayContent() { payment_type: paymentType, src_host: srcHost, src_url: srcUrl, + is_mobile: isMobile, }), }); diff --git a/src/lib/alipay/client.ts b/src/lib/alipay/client.ts index 7004b9e..84039de 100644 --- a/src/lib/alipay/client.ts +++ b/src/lib/alipay/client.ts @@ -27,18 +27,18 @@ function assertAlipayEnv(env: ReturnType) { } /** - * 生成电脑网站支付的跳转 URL(GET 方式) - * 用于 alipay.trade.page.pay + * 生成支付宝网站/H5支付的跳转 URL(GET 方式) + * PC: alipay.trade.page.pay H5: alipay.trade.wap.pay */ export function pageExecute( bizContent: Record, - options?: { notifyUrl?: string; returnUrl?: string }, + options?: { notifyUrl?: string; returnUrl?: string; method?: string }, ): string { const env = assertAlipayEnv(getEnv()); const params: Record = { ...getCommonParams(env.ALIPAY_APP_ID), - method: 'alipay.trade.page.pay', + method: options?.method || 'alipay.trade.page.pay', biz_content: JSON.stringify(bizContent), }; diff --git a/src/lib/alipay/provider.ts b/src/lib/alipay/provider.ts index ddacf53..4f97f00 100644 --- a/src/lib/alipay/provider.ts +++ b/src/lib/alipay/provider.ts @@ -22,16 +22,20 @@ export class AlipayProvider implements PaymentProvider { }; async createPayment(request: CreatePaymentRequest): Promise { + const method = request.isMobile ? 'alipay.trade.wap.pay' : 'alipay.trade.page.pay'; + const productCode = request.isMobile ? 'QUICK_WAP_WAY' : 'FAST_INSTANT_TRADE_PAY'; + const url = pageExecute( { out_trade_no: request.orderId, - product_code: 'FAST_INSTANT_TRADE_PAY', + product_code: productCode, total_amount: request.amount.toFixed(2), subject: request.subject, }, { notifyUrl: request.notifyUrl, returnUrl: request.returnUrl, + method, }, ); diff --git a/src/lib/order/service.ts b/src/lib/order/service.ts index c4e4ae6..3ccd7e8 100644 --- a/src/lib/order/service.ts +++ b/src/lib/order/service.ts @@ -19,6 +19,7 @@ export interface CreateOrderInput { clientIp: string; srcHost?: string; srcUrl?: string; + isMobile?: boolean; } export interface CreateOrderResult { @@ -134,6 +135,7 @@ export async function createOrder(input: CreateOrderInput): Promise