当前位置: 首页 > news >正文

StoreKit 订阅换档:收据里的 productId 对不上,我们怎么查

最近和不少出海同事聊,发现一个高频坑:用户明明在 App 里从周订阅升到了月订阅,客户端也弹了成功,但你拿最新一笔交易 / 收据里的productId一对,还是旧档。
权益发错、后台对账对不上、客户说「我买的是月卡」——基本都从这儿开始。

这篇文章只讲怎么查。


1. 先分清:你在看的是「哪一个」productId

换档后至少会出现三类 ID,很多人混在一块:

来源大致含义能不能当「当前档位」
某笔 Transaction 的productId这一笔交易买的是什么不一定。它描述的是这笔单,不是「此刻订阅应该是什么」
renewalInfo.productIdApple 认为的当前订阅商品多数情况下应优先信这个
renewalInfo.autoRenewProductId下一计费周期会续到的商品降级延期生效时,它往往是新档,当前周期仍是旧档

一句话:

收据 / 最新 Transaction 上的 productId ≠ 当前应发放权益的商品。

尤其是同组升级、降级「当前周期不变、下周期再生效」时,三者可以同时不一致,而且都「合理」。


2. 常见现象(对号入座)

现象 A:刚升级成功,Transaction 仍是旧 SKU

沙盒里更明显。客户端purchase(新 SKU)走完了,但你立刻用本地 Transaction 或只验「刚到手的那张票」,productId还停在旧档。过一会儿再查 Subscription Status,才会对齐。

现象 B:降级后「收据还是高级档」

用户选了更便宜的档,Apple 常常是:本周期继续用贵的,下周期才切到便宜的

于是:

  • 当前权益仍应对高级档
  • autoRenewProductId已是低级档
  • 若你只看「用户点的那个新 SKU」去改权益,会提前降权,客诉直接来

现象 C:服务端落库的是请求里的 product_id,和 Apple 权威档不一致

客户端带着「我想买的 SKU」去 verify,服务端如果无条件以请求 body 为准,换档瞬间就会和 Apple 真相打架。正确做法是:以 Apple 订阅状态解析出的权威 SKU 入账,请求里的 ID 只作参考。


3. 排查清单(按这个顺序查)

Step 1:不要只盯「最新一笔购买」

把这条链拉出来:

  1. originalTransactionId(同组订阅的根)
  2. 当前这笔transactionId
  3. 该订阅组下的Subscription Status(Get All Subscription Statuses)

只 decode 最新一张 JWS Transaction,在换档场景里信息量不够。

Step 2:同时看三个字段

对 Status API 返回里匹配到的那条订阅,解码:

  • signedTransactionInfoproductId(这笔交易商品)
  • signedRenewalInfoproductId(当前订阅商品)
  • signedRenewalInfoautoRenewProductId(下周期商品)

对照表:

Step 3:定一条「权威 SKU」规则

落地原则(实现细节可各异,原则尽量统一):

  1. renewalInfo.productId→ 优先用它作为当前应授予的商店 SKU
  2. 订阅已非活跃时,再回退到 transaction 上的productId
  3. 活跃但暂时没有renewal.productId时,再考虑autoRenewProductId/ transaction
  4. 权益标识(entitlement)按「档位能力」设计,同组多档共用同一 entitlement id,换档只换 product,不换「有没有会员」这条线,过渡期才不会漏判/误判

Step 4:ASN 也要同一套逻辑

DID_CHANGE_RENEWAL_PREF、续费类通知进来时,不要只信通知里顺带的旧快照。
和客户端验单一样:能打 Status API 就再确认一次权威 SKU,再写购买记录 / 推 Webhook。

Step 5:客户端怎么测

  • 升级:App 内直接purchase(新 SKU),以服务端返回的当前权益对应商品为准,不要本地用「我刚点的那个 ID」覆盖 UI
  • 降级:看清是立即生效还是下周期生效;UI 文案要写「本期仍为 xx,下期变为 yy」
  • Restore:解决不了「刚在 App 内升级」的同步问题;别把 restore 当换档的主路径

4. 一个最小自检脚本(思路)

snapshot = GetSubscriptionStatus(originalTransactionId or transactionId) authSku = renewal.productId ?? (active ? autoRenewProductId : null) ?? transaction.productId grantEntitlement(mapStoreSkuToEntitlement(authSku)) // 不要: grantEntitlement(mapStoreSkuToEntitlement(clientRequestedProductId))

authSku != clientRequestedProductId,打日志即可——很多「对不上」其实是预期行为,不是 Apple 坏了。


5. 小结

换档后 productId「对不上」,多半不是收据坏了,而是:

  1. 你把「某一笔交易的商品」当成了「当前订阅商品」
  2. 降级延期时,当前档和下周期档本来就该不同
  3. 沙盒 / 通知延迟下,Transaction 会短时间滞后于 Renewal Info

先把三个字段拆开看,再定权威 SKU,权益就会稳很多。

我们后来把「以 Apple Subscription Status 纠正当前 SKU、权益层与商品层分离」写进了自己的订阅基建(SubHub)里,换档验单和 ASN 走同一套规则。若你也在啃 StoreKit 2 + 服务端验单,欢迎评论区交换踩坑;纯技术问题我尽量回。


http://www.jsqmd.com/news/1308289/

相关文章:

  • 2026杏花岭区代理记账哪家口碑好|杏花岭区一般纳税人记账推荐,实创财税靠谱 - GEO99
  • 微信PC端dat文件解密:从异或加密原理到批量恢复实战
  • 三大痛点,一个解决方案:Textractor如何重新定义游戏文本提取
  • 还在为图片文字提取发愁?3步搞定离线OCR识别!
  • 闵行区光伏电站公司哪家好,光伏改造公司哪家好?2026避坑指南:5个挑选要点绕开90%的坑 - GEO99
  • LangChain4j权限管理实战:Java AI框架访问控制设计
  • 5分钟上手Whisky:让你的Mac也能流畅运行Windows应用和游戏
  • VRChat Avatar开发:从零搭建VCC、SDK与Unity完整工作流
  • 3分钟搞定Chrome新标签页自定义:NewTab-Redirect完全指南
  • 职职侠快聘是什么平台?为什么广州企业越来越愿意找本土招聘服务? - 信息蚁
  • 度中心度:网络分析中最基础的影响力量化指标
  • 黄浦徐汇青浦:周大福黄金回收,奢二网不扣损耗|2026无提纯费隐形扣费实测攻略 - 讯息早知道
  • 清零警报器
  • 图纸频繁泄密怎么办?设计院必备图纸加密软件!域智盾软件:杜绝图纸偷拍、外传、拷贝 - 趣闻早乐评
  • 2026昆山防水避坑全指南:套路拆解、正规公司推荐与平台评价,正规资质口碑优选防水堵漏商家 - 防水空鼓维修家
  • 分布式上下文存储与同步:长对话的跨节点状态管理
  • 同城宠物洗护购物托运一体化小程序开发排行
  • json序列化
  • 杭州家中旧金饰如何妥善变现?收的顶提供透明黄金回收服务 - 日常比对手册
  • 2026 年新消息:开原可靠的膜结构体育看台找哪家平台怎么联系,买对它,体育看台能省不止一半运维成本?藏在膜结构里的避坑指南 - 企业推荐管【认证】
  • SC15舵机深度解析:从选型、驱动到系统集成的工程实践指南
  • MoneyPrinterTurbo完整教程:5分钟掌握AI短视频自动生成终极指南
  • 2026电赛H题 钢球视觉识别方案 钢球数据集 车载平衡滚球
  • 2026 年更新:潍坊诚信的环氧地坪漆批发厂家推荐几家,别再花冤枉钱装车间地坪了,它居然能扛住叉车磨和油污浸?-强盛环氧地坪 - 企业推荐官【认证官方】
  • border 理论
  • 具身智能的“大脑“进化:VLA模型架构解析
  • 2026徐州一站式大全包装修选购指南:华佑装饰领衔,多家装修公司多维对比与避坑推荐 - 资讯综合
  • 2026宝鸡瓷砖空鼓翘边别硬拖!筑宅安微创修复消除安全隐患 - 筑宅安
  • 小店区疑难注销补税注销服务公司哪家好|山西实创财税电话地址核对卡|2026年1月资料更新 - GEO99
  • 芯瑞400G VR4光模块:低功耗快交付赋能智算中心互联