"use client"; import clsx from "clsx"; import Image from "next/image"; import { use,useState,useCallback } from "react"; import { useForm, get, useWatch } from "react-hook-form"; import { useRouter } from 'next/navigation' import { useCustomToast } from "@/utils/hooks/useToast"; import AirwallexCardInput from "../PaymentMethodAdditional/AirwallexCardInput"; import { airwallexManager, useAirwallexCardState } from "@/lib/Airwallex/useAirwallexCard"; import {RepayOrderPaymentMethodsData} from "@/types/checkout/type"; import { OrderDetails } from "@/types/customer/type"; import {FetchGraphqlResult} from "@/types/graphqlFetch/type"; import { usePlaceOrder } from "@/utils/hooks/usePlaceOrder"; import PaypalButton from "../PaymentButton/PaypalButton"; import { overlayLoading } from "@/components/theme/ui/kernel/loading/api"; import { confirmDialog } from "@/components/theme/ui/kernel/confirm/api"; import PaypalApplepayButton from "../PaymentButton/PaypalApplepayButton"; import KlarnaButton from "../PaymentButton/KlarnaButton"; import {getAddressFromOrderDetailAddressList} from "@/utils/orderDetailTools"; import { useConfig } from '@utils/hooks/useConfig'; import {usePaymentSDKContext} from "@/providers/PaymentSDKProvider"; /**@todo 优化目标:不使用 react-hook-form */ export function PaymentMethodContinueTpPay({ paymentMethodsDataPromise, defaultPaymentMethod, orderId, orderDetail }: { paymentMethodsDataPromise: Promise>; defaultPaymentMethod: {method: string; methodTitle: string;} orderId: number; orderDetail: OrderDetails; }) { const router = useRouter(); const { showToast } = useCustomToast(); const paymentMethodsData = use(paymentMethodsDataPromise); const paymentMethods = paymentMethodsData.data?.collectionRepayOrderPaymentMethods || []; const { paymentRepay, createPaymentCallback } = usePlaceOrder(); const {loadSdk} = usePaymentSDKContext(); const {store,currencies} = useConfig(); const currentCurrencyCode = store.currentCurrency; const orderCurrency = currencies.find(item => item.code === orderDetail.orderCurrencyCode) || null; const orderCurrencyCode = orderCurrency?.code || currentCurrencyCode; const airwallexCardState = useAirwallexCardState(); const [isPay, setIsPay] = useState(false); const shippingContact = getAddressFromOrderDetailAddressList(orderDetail.addresses,"order_shipping"); const billingContact = getAddressFromOrderDetailAddressList(orderDetail.addresses,"order_billing"); const { register, // watch, control, formState: { errors } } = useForm({ mode: "onChange", reValidateMode: "onChange", defaultValues:{ paymentMethod: defaultPaymentMethod.method } }); // 参考 https://github.com/react-hook-form/error-message/blob/master/src/ErrorMessage.tsx const paymentMethodError = get(errors, "paymentMethod"); // react 19中使用watch 会提示React Hook Form's `useForm()` API returns a `watch()` function which cannot be memoized safely. // const selectedPaymentMethod = watch("paymentMethod"); const selectedPaymentMethod = useWatch({ control, name:"paymentMethod", }); const paypalRepayOrder = async () => { overlayLoading.start(); const res = await paymentRepay({ orderId: Number(orderId), paymentMethod: selectedPaymentMethod }); overlayLoading.stop(); if(!res.error && res.data !== null) { return { error: false, msg: '', orderId: res.data.gatewayOrderId, webOrderId: res.data.orderId }; } else { confirmDialog({ title: "Warning", content: res.msg + " Create order failed. Please try again.", noCancel: true, }).then(() => {}); return { error: true, msg: '', orderId: '', webOrderId: '' }; } }; const airwallexRepay = async () => { setIsPay(true); overlayLoading.start(); const res = await paymentRepay({ orderId: Number(orderId), paymentMethod: selectedPaymentMethod, paymentSuccessUrl: window.location.origin + '/paymentresult/result' }); if(!res.error && res.data !== null) { // 创建订单成功了,跳转支付页面 window.location.href = res.data.gatewayOrderId; } else { //创建订单出错了 overlayLoading.stop(); confirmDialog({ title: "Warning", content: res.msg + " Create order failed. Please try again.", noCancel: true, }).then(() => {}); } setIsPay(false); }; const validateAirwallexCard = () => { const res = airwallexManager.validateCard(); if(res.msg) { showToast(res.msg, 'danger'); } return res.valid; }; const cardAirwallexRepay = async () => { setIsPay(true); overlayLoading.start(); const validRes = validateAirwallexCard(); if(validRes) { const res = await paymentRepay({ orderId: Number(orderId), paymentMethod: selectedPaymentMethod, }); if(!res.error && res.data !== null) { // 创建订单成功 const cardNumberElement = airwallexManager.getCardNumberElement(); const paymentIntentIdClientSecret = res.data.gatewayOrderId.split(':'); const paymentIntentId = paymentIntentIdClientSecret[0]; const paymentIntentClientSecret = paymentIntentIdClientSecret[1]; cardNumberElement?.confirm({ intent_id: paymentIntentId, client_secret: paymentIntentClientSecret, }).then((result) => { overlayLoading.stop(); console.log('cardNumberElement.confirm result ---- ', result); // 支付成功 跳转页面 router.replace('/paymentresult/result?orderId=' + orderId + '&return_result=success'); }).catch((error) => { overlayLoading.stop(); console.log('cardNumberElement.confirm error ---- ', error); // 支付失败 router.replace('/paymentresult/result?orderId=' + orderId + '&return_result=failure'); }); } else { //创建订单出错了 overlayLoading.stop(); confirmDialog({ title: "Warning", content: res.msg + " Create order failed. Please try again.", noCancel: true, }).then(() => {}); } }else { overlayLoading.stop(); } setIsPay(false); }; const afterpayPlaceOrder = async () => { setIsPay(true); overlayLoading.start(); if(window.AfterPay) { const res = await paymentRepay({ orderId: Number(orderId), paymentMethod: selectedPaymentMethod, paymentSuccessUrl: window.location.origin + '/paymentresult/result', paymentCancelUrl: window.location.origin + '/paymentresult/result' }); if(!res.error && res.data !== null) { const afterpayToken = res.data.gatewayOrderId; const webOrderId = res.data.orderId; let countryCode = "US"; if(orderCurrencyCode === "CAD") { countryCode = "CA"; } else if(orderCurrencyCode === "AUD") { countryCode = "AU"; } else if(orderCurrencyCode === "NZD") { countryCode = "NZ"; } else if(orderCurrencyCode === "GBP") { countryCode = "GB"; } window.AfterPay.initialize({countryCode: countryCode}); // To avoid triggering browser anti-popup rules, the AfterPay.open() // function must be directly called inside the click event listener window.AfterPay.open(); // If you don't already have a checkout token at this point, you can // AJAX to your backend to retrieve one here. The spinning animation // will continue until `AfterPay.transfer` is called. // If you fail to get a token you can call AfterPay.close() window.AfterPay.onComplete = async (event) => { console.log('window.AfterPay.onComplete event ---- ', event); const status: "success" | "cancel" | "failure" = event.data.status === "SUCCESS" ? 'success' : 'cancel'; const resCallback = await createPaymentCallback({ orderId: Number(webOrderId), gatewayOrderId: event.data.orderToken, status: status, }); overlayLoading.stop(); if (event.data.status == "SUCCESS") { // The customer confirmed the payment schedule. // The token is now ready to be captured from your server backend. // 跳转结果页 成功 if(!resCallback.error) { // 后端capture成功,跳转到成功落地页 router.replace('/paymentresult/result?orderId=' + webOrderId + '&return_result=success'); } else { // capture 失败,提示错误 confirmDialog({ title: "Somthing Wrong", content: resCallback.msg + " Please contact customer service." + " OrderId: "+ webOrderId, noCancel: true, }).then(() => { router.replace('/'); }); } } else { // The customer cancelled the payment or closed the popup window. confirmDialog({ title: "Payment Cancelled", content: "You canceled the payment.", noCancel: true, }).then(() => { }); } } window.AfterPay.transfer({token: afterpayToken}); } else { //创建订单出错了 overlayLoading.stop(); confirmDialog({ title: "Warning", content: res.msg + " Create order failed. Please try again.", noCancel: true, }).then(() => {}); } } else { overlayLoading.stop(); showToast("Please wait for the Afterpay to load completely.","warning"); } }; const applepayPlaceOrder = async () => { const res = await paymentRepay({ orderId: Number(orderId), paymentMethod: selectedPaymentMethod }); if(!res.error && res.data !== null) { return { orderId: res.data.gatewayOrderId, webOrderId: res.data.orderId }; } else { // 抛出错误让第三方支付能够捕获 throw new Error("REPAY_ORDER_ERROR: " + res.msg); } }; const validateCheckout = useCallback(async() => { return true; }, []); const klarnaPlaceOrder = async () => { overlayLoading.start(); const resRepay = await paymentRepay({ orderId:Number(orderId), paymentMethod: selectedPaymentMethod, paymentSuccessUrl: window.location.origin + '/paymentresult/result', paymentCancelUrl: window.location.origin + '/paymentresult/result' }); if(!resRepay.error && resRepay.data !== null) { const klarnaToken = resRepay.data.gatewayOrderId; const webOrderId = resRepay.data.orderId; const billingAddress = billingContact; const shippingAddress = shippingContact; const klarnaClientToken = klarnaToken.split("|")[0]; // const klarnaVerifyToken = klarnaToken.split("|")[1]; window.Klarna.Payments.init({ client_token: klarnaClientToken, }); //klarna-widget-container window.Klarna.Payments.load({ container: '#klarna-widget-container', }, (response) => { if(!response.show_form) { // klarna不可用 // 跳转结果页 router.replace('/paymentresult/result?orderId=' + webOrderId + '&return_result=failure'); } else { window.Klarna.Payments.authorize( {}, { billing_address: { given_name: billingAddress.firstName, family_name: billingAddress.lastName, email: billingAddress.email, phone: billingAddress.phone, street_address: billingAddress.address, postal_code: billingAddress.postcode, city: billingAddress.city, country: billingAddress.country }, shipping_address: { given_name: shippingAddress.firstName, family_name: shippingAddress.lastName, email: shippingAddress.email, street_address: shippingAddress.address, postal_code: shippingAddress.postcode, city: shippingAddress.city, phone: shippingAddress.phone, region: shippingAddress.state, country: shippingAddress.country }, // customer: { // date_of_birth: "1941-03-21", // }, }, async function(res) { console.log('klarna authorize res ---- ',res); if(res.approved && res.authorization_token) { // 可以支付 overlayLoading.stop(); router.replace('/paymentresult/result?orderId=' + webOrderId + '&return_result=success'); /* const resCallback = await createPaymentCallback({ orderId: Number(webOrderId), gatewayOrderId: res.authorization_token, verifyToken: klarnaVerifyToken, status: "success", }); // 跳转结果页 overlayLoading.stop(); if(!resCallback.error) { router.replace('/paymentresult/result?orderId=' + webOrderId + '&return_result=success'); } else { // callback 失败,提示错误 confirmDialog({ title: "Somthing Wrong", content: resCallback.msg + " Please contact customer service." + " OrderId: "+ webOrderId, noCancel: true, }).then(() => { router.replace('/'); }); } */ } else { // if(res.show_form) { // klarna可用,但是有报错 // } else { // // klarna 不可用 跳转结果页 // } overlayLoading.stop(); router.replace('/paymentresult/result?orderId=' + webOrderId + '&return_result=failure'); } } ); } }); } else { //创建订单出错了 overlayLoading.stop(); confirmDialog({ title: "Warning", content: resRepay.msg + " Create order failed. Please try again.", noCancel: true, }).then(() => {}); } }; const changePaymentMethod = async (method: string) => { if(method === 'klarna' || method === 'afterpay' || method === 'clearpay' || method === 'applepay' ) { loadSdk(method); } }; const airwallexCardElementShow = selectedPaymentMethod === 'airwallex' && airwallexCardState.cardNumberReady && airwallexCardState.expiryReady && airwallexCardState.cvcReady; return ( <>
{paymentMethodsData.error &&

{paymentMethodsData.error.message}

}
    { paymentMethods.map((item) => { return (
  • { item.method === "airwallex" &&
    }
  • ) }) }
{paymentMethodError &&

{paymentMethodError.message}

}

By providing your information, you agree to Wiggins'sPrivacy Policyand Terms of Use.

{(selectedPaymentMethod === 'awxklarna' || selectedPaymentMethod === 'awxafterpay') && } {selectedPaymentMethod === 'airwallex' && } {(selectedPaymentMethod === 'afterpay' || selectedPaymentMethod === 'clearpay') && }
); }