part 1
苹果支付是苹果公司推出的一种在线支付方式,可以让用户在应用内进行购买和付款。对于开发者来说,开通苹果支付可以为他们带来一定的收益。
下面详细介绍如何在iOS上架苹果支付。
注册开发者账号
创建App ID: 创建App ID时,你需要为你的应用程序选择一个唯一的Bundle ID,并将它与你的App ID关联起来。
创建证书
(1) 开发证书用于开发测试应用程序。
(2) 发布证书用于开发测试和在App Store上发布应用程序
4. 创建App Store连接
5. 集成苹果支付: 在集成苹果支付之前,你需要在苹果开发者后台对内购金额进行申请( 包含金额和内购对应的id , 创建之后金额可以在规则内随意进行修改, 但是id 无法变更)。
6. 提交应用程序
7. 审核应用程序
用户在app内购买的具体流程图 ( 简称: 内购 ):
步骤很完善, 但是需要细心去一步步的验证完成, 才能有效保证账单的准确性.
但是有部分用户的呢, 对这个过程动了歪脑筋
大家可以先想象这个过程会产生哪些问题, 有哪些漏洞
这里就不卖关子了, 直接说了, 用户在凭证上做了手脚, 导致账单通过服务器的验证,
具体操作流程如下,
用户操作流程
- 通过 步骤2 获取我们的内购对应的 内购id,
2. 在自己app通过相同 内购id 申请内购应用, 并上架应用市场
3. 在自己app完成支付之后拿到凭证( 步骤6 )
4. 通过技术手段进行数据请求, 拿着凭证通过步骤9 在我们接口进行验证充值到自己账户
或许有很多人会说, 我们的验证已经很完善了.
到此可以略过,
如果感觉自己做的还不完善的, 可以继续向下看, 或者点击这里
凭证验证地址
正式环境 'https://buy.itunes.apple.com/verifyReceipt'
测试环境 'https://sandbox.itunes.apple.com/verifyReceipt'
参数: receipt 为支付之后拿到的凭证
"receipt-data":receipt
通过上面的方法就能拿到我们对应的数据
获取到的凭证信息
{
"receipt": {
"app_item_id": "xxxxx", //App Store用来标识程序的字符串
"bid": "com.xxx.xx", //iPhone程序的 bundleid 标识
"bvrs": "63", //iPhone 程序的版本号
"in_app_ownership_type": "PURCHASED",
"is_in_intro_offer_period": "false",
"is_trial_period": "false",
"item_id": "6449450011",
"original_purchase_date": "2023-05-29 08:23:25 Etc/GMT", //原始购买时间 或者说是格林威治时间
"original_purchase_date_ms": "1685348605218", //购买时间毫秒
"original_purchase_date_pst": "2023-05-29 01:23:25 America/Los_Angeles", //购买时间,太平洋标准时间
"original_transaction_id": "2000000339644706", //原始交易ID
"product_id": "xxxxxxxx", //商品的标识
"purchase_date": "2023-05-29 08:23:25 Etc/GMT", //购买时间
"purchase_date_ms": "1685348605218",
"purchase_date_pst": "2023-05-29 01:23:25 America/Los_Angeles",
"quantity": "1",
"transaction_id": "200000033964xx06", //交易的标识
"unique_identifier": "00008020-001275303628002E", //唯一标识符
"unique_vendor_identifier": "2C471E00-BB68-4635-AA55-45D3D9621208" //开发商交易ID
},
"status": 0
}
首先需要保证
-
product_id
就是在苹果后台对应的设置的不能修改的id
-
transaction_id
是订单对应的唯一的 id , -
需要验证
bid
是不是我们公司自己的包名 或者说app_item_id
是不是你的app对应的 appleid -
其他的想要的话加上就行了, 不想要的话可以暂时不用考虑
我们就是因为缺少 步骤3, 吃了亏导致账单出现了问题, 这个问题排查了很久才找到了具体原因, 发现之后就立马进行修复, 算是及时止损的吧, 不管自己app 有没有上面的3个验证的, 都去验证一下的吧, 确保不能在自己手上出现问题, 对吧!!!
part 2
就上面的苹果认证过程, 请求结果的验证码有如下几种情况, 验证的错误码分别有
0 验证通过的 - 对 就上上面的 status
21000 验证请求不是使用HTTP POST请求方法发出的
21002 凭据数据不符合格式或服务遇到临时问题
21003 订单无法被验证
21004 密钥不匹配
21005 凭据服务器当前不可用
21006 凭据是有效的,但订阅服务已经过期(iOS 6之前会这样)。当收到这个信息时,解码后的收据信息也包含在返回内容中
21007 订单信息是测试用(sandbox),但却被发送到产品环境中验证
21008 订单信息是产品环境中使用,但却被发送到测试环境中验证
21009 内部数据访问错误
21010 找不到或已删除用户帐户
part 3
再实际开发中发现数据结果有
{
"receipt": {
...
"app_item_id": ""
...
},
"status": 0
}
还有这个, 数据解析可以参考上面的
{
"environment": "Sandbox",
"receipt": {
"adam_id": 0,
"app_item_id": 0,
"application_version": "518",
"bundle_id": "com.xxx.xxx",
"download_id": 0,
"in_app": [
{
"in_app_ownership_type": "PURCHASED",
...
},
{
"in_app_ownership_type": "PURCHASED",
...
},
],
"original_application_version": ""
...
},
"status": 0
}
这 2种 情况分别在什么情况下出现的呢? 为什么会有这2中情况的呢?
情况1 是在那这认证成功之后苹果的返回的凭证直接使用的 (就是 ewoJInNpZ25hdHVyZ...
格式的有效凭证)
情况2 是支付之后, 没有验证过的, 沙盒里面拿到的的(就是 MIIXRAYJKoZIhvcNAQcCoI...
格式的有效凭证), 这种方式的话, 如果有多个订单都没有进行服务器验证的话, 可以找服务器进行验证的, 验证之后可以删除了
可以通过 NSURL *receiptURL = [[NSBundle mainBundle] appStoreReceiptURL];
获取本地存储的支付凭证
part 4
记录苹果支付的问题
拿着苹果返回的和从沙盒拿到的同时给到了服务器的话, 导致数据库存储出现问题
-
先验证
receipt-data
给保证是唯一的 -
再验证 解析出来的
transaction_id
保证是唯一
通过上面 2步(可以加锁什么的)就可以大概率的保证数据的准确性了,
End