我的编程空间,编程开发者的网络收藏夹
学习永远不晚

服务端IOS订阅类型支付接入详细说明与注意事项

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

服务端IOS订阅类型支付接入详细说明与注意事项

由于本人在开发ios订阅类型支付接入的时候,遇到了很多坑,也查了不少资料,逐步完善了整个ios订阅支付服务端接入的功能,在这里写下总结和一些注意事项的记录,方便未来需要重新接入或者避免一些不必要的坑,这里主要讲的是服务端的接入。

客户端实现ios订阅支付后,支付成功会返回一个收据(一大串随机字符串),需要请求苹果服务器的接口来校验该收据的真实性,同时校验完成后苹果服务器也会发通知告诉我们的自己的服务器(ios后台配置的回调地址),这个时候就需要服务端来接入苹果服务器并处理该支付逻辑。这里不使用客户端直接接入苹果服务器校验收据接口的原因大概就是因为订阅类型需要共享密钥,防止该密钥暴露,同时服务器接入能更好处理逻辑。

订阅类型需要从苹果后台获取一个共享密钥

需要在苹果后台配置好回调地址

需要配置订阅产品(周期,价格,我自己没什么了解,这个需要注意的是订阅有按组分,同一个组和不同组的产品是有区别的,例如同一个组的不同产品进行购买,他们的原始订单可能相同)

简体中文文档 - Apple Developer

校验收据:通过 App Store 验证收据 - 简体中文文档 - Apple Developer

回调通知:启用 App Store 服务器通知 - 简体中文文档 - Apple Developer

退款处理:处理退款通知 - 简体中文文档 - Apple Developer

收据校验沙箱环境:https://sandbox.itunes.apple.com/verifyReceipt

收据校验生产环境:https://buy.itunes.apple.com/verifyReceipt

1.服务端接入apple校验收据接口

注意事项:防止相同数据重复校验或者相同请求大量请求导致的不稳定因素,建议使用时间戳校验预防,不要将共享密钥暴露在客户端,共享密钥同时也可以对回调通知进行校验,校验收据后不要做为订单处理,最好一切以回调为主。

接口地址:https://buy.itunes.apple.com/verifyReceipt

接口类型:POST

接口格式:appliaction/json

功能说明:该接口主要是用来恢复订阅和支付校验,校验完成会有回调通知到商户服务器

请求参数:

官方:Apple Developer Documentation

{    "password":"这里是共享密钥",    "receipt-data":"这里是收据的字符串"}

返回结果:

状态码:Apple Developer Documentation

失败:

{"status":21000}

成功:

成功结果参数文档:responseBody | Apple Developer Documentation

主要参数说明:

{    "environment": "Production",   //请求环境    "receipt": {        "receipt_type": "Production",        "adam_id": xxx,        "app_item_id": xxx,        "bundle_id": "com.xxx",        "application_version": "2",        "download_id": xxx,        "version_external_identifier": xxx,        "receipt_creation_date": "2022-10-24 07:14:36 Etc/GMT",        "receipt_creation_date_ms": "1666595676000",        "receipt_creation_date_pst": "2022-10-24 00:14:36 America/Los_Angeles",        "request_date": "2023-02-24 03:29:47 Etc/GMT",        "request_date_ms": "1677209387760",        "request_date_pst": "2023-02-23 19:29:47 America/Los_Angeles",        "original_purchase_date": "2022-07-04 03:24:29 Etc/GMT",        "original_purchase_date_ms": "1656905069000",        "original_purchase_date_pst": "2022-07-03 20:24:29 America/Los_Angeles",        "original_application_version": "2",        "in_app": [  //所有订单都可能存在,主要是非订阅订单            {                "quantity": "1",                "product_id": "xxxx",                "transaction_id": "xxxx",                "original_transaction_id": "xxx",                "purchase_date": "2022-07-04 03:25:29 Etc/GMT",                "purchase_date_ms": "1656905129000",                "purchase_date_pst": "2022-07-03 20:25:29 America/Los_Angeles",                "original_purchase_date": "2022-07-04 03:25:30 Etc/GMT",                "original_purchase_date_ms": "1656905130000",                "original_purchase_date_pst": "2022-07-03 20:25:30 America/Los_Angeles",                "expires_date": "2022-07-11 03:25:29 Etc/GMT",                "expires_date_ms": "1657509929000",                "expires_date_pst": "2022-07-10 20:25:29 America/Los_Angeles",                "web_order_line_item_id": "xxx",                "is_trial_period": "false",                "is_in_intro_offer_period": "false",                "in_app_ownership_type": "PURCHASED"            }        ]    },    "latest_receipt_info": [  //订单订阅集合,从上往下订单时间倒序,第一个为最新的支付订单        {            "quantity": "1",            "product_id": "xxx",  //订单产品id,apple后台支付配置的参数            "transaction_id": "xxx",  //apple当前订单号            "original_transaction_id": "xxx",  //apple原始订单号,该用户在该产品第一笔支付订单,可当做同一批订单朔源            "purchase_date": "2022-11-25 08:19:27 Etc/GMT", //订单时间            "purchase_date_ms": "1669364367000",            "purchase_date_pst": "2022-11-25 00:19:27 America/Los_Angeles",            "original_purchase_date": "2022-07-04 03:25:30 Etc/GMT",  //最初购买时间            "original_purchase_date_ms": "1656905130000",            "original_purchase_date_pst": "2022-07-03 20:25:30 America/Los_Angeles",            "expires_date": "2023-11-25 08:19:27 Etc/GMT",  //订阅过期时间            "expires_date_ms": "1700900367000",            "expires_date_pst": "2023-11-25 00:19:27 America/Los_Angeles",            "web_order_line_item_id": "xxx",            "is_trial_period": "false",  //是否是试用订单            "is_in_intro_offer_period": "false",            "in_app_ownership_type": "PURCHASED",            "subscription_group_identifier": "xxx"        }    ],    "latest_receipt": "------------加密串------------",    "pending_renewal_info": [        {            "auto_renew_product_id": "xxx",            "product_id": "xxx",            "original_transaction_id": "xxx",            "auto_renew_status": "0"        }    ],    "status": 0  //状态成功}

 

 2.apple支付回调通知接入

回调通知配置:苹果后台可配置生产环境和沙箱环境的APPLE回调通知地址

接入文档:responseBodyV1 | Apple Developer Documentation

提示:接入apple支付回调apple提供了v1和v2两种类型,v2需要多一步加解密的操作

功能说明:该通知主要是订单状态的变更等,包括续订,付费通知,取消订阅,退款等通知

可进行订单处理

通知类型说明:

INITIAL_BUY
首次购买
REFUND
退款
CANCEL
取消订阅
DID_RENEW
自动续订
INTERACTIVE_RENEWAL
应用界面或appstore手动续订
DID_RECOVER
恢复订阅

回调请求参数示例

{    "notification_type":"DID_RENEW",  //通知类型,该类型为续订通知    "auto_renew_product_id":"xxx",    "password":"xxx",  //共享密钥,可以验证是否真实通知    "environment":"Sandbox",    "original_transaction_id":xxx,    "unified_receipt":{        "status":0,        "environment":"Sandbox",        "latest_receipt_info":[  //第一笔为最新的通知订单            {                "quantity":"1",                "product_id":"xxx",                "transaction_id":"xxx", //当前订单号                "purchase_date":"2022-06-08 09:51:55 Etc/GMT",                "purchase_date_ms":"1654681915000",                "purchase_date_pst":"2022-06-08 02:51:55 America/Los_Angeles",                "original_purchase_date":"2022-06-08 04:36:20 Etc/GMT",                "original_purchase_date_ms":"1654662980000",                "original_purchase_date_pst":"2022-06-07 21:36:20 America/Los_Angeles",                "expires_date":"2022-06-08 09:54:55 Etc/GMT",                "expires_date_ms":"1654682095000",                "expires_date_pst":"2022-06-08 02:54:55 America/Los_Angeles",                "web_order_line_item_id":"xxx",                "is_trial_period":"false",                "is_in_intro_offer_period":"false",                "original_transaction_id":"xxx", //原始订单号,该产品首次的订单号                "in_app_ownership_type":"PURCHASED",                "subscription_group_identifier":"xxx"            },            {                "quantity":"1",                "product_id":"xxx",                "transaction_id":"xxx",                "purchase_date":"2022-06-08 09:48:03 Etc/GMT",                "purchase_date_ms":"xxx",                "purchase_date_pst":"2022-06-08 02:48:03 America/Los_Angeles",                "original_purchase_date":"2022-06-08 04:36:20 Etc/GMT",                "original_purchase_date_ms":"1654662980000",                "original_purchase_date_pst":"2022-06-07 21:36:20 America/Los_Angeles",                "expires_date":"2022-06-08 09:51:03 Etc/GMT",                "expires_date_ms":"1654681863000",                "expires_date_pst":"2022-06-08 02:51:03 America/Los_Angeles",                "web_order_line_item_id":"xxx",                "is_trial_period":"false",                "is_in_intro_offer_period":"false",                "original_transaction_id":"xxx",                "in_app_ownership_type":"PURCHASED",                "subscription_group_identifier":"xxx"            }        ],        "pending_renewal_info":[            {                "auto_renew_status":"1",                "auto_renew_product_id":"xxx",                "product_id":"xxx",                "original_transaction_id":"xxx"            }        ]    },    "bvrs":"xxx",    "bid":"com.xxx",    "auto_renew_status":"true"}

latest_receipt_info集合订单按时间倒序排序,所以第一笔为最新的订单

ios收据为账户维度,即收据和通知获取的数据为该账户的历史订单集合,非当前支付

ios订单未返回金额等参数,需要自己做处理

ios退款通知不支持订阅类型

apple支付为全球性支付,需要自己处理货币转换

同一个产品包括同产品组,在同一个账户支付会生成一个原始订单号,可根据该订单号溯源

订单校验只适用于恢复订阅和收据校验,具体支付处理按通知为主

状态码21007为测试环境的收据请求到了正式环境

来源地址:https://blog.csdn.net/weixin_42736075/article/details/127542621

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

服务端IOS订阅类型支付接入详细说明与注意事项

下载Word文档到电脑,方便收藏和打印~

下载Word文档

编程热搜

  • Android:VolumeShaper
    VolumeShaper(支持版本改一下,minsdkversion:26,android8.0(api26)进一步学习对声音的编辑,可以让音频的声音有变化的播放 VolumeShaper.Configuration的三个参数 durati
    Android:VolumeShaper
  • Android崩溃异常捕获方法
    开发中最让人头疼的是应用突然爆炸,然后跳回到桌面。而且我们常常不知道这种状况会何时出现,在应用调试阶段还好,还可以通过调试工具的日志查看错误出现在哪里。但平时使用的时候给你闹崩溃,那你就欲哭无泪了。 那么今天主要讲一下如何去捕捉系统出现的U
    Android崩溃异常捕获方法
  • android开发教程之获取power_profile.xml文件的方法(android运行时能耗值)
    系统的设置–>电池–>使用情况中,统计的能耗的使用情况也是以power_profile.xml的value作为基础参数的1、我的手机中power_profile.xml的内容: HTC t328w代码如下:
    android开发教程之获取power_profile.xml文件的方法(android运行时能耗值)
  • Android SQLite数据库基本操作方法
    程序的最主要的功能在于对数据进行操作,通过对数据进行操作来实现某个功能。而数据库就是很重要的一个方面的,Android中内置了小巧轻便,功能却很强的一个数据库–SQLite数据库。那么就来看一下在Android程序中怎么去操作SQLite数
    Android SQLite数据库基本操作方法
  • ubuntu21.04怎么创建桌面快捷图标?ubuntu软件放到桌面的技巧
    工作的时候为了方便直接打开编辑文件,一些常用的软件或者文件我们会放在桌面,但是在ubuntu20.04下直接直接拖拽文件到桌面根本没有效果,在进入桌面后发现软件列表中的软件只能收藏到面板,无法复制到桌面使用,不知道为什么会这样,似乎并不是很
    ubuntu21.04怎么创建桌面快捷图标?ubuntu软件放到桌面的技巧
  • android获取当前手机号示例程序
    代码如下: public String getLocalNumber() { TelephonyManager tManager =
    android获取当前手机号示例程序
  • Android音视频开发(三)TextureView
    简介 TextureView与SurfaceView类似,可用于显示视频或OpenGL场景。 与SurfaceView的区别 SurfaceView不能使用变换和缩放等操作,不能叠加(Overlay)两个SurfaceView。 Textu
    Android音视频开发(三)TextureView
  • android获取屏幕高度和宽度的实现方法
    本文实例讲述了android获取屏幕高度和宽度的实现方法。分享给大家供大家参考。具体分析如下: 我们需要获取Android手机或Pad的屏幕的物理尺寸,以便于界面的设计或是其他功能的实现。下面就介绍讲一讲如何获取屏幕的物理尺寸 下面的代码即
    android获取屏幕高度和宽度的实现方法
  • Android自定义popupwindow实例代码
    先来看看效果图:一、布局
  • Android第一次实验
    一、实验原理 1.1实验目标 编程实现用户名与密码的存储与调用。 1.2实验要求 设计用户登录界面、登录成功界面、用户注册界面,用户注册时,将其用户名、密码保存到SharedPreference中,登录时输入用户名、密码,读取SharedP
    Android第一次实验

目录