|
@@ -1,7 +1,7 @@
|
|
|
"use client";
|
|
"use client";
|
|
|
|
|
|
|
|
import Image from "next/image";
|
|
import Image from "next/image";
|
|
|
-import { use,useState } from "react";
|
|
|
|
|
|
|
+import { use,useState,useEffect } from "react";
|
|
|
import { useForm, get, useWatch } from "react-hook-form";
|
|
import { useForm, get, useWatch } from "react-hook-form";
|
|
|
import { useRouter } from 'next/navigation'
|
|
import { useRouter } from 'next/navigation'
|
|
|
import { useCustomToast } from "@/utils/hooks/useToast";
|
|
import { useCustomToast } from "@/utils/hooks/useToast";
|
|
@@ -13,6 +13,7 @@ import { usePlaceOrder } from "@/utils/hooks/usePlaceOrder";
|
|
|
import PaypalButton from "../PaymentButton/PaypalButton";
|
|
import PaypalButton from "../PaymentButton/PaypalButton";
|
|
|
import { overlayLoading } from "@/components/theme/ui/kernel/loading/api";
|
|
import { overlayLoading } from "@/components/theme/ui/kernel/loading/api";
|
|
|
import { confirmDialog } from "@/components/theme/ui/kernel/confirm/api";
|
|
import { confirmDialog } from "@/components/theme/ui/kernel/confirm/api";
|
|
|
|
|
+import {loadAfterpayScript} from "@/lib/Afterpay/afterpay";
|
|
|
|
|
|
|
|
/**@todo 优化目标:不使用 react-hook-form */
|
|
/**@todo 优化目标:不使用 react-hook-form */
|
|
|
export function PaymentMethodContinueTpPay({
|
|
export function PaymentMethodContinueTpPay({
|
|
@@ -22,14 +23,14 @@ export function PaymentMethodContinueTpPay({
|
|
|
}: {
|
|
}: {
|
|
|
paymentMethodsDataPromise: Promise<GraphqlRequestResult<RepayOrderPaymentMethodsData>>;
|
|
paymentMethodsDataPromise: Promise<GraphqlRequestResult<RepayOrderPaymentMethodsData>>;
|
|
|
defaultPaymentMethod: {method: string; methodTitle: string;}
|
|
defaultPaymentMethod: {method: string; methodTitle: string;}
|
|
|
- orderId: string;
|
|
|
|
|
|
|
+ orderId: number;
|
|
|
}) {
|
|
}) {
|
|
|
const router = useRouter();
|
|
const router = useRouter();
|
|
|
const { showToast } = useCustomToast();
|
|
const { showToast } = useCustomToast();
|
|
|
const paymentMethodsData = use(paymentMethodsDataPromise);
|
|
const paymentMethodsData = use(paymentMethodsDataPromise);
|
|
|
const paymentMethods = paymentMethodsData.data?.collectionRepayOrderPaymentMethods || [];
|
|
const paymentMethods = paymentMethodsData.data?.collectionRepayOrderPaymentMethods || [];
|
|
|
|
|
|
|
|
- const { paymentRepay } = usePlaceOrder();
|
|
|
|
|
|
|
+ const { paymentRepay, createPaymentCallback } = usePlaceOrder();
|
|
|
|
|
|
|
|
const {airwallexCardState,getCardElements} = useAirwallexCard(true,{
|
|
const {airwallexCardState,getCardElements} = useAirwallexCard(true,{
|
|
|
cardNumber: 'airwallex_cardNumber',
|
|
cardNumber: 'airwallex_cardNumber',
|
|
@@ -192,8 +193,83 @@ export function PaymentMethodContinueTpPay({
|
|
|
setIsPay(false);
|
|
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;
|
|
|
|
|
+ window.AfterPay.initialize({countryCode: "US"});
|
|
|
|
|
+ // 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);
|
|
|
|
|
+ let 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();
|
|
|
|
|
+ showToast("Please wait for the Afterpay to load completely.","warning");
|
|
|
|
|
+ }
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
const airwallexCardElementShow = selectedPaymentMethod === 'airwallex' && airwallexCardState.cardNumberReady && airwallexCardState.expiryReady && airwallexCardState.cvcReady;
|
|
const airwallexCardElementShow = selectedPaymentMethod === 'airwallex' && airwallexCardState.cardNumberReady && airwallexCardState.expiryReady && airwallexCardState.cvcReady;
|
|
|
|
|
|
|
|
|
|
+ useEffect(() => {
|
|
|
|
|
+ const hasAfterpay = paymentMethods.some(x=>x.method==="afterpay");
|
|
|
|
|
+
|
|
|
|
|
+ if(hasAfterpay){
|
|
|
|
|
+ loadAfterpayScript();
|
|
|
|
|
+ }
|
|
|
|
|
+ }, [paymentMethods]);
|
|
|
return (
|
|
return (
|
|
|
<>
|
|
<>
|
|
|
<form name="shipping method" className="w-full box-border px-4 mt-4">
|
|
<form name="shipping method" className="w-full box-border px-4 mt-4">
|
|
@@ -276,6 +352,13 @@ export function PaymentMethodContinueTpPay({
|
|
|
Pay
|
|
Pay
|
|
|
</button>
|
|
</button>
|
|
|
}
|
|
}
|
|
|
|
|
+ {selectedPaymentMethod === 'afterpay' &&
|
|
|
|
|
+ <button className="flex items-center justify-center w-full h-12 bg-ly-green text-white rounded-3xl text-ly-16 font-bold"
|
|
|
|
|
+ onClick={afterpayPlaceOrder}
|
|
|
|
|
+ >
|
|
|
|
|
+ Place Order
|
|
|
|
|
+ </button>
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|