구독 서비스 기획/개발기 (2)

Hoony·2022년 6월 30일
0

🙏가격을 낮추고 구독제로 전환

서비스는 런칭하였지만, 우리는 결제모듈을 붙이고 있지 않았다.

지금까지 B2B, B2G 형태의 사업과 수백만원~억단위(💸)의 제품가격
결제 모듈로 결제하기에는 어렵다고 판단했고
그래서 우리는 전화(📞)로만 제품을 구매 할 수 있었다.

고객들의 피드백과 내부적인 판단을 통해
가격을 낮추고, 구독제로 전환하기로 결정되었고
어떻게 개발을 해야할지 고민을 시작했다.

💳결제대행사 (토스페이먼츠)

결제대행사는 토스페이먼츠 로 결정되었는데
시장에서 큰 파이를 가지고 있으면서도
초기 비용과 수수료가 싸기 때문에 결정되었다.
국내 선두 IT기업에서 개발하고있다는점도 플러스가 되었다.

토스페이먼츠에 신청을 했더니,
"심사를 위한 조건을 알려드립니다.... 블라블라"
"개발을 하고나서, 링크를 보내주세요"
"링크를 받고 심사는 2~3주 소요됩니다."

심사기간까지 고려하여, 개발을 해야한다는 압박이 생겼다.

💻개발 연동 TEST

https://tosspayments.com 를 참조하면서

TEST를 위해 front는 CRA로 project를 만들고
Back은 예제로 제공하는 nodejs sample을 clone하였다.

우리는 Billing 결제 (자동결제)가 필요하여 가이드를 봤더니
일반 결제보다는 좀 더 복잡한 형태로 결제가 이루어 지는것을 알 수 있었다.

아래 이미지는 tossPayment가 제공하는 module로 결제하는 방식인데
카드를 입력하는 UI를 제공해주는 플로우를 설명하고 있다.

Module install & Code 작성

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) 얻기

빌링키(🔑)라는 것이 존재하는데 BillingKey 요청 API에
아래 정보와 카드 등록후 받은 AuthKey를 전달하여 얻을 수 있다.

  • 고객정보(customerKey)
    - 유니크하게 우리가 생성필요
  • 카드정보(CardInfo)
    - 고객이 입력하는 정보

발급된 빌링키를 가지고 우리는 정기적으로 결제를 수행하는 Logic을 개발하면 된다.
따라서, 유저와 빌링키를 1:1 대응하여 저장하고 있어야한다.

빌링키로 결제하기

빌링키와 결제는 secretKey가 필요하고,
추가적인 logic 구현(BillingKey 저장 등)이 필요하기 때문에
우리 Server Side에서 toss api를 호출해야한다.

  • billingKey는 PathParameter
  • secretKey는 Header의 Authorization

로 전달하여 API를 호출할 수 있고, Body에는 아래 정보를 넣어주었다.

  • amount ( 가격 )
  • customerKey ( 고객 정보 )
  • orderId ( 제품 유니크 id )
  • orderName ( 제품 이름 )

성공적으로 결제가 이루어지면 최종적으로 아래와 같이 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하여 전달해야하는데 ':'를 넣지않아 제대로 인코딩 되지 않는 문제

  • Basic Authorization이 HTTP 인증방식중 하나인데 username:password을 Base64로 인코딩한다고한다.
  • 토스페이먼츠 api는 username에 secretKey를 넣고 password는 사용하지않는다.
  • 따라서, {secretKey}: 를 인코딩했어야 했는데, ':'를 계속 빠져먹었던 문제였다.

테스트 할 때마다, 카드를 입력해야하는 문제

  • 위에서 진행한 방식대로하면, 카드를 항상 재입력하는 아주 귀찮은 일이 있었다.
  • 자동결제 API를 활용하면 '카드정보, 생년월일/사업자번호'를 파라미터로 던질 수 있었다.
  • 테스트 완료까지 활용하였고, 실제 환경에서는 Toss UI를 쓸 계획이다.
profile
아는 만큼 보인다

0개의 댓글