🐛 fix(payment): use native WeChat Pay QR data
This commit is contained in:
parent
e73df2d29b
commit
160e6da3f6
@ -276,6 +276,7 @@ const CheckoutForm: React.FC<Omit<StripePaymentProps, "publishable_key">> = ({
|
|||||||
const stripe = useStripe();
|
const stripe = useStripe();
|
||||||
const [errorMessage, setErrorMessage] = useState<string | null>(null);
|
const [errorMessage, setErrorMessage] = useState<string | null>(null);
|
||||||
const [qrCodeUrl, setQrCodeUrl] = useState<string | null>(null);
|
const [qrCodeUrl, setQrCodeUrl] = useState<string | null>(null);
|
||||||
|
const [qrCodeImageDataUrl, setQrCodeImageDataUrl] = useState<string | null>(null);
|
||||||
const [isSubmitted, setIsSubmitted] = useState(false);
|
const [isSubmitted, setIsSubmitted] = useState(false);
|
||||||
const { t } = useTranslation("payment");
|
const { t } = useTranslation("payment");
|
||||||
const qrCodeMap: Record<string, string> = {
|
const qrCodeMap: Record<string, string> = {
|
||||||
@ -328,12 +329,21 @@ const CheckoutForm: React.FC<Omit<StripePaymentProps, "publishable_key">> = ({
|
|||||||
|
|
||||||
if (paymentIntent?.status === "requires_action") {
|
if (paymentIntent?.status === "requires_action") {
|
||||||
const nextAction = paymentIntent.next_action as any;
|
const nextAction = paymentIntent.next_action as any;
|
||||||
const qrUrl =
|
// Stripe returns multiple WeChat QR-related fields.
|
||||||
method === "alipay"
|
// For native WeChat pay experience we should prefer the protocol data (weixin://...).
|
||||||
? nextAction?.alipay_handle_redirect?.url
|
// Fallback to the provided base64 image if present.
|
||||||
: nextAction?.wechat_pay_display_qr_code?.image_url_svg;
|
if (method === "alipay") {
|
||||||
|
const qrUrl = nextAction?.alipay_handle_redirect?.url;
|
||||||
|
setQrCodeUrl(qrUrl || null);
|
||||||
|
setQrCodeImageDataUrl(null);
|
||||||
|
} else {
|
||||||
|
const wechat = nextAction?.wechat_pay_display_qr_code;
|
||||||
|
const data = wechat?.data; // e.g. weixin://wxpay/bizpayurl?pr=...
|
||||||
|
const imageDataUrl = wechat?.image_data_url; // data:image/png;base64,...
|
||||||
|
|
||||||
setQrCodeUrl(qrUrl || null);
|
setQrCodeUrl(data || null);
|
||||||
|
setQrCodeImageDataUrl(!data ? imageDataUrl || null : null);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (_error) {
|
} catch (_error) {
|
||||||
handleError(t("stripe.error", "An error occurred"));
|
handleError(t("stripe.error", "An error occurred"));
|
||||||
@ -348,18 +358,26 @@ const CheckoutForm: React.FC<Omit<StripePaymentProps, "publishable_key">> = ({
|
|||||||
<div className="min-w-80 text-left">
|
<div className="min-w-80 text-left">
|
||||||
<CardPaymentForm clientSecret={client_secret} onError={handleError} />
|
<CardPaymentForm clientSecret={client_secret} onError={handleError} />
|
||||||
</div>
|
</div>
|
||||||
) : qrCodeUrl ? (
|
) : qrCodeUrl || qrCodeImageDataUrl ? (
|
||||||
<>
|
<>
|
||||||
<QRCodeCanvas
|
{qrCodeImageDataUrl ? (
|
||||||
imageSettings={{
|
<img
|
||||||
src: `./assets/payment/${method}.svg`,
|
alt={qrCodeMap[method] || t(`qrcode.${method}`, `Scan with ${method}`)}
|
||||||
width: 24,
|
className="mx-auto h-[208px] w-[208px]"
|
||||||
height: 24,
|
src={qrCodeImageDataUrl}
|
||||||
excavate: true,
|
/>
|
||||||
}}
|
) : (
|
||||||
size={208}
|
<QRCodeCanvas
|
||||||
value={qrCodeUrl}
|
imageSettings={{
|
||||||
/>
|
src: `./assets/payment/${method}.svg`,
|
||||||
|
width: 24,
|
||||||
|
height: 24,
|
||||||
|
excavate: true,
|
||||||
|
}}
|
||||||
|
size={208}
|
||||||
|
value={qrCodeUrl!}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
<p className="mt-4 text-center text-muted-foreground">
|
<p className="mt-4 text-center text-muted-foreground">
|
||||||
{qrCodeMap[method] || t(`qrcode.${method}`, `Scan with ${method}`)}
|
{qrCodeMap[method] || t(`qrcode.${method}`, `Scan with ${method}`)}
|
||||||
</p>
|
</p>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user