跳到主要内容

Payment API

Payment API

TudadaSDK.payment.* 是用于购买游戏内商品的支付 API。游戏无需了解支付方式与渠道,仅通过 productId 即可发起购买。支付方式选择、价格计算、收据验证、发放处理均由Tudada平台负责。

每个动作均分为回调版本getProducts 等 — success / fail / complete 回调,无返回值)与 *Async 版本getProductsAsync 等 — 返回 Promise)。回调的成功值与对应 *Async 的 resolve 值相同, *Async 的必填参数以位置参数传入。

支付可用性 · 商店展示
  • 不支持支付的环境getProductsAsync()PAYMENT_UNAVAILABLE reject(回调版本 getProducts() 调用 fail)。
  • 支持但无匹配商品 — 返回空数组(正常响应)。若为空数组,请不要展示商店 UI。
  • 通信失败 — 以 NETWORK_ERROR reject。
发放确认应在服务器进行

purchase() 的结果是用于界面展示与 UX 的精简信息。**最终发放确认请在游戏服务器进行。**交易中不包含金额与收据,权威的发放信息由游戏服务器与Tudada服务器持有。

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-不透明回传字符串(≤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 毫秒)
grantedAtnumber | null首次发放时刻(epoch 毫秒)。未发放状态时为 null

交易状态(status):

说明
PENDING已受理,发放未确认
GRANTED发放完成
FAILED失败
PARTIALLY_REFUNDED已部分退款(存在过往发放记录)
REFUNDED已退款(存在过往发放记录)

purchase 只会以 GRANTED / 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('支付失败。');
}
}