在2019年末的时候,苹果总算是姗姗来迟推出了服务端通知功能,在2020年中下旬推出了退款通知,做过微信、支付宝支付的同学应该很了解这个模式了。 这个模式在微信、支付宝支付中通常的流程都是前端发起了支付行为,前台会即时的返回一个收款确认,而在很短的一段时间后,支付平台会向我们的服务器端发送 一条(得不到正确响应的时候会多次间隔发送)通知请求,一般称之为Notify。
Notify一般会加密携带订单的支付数据,成功与否等,相当于给后端一个比较安全的确认,因为前端即时的反馈数据并不能保证绝对的可靠。 早前在做苹果的应用内支付的时候就对苹果没有回调通知感到很苦恼,因为确认只能自己从服务端向苹果发送验证请求,而且通常是要二次确认才能判断充值是否有效。
这次苹果更新了服务端通知功能,当然是用起来了。
这个功能的使用也是非常简单,苹果的要求有3点:
1. 服务器支持ATS访问
这个其实也就是后台的连接可以支持443( https: ) 方式访问
2. 配置一个用于接收POST消息的 URL
实际上就是提供一个POST接口地址专门用来接收苹果的消息通知 譬如说 举个例子: https://api.shezw.com/notify/appstore
3. 在App Store Connect中配置对应的URL
这个比较简单,打开App Store connect,在 应用 > App信息 > 综合信息 > App Store 服务器通知网址 (URL)
中填入上面的URL就可以了。
其实就是选择 应用语言、应用分类的下面。
苹果发送的通知格式
POST requestBody (JSON)
苹果会以POST方式发送数据到我们的服务器,其中数据以JSON格式被写入在requestBody中。 ps: 如果在PHP语言中,需要以file_get_contents("php://input")
来获取数据内容。
接下来说一下具体处理通知数据,以及有哪些注意事项。
整个数据是一个json对象,字段分别有:
代码语言:javascript复制/*
auto_renew_adam_id string
auto_renew_product_id string
auto_renew_status string
auto_renew_status_change_date string
auto_renew_status_change_date_ms string
auto_renew_status_change_date_pst string
environment string Sandbox, PROD
expiration_intent int
bid string A string that contains the app bundle ID.
bvrs string A string that contains the app bundle version.
password string The same value as the shared secret you submit in the password field of the requestBody when validating receipts.
unified_receipt An object that contains information about the most-recent, in-app purchase transactions for the app.
*/
首先看一下,通知类型:
notification_type
代码语言:javascript复制/*
CANCEL
表示Apple客户支持取消了订阅或用户升级了订阅。 cancel_date键包含更改的日期和时间。
DID_CHANGE_RENEWAL_PREF
指示客户对其订购计划进行了更改,该更改在下一次续订时生效。当前有效的计划不受影响。
DID_CHANGE_RENEWAL_STATUS
指示订阅续订状态的更改。在JSON响应中,检查auto_renew_status_change_date_ms以了解上一次状态更新的日期和时间。检查auto_renew_status以了解当前的续订状态。
DID_FAIL_TO_RENEW
表示由于计费问题而无法续订的订阅。检查is_in_billing_retry_period以了解订阅的当前重试状态。如果订阅处于计费宽限期内,请检查grace_period_expires_date以了解新服务的到期日期。
DID_RECOVER
表示成功的自动更新已过期的订阅,而该订阅过去无法更新。检查expires_date,以确定下一个续订日期和时间。
DID_RENEW
表示客户的订阅已成功自动续订了新的交易期。
INITIAL_BUY
在用户最初购买订阅时发生。通过在App Store上对其进行身份验证,可以将Latest_receipt作为令牌存储在服务器上,以随时验证用户的订阅状态。
INTERACTIVE_RENEWAL
指示客户使用您的应用程序界面或在该帐户的“订阅”设置中的App Store上以交互方式续订了订阅。立即提供服务。
PRICE_INCREASE_CONSENT
表示App Store已开始要求客户同意您的应用的订阅价格上涨。在Unified_receipt.Pending_renewal_info对象中,price_consent_status值为0,表示App Store正在征求客户的同意,但尚未收到。除非用户同意新价格,否则订阅不会自动续订。当客户同意提价时,系统将price_consent_status设置为1。使用verifyReceipt检查收货以查看更新的价格同意状态。
REFUND
表示App Store成功退还了一笔交易。 cancel_date_ms包含已退款交易的时间戳。 original_transaction_id和product_id标识原始交易和产品。 cancel_reason包含原因。
RENEWAL (在沙盒中弃用)
表示成功的自动更新已过期的订阅,而该订阅过去无法更新。检查expires_date,以确定下一个续订日期和时间。此通知在沙箱环境中已弃用,计划于2021年3月在生产中弃用。更新现有代码以改为依赖DID_RECOVER通知类型。
REVOKE 撤销
表示用户不再可以通过“家庭共享”获得应用内购买。当购买者禁用产品的家庭共享,购买者(或家庭成员)离开家庭组或购买者要求并收到退款时,StoreKit会发送此通知。您的应用程序还将收到PaymentQueue(_:didRevokeEntitlementsForProductIdentifiers :)调用。有关家庭共享的更多信息,请参阅在应用程序中支持家庭共享。
*/
Password 不是必须的,只有购买订阅和收到订阅相关的消息,才会需要这一项. 只是普通内购 就没有这一项。
Send the Receipt Data to the App Store On your server, create a JSON object with the receipt-data, password (if the receipt contains an auto-renewable subscription), and exclude-old-transactions keys detailed in requestBody.