feat: integrate Stripe payment with bugfixes and active timeout cancellation
- Add Stripe payment provider with Checkout Session flow - Payment provider abstraction layer (EasyPay + Stripe unified interface) - Stripe webhook with proper raw body handling and signature verification - Frontend: Stripe button with URL validation, anti-duplicate click, noopener - Active timeout cancellation: query platform before expiring, recover paid orders - Singleton Stripe client, idempotency keys, Math.round for amounts - Handle async_payment events, return null for unknown webhook events - Set Checkout Session expires_at aligned with order timeout - Add cancelPayment to provider interface (Stripe: sessions.expire, EasyPay: no-op) - Enable stripe in frontend payment type list
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
'use client';
|
||||
|
||||
import { useSearchParams } from 'next/navigation';
|
||||
import { useState, useEffect, Suspense, useMemo } from 'react';
|
||||
import { useState, useEffect, Suspense } from 'react';
|
||||
import PaymentForm from '@/components/PaymentForm';
|
||||
import PaymentQRCode from '@/components/PaymentQRCode';
|
||||
import OrderStatus from '@/components/OrderStatus';
|
||||
@@ -13,9 +13,10 @@ interface OrderResult {
|
||||
orderId: string;
|
||||
amount: number;
|
||||
status: string;
|
||||
paymentType: 'alipay' | 'wxpay';
|
||||
paymentType: 'alipay' | 'wxpay' | 'stripe';
|
||||
payUrl?: string | null;
|
||||
qrCode?: string | null;
|
||||
checkoutUrl?: string | null;
|
||||
expiresAt: string;
|
||||
}
|
||||
|
||||
@@ -47,7 +48,7 @@ function PayContent() {
|
||||
const [activeMobileTab, setActiveMobileTab] = useState<'pay' | 'orders'>('pay');
|
||||
|
||||
const [config] = useState<AppConfig>({
|
||||
enabledPaymentTypes: ['alipay', 'wxpay'],
|
||||
enabledPaymentTypes: ['alipay', 'wxpay', 'stripe'],
|
||||
minAmount: 1,
|
||||
maxAmount: 10000,
|
||||
});
|
||||
@@ -185,6 +186,7 @@ function PayContent() {
|
||||
paymentType: data.paymentType || paymentType,
|
||||
payUrl: data.payUrl,
|
||||
qrCode: data.qrCode,
|
||||
checkoutUrl: data.checkoutUrl,
|
||||
expiresAt: data.expiresAt,
|
||||
});
|
||||
|
||||
@@ -385,6 +387,7 @@ function PayContent() {
|
||||
orderId={orderResult.orderId}
|
||||
payUrl={orderResult.payUrl}
|
||||
qrCode={orderResult.qrCode}
|
||||
checkoutUrl={orderResult.checkoutUrl}
|
||||
paymentType={orderResult.paymentType}
|
||||
amount={orderResult.amount}
|
||||
expiresAt={orderResult.expiresAt}
|
||||
|
||||
Reference in New Issue
Block a user