본문으로 건너뛰기

Payment API

Payment API

TudadaSDK.payment.* 는 게임 내 상품 구매를 위한 결제 API입니다. 게임은 결제 수단·레일을 알 필요 없이 productId 로만 구매를 요청합니다. 결제 수단 선택, 가격 산출, 영수증 검증, 지급 처리는 모두 투다다 플랫폼이 담당합니다.

각 동작은 콜백 버전(getProducts 등 — success / fail / complete 콜백, 반환 없음)과 *Async 버전(getProductsAsync 등 — Promise 반환)으로 분리되어 있습니다. 콜백의 성공값은 대응 *Async 의 resolve 값과 동일하며, *Async 의 필수 인자는 위치 인자로 전달합니다.

결제 가용성 · 상점 노출
  • 결제 미지원 환경getProductsAsync()PAYMENT_UNAVAILABLE 로 reject(콜백 버전 getProducts()fail 호출)됩니다.
  • 지원 환경, 매칭 상품 없음빈 배열을 반환합니다(정상 응답). 빈 배열이면 상점 UI를 노출하지 마세요.
  • 통신 실패NETWORK_ERROR 로 reject됩니다.
지급 확정은 서버에서

purchase() 의 결과는 화면 표시·UX 용 축소 정보입니다. 최종 지급 확정은 게임 서버에서 확인하세요. 트랜잭션에는 금액·영수증이 포함되지 않으며, 권위 있는 지급 정보는 게임 서버·투다다 서버가 보유합니다.

payment.getProducts(options?)

구매 가능한 상품 목록을 조회합니다(콜백 버전, 반환 없음).

옵션:

파라미터타입필수설명
successfunction-성공 콜백 — PaymentProduct[]
failfunction-실패 콜백 — PaymentFailResult
completefunction-완료 콜백
TudadaSDK.payment.getProducts({
success: (products) => {
if (products.length === 0) hideStore(); // 빈 배열 → 상점 미노출
else renderStore(products);
},
fail: (err) => console.warn('상품 조회 실패:', err.code),
});

payment.getProductsAsync()

getProducts() 의 Promise 버전입니다. Promise<PaymentProduct[]> 를 반환하며, 판매 가능한 상품이 없으면 빈 배열입니다.

const products = await TudadaSDK.payment.getProductsAsync();
if (products.length === 0) {
hideStore(); // 빈 배열 → 상점 미노출
} else {
renderStore(products);
}

payment.getProduct(options)

단일 상품을 조회합니다(콜백 버전). 미존재/판매 불가 시 fail 콜백에 PRODUCT_NOT_FOUND 가 전달됩니다.

옵션:

파라미터타입필수설명
productIdstring조회할 상품 ID
successfunction-성공 콜백 — PaymentProduct
failfunction-실패 콜백
completefunction-완료 콜백
TudadaSDK.payment.getProduct({
productId: 'coin_100',
success: (product) => console.log(product.name, product.price),
fail: (err) => {
if (err.code === 'PRODUCT_NOT_FOUND') showToast('판매 중인 상품이 아닙니다.');
},
});

payment.getProductAsync(productId)

getProduct() 의 Promise 버전입니다. productId 를 위치 인자로 받아 Promise<PaymentProduct> 를 반환하며, 미존재/판매 불가 시 PRODUCT_NOT_FOUND 로 reject됩니다.

try {
const product = await TudadaSDK.payment.getProductAsync('coin_100');
console.log(product.name, product.price);
} catch (err) {
if (err.code === 'PRODUCT_NOT_FOUND') showToast('판매 중인 상품이 아닙니다.');
}

payment.purchase(options)

상품을 구매합니다(콜백 버전). 성공 시 트랜잭션이 GRANTED(지급 완료) 또는 PENDING(접수·확정 대기) 상태로 전달되며, 그 외에는 fail 콜백이 호출됩니다.

옵션:

파라미터타입필수설명
productIdstring구매할 상품 ID
passthroughPayloadstring-불투명 echo 문자열(≤1000 UTF-8 바이트). 구매 검증 시 원문 그대로 반환됩니다. 비밀·개인정보 금지
successfunction-성공 콜백 — PaymentTransaction
failfunction-실패 콜백
completefunction-완료 콜백
TudadaSDK.payment.purchase({
productId: 'coin_100',
passthroughPayload: 'order-1234', // 선택 — 검증 시 원문 반환
success: (txn) => {
if (txn.status === 'GRANTED') {
// 지급 완료 — UX 반영 (최종 확정은 게임 서버에서)
} else if (txn.status === 'PENDING') {
// 접수됨 — 확정 대기. getTransaction 으로 이후 상태 확인 가능
}
},
fail: (err) => {
if (err.code === 'USER_CANCELLED') return; // 사용자가 결제창을 닫음
console.error('결제 실패:', err.code);
},
});

payment.purchaseAsync(productId, passthroughPayload?)

purchase() 의 Promise 버전입니다. productId(필수)와 passthroughPayload(선택)를 위치 인자로 받아 Promise<PaymentTransaction>(GRANTED / PENDING)를 반환합니다.

try {
const txn = await TudadaSDK.payment.purchaseAsync('coin_100', 'order-1234');

if (txn.status === 'GRANTED') {
// 지급 완료 — UX 반영 (최종 확정은 게임 서버에서)
} else if (txn.status === 'PENDING') {
// 접수됨 — 확정 대기. getTransactionAsync 으로 이후 상태 확인 가능
}
} catch (err) {
if (err.code === 'USER_CANCELLED') return; // 사용자가 결제창을 닫음
console.error('결제 실패:', err.code);
}

payment.getTransaction(options)

트랜잭션 상태·결과를 조회합니다(콜백 버전). purchasePENDING 으로 끝난 경우의 후속 확인 등에 사용합니다. 미존재/미소유 시 fail 콜백에 TRANSACTION_NOT_FOUND 가 전달됩니다.

옵션:

파라미터타입필수설명
txnKeystring조회할 트랜잭션 키
successfunction-성공 콜백 — PaymentTransaction
failfunction-실패 콜백
completefunction-완료 콜백
TudadaSDK.payment.getTransaction({
txnKey: prevTxn.txnKey,
success: (txn) => console.log(txn.status),
});

payment.getTransactionAsync(txnKey)

getTransaction() 의 Promise 버전입니다. txnKey 를 위치 인자로 받아 Promise<PaymentTransaction> (5개 상태 모두 가능)를 반환하며, 미존재/미소유 시 TRANSACTION_NOT_FOUND 로 reject됩니다.

const txn = await TudadaSDK.payment.getTransactionAsync(prevTxn.txnKey);
console.log(txn.status); // 'PENDING' | 'GRANTED' | 'FAILED' | 'PARTIALLY_REFUNDED' | 'REFUNDED'

데이터 타입

PaymentProduct

필드타입설명
productIdstring마켓 무관 단일 상품 ID (구매 시 지정)
namestring등록 상품명
pricestring(할인 적용된) 현재 가격 — 표시-완성 문자열(예 "4,400", "4.99"). 산술 금지, 그대로 표시
currencystring통화 식별 문자열(예 "KRW"). 미인지 값은 문자열 그대로 표시
originalPricestring?할인 전 가격(표시-완성 문자열). 취소선 등 표시용
discountRatestring?할인율 표시 문자열(예 "20%"). 마케팅 표기 — 가격으로 역산 금지

가격은 모두 표시용 완성 문자열입니다. 천단위 구분자·소수 자릿수가 적용된 상태이므로 그대로 출력하고, 직접 계산에 사용하지 마세요.

PaymentTransaction

검증·UX 용 축소 뷰입니다(금액·영수증 없음).

필드타입설명
txnKeystring고유 키 — 재조회에 사용
statusstring트랜잭션 상태 (아래 표)
productIdstring거래 상품
failReasonstring | null진단·로깅용 상세 사유(사용자 노출 금지, 값 변경 가능). 없으면 null
passthroughPayloadstring | null구매 시 넘긴 값 그대로. 생략·빈 문자열이면 null
requestedAtnumber요청 시각 (Unix epoch ms)
grantedAtnumber | null최초 지급 시각 (epoch ms). 미지급 상태면 null

트랜잭션 상태(status):

설명
PENDING접수됨, 지급 미확정
GRANTED지급 완료
FAILED실패
PARTIALLY_REFUNDED부분 환불됨(과거 지급 이력 존재)
REFUNDED환불됨(과거 지급 이력 존재)

purchaseGRANTED / PENDING 만 resolve하고, getTransaction 은 5개 상태를 모두 반환할 수 있습니다.

에러 처리

실패는 콜백 fail(콜백 버전) 또는 Promise reject(*Async 버전)로 전달되며, 분기는 항상 code 로 합니다.

필드타입설명
codestring에러 코드 (아래 표) — 분기 기준
errMsgstring메시지(사용자 노출 금지)
txnKeystring?거래가 기록된 실패에만 존재
failReasonstring?진단·로깅용 상세 사유

에러 코드(code):

코드설명
PAYMENT_UNAVAILABLE결제 불가 환경
USER_CANCELLED사용자가 결제창을 닫음
PAYMENT_FAILED결제 실패(카드 거절·잔액 부족 등)
PRODUCT_NOT_FOUND등록되지 않은 productId
INVALID_PARAM잘못된 인자(passthroughPayload 초과 등)
PURCHASE_REJECTED검증/지급 거절
PAYMENT_IN_PROGRESS진행 중 구매가 있어 신규 호출 거부(동시 1건)
TRANSACTION_NOT_FOUND트랜잭션 미존재 또는 미소유
SESSION_EXPIRED세션 만료 — 재로그인 필요
NETWORK_ERROR통신 실패
try {
await TudadaSDK.payment.purchaseAsync('coin_100');
} catch (err) {
switch (err.code) {
case 'USER_CANCELLED': break; // 조용히 무시
case 'PAYMENT_IN_PROGRESS': showToast('처리 중입니다.'); break;
case 'SESSION_EXPIRED': requestRelogin(); break;
default: showToast('결제에 실패했습니다.');
}
}