iOS內購:自動續期訂閱總結

前言:內購類型有四種:消耗型商品,非消耗型商品,非續期訂閱,自動續期訂閱. 顧名思義,從中最有難度的就是自動續期訂閱的實現,開通自動續期訂閱后,訂閱會員的處理將會遇到如下問題:自動訂閱的到期繼續自動訂閱的處理,訂閱取消的處理,取消后又在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里創建

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網址中間能看到如下的介紹:
    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。缺了用戶無操作自動訂閱的通知??!
  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: // 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

參考:

  1. http://www.lxweimin.com/p/f2d30aa59cbb
  2. http://www.lxweimin.com/p/17e0d11149f3

記錄:微信和支付寶支付-看我的,用我的就夠了http://www.lxweimin.com/p/020621c3a660#

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,882評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,208評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,746評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,666評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,477評論 6 407
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,960評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,047評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,200評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,726評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,617評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,807評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,327評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,049評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,425評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,674評論 1 281
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,432評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,769評論 2 372

推薦閱讀更多精彩內容

  • Spring Cloud為開發人員提供了快速構建分布式系統中一些常見模式的工具(例如配置管理,服務發現,斷路器,智...
    卡卡羅2017閱讀 134,781評論 18 139
  • App Store 審核指南2017/07/27 簡介 App 正在改變世界,豐富人們的生活,并為像您一樣的開發者...
    小白沐春風閱讀 3,618評論 0 2
  • 最近一直忙于公司項目、今天抽空總結了一下關于上線審核的一些變動!和大家分享一下相互學習。 這兩天發現蘋果在審核指南...
    _VisitorsZsl閱讀 1,039評論 0 1
  • 像我這么完美的人,從每天的讀書健身,碰到那個最愛的人,遇到此生為之付出生命的事業,為所有的家人朋友錦囊相助。學習了...
    徐棟_8632閱讀 397評論 0 0
  • 什么是母子之間的分離焦慮呢?給大家提供三個場景: 場景一:亮亮,十個月大的男孩,和父母都在爺爺奶奶家里玩,然后,母...
    天星心理咨詢閱讀 2,143評論 0 4