Onerway
快速开始

币种与金额校验

在创建支付请求前校验交易币种、金额精度和支付方式能力,避免因金额不合法被拒绝。

创建支付请求前,请在服务端一起校验 orderCurrency、orderAmount 和可用支付方式。orderCurrency 是三位 ISO 4217 交易币种;orderAmount 是按交易币种展示单位提交的正数十进制字符串,例如 USD 99.99 传 99.99,JPY 1000 可传 1000 或 1000.00。

不要用 JavaScript number、二进制浮点数或临时四舍五入后的值直接生成 orderAmount。建议内部用整数 minor unit 值或 decimal library 计算,确认金额后再格式化成 Onerway API 需要的字符串。

校验顺序

校验币种代码

orderCurrency 必须使用大写三位 ISO 4217 字母代码,例如 USD、EUR、JPY。不要传货币符号、国家代码、非官方缩写或大小写混用的值。

如果某个 ISO 4217 代码是基金、贵金属、测试代码或“无币种”代码,例如 XAU、XTS、XXX,不要用于支付请求,除非 Onerway 已明确为你的商户、支付方式和交易场景开通。

校验金额格式与精度

orderAmount 必须是正数十进制字符串,以 . 作为小数分隔符。不要包含逗号、空格、货币符号、正负号或指数写法。

Minor unit校验规则常见示例
0必须表示整数金额;可以不带小数,也可以只带全 0 小数JPY 可传 1000 或 1000.00;不要传 4.12
2最多两位小数;整数金额可以不带 .00USD 可传 100、100.00、99.99
3最多三位小数;支付方式可能还有额外限制KWD 可传 10、10.500、0.001
币种精度应来自你们维护的已开通币种配置,或来自 ISO 4217 minor unit 数据。不要把所有币种都固定成两位小数;零小数币种和三位小数币种需要单独处理。

校验支付方式能力

金额格式合法不代表交易一定可处理。支付方式、国家或地区、发卡机构、本地支付提供方、商户配置以及单笔限额都可能影响可用性。

在展示币种或让客户输入金额前,建议先调用可用支付方式查询,按国家或地区、币种、金额和商户配置筛选可用方式。对本地支付方式,不要只按币种判断可用性。

校验订单合计

如果请求包含 txnOrderMsg.products、折扣、运费或其他订单明细,请用同一币种和同一精度计算合计,并确保明细金额与 orderAmount 一致。折扣项应按接口字段要求使用负数。

请求示例

{
  "orderAmount": "99.99",
  "orderCurrency": "USD"
}
{
  "orderAmount": "1000.00",
  "orderCurrency": "JPY"
}
{
  "orderAmount": "10.500",
  "orderCurrency": "KWD"
}

服务端校验示例

下面的示例只演示金额格式校验。生产环境应从你们的商户配置读取已开通币种、minor unit、最小金额、最大金额和可用支付方式。

type CurrencyRule = {
  minorUnit: number
  minAmount?: string
  maxAmount?: string
}

const enabledCurrencies: Record<string, CurrencyRule> = {
  USD: { minorUnit: 2, minAmount: '0.01' },
  JPY: { minorUnit: 0, minAmount: '1' },
  KWD: { minorUnit: 3, minAmount: '0.001' }
}

function validateOrderAmount(amount: string, currency: string) {
  const code = currency.trim().toUpperCase()
  const rule = enabledCurrencies[code]

  if (!rule) {
    return { valid: false, reason: 'invalid_currency_code' }
  }

  if (!/^\d+(?:\.\d+)?$/.test(amount)) {
    return { valid: false, reason: 'invalid_amount_format' }
  }

  const [, fraction = ''] = amount.split('.')
  const hasTooManyDecimals = fraction.length > rule.minorUnit
  const isWholeAmountWithZeroFraction = rule.minorUnit === 0 && /^0*$/.test(fraction)
  if (hasTooManyDecimals && !isWholeAmountWithZeroFraction) {
    return { valid: false, reason: 'invalid_minor_unit' }
  }

  if (/^0+(?:\.0+)?$/.test(amount)) {
    return { valid: false, reason: 'amount_must_be_positive' }
  }

  return { valid: true, code, minorUnit: rule.minorUnit }
}
前端可以根据币种动态限制小数位并格式化展示;最终仍应以服务端校验结果为准。不要在服务端请求前静默截断或四舍五入客户已经确认的金额。

常见拦截原因

场景原因处理方式
JPY 传 4.12零小数币种不能包含非零小数改为整数金额或全 0 小数,例如 1000 或 1000.00;否则可能返回 respCode=40000 和 Illegal parameter orderAmount
USD 传 99.999超过两位小数在客户确认金额前按业务规则处理精度
KWD 被固定成两位小数三位小数币种被通用金额组件误处理输入控件和服务端校验都按币种配置动态设置精度
使用 1,000.00API 金额不接受千分位分隔符提交前移除展示格式,只保留 decimal string
支付方式不可用币种格式正确,但支付方式、地区或限额不匹配先查询可用支付方式,或联系 Onerway 确认商户配置

参考资料