CheckoutPlaceOrder.tsx 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. "use client";
  2. import { useRouter } from 'next/navigation'
  3. import PaypalButton from "./PaymentButton/PaypalButton";
  4. import { overlayLoading } from "@/components/theme/ui/kernel/loading/api";
  5. import { PlaceOrderFunction } from "@/types/checkout/type";
  6. import { useCustomToast } from "@/utils/hooks/useToast";
  7. import { usePlaceOrder } from "@/utils/hooks/usePlaceOrder";
  8. import { confirmDialog } from "@/components/theme/ui/kernel/confirm/api";
  9. export default function CheckoutPlaceOrder({
  10. paymentMethod,
  11. clickPlaceOrder, // 校验运输方式,地址
  12. }: {
  13. paymentMethod: string;
  14. clickPlaceOrder: PlaceOrderFunction;
  15. }) {
  16. const router = useRouter();
  17. const { showToast } = useCustomToast();
  18. const { createPaymentCallback } = usePlaceOrder();
  19. const paypalCreateOrder = async () => {
  20. const placeOrderRes = await clickPlaceOrder();
  21. if(placeOrderRes.valid && placeOrderRes.data !== null) {
  22. return {
  23. error: false,
  24. msg: '',
  25. orderId: placeOrderRes.data.gatewayOrderId,
  26. webOrderId: placeOrderRes.data.orderId
  27. };
  28. } else {
  29. return {
  30. error: true,
  31. msg: '',
  32. orderId: '',
  33. webOrderId: ''
  34. };
  35. }
  36. };
  37. const airwallexPlaceOrder = async () => {
  38. const placeOrderRes = await clickPlaceOrder({
  39. paymentSuccessUrl: window.location.origin + '/paymentresult/result'
  40. });
  41. overlayLoading.stop();
  42. if(placeOrderRes.valid && placeOrderRes.data !== null) {
  43. window.location.href = placeOrderRes.data.gatewayOrderId;
  44. }
  45. };
  46. const cardAirwallexPlaceOrder = async () => {
  47. const placeOrderRes = await clickPlaceOrder();
  48. if(placeOrderRes.valid && placeOrderRes.data !== null && placeOrderRes.otherData !== null) {
  49. const webOrderId = placeOrderRes.data.orderId;
  50. const cardNumberElement = placeOrderRes.otherData;
  51. const paymentIntentIdClientSecret = placeOrderRes.data.gatewayOrderId.split(':');
  52. const paymentIntentId = paymentIntentIdClientSecret[0];
  53. const paymentIntentClientSecret = paymentIntentIdClientSecret[1];
  54. cardNumberElement.confirm({
  55. intent_id: paymentIntentId,
  56. client_secret: paymentIntentClientSecret,
  57. }).then((result) => {
  58. overlayLoading.stop();
  59. console.log('cardNumberElement.confirm result ---- ', result);
  60. // 支付成功 跳转页面
  61. router.replace('/paymentresult/result?orderId=' + webOrderId + '&return_result=success');
  62. }).catch((error) => {
  63. overlayLoading.stop();
  64. console.log('cardNumberElement.confirm error ---- ', error);
  65. // 支付失败
  66. router.replace('/paymentresult/result?orderId=' + webOrderId + '&return_result=failure');
  67. });
  68. }
  69. };
  70. const afterpayPlaceOrder = async () => {
  71. if(window.AfterPay) {
  72. const placeOrderRes = await clickPlaceOrder({
  73. paymentSuccessUrl: window.location.origin + '/paymentresult/result',
  74. paymentCancelUrl: window.location.origin + '/paymentresult/result'
  75. });
  76. if(placeOrderRes.valid && placeOrderRes.data !== null) {
  77. const afterpayToken = placeOrderRes.data.gatewayOrderId;
  78. const webOrderId = placeOrderRes.data.orderId;
  79. window.AfterPay.initialize({countryCode: "US"});
  80. // To avoid triggering browser anti-popup rules, the AfterPay.open()
  81. // function must be directly called inside the click event listener
  82. window.AfterPay.open();
  83. // If you don't already have a checkout token at this point, you can
  84. // AJAX to your backend to retrieve one here. The spinning animation
  85. // will continue until `AfterPay.transfer` is called.
  86. // If you fail to get a token you can call AfterPay.close()
  87. window.AfterPay.onComplete = async (event) => {
  88. console.log('window.AfterPay.onComplete event ---- ', event);
  89. let status: "success" | "cancel" | "failure" = event.data.status === "SUCCESS" ? 'success' : 'cancel';
  90. const resCallback = await createPaymentCallback({
  91. orderId: Number(webOrderId),
  92. gatewayOrderId: event.data.orderToken,
  93. status: status,
  94. });
  95. overlayLoading.stop();
  96. if (event.data.status == "SUCCESS") {
  97. // The customer confirmed the payment schedule.
  98. // The token is now ready to be captured from your server backend.
  99. // 跳转结果页 成功
  100. if(!resCallback.error) {
  101. // 后端capture成功,跳转到成功落地页
  102. router.replace('/paymentresult/result?orderId=' + webOrderId + '&return_result=success');
  103. } else {
  104. // capture 失败,提示错误
  105. confirmDialog({
  106. title: "Somthing Wrong",
  107. content: resCallback.msg + " Please contact customer service." + " OrderId: "+ webOrderId,
  108. noCancel: true,
  109. }).then(() => {
  110. router.replace('/');
  111. });
  112. }
  113. } else {
  114. // The customer cancelled the payment or closed the popup window.
  115. // 跳转结果页 取消
  116. router.replace('/paymentresult/result?orderId=' + webOrderId + '&return_result=cancel');
  117. }
  118. }
  119. window.AfterPay.transfer({token: afterpayToken});
  120. }
  121. } else {
  122. overlayLoading.stop();
  123. showToast("Please wait for the Afterpay to load completely.","warning");
  124. }
  125. };
  126. return (
  127. <>
  128. <div className="relative w-full">
  129. {paymentMethod === 'paypal_smart_button' &&
  130. <PaypalButton
  131. createOrder={paypalCreateOrder}
  132. />
  133. }
  134. {(paymentMethod === 'awxklarna' || paymentMethod === 'awxafterpay') &&
  135. <button className="flex items-center justify-center w-full h-12 bg-ly-green text-white rounded-3xl text-ly-16 font-bold"
  136. onClick={airwallexPlaceOrder}
  137. >
  138. Place Order
  139. </button>
  140. }
  141. {paymentMethod === 'airwallex' &&
  142. <button className="flex items-center justify-center w-full h-12 bg-ly-green text-white rounded-3xl text-ly-16 font-bold"
  143. onClick={cardAirwallexPlaceOrder}
  144. >
  145. Place Order
  146. </button>
  147. }
  148. {paymentMethod === 'afterpay' &&
  149. <button className="flex items-center justify-center w-full h-12 bg-ly-green text-white rounded-3xl text-ly-16 font-bold"
  150. onClick={afterpayPlaceOrder}
  151. >
  152. Place Order
  153. </button>
  154. }
  155. </div>
  156. </>
  157. );
  158. }