前言:内购类型有四种:消耗型商品,非消耗型商品,非续期订阅,自动续期订阅. 顾名思义,从中最有难度的就是自动续期订阅的实现,开通自动续期订阅后,订阅会员的处理将会遇到如下问题:自动订阅的到期继续自动订阅的处理,订阅取消的处理,取消后又在App Store开启自动订阅的处理等一系列问题。我希望通过此篇,能提供完整的思路给需要的人,并希望读者能一起探讨成长。

1. 自动续订订阅前期准备

前期准备无非就是在App Store 建内购的选项,这部分网上有很多文章,我直接推荐看此篇 iOS 内购最新版(埋坑) - 简书 完成前期准备及一些常理的知识了解。当然,项目中我也是直接集成IAPHelper https://github.com/saturngod/IAPHelper 进行内购API集成。

2. 自动续订服务端验证

主要参考如下解决:

http://www.cnblogs.com/zhaoqingqing/p/4597794.html
https://baijunyao.com/article/106

上面的部分解决了消耗型商品内购的功能。
但是此篇是自动订阅:所以需要增加一个参数: password: 秘钥, 就可以了, 但是官方文档说秘钥仅仅用在自动续订上面
大家叫后台加个验证,如果苹果验证返回21004的话(21004 你提供的共享密钥和账户的共享密钥不一致),就加上password字段去验证,可以成功。
 秘钥去https://itunesconnect.apple.com/ 里面对应的APP里创建

image

经过验证:购买过自动续期订阅后,验证内购时(即使是消耗型商品)必须带上password字段。

3. 自动续订服务端验证问题

2中主要是手机内购成功后传receipt给服务端,然后去验证的。然后有没有想到很多需解决的问题?
3.1 订阅状态的处理

  1. 苹果是有提供服务端到服务端通知的处理:
    启用针对自动续期订阅的服务器通知:参考https://help.apple.com/app-store-connect/#/dev0067a330b
  2. 当然去看苹果的文档: 应用程序内购买编程指南
    https://developer.apple.com/library/archive/documentation/NetworkingInternet/Conceptual/StoreKitGuide/Chapters/Subscriptions.html#//apple_ref/doc/uid/TP40008267-CH7-SW6
  3. 状态更新通知
    第2网址中间能看到如下的介绍:
    statusUpdateNotification是用于自动续订订阅的服务器到服务器通知服务。通知指定发送通知时的订阅状态。
    要在处理事件时获取最新信息,您的应用应通过App Store验证最新收据。建议您使用状态更新通知服务以及收据验证来验证用户的当前订阅状态并为其提供服务。有关收据验证的信息,请参阅“ 收据验证编程指南”。
    要接收状态更新通知,请在App Store Connect中为您的应用配置订阅状态URL。App Store将通过HTTP POST将JSON对象传送到您的服务器,以获取表6-3中列出的密钥订阅事件。您的服务器负责解析,解释和响应所有statusUpdateNotification帖子。
    但是状态只有如下五种:INITIAL_BUY,CANCEL,RENEWAL,INTERACTIVE_RENEWAL,DID_CHANGE_RENEWAL_PREF。缺了用户无操作自动订阅的通知??!
  4. 用户无操作自动订阅通知
 If you read the description of the RENEWAL event, you will note - "Automatic renewal was successful for an expired subscription. Check Subscription Expiration Date to determine the next renewal date and time." In general, iTunes will attempt to charge the user account a day before an auto-renewing subscription is scheduled to expire. If the renewal is successful, there is no server-to server notification because the auto-renewing subscription did not enter into an expired state. However, in the few cases that iTunes is unable to renew the subscription (generally there was a connection problem with the credit card server) and the auto-renewing subscription is not renewed before the expiration_date passes, the auto-renewing subscription is technically considered “expired”. However, iTunes will still continue to attempt to renew the subscription. It iTunes is successful, then the “RENEWAL” event is sent. for this reason, the advice is presented - “Check Subscription Expiration Date to determine the next renewal date and time.”

主要处理如下:
如果您阅读了RENEWAL事件的描述,您将注意到 - “过期订阅的自动续订成功。检查订阅到期日期以确定下一个续订日期和时间。” 通常,iTunes会在计划自动续订订阅到期前一天尝试向用户帐户收费。如果续订成功,则没有服务器到服务器通知,因为自动续订订阅未进入过期状态。但是,在少数情况下,iTunes无法续订订阅(通常与信用卡服务器存在连接问题)并且在expiration_date通过之前未续订自动续订订阅,从技术上讲,自动续订订阅被视为“过期”。然而,iTunes仍将继续尝试续订订阅。iTunes成功,然后发送“RENEWAL”事件。出于这个原因,提出了建议 - “检查订阅到期日期以确定下一个续订日期和时间”。

要验证自动续订订阅In-App Purchase是否是最新的,请使用verifyReceipt服务器验证appStoreReceipt。假设in_app数组中存在自动续订订阅项,则查看latest_receipt_info记录并查找具有晚于当前日期的expires_date的订阅记录,其中一个未设置cancellation_date字段。备注:被退款订单的唯一标识是:它带有一个cancellation_date字段。
参考:https://forums.developer.apple.com/message/283579#283579

注意

in_app与latest_receipt_info
测试时发现,这两个字段的数值几乎相同,不过有几点需要注意:
(1)自动续订订阅类型,在到期后会再生成一条购买记录,这条记录会出现在last_receipt_info里,但不会出现在in_app里
(2)自动续订订阅类型可以配置试用,试用记录只有在latest_receipt_info里,is_trial_period字段才是true
(3)消耗型购买记录有可能不会出现在latest_receipt_info,因此需要检查in_app来确保校验正确

用户取消订阅

购买了一个订阅后得全额付款,只有通过联系苹果客服服务才能退款。 比如,如果用户意外买错了产品,客服中心可以取消该交易并退款。 用户不能在订阅周期中间改变注意不支付剩余的订阅。
要想确认某次交易是否已经被取消,在收据 (receipt) 中查找 Cancellation Date (取消日期)字段。 如果该字段有日期,不管该订阅的过期日期是什么,该交易都已经被取消---取消交易就是跟没有购买过一样。
根据产品类型,只能检查当前的活动交易,可能需要检查过去所有的交易。比如,杂志应用需要检查过去所有的交易来决定用户访问了那些期刊。

附下自动订阅的小票:

string(42) "https://buy.itunes.apple.com/verifyReceipt"
string(16) "{"status":21007}"
string(46) "https://sandbox.itunes.apple.com/verifyReceipt"
string(9266) "{"status":0, "environment":"Sandbox",
"receipt":{"receipt_type":"ProductionSandbox", "adam_id":0, "app_item_id":0, "bundle_id":"com.mbalib.ios.wiki", "application_version":"244", "download_id":0, "version_external_identifier":0, "receipt_creation_date":"2018-07-18 07:55:17 Etc/GMT", "receipt_creation_date_ms":"1531900517000", "receipt_creation_date_pst":"2018-07-18 00:55:17 America/Los_Angeles", "request_date":"2018-07-18 07:55:46 Etc/GMT", "request_date_ms":"1531900546430", "request_date_pst":"2018-07-18 00:55:46 America/Los_Angeles", "original_purchase_date":"2013-08-01 07:00:00 Etc/GMT", "original_purchase_date_ms":"1375340400000", "original_purchase_date_pst":"2013-08-01 00:00:00 America/Los_Angeles", "original_application_version":"1.0",
"in_app":[
{"quantity":"1", "product_id":"com.mbalib.ios.wiki_r", "transaction_id":"1000000419163890", "original_transaction_id":"1000000419163890", "purchase_date":"2018-07-18 07:55:15 Etc/GMT", "purchase_date_ms":"1531900515000", "purchase_date_pst":"2018-07-18 00:55:15 America/Los_Angeles", "original_purchase_date":"2018-07-18 07:55:17 Etc/GMT", "original_purchase_date_ms":"1531900517000", "original_purchase_date_pst":"2018-07-18 00:55:17 America/Los_Angeles", "expires_date":"2018-07-18 08:55:15 Etc/GMT", "expires_date_ms":"1531904115000", "expires_date_pst":"2018-07-18 01:55:15 America/Los_Angeles", "web_order_line_item_id":"1000000039541410", "is_trial_period":"true", "is_in_intro_offer_period":"false"}]},
"latest_receipt_info":[
{"quantity":"1", "product_id":"com.mbalib.ios.wiki_r", "transaction_id":"1000000419163890", "original_transaction_id":"1000000419163890", "purchase_date":"2018-07-18 07:55:15 Etc/GMT", "purchase_date_ms":"1531900515000", "purchase_date_pst":"2018-07-18 00:55:15 America/Los_Angeles", "original_purchase_date":"2018-07-18 07:55:17 Etc/GMT", "original_purchase_date_ms":"1531900517000", "original_purchase_date_pst":"2018-07-18 00:55:17 America/Los_Angeles", "expires_date":"2018-07-18 08:55:15 Etc/GMT", "expires_date_ms":"1531904115000", "expires_date_pst":"2018-07-18 01:55:15 America/Los_Angeles", "web_order_line_item_id":"1000000039541410", "is_trial_period":"true", "is_in_intro_offer_period":"false"}],
"latest_receipt":"MII.....",
"pending_renewal_info":[
{"auto_renew_product_id":"com.mbalib.ios.wiki_r", "original_transaction_id":"1000000419163890", "product_id":"com.mbalib.ios.wiki_r", "auto_renew_status":"1"}]}"
{"error":"\u8be5\u4ea7\u54c1\u4e0d\u5b58\u5728","errorno":13105}

添加自动订阅免费试用:

image

官方文档 https://help.apple.com/app-store-connect/#/dev7e89e149d

如果用户再同一自动订阅组,如用户自动订阅买过,免费试用标识就要隐藏掉。因为内购支付购买不会出现免费试用。
首次购买 is_trial_period = true; is_in_intro_offer_period是否是否是在试用期 ; expires_date-purchase_date 就是免费的周期

自动订阅expires_date 会苹果会自动订阅,然后App启动会- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions

在APP启动时候要增加侦听:
[[SKPaymentQueue defaultQueue] addTransactionObserver:self];

- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions
{for (SKPaymentTransaction *transaction in transactions){switch (transaction.transactionState){case SKPaymentTransactionStatePurchasing: // 0break;case SKPaymentTransactionStatePurchased: // 1//订阅特殊处理if(transaction.originalTransaction){//如果是自动续费的订单originalTransaction会有内容 }else{//普通购买,以及 第一次购买 自动订阅}break;case SKPaymentTransactionStateFailed: // 2[self failTracker:transaction];break;case SKPaymentTransactionStateRestored: // 3[self restoreTransaction:transaction];break;default:break;}}
}
    [latest_receipt_info] => Array([0] => Array([quantity] => 1[product_id] => com....[transaction_id] => 1000000498609863[original_transaction_id] => 1000000498609863[purchase_date] => 2019-01-30 09:12:46 Etc/GMT[purchase_date_ms] => 1548839566000[purchase_date_pst] => 2019-01-30 01:12:46 America/Los_Angeles[original_purchase_date] => 2019-01-30 09:12:47 Etc/GMT[original_purchase_date_ms] => 1548839567000[original_purchase_date_pst] => 2019-01-30 01:12:47 America/Los_Angeles[expires_date] => 2019-01-30 09:15:46 Etc/GMT[expires_date_ms] => 1548839746000[expires_date_pst] => 2019-01-30 01:15:46 America/Los_Angeles[web_order_line_item_id] => 1000000042488789[is_trial_period] => true[is_in_intro_offer_period] => false))

让用户管理订阅
不需要编码实现订阅管理 UI ,应用程序可以打开以下 URL

https://buy.itunes.apple.com/WebObjects/MZFinance.woa/wa/manageSubscriptions

参考:

  1. IAP (In-App purchase) - 简书
  2. iOS内购编程指南 - 简书

记录:微信和支付宝支付-看我的,用我的就够了微信和支付宝支付-看我的,用我的就够了 - 简书

iOS内购:自动续期订阅总结相关推荐

  1. IOS内购自动续费订阅测试

    一.IOS 内购类型 1.消耗型商品: 只可使用一次的产品,使用之后即失效,必须再次购买. 示例:抽奖券. 2.非消耗型商品: 只需购买一次,不会过期或随着使用而减少的产品. 示例:游戏 App 的赛 ...

  2. iOS开发,自动续期订阅的坑

    自动续期订阅相较于普通内购,需要一个共享密钥,这个共享密钥在申请内购时获得.秘钥用于向苹果服务器请求收据信息. 购买过程不再赘述. 购买成功后,自动续期订阅最大的问题在于购买成功后是否续期成功,和到期 ...

  3. 应用内购:自动更新订阅教程

    原文:In-App Purchases: Auto-Renewable Subscriptions Tutorial 作者:Chris Wagner 译者:kmyhy 苹果在 WWDC 2016 前推 ...

  4. php++内购续期订阅,iOS内购:自动续期订阅总结

    前言:内购类型有四种:消耗型商品,非消耗型商品,非续期订阅,自动续期订阅. 顾名思义,从中最有难度的就是自动续期订阅的实现,开通自动续期订阅后,订阅会员的处理将会遇到如下问题:自动订阅的到期继续自动订 ...

  5. iOS内购(IAP)自动续订订阅

    一.介绍 iOS 的 App 内购类型有四种: 消耗型商品:只可使用一次的产品,使用之后即失效,必须再次购买. 示例:钓鱼 App 中的鱼食. 非消耗型商品:只需购买一次,不会过期或随着使用而减少的产 ...

  6. IOS 内购IAP 自动订阅收据验证文档服务端翻译

    将收据数据发送到App Store: 提交此JSON对象作为HTTP POST请求的有效负载. 中文文档:https://help.apple.com/app-store-connect/#/dev7 ...

  7. php++内购续期订阅,appstore:内购项目之自动续期订阅

    自动续期订阅指南 自动续期订阅让用户能持续地访问App中的内容.服务或高级功能.除非用户选择取消订阅,否则自动续期订阅会在到期时自动续期.设置自动续期订阅,与设置其他App内购买项目类型不同.每个自动 ...

  8. iOS 自动续期订阅 恢复购买

    恢复购买 内购有4种:消耗型项目,非消耗型,自动续期订阅,非续期订阅. 其中"非消耗型"和"自动续期订阅"需要提供恢复购买的功能,例如创建一个恢复按钮,不然审核 ...

  9. ios自动订阅服务器,iOS IAP - 自动续期订阅

    自动续期订阅是苹果推出的一项苹果内购服务,当用户在App Store订阅了某项服务后,App Store会在订阅时间快到期之前,自动扣费并帮用户续订该服务. 自动续期订阅的优势 创建自动续期订阅 1. ...

最新文章

  1. 用来定制shell环境 set/shopt
  2. Android—WebView与JS交互
  3. 开源开放 | DeepKE发布新版本:支持低资源、长篇章、多任务的图谱抽取开源框架(浙江大学)...
  4. 一加9系列曝光:骁龙875旗舰芯片加持 可能存在超过四种机型
  5. 5.4寸iPhone 12真机曝光:可单手握住的快乐!
  6. ICT学习笔记(1) 网络以及网络模型的相关知识
  7. jsonrpc-c编译
  8. hashcat简单使用
  9. 有效使用网易有道词典客户端
  10. Unity Webgl 问题总结
  11. C#开发WPF/Silverlight动画及游戏系列教程(Game Tutorial):(二十四) Be careful!前方怪物出没...
  12. 日本房地产泡沫破裂后的平民生活
  13. C++设计模式——建造者模式(高屋建瓴)
  14. FPGA----ZCU106基于axi-hp通道的pl与ps数据交互(全网唯一最详)
  15. 火狐浏览器httpRequest插件
  16. 软件中级设计师 - 计算机组成与结构
  17. php分页无极类的讲解_一个完美php分页类,推荐给大家
  18. iconfont图标样式库
  19. 蓝手指安卓模拟器中文版 V1.2.0 官方正式版
  20. 如何将markdown文档一键转化为视频?

热门文章

  1. js浏览器消息通知接口Notification
  2. 电脑怎么把mv快速转换成mp3
  3. java1.8.0 jce下载,关于jar:Java错误:请安装JCE无限强度管辖权策略文件
  4. linux远程运行桌面,Linux 远程桌面的实现
  5. 星辰大海——桃花庵歌
  6. 短信登录、短信注册,(仅供参考)
  7. FPS之游戏基址(二)
  8. java控制指令和stomp_Stomp与Jackson
  9. 【MacOS】最小化当前窗口的快捷键
  10. 重启网卡提示Bringing up interface eth0: Device eth0 does not seem to be present,delaying initialization.