苹果内购记录

修改于 2024/1/26

最近整了一把苹果内购集成,记录一波。

1. 准备事项

  1. 苹果开发者账号
  2. 苹果appstoreconnect 认证(付费)
  3. 付款信息
  4. 提供一个账号给开发
  5. 配置内购产品信息:名称和价格这些属性

嘿嘿,以上这些事情统统交给产品。如果没有产品,那就交给老板吧。
【图片】

如果他们不愿意,和他们说的时候带上这个
【图片】

3. 开搞前缕缕思路

苹果内购集成有两个版本:
V1:集成体验差
V2:集成体验不错,有SDK

看起来选择V2没跑了,可是那个劳什子产品说我们的App要兼容iOS14,我直接谢。敢情玩我呢,让我看到了希望,又把我的希望给掐灭了。反思了一下,应该是技术方案评审的时候忘记带谈判神器了,毕竟神器在手,产品只能苟。
在这里插入图片描述

棋差一着,只能忍着心里的不痛快,赶紧把思路给搞出来。毕竟老板也想着快点赚钱,要是耽误了老板赚钱,直接降本增笑就难受了。那就继续搬砖吧,先把逻辑给搞一下:

在这里插入图片描述

这整套流程执行下来如果都成功,那是相当完美的。这句话的意思是如果有些地方执行不成了,那就完犊子了。相信你也发现了,这里最关键的一步是:【完成交易】。如果这一步出问题,那就是用户给钱了,但没给用户发服务。

这就是著名的苹果内购掉单问题。那怎么破呢?
第一步:穿上西装站直
第二步:弯腰90度
第三步:虔诚地说出:对不起

不好意思,走错片场了。

第一步发现问题:

  • 用户写邮件来对线了
  • 每天查一下苹果后台交易成功的数量和后台数据库交易成功的数量能不能对上
  • 客户端和服务端加上日志

第二步排查问题:

  • 用户找你的时候要他提供订单号,然后可以通过API查询到这笔订单是否真实存在
  • 苹果后台数据和服务后台数据对不上的时候赶紧查日志去

第三步解决问题:

  • 客户端做另外的掉单处理,比如说轮训查还有有没有交易是没完成的,然后重新提交服务端
  • 手动给用户补发
  • 退款(让用户去苹果退,开发者只能协助)

4. 差不多了,开搞

其实,已经搞完了。。

还有一个问题:苹果的订单怎么和后台的订单对应上?

正常情况下,苹果和后台是通过交易ID关联起来的。但怕的就是不正常的情况。
假设用户购买了一个商品之后,去服务端发放权益的时候失败了。用户以为是App的bug,结果把App卸载重装了,一重装App保存的交易ID可就没了。

这个时候还剩下什么?用户的设备ID,用户的uid和交易凭证。
我们只能在这三个值之间开辟出一条路来的。众所周知,交易凭证不能带任何自定义的信息(applicationUsername这个属性是个坑,别踩),所以抛去一切复杂的逻辑之后,最简单的就是根据这三个值:uid+商品id+购买时间 来寻找一个后台合适的交易挂上(这里不得不淬一口,是真的恶心)

在这里插入图片描述

交易凭证验证:

这玩意解析压根就不用token

官方文档:verifyReceipt | Apple Developer Documentation

退款回调:(夭寿啦,忘了这一步,老板差点就启动减本增笑技能了)

注意:URL只能配置HTTPS协议的

在这里插入图片描述

@PostMapping("/notifications")
public Object notify(@Valid @RequestBody String body) {
    log.info("App store server notifications: {}", body);

/*
{
"notification_type": "REFUND",
"password": "xxxxxxxx",
"environment": "PROD","unified_receipt": {
    "status": 0,
    "environment": "Production",
    "latest_receipt_info": [
        {
            "quantity": "1",
            "product_id": "xxxxxx",
            "transaction_id": "xxxxxx",
            "purchase_date": "2024-01-13 23:09:30 Etc/GMT",
            "purchase_date_ms": "1705187370000",
            "purchase_date_pst": "2024-01-13 15:09:30 America/Los_Angeles",
            "original_purchase_date": "2024-01-13 23:09:30 Etc/GMT",
            "original_purchase_date_ms": "1705187370000",
            "original_purchase_date_pst": "2024-01-13 15:09:30 America/Los_Angeles",
            "is_trial_period": "false",
            "original_transaction_id": "xxxxxx",
            "cancellation_date": "2024-01-15 21:57:44 Etc/GMT",
            "cancellation_date_ms": "1705355864000",
            "cancellation_date_pst": "2024-01-15 13:57:44 America/Los_Angeles",
            "cancellation_reason": "0",
            "in_app_ownership_type": "PURCHASED"
        }
    ],
    "latest_receipt": "MIIUcQYJKoZIhvcNAQcCxxxxxx......."
},
"bid": "<bundleID>",
"bvrs": "64",
"original_transaction_id": xxxxxxxx,
"deprecation": "Mon, 5 Jun 2023 23:59:59 GMT"
}
*/

    // https://developer.apple.com/documentation/appstoreservernotifications/app_store_server_notifications_v1
    // https://developer.apple.com/documentation/appstoreservernotifications/responsebodyv1
    // https://developer.apple.com/documentation/appstoreservernotifications/notification_type
    JsonNode jsonNode = JacksonUtils.parseJson(body);
    String notificationType = jsonNode.get("notification_type").asText();
    IapV1NotificationType type = IapV1NotificationType.of(notificationType);

    //TODO 处理逻辑

    return ResponseEntity.ok().body("OK");
}

Ref

代码看这个大佬的:Java接入苹果支付 – IAP支付 – IOS应用内支付- 完整版 - Java实战博客 (zanglikun.com)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值