본문으로 건너뛰기

Payment API

Payment API

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

네 메서드 모두 콜백 기반입니다 — onSuccess(결과별 타입)와 onFail(Action<PaymentFailResult>)을 받습니다. 실패 분기는 항상 PaymentFailResult.code 로 합니다.

결제 가용성 · 상점 노출
  • 결제 미지원 환경GetProductsonFailPAYMENT_UNAVAILABLE 로 호출됩니다.
  • 지원 환경, 매칭 상품 없음products빈 배열입니다(정상 응답). 빈 배열이면 상점 UI를 노출하지 마세요.
  • 통신 실패NETWORK_ERROR 로 실패합니다.
지급 확정은 게임 서버에서

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

참고: 결제는 WebGL 빌드에서만 동작합니다. Unity 에디터 시뮬레이션에서는 onFailPAYMENT_UNAVAILABLE 로 호출됩니다(에디터 시뮬레이션 참조).

payment.GetProducts(onSuccess, onFail)

구매 가능한 상품 목록을 조회합니다. 판매 가능한 상품이 없으면 products 가 빈 배열입니다.

파라미터:

파라미터타입필수설명
onSuccessAction<GetProductsResult>-성공 콜백
onFailAction<PaymentFailResult>-실패 콜백

성공 응답 (GetProductsResult):

필드타입설명
productsPaymentProduct[]판매 가능한 상품 목록 (없으면 빈 배열)
errMsgstring결과 메시지
TudadaSDK.Instance.payment.GetProducts(
onSuccess: (res) => {
if (res.products.Length == 0) { HideStore(); return; } // 빈 배열 → 상점 미노출
foreach (var p in res.products)
Debug.Log($"{p.productId} / {p.name} / {p.price} {p.currency}");
RenderStore(res.products);
},
onFail: (err) => Debug.LogError("상품 조회 실패: " + err.code)
);

payment.GetProduct(productId, onSuccess, onFail)

단일 상품을 조회합니다. 미존재/판매 불가 시 onFailPRODUCT_NOT_FOUND 로 호출됩니다.

파라미터:

파라미터타입필수설명
productIdstring조회할 상품 ID
onSuccessAction<GetProductResult>-성공 콜백
onFailAction<PaymentFailResult>-실패 콜백

성공 응답 (GetProductResult):

필드타입설명
productPaymentProduct상품 정보
errMsgstring결과 메시지
TudadaSDK.Instance.payment.GetProduct("coin_100",
onSuccess: (res) => Debug.Log($"{res.product.name} / {res.product.price}"),
onFail: (err) => {
if (err.code == PaymentErrorCode.ProductNotFound) ShowToast("판매 중인 상품이 아닙니다.");
}
);

payment.Purchase(productId, passthroughPayload, onSuccess, onFail)

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

파라미터:

파라미터타입필수설명
productIdstring구매할 상품 ID
passthroughPayloadstring-불투명 echo 문자열(≤1000 UTF-8 바이트). 구매 검증 시 원문 그대로 반환됩니다. 비밀·개인정보 금지
onSuccessAction<PurchaseResult>-성공 콜백
onFailAction<PaymentFailResult>-실패 콜백

성공 응답 (PurchaseResult):

필드타입설명
transactionPaymentTransaction트랜잭션 (GRANTED / PENDING)
errMsgstring결과 메시지
TudadaSDK.Instance.payment.Purchase("coin_100", "order-1234",
onSuccess: (res) => {
var txn = res.transaction;
if (txn.status == PaymentTxnStatus.Granted) {
// 지급 완료 — UX 반영 (최종 확정은 게임 서버에서)
} else if (txn.status == PaymentTxnStatus.Pending) {
// 접수됨 — 확정 대기. GetTransaction 으로 이후 상태 확인 가능
}
},
onFail: (err) => {
if (err.code == PaymentErrorCode.UserCancelled) return; // 사용자가 결제창을 닫음
Debug.LogError("결제 실패: " + err.code);
}
);

payment.GetTransaction(txnKey, onSuccess, onFail)

트랜잭션 상태·결과를 조회합니다. PurchasePENDING 으로 끝난 경우의 후속 확인 등에 사용합니다. 미존재/미소유 시 onFailTRANSACTION_NOT_FOUND 로 호출됩니다.

파라미터:

파라미터타입필수설명
txnKeystring조회할 트랜잭션 키
onSuccessAction<GetTransactionResult>-성공 콜백
onFailAction<PaymentFailResult>-실패 콜백

성공 응답 (GetTransactionResult):

필드타입설명
transactionPaymentTransaction트랜잭션 (5개 상태 모두 가능)
errMsgstring결과 메시지
TudadaSDK.Instance.payment.GetTransaction(prevTxnKey,
onSuccess: (res) => Debug.Log("상태: " + res.transaction.status),
onFail: (err) => Debug.LogError("조회 실패: " + err.code)
);

데이터 타입

PaymentProduct

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

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

PaymentTransaction

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

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

트랜잭션 상태(status):

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

PurchaseGRANTED / PENDING 만 전달하고, GetTransaction 은 5개 상태를 모두 반환할 수 있습니다.

에러 처리

실패는 onFailPaymentFailResult 로 전달되며, 분기는 항상 code 로 합니다.

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

에러 코드(code, PaymentErrorCode 상수):

코드설명
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통신 실패
TudadaSDK.Instance.payment.Purchase("coin_100", null,
onSuccess: (res) => { /* ... */ },
onFail: (err) => {
switch (err.code) {
case PaymentErrorCode.UserCancelled: break; // 조용히 무시
case PaymentErrorCode.PaymentInProgress: ShowToast("처리 중입니다."); break;
case PaymentErrorCode.SessionExpired: RequestRelogin(); break;
default: ShowToast("결제에 실패했습니다.");
}
}
);