I need to receive the server notification of iOS "automatic renewal subscription" in Ruby, and I checked various things, so I will summarize it as a memorandum!
Multi-platform service iOS app: Swift Server side: Ruby (Ruby on Rails)
By registering your server-side URL in App Store Connect, you can be notified by Apple when the status of your auto-renewable subscription changes.
With this function, the distributor can check and know on-time membership, cancellation, upgrade, downgrade, etc.
AppStoreConnect> Open the relevant app page. If you register the URL in "URL of App Store server notification" at the bottom right of the App information (where you register the name etc.) of the corresponding application page, the notification from the Apple Store will be sent to the registered URL at the timing described later. Will be!
User event | Notification type |
---|---|
First purchase | INITIAL_BUY |
upgrade | CANCEL,DID_CHANGE_RENEWAL_STATUS, INTERACTIVE_RENEWAL |
Downgrade | DID_CHANGE_RENEWAL_PREF |
Resubscribe after expiration | DID_CHANGE_RENEWAL_STATUS |
Subscribe to another subscription after it expires | INTERACTIVE_RENEWAL, DID_CHANGE_RENEWAL_STATUS |
Cancel subscription | DID_CHANGE_RENEWAL_STATUS |
Refund by Apple | CANCEL,DID_CHANGE_RENEWAL_STATUS |
Subscription renewal failed due to payment issue | DID_FAIL_TO_RENEW |
Refund to user | REFUND |
I agreed to raise the subscription price | PRICE_INCREASE_CONSENT |
Successful automatic update | DID_RENEW |
{
"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"
},{
#The column is the same as above. Each item contains the value for the previous time.
}],
"latest_receipt":"", #Base64 encoded receipt
"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",
}
}
You can see the basics by looking at this official website! Official reference site
I will summarize only the values that I want to use in the main
Field name | meaning |
---|---|
auto_renew_status | Current renewal status of auto-renewable subscription products |
auto_renew_status_change_date | The time when the user turned on or off the renewal status of an auto-renewable subscription. |
original_transaction_id | Transaction ID of the first purchase. This value is the same unless the user restores the purchase or renews the subscription. |
environment | The environment in which the App Store generated the receipt. |
latest_receipt | Base64-encoded latest transaction receipt |
latest_receipt_info | JSON representation of the value. This field is an array of receipts, but a single object for server-to-server notifications |
cancellation_date | The time when Apple Customer Support canceled the transaction. This field only appears for refunded transactions. |
cancellation_reason | The reason for the refunded transaction. If the customer cancels the transaction, the App Store will refund the customer and provide the value of this key. A value of “1” indicates that the customer canceled the transaction due to a real or recognized issue within the app. The value of is “0”, which indicates that the transaction was canceled for another reason. For example, if a customer makes an accidental purchase. |
expires_date | The time your subscription expires or the time your subscription renews |
is_trial_period | An indicator of whether your subscription is within the free trial period. |
is_upgraded | An indicator that the system has canceled the subscription because the user has upgraded. This field only appears for upgrade transactions. |
product_id | A unique identifier for the purchased product. This value corresponds to the property of the object that you specify when you create the product in App Store Connect and is stored in the transaction properties. |
purchase_date | The time the App Store charges your account for a subscription purchase or renewal in a date and time format similar to the ISO 8601 standard. |
quantity | The number of consumables purchased. |
subscription_group_identifier | The identifier of the subscription group to which the subscription belongs. The value of this field is the same as the property of SKProduct. |
transaction_id | Unique identifier for transactions such as purchases, restores, updates, etc. |
notification_type | Subscription event that triggered the notification |
password | Same value as the shared secret sent to the password field of requestBody when validating the receipt |
In a word, process the above JSON format and describe the processing of the application according to the timing and the value of each property.
#Receive as an example_appserver_Create as notification method
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() #Prepare models and objects for storage
@mTestObj.auto_renew_product_id = unified_receipt['auto_renew_product_id']
@mTestObj.expires_date = latest_receipt_info['expires_date']
#==Omitted below==
#Describe if there is processing
if @mTestObj.notification_type == 'INITIAL_BUY'
#For example, processing when it was an initial purchase ...
end
#Save
begin
@mTestObj.save
puts "Save completed!!"
rescue => exception
end
end