TEAM-LEG3ND / luwak

Backend server for on-demand-cafe project
4 stars 0 forks source link

[BE] 결제 화면 API 설계 #9

Open d0lim opened 10 months ago

d0lim commented 10 months ago

개요

selgyun commented 10 months ago

객체 리스트

카드 결제만 구현하는 것으로 정함! (4주차 회의)

selgyun commented 9 months ago

Payment 객체

결제 응답은 Payment 객체를 내린다.

pseudo code

    version : string; // 결제 버전 [ 날짜 기반 버저닝 ]
    paymentKey : string;  // 결제 키 값
    type : string; // 결제 타입 [ NORMAL, BILLING, BRANDPAY ] 중 하나. [ 일반 결제, 간편 결제, 브랜드페이(네이버페이 등) ]
    orderId : string; // 주문 ID 결제 요청 시 생성한 값. 고유한 값이어야 함. 결제 상태 변해도 값 유지. 6~64자
    orderName : string; // "우유, 에스프레소 외 1건" 최대 100자
    mId : string // 상점 ID
    currency : string; // 통화  [ KRW, USD ]
    method : string; // 결제수단 [ 카드, 가상계좌, 간편결제, 휴대폰 등]
    totalAmount : number; // 총 결제 금액, 결제 취소해도 초기 금액으로 유지됨.
    balanceAmount : number; // 취소할 수 있는 금액, 부분 취소가 되고 남은 금액.
    status : string; // 결제 처리 상태 [READY, IN_PROGRESS, WAITING_FOR_DEPOSIT, DONE, CANCELED, PARTIAL_CANCELED, ABORTED, EXPIRED]
    requestedAt : string; // 결제 요청 시작 시각 iso 8601 형태로 제공 : (e.g. 2022-01-01T00:00:00+09:00)
    approvedAt : string; // 결제 승인된 시각 iso 8601 형태로 제공 : (e.g. 2022-01-01T00:00:00+09:00)
    useEscrow : boolean; // 에스크로 사용 여부: 2013년 부터 에스크로 의무적.. 5만원 이하 결제도 고객이 선택할 수 있어야 함.
    lastTransactionKey : string; // nullable  마지막 거래 값. 한 결제에서 취소와 승인 구분하기 위해 내려보냄.
    suppliedAmount : number; // 공급가액: 결제 부분 취소 시 공급가액도 수정 됨.
    vat : number; // 부가세: 결제 부분 취소 시 부가세도 수정 됨. (결제금액 - 면세가) / 11 후 소수 첫째 자리에서 반올림
    taxFreeAmount : number; // 면세금액 : 보통은 0
    cancels : object[]; // nullable 취소 이력이 담기는 Cancel 객체 배열 
    isPartialCancelable : boolean; // 부분결제 취소 가능 여부. false면 전액 취소만 가능.
    card : object; // nullable 카드결제 시 관련 정보
    receipt : object; // nullable { url: string } 발행한 영수증 정보
    checkout : object; // nullable { url: string } 결제창 정보
    easyPay : object; // nullable 간편결제 정보
    country : string; // 결제 국가 ISO-3166 두자리 국가 코드
    failure : object; // nullable 결제 실패 에러 객체 {code : string // 에러 코드, message : string // 에러 이유}
    cashReceipt : object; // nullable 현금 영수증 정보
    discount : object; // nullable {amount: number}카드사 즉시 할인 이벤트로 적용된 금액. 이벤트 있을 때만 보냄.

API 구성

selgyun commented 9 months ago

결제 status flow chart

붉은 상태 표기에서는 웹훅 이벤트를 전송합니다.

v1/payments/webhook

eventType : PAYMENT_STATUS_CHANGED
createdAt : date
data : object // payment 객체 반환
flowchart TD
    classDef shootEvent fill:#F9D9CA
    A[*] -- 결제창 실행 --> B[READY]
    B -- 유효 시간 만료 --> C[EXPIRED]:::shootEvent
    B -- 결제 인증 완료 --> D[IN_PROGRESS]
    D -- 유효 시간 만료 --> C
    D -- 승인 성공 --> E[DONE]:::shootEvent
    D -- 승인 실패 --> F[ABORTED]:::shootEvent
    E -- 결제 취소 --> G[CANCELED]:::shootEvent
    E -- 결제 부분 취소 --> H[PARTIAL_CANCELED]:::shootEvent
selgyun commented 9 months ago

Payment 관련 객체 리스트

Cancel

   cancelAmount : number // 결제 취소한 금액
   cancelReason : string // 결제 취소 이유
   taxFreeAmount : number // 취소된 금액 중 면세 금액
   refundableAmount: number // 결제 취소 후 환불 가능한 잔액
   easyPayDiscountAmount : number // n-페이 포인트, k-페이 포인트, 쿠폰 등 적립식 결제수단에서 취소된 금액
   canceledAt : string // 결제 취소된 날짜 시간 정보 ISO 8601 형식 2022-01-01T00:00:00+09:00
   transactionKey : string // 취소 거래의 키 값. 여러 건의 취소를 구분하기 위해 사용.
   receiptKey : string // 취소 건의 영수증 키 값

Card

   amount : number // 결제 요청 금액
   isuserCode : string // 카드 발급사 번호 
   acquirerCode : string // 카드 매입사 번호 , [우리BC카드 매입사 : BC카드, 우리카드 매입사 : 우리은행]
   number : string // 카드번호
   installmentPlanMonths : number // 할부 개월 수. 일시불 : 0
   approveNo : string // 카드사 승인 번호
   useCardPoint : boolean // 카드 포인트 사용 여부
   cardType : string // 카드 타입:  신용 | 체크| 기프트| 미확인
   ownerType : string // 소유자 타입 : 개인 | 법인 | 미확인
   acquireStatus : string // 카드결제 상태 READY | REQUESTED | COMPLETED | CANCEL_REQUESTED | CANCELED
   isInterestFree : boolean // 무이자 할부인가?
   interestPayer : string // 할부할 때 수수료 부담하는 사람. BUYER(일반) | CARD_COMPANY(무이자) | MERCHANT(무이자)
selgyun commented 9 months ago

Transaction 객체

거래 정보를 담고 있음. 하나의 결제 건에 여러 개의 Transaction 객체 생성 가능, 기간 별 조회 시 그 기간에 생긴 모든 Transaction 객체 배열로 내려줌

    mId : string // 상점 아이디
    transactionKey : string // 거래 키 값
    paymentKey : string // 결제 키 값
    orderId : string // 주문 ID
    method : string // 결제 수단 카드 | 가상계좌 | 간편결제 | 휴대폰 | 계좌이체 | 문화상품권 | 기타 (우린 카드로!)
    customerKey : string // 고객 ID
    userEscrow : boolean // 에스크로 사용 여부
    receiptUrl : string // 거래 영수증 확인할 수 있는 주소
    status : string // 결제 처리 상태 READY | IN_PROGRESS | WAITING_FOR_DEPOSIT | DONE | CANCELED | PARTIAL_CANCELED | ABORTED | EXPIRED
    transactionAt : string // 거래 처리 시점의 날짜 시간 정보 ISO 8601 형식 yyyy-MM-dd'T'HH:mm:ss±hh:mm
    currency : string // 결제 통화
    amount : number // 결제 금액
selgyun commented 9 months ago

CashReceipt 객체

    receiptKey : string // 현금 영수증 키, 취소 시에 prefix로 c_ 붙음
    issueNumber  : string // 현금 영수증 발급 번호
    issueStatus : string // 발급 상태 IN_PROGRESS | COMPLETED | FAILED
    amount : number // 현금 영수증 처리 금액
    taxFreeAmount : number // 면세 금액
    orderID : string // 주문 ID
    orderName : string // 주문 명 (e.g. '우유 외 1건')
    type : string // 현금 영수증 종류 소득공제 | 지출증빙
    transactionType : string // 발급 종류 CONFIRM | CANCEL
    businessNumber : string // 사업자 등록 번호 10자
    customerIdentityNumber : string // 소비자 인증 수단, 핸드폰 번호 or 주민등록번호 or 사업자 등록 번호
    failure : object // 결제 실패 정보 { code : string, message: string }
    requestedAt : string // 현금 영수증 발급 or 취소를 요청한 날짜 및 시간 ISO8601 형식
    receiptUrl : string // 발행된 현금 영수증 확인할 수 있는 주소
selgyun commented 9 months ago

CardPromotion 객체

조회 시 CardPromotion 객체 반환

    discountCards : array // 카드사 즉시 할인 정보
        companyCode : string // 카드사 숫자 코드
        discountAmount : number // 할인 금액
        balance : number // 프로모션 남은 예산. 0 되면 프로모션 못 함
        dueDate : string // 할인 종료 일  yyyy-MM-dd 형식 
        minimumPaymentAmount : number // 혜택을 받을 수 있는 최소 금액
        maximumPaymentAmount : number // 혜택을 받을 수 있는 최대 금액
    interestFreeCards : array // 카드사 무이자 할부 정보
        companyCode : string // 카드사 숫자 코드
        dueDate : string // 무이자 할부 행사 종료 일  yyyy-MM-dd 형식 
        installmentFreeMonths: array // 무이자 할부 할 수 있는 개월 수 , ( e.g. [2, 3, 4, 5, 6] )
        minimumPaymentAmount : number // 무이자 할부 할 수 있는 최소 금액
selgyun commented 9 months ago

카드사 코드 참조 링크 : https://docs.tosspayments.com/reference/codes#%EC%B9%B4%EB%93%9C%EC%82%AC-%EC%BD%94%EB%93%9C

d0lim commented 9 months ago

@selgyun

혹시 결제 승인 플로우가 어떻게 되나요? 결제 금액을 FE로부터 전달받는 것으면 문제가 발생할 수 있을 것 같아서, 주문을 생성하고 해당 주문 기준으로 금액은 서버 로직으로 연산하는 것이 맞는 방향일 것 같습니다.

결제 승인을 시도하게 되면 FE 입장에선 결제가 완료되었음을 확인하기 위해서 GET /v1/payments/{paymentKey} 요 API 폴링하는 것으로 생각하고 계신것이져?

selgyun commented 9 months ago

결제 플로우

  1. 클라 <-> 토스페이먼츠 (confirm 작업)
  2. 클라 -> 서버 ( 결제 요청 ) + 장바구니정보를 보낼 것인가?? (e.g. Cart = {"001" : 1, "003" : 2})
  3. 서버 <-> 토스페이먼츠 ( 결제 요청 )
  4. 서버 -> 클라 (응답값 반환)
sequenceDiagram
   participant Client
   participant Server
   participant TossPayments
   Client ->>TossPayments: request auth payment
   TossPayments ->> Client: response auth payment
   Client ->> Server : request confirm payment
   Server ->> TossPayments: request confirm payment
   TossPayments ->> Server: response confirm payment
   Server ->> Client: response confirm payment