import './checkout.scss'; import * as log from 'loglevel'; import React, { FC, useEffect, useState } from 'react'; import Button from '../../components/Button/button'; import ImageIcon from '../../components/ImageIcon'; import Modal from '../../components/Modal'; import { getBalance, getClientID, getUserPaymentId, makePayment as makePaymentAPI, } from '../../factory/api'; import { numberWithCommas } from '../../utils/helperFunctions'; import Method from './Method'; import { MiniAppErrorType } from '../../model/miniAppError'; import i18n from '../../i18n'; enum PaymentState { Payment = 0, InsufficientBalance, SelectPaymentMethod, PaymentLoading, PaymentFailed, Done, Cancelled, } export interface CheckoutProp { visible: boolean; toggleVisible: (v: boolean) => void; successCB?: (result: any) => void; failCB?: (error: any) => void; completeCB?: () => void; paymentParams: any; } const Checkout: FC = (props) => { const { visible, toggleVisible, successCB, failCB, completeCB, paymentParams, } = props; const [state, setState] = useState(PaymentState.Payment); const [balance, setBalance] = useState(0); useEffect(() => { const f = async () => { try { const res: any = await getBalance(); if (res.data.unsigned.resultInfo.code === 'SUCCESS') { const newBalance = res.data.unsigned.data.totalBalance .amount as number; setBalance(newBalance); } } catch (error) { setState(PaymentState.PaymentFailed); log.error(`Get balance error: ${JSON.stringify(error)}`); } }; if (visible) { f(); } else { // restore all status here const timer = setTimeout(() => { setState(PaymentState.Payment); }, 500); return () => clearTimeout(timer); } }, [visible]); const handlePayment = async () => { try { setState(PaymentState.PaymentLoading); const paymentIdResponse: any = await getUserPaymentId({ merchant: paymentParams.merchantAlias || '214489107898851328', sourceInfoApp: paymentParams.sourceInfoApp, type: paymentParams.type || 'ACQUIRING', }); const paymentMethodId = paymentIdResponse?.data?.unsigned?.data?.payload?.paymentMethodList?.find( (o: any) => o.paymentMethodType === 'WALLET' ).paymentMethodId; const res: any = await makePaymentAPI( { clientId: getClientID(), merchant: paymentParams.merchantAlias || '214489107898851328', agreeSimilarTransaction: true, }, { merchantPaymentId: paymentParams.merchantPaymentId || '7615c171-a97d-4cc1-b749-b7644929c5b9-TEST-BY-ME-AGAIN', amount: paymentParams.amount, paymentMethodId: paymentMethodId, requestedAt: paymentParams.requestedAt || Math.round(Date.now() / 1000), storeId: paymentParams.storeId, terminalId: paymentParams.storeId, orderReceiptNumber: paymentParams.orderReceiptNumber, orderDescription: paymentParams.orderDescription, orderItems: paymentParams.orderItems, sourceInfoApp: paymentParams.sourceInfoApp, } ); if ( res.data.unsigned.resultInfo.code === 'SUCCESS' && res.data.unsigned.data.status === 'COMPLETED' ) { setState(PaymentState.Done); successCB && successCB({ jws: res.data.signed.jws, }); } else if (res.status === 401) { failCB && failCB({ errorCode: MiniAppErrorType.invalidHeader, }); } else { failCB && failCB({ errorCode: MiniAppErrorType.paymentFail, }); } } catch (error) { failCB && failCB({ errorCode: MiniAppErrorType.serverError, }); } finally { completeCB && completeCB(); toggleVisible(!visible); await new Promise((r) => setTimeout(() => r(), 100)); } }; const renderSuccessToast = () => { return state === PaymentState.Done ? (
) : null; }; const renderPaymentLoading = () => { return state === PaymentState.PaymentLoading ? (
{i18n.t('checkout.loadinglbl')}
) : null; }; const renderInsufficientText = () => { return state === PaymentState.InsufficientBalance ? (
{i18n.t('checkout.nobalance')}
) : null; }; const renderButtons = () => { if (state === PaymentState.Done) { return null; } let payBtnText = ''; if (state === PaymentState.Payment) { payBtnText = i18n.t('button.pay'); } else if (state === PaymentState.InsufficientBalance) { payBtnText = i18n.t('button.charge'); } return ( <> {state === PaymentState.InsufficientBalance ? ( ) : null} ); }; const renderTopIcon = () => { const set = new Set([PaymentState.PaymentLoading, PaymentState.Done]); return !set.has(state) ? ( toggleVisible(!visible)} /> ) : null; }; const renderBalanceSection = () => { const set = new Set([PaymentState.PaymentLoading, PaymentState.Done]); return !set.has(state) ? ( <>
{i18n.t('checkout.method')}
{i18n.t('checkout.paybalance')}
{`利用可能額:${balance}円`}
setState(PaymentState.SelectPaymentMethod)} />
) : null; }; const renderPayment = () => { return state !== PaymentState.SelectPaymentMethod ? (
{renderTopIcon()}

{i18n.t('checkout.payment')}

{i18n.t('checkout.payamount')}
{numberWithCommas(paymentParams.amount.amount)}
{renderBalanceSection()} {renderInsufficientText()}
{renderSuccessToast()} {renderPaymentLoading()} {renderButtons()}
) : null; }; const renderSelectPaymentMethod = () => { const isVisible = state === PaymentState.SelectPaymentMethod; return isVisible ? ( setState(PaymentState.Payment)} /> ) : null; }; return ( {renderPayment()} {renderSelectPaymentMethod()} ); }; export default Checkout;