前言:內購類型有四種:消耗型商品,非消耗型商品,非續期訂閱,自動續期訂閱. 顧名思義,從中最有難度的就是自動續期訂閱的實現,開通自動續期訂閱后,訂閱會員的處理將會遇到如下問題:自動訂閱的到期繼續自動訂閱的處理,訂閱取消的處理,取消后又在App Store開啟自動訂閱的處理等一系列問題。我希望通過此篇,能提供完整的思路給需要的人,并希望讀者能一起探討成長。
1. 自動續訂訂閱前期準備
前期準備無非就是在App Store 建內購的選項,這部分網上有很多文章,我直接推薦看此篇 http://www.lxweimin.com/p/479cf9e31104 完成前期準備及一些常理的知識了解。當然,項目中我也是直接集成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里創建
經過驗證:購買過自動續期訂閱后,驗證內購時(即使是消耗型商品)必須帶上password字段。
3. 自動續訂服務端驗證問題
2中主要是手機內購成功后傳receipt給服務端,然后去驗證的。然后有沒有想到很多需解決的問題?
3.1 訂閱狀態的處理
- 蘋果是有提供服務端到服務端通知的處理:
啟用針對自動續期訂閱的服務器通知:參考https://help.apple.com/app-store-connect/#/dev0067a330b - 當然去看蘋果的文檔: 應用程序內購買編程指南
https://developer.apple.com/library/archive/documentation/NetworkingInternet/Conceptual/StoreKitGuide/Chapters/Subscriptions.html#//apple_ref/doc/uid/TP40008267-CH7-SW6 - 狀態更新通知
第2網址中間能看到如下的介紹:
A 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。缺了用戶無操作自動訂閱的通知??! - 用戶無操作自動訂閱通知
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}
添加自動訂閱免費試用:
官方文檔 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: // 0
break;
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
參考:
記錄:微信和支付寶支付-看我的,用我的就夠了http://www.lxweimin.com/p/020621c3a660#