前言:內(nèi)購類型有四種:消耗型商品,非消耗型商品,非續(xù)期訂閱,自動續(xù)期訂閱. 顧名思義,從中最有難度的就是自動續(xù)期訂閱的實現(xiàn),開通自動續(xù)期訂閱后,訂閱會員的處理將會遇到如下問題:自動訂閱的到期繼續(xù)自動訂閱的處理,訂閱取消的處理,取消后又在App Store開啟自動訂閱的處理等一系列問題。我希望通過此篇,能提供完整的思路給需要的人,并希望讀者能一起探討成長。
1. 自動續(xù)訂訂閱前期準(zhǔn)備
前期準(zhǔn)備無非就是在App Store 建內(nèi)購的選項,這部分網(wǎng)上有很多文章,我直接推薦看此篇 http://www.itdecent.cn/p/479cf9e31104 完成前期準(zhǔn)備及一些常理的知識了解。當(dāng)然,項目中我也是直接集成IAPHelper https://github.com/saturngod/IAPHelper 進行內(nèi)購API集成。
2. 自動續(xù)訂服務(wù)端驗證
主要參考如下解決:
http://www.cnblogs.com/zhaoqingqing/p/4597794.html
https://baijunyao.com/article/106
上面的部分解決了消耗型商品內(nèi)購的功能。
但是此篇是自動訂閱:所以需要增加一個參數(shù): password: 秘鑰, 就可以了, 但是官方文檔說秘鑰僅僅用在自動續(xù)訂上面
大家叫后臺加個驗證,如果蘋果驗證返回21004的話(21004 你提供的共享密鑰和賬戶的共享密鑰不一致),就加上password字段去驗證,可以成功。 秘鑰去https://itunesconnect.apple.com/ 里面對應(yīng)的APP里創(chuàng)建

經(jīng)過驗證:購買過自動續(xù)期訂閱后,驗證內(nèi)購時(即使是消耗型商品)必須帶上password字段。
3. 自動續(xù)訂服務(wù)端驗證問題
2中主要是手機內(nèi)購成功后傳receipt給服務(wù)端,然后去驗證的。然后有沒有想到很多需解決的問題?
3.1 訂閱狀態(tài)的處理
- 蘋果是有提供服務(wù)端到服務(wù)端通知的處理:
啟用針對自動續(xù)期訂閱的服務(wù)器通知:參考https://help.apple.com/app-store-connect/#/dev0067a330b - 當(dāng)然去看蘋果的文檔: 應(yīng)用程序內(nèi)購買編程指南
https://developer.apple.com/library/archive/documentation/NetworkingInternet/Conceptual/StoreKitGuide/Chapters/Subscriptions.html#//apple_ref/doc/uid/TP40008267-CH7-SW6 - 狀態(tài)更新通知
第2網(wǎng)址中間能看到如下的介紹:
A statusUpdateNotification是用于自動續(xù)訂訂閱的服務(wù)器到服務(wù)器通知服務(wù)。通知指定發(fā)送通知時的訂閱狀態(tài)。
要在處理事件時獲取最新信息,您的應(yīng)用應(yīng)通過App Store驗證最新收據(jù)。建議您使用狀態(tài)更新通知服務(wù)以及收據(jù)驗證來驗證用戶的當(dāng)前訂閱狀態(tài)并為其提供服務(wù)。有關(guān)收據(jù)驗證的信息,請參閱“ 收據(jù)驗證編程指南”。
要接收狀態(tài)更新通知,請在App Store Connect中為您的應(yīng)用配置訂閱狀態(tài)URL。App Store將通過HTTP POST將JSON對象傳送到您的服務(wù)器,以獲取表6-3中列出的密鑰訂閱事件。您的服務(wù)器負(fù)責(zé)解析,解釋和響應(yīng)所有statusUpdateNotification帖子。
但是狀態(tài)只有如下五種:INITIAL_BUY,CANCEL,RENEWAL,INTERACTIVE_RENEWAL,DID_CHANGE_RENEWAL_PREF。缺了用戶無操作自動訂閱的通知??! - 用戶無操作自動訂閱通知
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事件的描述,您將注意到 - “過期訂閱的自動續(xù)訂成功。檢查訂閱到期日期以確定下一個續(xù)訂日期和時間。” 通常,iTunes會在計劃自動續(xù)訂訂閱到期前一天嘗試向用戶帳戶收費。如果續(xù)訂成功,則沒有服務(wù)器到服務(wù)器通知,因為自動續(xù)訂訂閱未進入過期狀態(tài)。但是,在少數(shù)情況下,iTunes無法續(xù)訂訂閱(通常與信用卡服務(wù)器存在連接問題)并且在expiration_date通過之前未續(xù)訂自動續(xù)訂訂閱,從技術(shù)上講,自動續(xù)訂訂閱被視為“過期”。然而,iTunes仍將繼續(xù)嘗試?yán)m(xù)訂訂閱。iTunes成功,然后發(fā)送“RENEWAL”事件。出于這個原因,提出了建議 - “檢查訂閱到期日期以確定下一個續(xù)訂日期和時間”。
要驗證自動續(xù)訂訂閱In-App Purchase是否是最新的,請使用verifyReceipt服務(wù)器驗證appStoreReceipt。假設(shè)in_app數(shù)組中存在自動續(xù)訂訂閱項,則查看latest_receipt_info記錄并查找具有晚于當(dāng)前日期的expires_date的訂閱記錄,其中一個未設(shè)置cancellation_date字段。備注:被退款訂單的唯一標(biāo)識是:它帶有一個cancellation_date字段。
參考:https://forums.developer.apple.com/message/283579#283579
注意
in_app與latest_receipt_info
測試時發(fā)現(xiàn),這兩個字段的數(shù)值幾乎相同,不過有幾點需要注意:
(1)自動續(xù)訂訂閱類型,在到期后會再生成一條購買記錄,這條記錄會出現(xiàn)在last_receipt_info里,但不會出現(xiàn)在in_app里
(2)自動續(xù)訂訂閱類型可以配置試用,試用記錄只有在latest_receipt_info里,is_trial_period字段才是true
(3)消耗型購買記錄有可能不會出現(xiàn)在latest_receipt_info,因此需要檢查in_app來確保校驗正確
用戶取消訂閱
購買了一個訂閱后得全額付款,只有通過聯(lián)系蘋果客服服務(wù)才能退款。 比如,如果用戶意外買錯了產(chǎn)品,客服中心可以取消該交易并退款。 用戶不能在訂閱周期中間改變注意不支付剩余的訂閱。
要想確認(rèn)某次交易是否已經(jīng)被取消,在收據(jù) (receipt) 中查找 Cancellation Date (取消日期)字段。 如果該字段有日期,不管該訂閱的過期日期是什么,該交易都已經(jīng)被取消---取消交易就是跟沒有購買過一樣。
根據(jù)產(chǎn)品類型,只能檢查當(dāng)前的活動交易,可能需要檢查過去所有的交易。比如,雜志應(yīng)用需要檢查過去所有的交易來決定用戶訪問了那些期刊。
附下自動訂閱的小票:
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}
添加自動訂閱免費試用:

官方文檔 https://help.apple.com/app-store-connect/#/dev7e89e149d
如果用戶再同一自動訂閱組,如用戶自動訂閱買過,免費試用標(biāo)識就要隱藏掉。因為內(nèi)購支付購買不會出現(xiàn)免費試用。
首次購買 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: // 0
break;
case SKPaymentTransactionStatePurchased: // 1
//訂閱特殊處理
if(transaction.originalTransaction){
//如果是自動續(xù)費的訂單originalTransaction會有內(nèi)容
}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
)
)
讓用戶管理訂閱
不需要編碼實現(xiàn)訂閱管理 UI ,應(yīng)用程序可以打開以下 URL
https://buy.itunes.apple.com/WebObjects/MZFinance.woa/wa/manageSubscriptions
參考:
記錄:微信和支付寶支付-看我的,用我的就夠了http://www.itdecent.cn/p/020621c3a660#