0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

iOS「自動更新サブスクリプション」のサーバー通知をRubyで受け取る

Last updated at Posted at 2021-01-12

##iOS「自動更新サブスクリプション」のサーバー通知をRubyで受け取る

iOS「自動更新サブスクリプション」のサーバー通知をRubyで受け取る必要があり、いろいろ調べたので備忘録としてまとめてみます!

##構成
マルチプラットフォーム型のサービス
iOSアプリ:Swift
サーバーサイド:Ruby (Ruby on Rails)
※サーバーサイドでの決済システムは他のサービスを利用

##おさらい:サーバー通知とは
サーバーサイドのURLをAppStoreConnectに登録しておくことで、自動更新サブスクリプションのステータスが変更したときにAppleから通知を取得することができます。

この機能があることで、入会・解約・アップグレード・ダウングレードなども配信者側はオンタイムで確認・知ることができます。

##サーバー通知を受信するURL(サーバー)の登録
AppStoreConnect > 該当アプリページ を開きます。
該当アプリページのApp情報(名前などを登録するところ)の右下にある「App Storeサーバー通知のURL」にURLを登録すると、後述のタイミングでAppleStoreからの通知が登録したURLに送られてくるようになります!

##サーバー通知が送られてくるタイミング

ユーザーのイベント 通知タイプ
初回購入 INITIAL_BUY
アップグレード CANCEL,DID_CHANGE_RENEWAL_STATUS, INTERACTIVE_RENEWAL
ダウングレード DID_CHANGE_RENEWAL_PREF
期限が切れた後に再購読 DID_CHANGE_RENEWAL_STATUS
期限が切れた後に別のサブスクを購読 INTERACTIVE_RENEWAL, DID_CHANGE_RENEWAL_STATUS
購読をキャンセル DID_CHANGE_RENEWAL_STATUS
Appleによる返金 CANCEL,DID_CHANGE_RENEWAL_STATUS
決済の問題でサブスクリプションの更新に失敗 DID_FAIL_TO_RENEW
ユーザーへ払い戻し REFUND
サブスクリプションの値上げに同意した PRICE_INCREASE_CONSENT
自動更新が成功 DID_RENEW

##送られてくるJSONの形式

{
    "notification_type": "DID_RENEW",
    "password": " "
    "environment": "Sandbox",
    "auto_renew_product_id": " ",
    "auto_renew_status": "false",
    "unified_receipt": {
        "status":0,
        "environment":"Sandbox",
        "latest_receipt_info": [{
            "quantity": "1",
            "product_id": " ",
            "transaction_id": "000000000000000",
            "purchase_date":"2000-00-00 00:00:00 Etc/GMT", 
            "purchase_date_ms": "0000000000000",
            "purchase_date_pst": "2000-00-00 00:00:00America/Los_Angeles",
            "original_purchase_date": "2000-00-00 00:00:00 Etc/GMT",
            "original_purchase_date_ms": "0000000000000",
            "original_purchase_date_pst": "2000-00-00 00:00:00 America/Los_Angeles",
            "original_transaction_id": "000000000000000",
            "expires_date": "0000000000000",
            "expires_date_ms": "2000-00-00 00:00:00 Etc/GMT",
            "expires_date_pst": "2000-00-00 00:00:00 America/Los_Angeles",
            "web_order_line_item_id": "000000000000000"
            "is_trial_period": "false",
            "is_in_intro_offer_period": "false",
            "original_transaction_id": "00000000",
            "subscription_group_identifier": "00000000"
        },{
           #カラムは上と一緒。各項目には前回分の値が入る。 
        }],
        "latest_receipt":"",  #Base64エンコードされたレシート
        "pending_renewal_info":[{
            "auto_renew_status": "false",
            "auto_renew_product_id": " ",
            "product_id": " ",
            "original_transaction_id": "000000000000000",
        }]
    },
    "bid": " ",
    "bvrs": "1",
    "controller":"",#Ruby 
    "action":"", #Ruby 
    "appstore_notification": {
        "auto_renew_product_id":"", 
        "auto_renew_status":"true", 
        "environment":"Sandbox", 
        "bid":"jp.〇〇.〇〇",
        "bvrs":"1",
        "notification_type":"DID_RENEW",
        "password":""
        "cancellation_date": "0000000000000",
    }

}

##送られてくるJSONの各プロパティの意味
基本はこちらの公式サイトを見ることでわかります!
公式参考サイト

主要で利用したい値だけ今回まとめてみます
※オフィシャルサイトの英文をグーグル翻訳しただけの情報になります。正確な情報は公式サイトを確認してください。

フィールド名 意味
auto_renew_status 自動更新可能なサブスクリプション製品の現在の更新ステータス
auto_renew_status_change_date ユーザーが自動更新可能なサブスクリプションの更新ステータスをオンまたはオフにした時刻。
original_transaction_id 最初の購入のトランザクションID。この値は、ユーザーが購入を復元するか、サブスクリプションを更新する場合を除いて、同じです。
environment AppStoreがレシートを生成した環境。
latest_receipt Base64でエンコードされた最新のトランザクションレシート
latest_receipt_info 値のJSON表現。このフィールドはレシートの配列ですが、サーバー間通知では単一のオブジェクトです
cancellation_date アップルカスタマーサポートがトランザクションをキャンセルした時刻。このフィールドは、返金されたトランザクションにのみ表示されます。
cancellation_reason 返金された取引の理由。顧客がトランザクションをキャンセルすると、App Storeは顧客に返金を行い、このキーの値を提供します。の値は“1” 、アプリ内の実際の問題または認識された問題が原因で顧客がトランザクションをキャンセルしたことを示します。の値は“0” 、トランザクションが別の理由でキャンセルされたことを示します。たとえば、顧客が誤って購入した場合です。
expires_date サブスクリプションの有効期限が切れる時間、またはサブスクリプションが更新される時間
is_trial_period サブスクリプションが無料試用期間内にあるかどうかの指標。
is_upgraded ユーザーがアップグレードしたためにシステムがサブスクリプションをキャンセルしたことを示すインジケーター。このフィールドは、アップグレードトランザクションの場合にのみ表示されます。
product_id 購入した製品の一意の識別子。この値は、App Store Connectで製品を作成するときに指定し、トランザクションのプロパティに格納されているオブジェクトのプロパティに対応します。
purchase_date App Storeが、ISO 8601標準と同様の日時形式で、サブスクリプションの購入または更新に対してユーザーのアカウントに請求した時刻。
quantity 購入した消耗品の数。
subscription_group_identifier サブスクリプションが属するサブスクリプショングループの識別子。このフィールドの値は、SKProductのプロパティと同じです。
transaction_id 購入、復元、更新などのトランザクションの一意の識別子
notification_type 通知をトリガーしたサブスクリプションイベント
password レシートを検証するときにrequestBodyのpasswordフィールドに送信する共有シークレットと同じ値

##送られてくるJSONをRubyで処理するコード
一言で言うと、上記のJSON形式を処理し、タイミング・各プロパティの値に合わせてアプリの処理を記載します。

#例としてreceive_appserver_notificationメソッドとして作成します
def receive_appserver_notification
    unified_receipt = params['unified_receipt'].as_json
    latest_receipt = unified_receipt['latest_receipt']
    latest_receipt_info = unified_receipt['latest_receipt_info']
    
   @mTestObj = TestObj.new()  #保存用のモデル、オブジェクトを用意
   @mTestObj.auto_renew_product_id = unified_receipt['auto_renew_product_id']
   @mTestObj.expires_date = latest_receipt_info['expires_date']
   #==以下省略==

   #処理があれば記載
   if @mTestObj.notification_type == 'INITIAL_BUY'
       #例えば、初期購入だった場合の処理・・・  
   end

   #保存
   begin 
      @mTestObj.save
      puts "保存完了!!"
   rescue => exception
                
   end

end


##まとめ
1.AppStoreConnectで受信するURLを設定しましょう
2.送られてくる形式、パラメーターを理解しましょう
3.サーバーで受け取り、jsonを処理しましょう
4.値に合わせて、必要な処理を実装しましょう

0
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?