Flutter+Node栈iOS内购收据验证返回21002、498错误如何解决?
收据验证失败问题排查方案
21002 错误(苹果App Store验证接口返回)
- 先确认凭证来源:该错误仅在验证iOS收据时出现,若将安卓平台的购买令牌传入苹果验证接口必然触发格式错误,需先区分两端凭证,分别走对应验证逻辑。
- 检查base64编码正确性:
- Flutter端获取iOS交易凭证
transaction.transactionReceipt时,直接调用base64Encode转换为字符串,不要做trim、移除换行、url编码等额外处理,也不要直接传收据url。 - 后端收到base64字符串后先做合法性校验:确认传输过程中没有被url转义(比如
+被转成%2B、空格被转成+这类情况,建议凭证放在请求body中以raw格式传输,不要放在url参数中。
- Flutter端获取iOS交易凭证
- 确认验证地址匹配:沙箱环境必须请求苹果沙箱验证地址,误传生产地址会返回格式错误,兼容方案为先请求生产验证地址,返回21007状态码时自动切换到沙箱地址重试。
- Node.js请求构造参考:
const axios = require('axios'); async function verifyIOSReceipt(receiptBase64, isSandbox = false) { const url = isSandbox ? 'https://sandbox.itunes.apple.com/verifyReceipt' : 'https://buy.itunes.apple.com/verifyReceipt'; const res = await axios.post(url, { "receipt-data": receiptBase64, "password": "你的App Store Connect共享密钥", "exclude-old-transactions": true }, { headers: { 'Content-Type': 'application/json' } }); return res.data; }
498 错误(谷歌Play验证接口返回)
- 确认令牌使用场景:该错误为安卓端购买令牌校验时返回,将iOS收据传入谷歌验证接口会触发该错误。
- 检查令牌时效性:沙箱环境的购买令牌有效期极短,购买完成后需立即发起验证,延迟几分钟就会过期失效。
- 确认服务账号权限:谷歌Play Developer API对应的服务账号必须开通对应应用的财务数据查看权限,权限不足会返回令牌无效。
- 确认产品ID匹配:验证时传入的产品ID需和谷歌Play后台配置的产品ID完全一致,大小写敏感。
通用排查步骤
- 两端凭证标记:Flutter端拿到购买凭证后,同步标记凭证所属平台,后端接收后先判断平台再走对应验证逻辑,不要混用接口。
- 传输一致性校验:后端收到凭证后打印完整内容,和前端原始凭证逐字符对比,确认没有被框架自动转义。
- 沙箱环境使用官方提供的测试账号完成测试,不要用正式账号测试沙箱内购。
内容的提问来源于stack exchange,提问作者Buddhika Bandara
相关产品推荐
相关产品推荐

