우리 회사 서비스는 현재 국내에서 서비스하고 있는데 글로벌 런칭 준비중이라 그에 맞춰 결제 서비스도 해외결제가 가능하도록 바꾸는 스프린트가 진행됐다💪
해외결제는 토스페이먼츠를 붙히면 됐고 거의 다 완성되어갈 즈음..
국내결제도 토스페이먼츠로 변경해야한다는 것을 알았다..😳😳(지금은 아임포트..)
구현했던 컴포넌트를 공통으로 사용하고자 코드를 수정하고..
아임포트에서 점진적으로 토스페이먼츠로 전환하는 코드를 추가하고..
그 과정에서 해외결제에 페이팔 + 해외카드를 추가하는 과정이.. 생각보다 순탄하지는 않았던..🫠🫠(이 과정에서 토스페이먼츠에서 운영하는 디코에서 많은 도움을 받았다!!👍👍)
어찌저찌 QA까지 진행했으나.. 가장 중요한 계약이 완료되지 않아.. 결국 완성된 코드는.. PR만 올라가있는 상태다..😕
(계약 시작한건 5월말인데.. 8월초인 지금도.. 이 코드를 질질 끌고 가고 있..😮💨😮💨)
일단, 여기까지 진행한 내용을 또.. 기록해보자!!!!!🔥🔥
yarn add @tosspayments/payment-widget-sdk
# 또는
npm i @tosspayments/payment-widget-sdk
loadPaymentWidget
로 PaymentWidget
인스턴스를 반환하기loadPaymentWidget
는 clientKey
랑 customerKey
를 파라미터는 받는데clientKey
는 위젯을 렌더링하는 상점을 식별하고customerKey
로 결제 고객을 식별한다@tosspayments/payment-widget-sdk
에서 ANONYMOUS
를 불러와서 사용할 수 있는데, 우리 서비스는 로그인 없이는 결제할 수 없기에 별도로 지정하진 않았다<div id="payment-widget" />
를 추가하기loadPaymentWidget()
을 호출해서 인스턴스를 생성하고renderPaymentMethods()
로 결제 위젯을 렌더링하고 useRef
를 사용해서 인스턴스를 저장하기currency
와 country
를 추가했다import React, { useEffect, useRef } from "react"
import { loadPaymentWidget, PaymentWidgetInstance } from "@tosspayments/payment-widget-sdk"
import useTranslation from 'next-translate/useTranslation';
const TossPayments = () => {
const { t } = useTranslation();
const paymentWidgetRef = useRef<PaymentWidgetInstance | null>(null);
const paymentMethodsWidgetRef = useRef<ReturnType<
PaymentWidgetInstance['renderPaymentMethods']
> | null>(null);
useEffect(() => {
const TOSS_CLIENT_KEY = isDevelopment()
? process.env.NEXT_PUBLIC_TOSS_CLIENT_KEY_DEV
: process.env.NEXT_PUBLIC_TOSS_CLIENT_KEY
(async () => {
const paymentWidget = await loadPaymentWidget(
TOSS_CLIENT_KEY,
String(userData?.getUser.userId),
);
const paymentMethodsWidget = paymentWidget.renderPaymentMethods(
'#payment-widget',
{
value: paymentInfo.price,
currency: listCoin?.listInappCoin[0].currency, // 'USD' 해외결제는 필수,
country: listCoin?.listInappCoin[0].countryCode, //'US' 해외결제는 필수,
},
);
paymentWidgetRef.current = paymentWidget; // 결제 위젯 인스턴스 저장
paymentMethodsWidgetRef.current = paymentMethodsWidget; // 결제 방법을 가져오거나 커스텀 결제 수단을 추가할 때 사용
})();
}, []);
return (
<section css={container}>
<div id="payment-widget" />
<button type='button' onClick={onRequestPayment}>{`${t('payment_screen_description_price_monetary_unit', {
value: paymentInfo?.price ?? 0,
})} ${t('payment_screen_button_pay')}`}</button>
</section>
);
};
ref
에 저장했던 결제 위젯 인스턴스에서 결제를 요청하는 requestPayment()로 결제 함수 구현하기http://{ORIGIN}/complete/tosspayments?paymentType=NORMAL&orderId=RUxTyT8ajvSX2xDXKnybC&amount=664.98
paymentKey
: 결제의 키값.orderId
: 상점에서 발급한 주문 건 ID. requestPayment()에 담아 보낸 값.amount
: 실제로 결제된 금액paymentType
: 결제 유형. NORMAL | BRANDPAY
https://{ORIGIN}/complete/tosspayments?code={ERROR_CODE}&message={ERROR_MESSAGE}&orderId={ORDER_ID}
const onRequestPayment = async () => {
// 결제 성공하면 필요한 쿼리를 추가할 수 있다
const successQuery = `price=${paymentInfo?.price}&coin=${paymentInfo?.amount}&method=${selectedPaymentMethod}`;
const successUrl = `${window.location.origin}/payment/complete/toss_payments?${successQuery}`
const failUrl = `${window.location.origin}/payment/complete/toss_payments`
await paymentWidgetRef.current?.requestPayment({
orderId: paymentInfo?.orderId,
orderName: paymentInfo?.name,
successUrl,
failUrl,
customerEmail: userData?.getUser.email,
customerName: userData?.getUser.name,
products: [
{
name: paymentInfo?.name,
quantity: 1,
unitAmount: paymentInfo?.price,
currency: listCoin?.listInappCoin[0].currency,
description: userData?.getUser.name,
},
],
});
};
결제 위젯에 추가로 결제 경로를 설정할 수 있다
상점 관리자에서 UI를 추가한다
설정한 key값 기준으로 결제 코드를 추가한다
해외결제를 지원할 때 페이팔 외에 다국어 결제창을 띄우기 위한 코드를 추가했다
paymentMethodsWidgetRef.current?.on('customRequest', paymentMethodKey => {
if (paymentMethodKey === 'card') { // 상점관리자에서 설정한 key값
// 커스텀 결제수단으로 결제하는 코드
}
})
추가했다가.. 1~2개월 뒤에 페이팔에서 해외카드도 지원될 예정이라고 들어서 우선 페이팔 먼저 오픈하기로 했다!
구현은 끝났고.. QA도 마쳤는데.. 토스페이먼츠와 계약이 아직 진행중이라.. 실제 결제가 진행되는 것은 조금 더 이후가 될 것 같다..🫠🫠
유익한 글이었습니다.