更新ios
This commit is contained in:
@@ -405,24 +405,37 @@ const SubscriptionScreen = () => {
|
|||||||
const purchase = await iapService.purchaseProduct(productInfo.productId);
|
const purchase = await iapService.purchaseProduct(productInfo.productId);
|
||||||
|
|
||||||
// 验证收据并激活订阅
|
// 验证收据并激活订阅
|
||||||
|
// 注意:purchaseUpdatedListener 也可能触发验证,但后端有防重复机制
|
||||||
if (purchase && purchase.transactionReceipt) {
|
if (purchase && purchase.transactionReceipt) {
|
||||||
const result = await iapService.verifyAndActivateSubscription(
|
// 标记此交易正在处理中(防止监听器重复处理)
|
||||||
purchase.transactionReceipt,
|
if (purchase.transactionId) {
|
||||||
productInfo.productId
|
iapService.processingTransactions.add(purchase.transactionId);
|
||||||
);
|
}
|
||||||
|
|
||||||
if (result.success) {
|
try {
|
||||||
// 完成交易(传入完整的 purchase 对象)
|
const result = await iapService.verifyAndActivateSubscription(
|
||||||
await iapService.finishPurchase(purchase);
|
purchase.transactionReceipt,
|
||||||
|
productInfo.productId
|
||||||
// 刷新用户信息
|
|
||||||
await refreshUser();
|
|
||||||
|
|
||||||
Alert.alert(
|
|
||||||
'订阅成功',
|
|
||||||
`您已成功订阅${plan.displayName}!`,
|
|
||||||
[{ text: '好的', onPress: () => navigation.goBack() }]
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (result.success) {
|
||||||
|
// 完成交易(传入完整的 purchase 对象)
|
||||||
|
await iapService.finishPurchase(purchase);
|
||||||
|
|
||||||
|
// 刷新用户信息
|
||||||
|
await refreshUser();
|
||||||
|
|
||||||
|
Alert.alert(
|
||||||
|
'订阅成功',
|
||||||
|
`您已成功订阅${plan.displayName}!`,
|
||||||
|
[{ text: '好的', onPress: () => navigation.goBack() }]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
// 移除处理中标记
|
||||||
|
if (purchase.transactionId) {
|
||||||
|
iapService.processingTransactions.delete(purchase.transactionId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|||||||
@@ -110,6 +110,8 @@ class IAPService {
|
|||||||
this.subscriptions = [];
|
this.subscriptions = [];
|
||||||
this.purchaseUpdateSubscription = null;
|
this.purchaseUpdateSubscription = null;
|
||||||
this.purchaseErrorSubscription = null;
|
this.purchaseErrorSubscription = null;
|
||||||
|
// 用于防止重复验证的标记
|
||||||
|
this.processingTransactions = new Set();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -170,11 +172,26 @@ class IAPService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 购买成功/更新监听器
|
// 购买成功/更新监听器
|
||||||
|
// 注意:这个监听器主要用于处理后台恢复的购买或 App 重启后的未完成交易
|
||||||
|
// 正常购买流程由 SubscriptionScreen 的 handleSubscribe 处理
|
||||||
this.purchaseUpdateSubscription = purchaseUpdatedListener(async (purchase) => {
|
this.purchaseUpdateSubscription = purchaseUpdatedListener(async (purchase) => {
|
||||||
console.log('[IAPService] 购买更新:', purchase);
|
console.log('[IAPService] 购买更新:', purchase);
|
||||||
|
|
||||||
|
const transactionId = purchase.transactionId;
|
||||||
|
|
||||||
|
// 检查是否已经在处理中(防止重复验证)
|
||||||
|
if (transactionId && this.processingTransactions.has(transactionId)) {
|
||||||
|
console.log('[IAPService] 交易已在处理中,跳过:', transactionId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (purchase.transactionReceipt) {
|
if (purchase.transactionReceipt) {
|
||||||
try {
|
try {
|
||||||
|
// 标记为处理中
|
||||||
|
if (transactionId) {
|
||||||
|
this.processingTransactions.add(transactionId);
|
||||||
|
}
|
||||||
|
|
||||||
// 验证收据
|
// 验证收据
|
||||||
const verifyResult = await this.verifyAndActivateSubscription(
|
const verifyResult = await this.verifyAndActivateSubscription(
|
||||||
purchase.transactionReceipt,
|
purchase.transactionReceipt,
|
||||||
@@ -188,6 +205,11 @@ class IAPService {
|
|||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('[IAPService] 处理购买失败:', error);
|
console.error('[IAPService] 处理购买失败:', error);
|
||||||
|
} finally {
|
||||||
|
// 移除处理中标记
|
||||||
|
if (transactionId) {
|
||||||
|
this.processingTransactions.delete(transactionId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
6
app.py
6
app.py
@@ -3995,6 +3995,9 @@ def apple_webhook():
|
|||||||
|
|
||||||
文档: https://developer.apple.com/documentation/appstoreservernotifications
|
文档: https://developer.apple.com/documentation/appstoreservernotifications
|
||||||
"""
|
"""
|
||||||
|
import base64
|
||||||
|
import json as json_lib
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# 获取请求数据
|
# 获取请求数据
|
||||||
data = request.get_json()
|
data = request.get_json()
|
||||||
@@ -4011,9 +4014,6 @@ def apple_webhook():
|
|||||||
# TODO: 实现 JWT 签名验证(使用苹果的公钥)
|
# TODO: 实现 JWT 签名验证(使用苹果的公钥)
|
||||||
# 目前先解码 payload 部分(不验证签名,生产环境应验证)
|
# 目前先解码 payload 部分(不验证签名,生产环境应验证)
|
||||||
try:
|
try:
|
||||||
import base64
|
|
||||||
import json as json_lib
|
|
||||||
|
|
||||||
# JWT 格式: header.payload.signature
|
# JWT 格式: header.payload.signature
|
||||||
parts = signed_payload.split('.')
|
parts = signed_payload.split('.')
|
||||||
if len(parts) >= 2:
|
if len(parts) >= 2:
|
||||||
|
|||||||
Reference in New Issue
Block a user