iOS实体设备上沙盒收据验证失败,错误码21003(Firebase Cloud Run函数+App Store Connect环境)
嘿,我来帮你排查这个让人头疼的21003错误!这个错误码本质是苹果验证服务器无法识别你提交的收据数据,或者请求的格式、权限存在问题。结合你的Firebase Cloud Run+沙盒测试场景,咱们一步步拆解排查:
先确认收据数据的编码是否合规
苹果要求收据必须是Base64编码的字符串,而且不能包含换行、空格这类多余字符。你用了自定义的SKReceiptManager.retrieveReceiptData(),得检查这个helper是不是把原始的Data正确转成了符合要求的Base64字符串。可以在客户端打印发送前的收据片段,或者在Cloud Run函数里接收后先验证下是否为有效Base64——如果编码错了,直接就会触发21003。检查Cloud Run函数调用的苹果端点是否正确
沙盒环境的验证端点是https://sandbox.itunes.apple.com/verifyReceipt,生产环境是另一个URL,千万不要搞混!如果你的函数误用了生产端点,在沙盒测试时必然报错。另外,请求必须是POST方法,Content-Type要设为application/json,请求体格式必须是:{"receipt-data": "你的Base64收据字符串"}如果是自动续期订阅,还要加上
password字段(对应App Store Connect里的共享密钥),少了这个也会验证失败。确认沙盒账号和设备环境的正确性
- 确保你用的是App Store Connect里创建的正式沙盒测试员账号,不是普通Apple ID。沙盒账号需要在「用户和访问」->「沙盒测试员」里生成。
- 实体设备上要退出所有正式Apple ID,只登录沙盒账号。如果之前用正式账号下载过这个App,建议删除App后重新安装,避免设备自动跳转到生产环境。
- 检查Cloud Run函数的网络连通性:有没有防火墙、VPC规则阻止了函数访问苹果的沙盒端点?可以去Cloud Run的日志里查看请求苹果端点的返回详情,看是不是连不上或者有其他网络错误。
排查请求格式的细节问题
- 别写错请求体的键名!苹果API对键名是严格区分的,比如把
receipt-data写成receiptData这种小错误,都会导致验证失败。 - 不要在请求体里加多余的字段,苹果的验证服务器只认指定的几个参数,多余内容可能干扰验证逻辑。
- 别写错请求体的键名!苹果API对键名是严格区分的,比如把
验证收据本身是否有效
有时候问题出在客户端获取收据的环节:比如SKReceiptManager.retrieveReceiptData()返回的是空数据,或者收据本身损坏。你可以把客户端拿到的收据数据,用curl直接发送到沙盒端点测试(本地执行),如果本地测试也失败,那就能确定问题不在Cloud Run函数,而是客户端获取收据的逻辑有问题。检查Cloud Run的权限和环境配置
如果你的Cloud Run函数用了VPC连接器,要确保配置了允许访问外部HTTPS地址的权限。另外,像共享密钥这类敏感信息,别硬编码在函数里,用环境变量管理,但要确认环境变量已经正确加载,没有拼写错误。
最后给个实用小技巧:在Cloud Run函数里加详细的日志,比如打印请求苹果的URL、请求体的关键片段(别打印完整Base64避免泄露)、苹果返回的完整响应——这些日志能帮你快速定位到底是请求发错了,还是苹果返回了额外的错误提示。
备注:内容来源于stack exchange,提问作者NUVA

