서비스는 런칭하였지만, 우리는 결제모듈을 붙이고 있지 않았다.
지금까지 B2B, B2G 형태의 사업과 수백만원~억단위(💸)의 제품가격
결제 모듈로 결제하기에는 어렵다고 판단했고
그래서 우리는 전화(📞)로만 제품을 구매 할 수 있었다.
고객들의 피드백과 내부적인 판단을 통해
가격을 낮추고, 구독제로 전환하기로 결정되었고
어떻게 개발을 해야할지 고민을 시작했다.
결제대행사는 토스페이먼츠 로 결정되었는데
시장에서 큰 파이를 가지고 있으면서도
초기 비용과 수수료가 싸기 때문에 결정되었다.
국내 선두 IT기업에서 개발하고있다는점도 플러스가 되었다.
토스페이먼츠에 신청을 했더니,
"심사를 위한 조건을 알려드립니다.... 블라블라"
"개발을 하고나서, 링크를 보내주세요"
"링크를 받고 심사는 2~3주 소요됩니다."
심사기간까지 고려하여, 개발을 해야한다는 압박이 생겼다.
https://tosspayments.com 를 참조하면서
TEST를 위해 front는 CRA로 project를 만들고
Back은 예제로 제공하는 nodejs sample을 clone하였다.
우리는 Billing 결제 (자동결제)가 필요하여 가이드를 봤더니
일반 결제보다는 좀 더 복잡한 형태로 결제가 이루어 지는것을 알 수 있었다.
아래 이미지는 tossPayment가 제공하는 module로 결제하는 방식인데
카드를 입력하는 UI를 제공해주는 플로우를 설명하고 있다.
yarn add @tosspayments/payment-sdk
모듈을 다운받고 아래와 같이 실행하면 카드를 입력하는 UI가 떴다.
import tossPayments from 'tosspayments';
const clientKey = 'test_ck_D5GePWvyJnrK0W0k6q8gLzN97Eoq';
tossPayments.requestBillingAuth('카드', {
customerKey: 'LRKEp7lSTiwnO8eSdX9x6',
successUrl: 'window.location.origin/success',
failUrl: 'window.location.origin/fail',
})
clientKey와 secretKey가 존재하는데
clientKey는 front단에서 secretKey는 back단에서 핸들링 하면된다.
카드 등록 성공여부에 따라 successUrl/faileUrl로 Redirect 된다.
success가 된 경우에는, AuthKey를 query parmeter로 전달해준다.
fail인 경우에는 실패한 이유를 마찬가지로 query parameter로 전달해준다.
빌링키(🔑)라는 것이 존재하는데 BillingKey 요청 API에
아래 정보와 카드 등록후 받은 AuthKey를 전달하여 얻을 수 있다.
발급된 빌링키를 가지고 우리는 정기적으로 결제를 수행하는 Logic을 개발하면 된다.
따라서, 유저와 빌링키를 1:1 대응하여 저장하고 있어야한다.
빌링키와 결제는 secretKey가 필요하고,
추가적인 logic 구현(BillingKey 저장 등)이 필요하기 때문에
우리 Server Side에서 toss api를 호출해야한다.
로 전달하여 API를 호출할 수 있고, Body에는 아래 정보를 넣어주었다.
성공적으로 결제가 이루어지면 최종적으로 아래와 같이 return된 값이 온다.
{
"mId": "tosspayments",
"version": "2022-06-08",
"paymentKey": "p7V5ajBUBIIaHi6y5DY0-",
"status": "DONE",
"transactionKey": "S-DnLFGTUSG_tDv06bEml",
"lastTransactionKey": "bE7-WcGD0iwLkr_lBhXTQ",
"orderId": "Mf8RKH3FL1LGfQ3_I9dQW",
"orderName": "토스 프라임 구독",
"requestedAt": "2022-06-08T15:40:09+09:00",
"approvedAt": "2022-06-08T15:40:49+09:00",
"useEscrow": false,
"cultureExpense": false,
"card": {
"company": "농협",
"number": "123456******7890",
"installmentPlanMonths": 0,
"isInterestFree": false,
"interestPayer": null,
"approveNo": "00000000",
"useCardPoint": false,
"cardType": "신용",
"ownerType": "개인",
"acquireStatus": "READY",
"receiptUrl": "https://dashboard.tosspayments.com/sales-slip?transactionId=KAgfjGxIqVVXDxOiSW1wUnRWBS1dszn3DKcuhpm7mQlKP0iOdgPCKmwEdYglIHX&ref=PX",
"amount": 5000
},
"virtualAccount": null,
"transfer": null,
"mobilePhone": null,
"giftCertificate": null,
"cashReceipt": null,
"discount": null,
"cancels": null,
"secret": null,
"type": "BILLING",
"easyPay": null,
"country": "KR",
"failure": null,
"isPartialCancelable": true,
"receipt": {
"url": "https://dashboard.tosspayments.com/sales-slip?transactionId=KAgfjGxIqVVXDxOiSW1wUnRWBS1dszn3DKcuhpm7mQlKP0iOdgPCKmwEdYglIHX&ref=PX"
},
"currency": "KRW",
"totalAmount": 5000,
"balanceAmount": 5000,
"suppliedAmount": 3636,
"vat": 364,
"taxFreeAmount": 0,
"method": "카드"
}
secretKey는 encoding하여 전달해야하는데 ':'를 넣지않아 제대로 인코딩 되지 않는 문제
username:password
을 Base64로 인코딩한다고한다.{secretKey}:
를 인코딩했어야 했는데, ':'를 계속 빠져먹었던 문제였다.테스트 할 때마다, 카드를 입력해야하는 문제