客户端请使用StoreKit2, 服务端通知

数据库设计(省略不重要字段)代码语言:javascript复制# 订单表

mysql> desc orders;

+------------------+---------------------+------+-----+---------+----------------+

| Field | Type | Null | Key | Default | Extra |

+------------------+---------------------+------+-----+---------+----------------+

| id | bigint(20) unsigned | NO | PRI | NULL | auto_increment |

| no | varchar(255) | NO | UNI | NULL | |

| trade_no | varchar(255) | YES | | NULL | |

| status | tinyint(4) | NO | | NULL | |

| origin_no | varchar(255) | YES | | NULL | |

+------------------+---------------------+------+-----+---------+----------------+

# 用户签约表

mysql> desc member_contracts;

+-----------------+---------------------+------+-----+---------+-------+

| Field | Type | Null | Key | Default | Extra |

+-----------------+---------------------+------+-----+---------+-------+

| user_id | bigint(20) unsigned | NO | PRI | NULL | |

| status | tinyint(4) | NO | | NULL | |

| contract_id | varchar(255) | NO | MUL | NULL | |

+-----------------+---------------------+------+-----+---------+-------+服务端处理逻辑订阅到期重新订阅appAccountToken,originalTransactionId会变(订阅退订, 然后超过有效期后)订阅期内取消订阅, 然后又重新订阅appAccountToken,originalTransactionId不变客户端下单代码语言:javascript复制## 客户端请求创建订单接口生成订单号`$uuid`, 返回给客户端放入`appAccountToken`

INSERT INTO orders(no) VALUES('$uuid');服务端事件回调-用户订阅苹果服务端notificationV2回调处理 && 客户端回调处理 (一个JWS字符串)代码语言:javascript复制## 解析服务端回调, 确认`notificationType=SUBSCRIBED`且二级事件`subtype in INITIAL_BUY RESUBSCRIBE AUTO_RENEW_ENABLED`(根据自己要求处理事件, 验证商品`ID`和包名等是否符合条件)

## 重要的字段: appAccountToken,transactionId,originalTransactionId,expiresDate

## 1. 查询 appAccountToken 订单是否存在

select * from orders where no='{$appAccountToken}' limit 1 => $id;

## 2. 修改订单状态信息, 包括已付款

update orders set trace_no='$transactionId', origin_no='$originalTransactionId' where id=$id;

## 3. 修改用户订阅状态

update member_contracts set contract_id='$originalTransactionId';

## ... 赠送会员等等等服务端事件回调-用户订阅代码语言:javascript复制## notificationType=DID_RENEW

## 1. 通过`transactionId`查询订单是否存在, 如果存在直接返回已经通知过

select * from orders where trade_no='{$transactionId}' limit 1 => $id

## 2. 如果不存在, 那么通过 originalTransactionId 查询到订阅表, 得到订阅的创建订单信息;

select * from member_contracts where contract_id='$originalTransactionId' limit 1;

## 3. 通过订阅表信息直接插入一条已付款的订单信息

INSERT INTO orders(no, trade_no, origin_no) VALUES('$uuid', '$transactionId', '$originalTransactionId');

## ... 赠送会员等等等退订事件代码语言:javascript复制update member_contracts set status=xxx where contract_id='$originalTransactionId';客户端回调客户端回调得到的JWS字符串解析出来的字段 === 苹果服务端回调的字段.Data.SignedTransactionInfo所以客户端把凭证串发给服务端, 服务端抽象出订阅事件的代码, 在苹果服务端回调和客户端验单共用就行代码语言:javascript复制// 获取商品信息

products = try await Product.products(for: Set(productIds))

// 支付,先请求服务端创建订单接口获得 uuid

let uuid = Product.PurchaseOption.appAccountToken(UUID.init(uuidString: "$uuid")!)

let result = try await product.purchase(options: [uuid])

//处理支付结果,此时苹果内部已经进行了JWS校验

switch result {

case .success(let verificationResult):

// 把 verificationResult 发给服务端去校验, 防止苹果服务端回调慢

// 把 verificationResult 发给服务端去校验, 防止苹果服务端回调慢

// 把 verificationResult 发给服务端去校验, 防止苹果服务端回调慢

case .userCancelled:

//处理取消

case .pending:

//交易可能会在未来成功,通过Transaction.updates进行通知。

}更多事件请按需处理

Copyright © 2088 世界杯名额_世界杯结果 - tylzr.com All Rights Reserved.
友情链接