598 lines
22 KiB
Objective-C
598 lines
22 KiB
Objective-C
//
|
||
// IAPManager.m
|
||
// YuMi
|
||
//
|
||
// Created by P on 2024/9/24.
|
||
//
|
||
|
||
#import "IAPManager.h"
|
||
#import <Bugly/Bugly.h>
|
||
#import "Api+Mine.h"
|
||
#import "YuMi-swift.h"
|
||
#import "RechargeStorage.h"
|
||
|
||
#define MAX_RETRY_COUNT 10
|
||
|
||
@interface IAPManager()
|
||
|
||
@property (nonatomic, assign) BOOL isLogin;
|
||
|
||
@property (nonatomic, assign) NSInteger recheckInterval;
|
||
@property (nonatomic, assign) NSInteger recheckIndex;
|
||
@property (nonatomic, strong) NSTimer *recheckTimer;
|
||
@property (nonatomic, assign) BOOL isProcessing;
|
||
|
||
@property (nonatomic, copy) NSString *orderID;
|
||
@property (nonatomic, copy) NSString *transactionID;
|
||
|
||
@property (nonatomic, copy) void(^successPurchase)(NSString *transactionID, NSString *orderID);
|
||
@property (nonatomic, copy) void(^successRecheck)(void);
|
||
@property (nonatomic, copy) void(^failurePurchase)(NSError *error);
|
||
@property (nonatomic, copy) void(^contactCustomerService)(NSString *uid);
|
||
|
||
// 记录交易重试次数
|
||
@property (nonatomic, strong) NSMutableDictionary *retryCountMap;
|
||
|
||
@end
|
||
|
||
@implementation IAPManager
|
||
|
||
+ (instancetype)sharedManager {
|
||
static IAPManager *proxy;
|
||
static dispatch_once_t onceToken;
|
||
|
||
dispatch_once(&onceToken, ^{
|
||
proxy = [[self alloc] init];
|
||
|
||
proxy.recheckIndex = 0;
|
||
proxy.recheckInterval = 1.0;
|
||
proxy.retryCountMap = [NSMutableDictionary dictionary];
|
||
});
|
||
|
||
return proxy;
|
||
}
|
||
|
||
- (void)handleLogin {
|
||
self.isLogin = YES;
|
||
}
|
||
|
||
- (void)handleLogout {
|
||
self.isLogin = NO;
|
||
if (self.recheckTimer) {
|
||
[self.recheckTimer invalidate];
|
||
}
|
||
}
|
||
|
||
- (NSString *)fetchEncodedReceipt {
|
||
NSURL *receiptURL = [[NSBundle mainBundle] appStoreReceiptURL];
|
||
NSData *receiptData = [NSData dataWithContentsOfURL:receiptURL];
|
||
if (!receiptData) return nil;
|
||
return [receiptData base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithLineFeed];
|
||
}
|
||
|
||
- (BOOL)isValidTransactionID:(NSString *)tID orderID:(NSString *)orderID {
|
||
return (tID.length > 0 && orderID.length > 0);
|
||
}
|
||
|
||
// 开始正常内购流程
|
||
- (void)purchase:(NSString *)productId
|
||
success:(void(^)(NSString *transactionID, NSString *orderID))success
|
||
failure:(void(^)(NSError *error))failure
|
||
contactCS:(void(^)(NSString *uid))contactCS {
|
||
|
||
self.successPurchase = success;
|
||
self.failurePurchase = failure;
|
||
self.contactCustomerService = contactCS;
|
||
|
||
[self handleIAPState];
|
||
[self requestAPPOrderData:productId isFroRecheck:NO];
|
||
}
|
||
|
||
// 定时轮训未完成的订单并进行验单
|
||
- (void)retryCheckAllReceipt {
|
||
// 先清理旧定时器
|
||
if (self.recheckTimer) {
|
||
[self.recheckTimer invalidate];
|
||
self.recheckTimer = nil;
|
||
}
|
||
|
||
// 设置最大重试间隔
|
||
NSTimeInterval interval = MIN(self.recheckInterval, 300.0);
|
||
|
||
// 使用传统定时器创建方式,避免在旧版iOS上的兼容性问题
|
||
self.recheckTimer = [NSTimer scheduledTimerWithTimeInterval:interval
|
||
target:self
|
||
selector:@selector(handleRetryCheckReceipt)
|
||
userInfo:nil
|
||
repeats:NO];
|
||
}
|
||
|
||
// 验单逻辑
|
||
- (void)handleRetryCheckReceipt {
|
||
// NSLog(@"[YuMi IAP] 用户触发补单检查 - Retry checking receipts");
|
||
|
||
NSArray *array = [RechargeStorage getAllReceiptsWithUid:[AccountInfoStorage instance].getUid];
|
||
// NSLog(@" ------------.------------ 尝试:%@", array);
|
||
@synchronized (array) {
|
||
if (array.count == 0 || self.isProcessing) {
|
||
return;
|
||
}
|
||
|
||
if (!self.isLogin) {
|
||
return;
|
||
}
|
||
|
||
if (self.recheckIndex >= array.count) {
|
||
self.recheckIndex = 0;
|
||
}
|
||
#if DEBUG
|
||
// [self requestAPPOrderData:@"com.hflighting.yumi.gold.1_7000" isFroRecheck:YES];
|
||
#endif
|
||
self.isProcessing = YES;
|
||
NSDictionary *dic = [array xpSafeObjectAtIndex:self.recheckIndex];
|
||
NSString *transactionId = dic[@"transactionId"];
|
||
|
||
[self _logToBugly:transactionId oID:dic[@"orderId"] status:0];
|
||
|
||
NSInteger retryCount = [self getRetryCountForTransaction:transactionId];
|
||
|
||
if (retryCount > MAX_RETRY_COUNT) {
|
||
// 超过最大重试次数,记录并清理
|
||
[self _logToBugly:transactionId oID:dic[@"orderId"] status:4]; // 新状态:重试次数过多
|
||
[RechargeStorage delegateTransactionId:transactionId uid:[AccountInfoStorage instance].getUid];
|
||
self.isProcessing = NO;
|
||
return;
|
||
}
|
||
|
||
// 增加重试计数
|
||
[self incrementRetryCountForTransaction:transactionId];
|
||
|
||
@kWeakify(self);
|
||
[self backgroundCheckReceiptWithTransactionID:transactionId
|
||
orderID:dic[@"orderId"]
|
||
next:^(BOOL isSuccess){
|
||
@kStrongify(self);
|
||
if (isSuccess) {
|
||
[RechargeStorage delegateTransactionId:transactionId
|
||
uid:[AccountInfoStorage instance].getUid];
|
||
self.recheckInterval = MIN(self.recheckInterval * 2, 300.0);
|
||
|
||
[self _logToBugly:transactionId oID:dic[@"orderId"] status:1];
|
||
|
||
// 成功后移除重试记录
|
||
[self removeRetryCountForTransaction:transactionId];
|
||
|
||
} else {
|
||
self.recheckInterval = self.recheckInterval * 2;
|
||
[self _logToBugly:transactionId oID:dic[@"orderId"] status:2];
|
||
}
|
||
|
||
self.recheckIndex += 1;
|
||
|
||
self.isProcessing = NO;
|
||
|
||
[self.recheckTimer invalidate];
|
||
[self retryCheckAllReceipt];
|
||
}];
|
||
}
|
||
}
|
||
|
||
- (void)_logToBugly:(NSString *)tid oID:(NSString *)oid status:(NSInteger)status {
|
||
|
||
NSMutableDictionary *logDic = [NSMutableDictionary dictionary];
|
||
[logDic setObject:tid forKey:@"内购 transactionId"];
|
||
[logDic setObject:oid forKey:@"内购 orderId"];
|
||
[logDic setObject:[AccountInfoStorage instance].getUid forKey:@"内购 用户id"];
|
||
|
||
NSString *statusMsg = @"";
|
||
NSInteger code = -20000;
|
||
switch (status) {
|
||
case 0:
|
||
statusMsg = [NSString stringWithFormat:@"UID: %@, 尝试验单",
|
||
[AccountInfoStorage instance].getUid];
|
||
break;
|
||
case 1:
|
||
statusMsg = [NSString stringWithFormat:@"UID: %@, 验单-补单成功",
|
||
[AccountInfoStorage instance].getUid];
|
||
code = -20001;
|
||
break;
|
||
case 2:
|
||
statusMsg = [NSString stringWithFormat:@"UID: %@, 验单-补单失败",
|
||
[AccountInfoStorage instance].getUid];
|
||
code = -20002;
|
||
break;
|
||
case 3:
|
||
statusMsg = [NSString stringWithFormat:@"UID: %@, 验单-补单 id 异常",
|
||
[AccountInfoStorage instance].getUid];
|
||
code = -20002;
|
||
break;
|
||
case 4:
|
||
statusMsg = [NSString stringWithFormat:@"UID: %@, 重试次数过多",
|
||
[AccountInfoStorage instance].getUid];
|
||
code = -20003;
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
|
||
dispatch_async(dispatch_get_global_queue(0, 0), ^{
|
||
[Bugly reportError:[NSError errorWithDomain:statusMsg
|
||
code:code
|
||
userInfo:logDic]];
|
||
});
|
||
}
|
||
|
||
// 内购成功并通知外部
|
||
- (void)handleSuccessPurchase:(NSString *)tID order:(NSString *)orderID {
|
||
if (self.successPurchase) {
|
||
@kWeakify(self);
|
||
dispatch_async(dispatch_get_main_queue(), ^{
|
||
@kStrongify(self);
|
||
self.successPurchase(tID, orderID);
|
||
});
|
||
}
|
||
|
||
if (self.successRecheck) {
|
||
@kWeakify(self);
|
||
dispatch_async(dispatch_get_main_queue(), ^{
|
||
@kStrongify(self);
|
||
self.successRecheck();
|
||
});
|
||
}
|
||
}
|
||
|
||
// 内购失败并通知外部
|
||
- (void)handleFailurePurchase:(NSString *)errorMsg {
|
||
if (self.failurePurchase) {
|
||
@kWeakify(self);
|
||
dispatch_async(dispatch_get_main_queue(), ^{
|
||
@kStrongify(self);
|
||
if (errorMsg.length == 0) {
|
||
self.failurePurchase(nil);
|
||
} else {
|
||
self.failurePurchase([NSError errorWithDomain:errorMsg code:-1 userInfo:nil]);
|
||
}
|
||
});
|
||
}
|
||
}
|
||
|
||
// 获取客服内容
|
||
- (void)handleContactCS {
|
||
@kWeakify(self);
|
||
dispatch_async(dispatch_get_main_queue(), ^{
|
||
@kStrongify(self);
|
||
TTAlertConfig *config = [[TTAlertConfig alloc]init];
|
||
config.title = YMLocalizedString(@"XPIAPRechargeViewController7");
|
||
config.message = YMLocalizedString(@"XPIAPRechargeViewController8");
|
||
TTAlertButtonConfig *confirmButtonConfig = [[TTAlertButtonConfig alloc]init];
|
||
confirmButtonConfig.title = YMLocalizedString(@"XPIAPRechargeViewController9");
|
||
UIImage *image = [UIImage gradientColorImageFromColors:@[UIColorFromRGB(0x13E2F5),UIColorFromRGB(0x9DB4FF),UIColorFromRGB(0xCC67FF)] gradientType:GradientTypeLeftToRight imgSize:CGSizeMake(200, 200)];
|
||
confirmButtonConfig.backgroundColor = [UIColor colorWithPatternImage:image];
|
||
confirmButtonConfig.cornerRadius = 38/2;
|
||
config.confirmButtonConfig = confirmButtonConfig;
|
||
|
||
@kWeakify(self);
|
||
[TTPopup alertWithConfig:config confirmHandler:^{
|
||
@kStrongify(self);
|
||
[self loadCSUid];
|
||
} cancelHandler:^{}];
|
||
});
|
||
}
|
||
|
||
// 获取客服 UID
|
||
- (void)loadCSUid {
|
||
if (self.contactCustomerService) {
|
||
[Api requestContactCustomerServiceCompletion:^(BaseModel * _Nullable data, NSInteger code, NSString * _Nullable msg) {
|
||
if (code == 200) {
|
||
NSString *uid = [NSString stringWithFormat:@"%@",data.data];
|
||
self.contactCustomerService(uid);
|
||
}
|
||
}];
|
||
}
|
||
}
|
||
|
||
// 监听内购流程状态
|
||
- (void)handleIAPState {
|
||
if (@available(iOS 15.0, *)) {
|
||
@kWeakify(self);
|
||
[[PIIAPRegulate shared] setConditionBlock:^(enum StoreConditionResult state, NSDictionary<NSString *,NSString *> * _Nullable param) {
|
||
@kStrongify(self);
|
||
switch (state) {
|
||
case StoreConditionResultStart:
|
||
// NSLog(@"~~~```~~~ Purchase started");
|
||
break;
|
||
case StoreConditionResultPay:
|
||
// NSLog(@"~~~```~~~ Processing payment");
|
||
break;
|
||
case StoreConditionResultVerifiedServer:
|
||
// NSLog(@"~~~```~~~ Verified by server");
|
||
[self handleIAPSuccess:param];
|
||
break;
|
||
case StoreConditionResultUserCancelled:
|
||
// NSLog(@"~~~```~~~ User cancelled purchase");
|
||
[self handleFailurePurchase:@""];
|
||
break;
|
||
case StoreConditionResultNoProduct:
|
||
// NSLog(@"~~~```~~~ No product found");
|
||
[self handleFailurePurchase:[NSString stringWithFormat:@"%@ No product found", YMLocalizedString(@"XPIAPRechargeViewController1")]];
|
||
break;
|
||
case StoreConditionResultFailedVerification:
|
||
// NSLog(@"~~~```~~~ Verification failed");
|
||
[self handleFailurePurchase:YMLocalizedString(@"XPIAPRechargeViewController1")];
|
||
break;
|
||
case StoreConditionResultUnowned:
|
||
// NSLog(@"~~~```~~~ Result Unowned");
|
||
[self handleFailurePurchase:YMLocalizedString(@"XPIAPRechargeViewController1")];
|
||
break;
|
||
default:
|
||
[self handleFailurePurchase:YMLocalizedString(@"XPIAPRechargeViewController0")];
|
||
break;
|
||
}
|
||
}];
|
||
}
|
||
}
|
||
|
||
// 生成后端订单
|
||
- (void)requestAPPOrderData:(NSString *)productId isFroRecheck:(BOOL)isFroRecheck {
|
||
if (@available(iOS 15.0, *)) {
|
||
@kWeakify(self);
|
||
[Api requestIAPRecharge:^(BaseModel * _Nullable data, NSInteger code, NSString * _Nullable msg) {
|
||
if (isFroRecheck) {
|
||
return;
|
||
}
|
||
@kStrongify(self);
|
||
if (code == 200) {
|
||
NSString *orderId = (NSString *)data.data[@"recordId"];
|
||
NSString *uuid = (NSString *)data.data[@"appAccountToken"];
|
||
[self requestIAPOrder:orderId
|
||
productID:productId
|
||
uuid:uuid];
|
||
} else if (code == 50000) {
|
||
[self handleContactCS];
|
||
[self handleFailurePurchase:@""];
|
||
} else {
|
||
[self handleFailurePurchase:msg];
|
||
}
|
||
}
|
||
chargeProdId:productId
|
||
uid:[AccountInfoStorage instance].getUid
|
||
ticket:[AccountInfoStorage instance].getTicket
|
||
deviceInfo:[YYUtility deviceID]
|
||
clientIp:[YYUtility ipAddress]];
|
||
} else {
|
||
[self handleFailurePurchase:YMLocalizedString(@"XPIAPRechargeViewController10")];
|
||
}
|
||
}
|
||
|
||
|
||
// 获取后端订单后,查询线上是否有对应 productID 的物品,如果有,会自动拉起付费弹窗(PIIAPRegulate - purchase)
|
||
- (void)requestIAPOrder:(NSString *)orderID productID:(NSString *)productID uuid:(NSString *)uuid {
|
||
self.orderID = orderID;
|
||
|
||
if (@available(iOS 15.0, *)) {
|
||
// @kWeakify(self);
|
||
[[PIIAPRegulate shared] demandCommodityThingWithProductId:productID
|
||
uuid:uuid
|
||
completionHandler:^(NSError * _Nullable error) {
|
||
// @kStrongify(self);
|
||
if (error) {
|
||
// 已在 ConditionBlock 中回调
|
||
}
|
||
}];
|
||
}
|
||
}
|
||
|
||
// 处理内购付款成功
|
||
- (void)handleIAPSuccess:(NSDictionary *)param {
|
||
id tid = param[@"transactionId"];
|
||
self.transactionID = tid;
|
||
|
||
if (self.transactionID.length == 0) {
|
||
[self handleFailurePurchase:YMLocalizedString(@"XPIAPRechargeViewController1")];
|
||
return;
|
||
}
|
||
|
||
[self saveTransactionID];
|
||
[self checkReceiptWithTransactionID:self.transactionID
|
||
orderID:self.orderID];
|
||
}
|
||
|
||
// 内购付款成功后保存收据 id 到钥匙串
|
||
- (void)saveTransactionID {
|
||
NSString *encodedReceipt = [self fetchEncodedReceipt];
|
||
NSMutableDictionary *receiptInfo = [NSMutableDictionary dictionary];
|
||
|
||
[self addValueIfNotNil:self.transactionID forKey:@"transactionId" toDictionary:receiptInfo];
|
||
[self addValueIfNotNil:encodedReceipt forKey:@"receipt" toDictionary:receiptInfo];
|
||
[self addValueIfNotNil:self.orderID forKey:@"orderId" toDictionary:receiptInfo];
|
||
|
||
// 添加时间戳便于后续判断过期交易
|
||
[receiptInfo setObject:[[NSDate date] description] forKey:@"timestamp"];
|
||
|
||
@synchronized (self.transactionID) {
|
||
[RechargeStorage saveTransactionId:self.transactionID
|
||
receipt:[receiptInfo toJSONString]
|
||
uid:[AccountInfoStorage instance].getUid];
|
||
}
|
||
}
|
||
|
||
// 通过苹果收据与后端订单进行验单与发货
|
||
// MARK: 必须等待结果
|
||
- (void)checkReceiptWithTransactionID:(NSString *)tID
|
||
orderID:(NSString *)orderID {
|
||
|
||
// NSLog(@" ------------.------------ 后端验单:%@ | %@", tID, orderID);
|
||
|
||
@kWeakify(self);
|
||
[Api checkReceipt:^(BaseModel * _Nullable data, NSInteger code, NSString * _Nullable msg) {
|
||
@kStrongify(self);
|
||
if (code == 200) {
|
||
[self handleSuccessPurchase:tID order:orderID];
|
||
[self handleCheckReceiptSuccess:tID isFromRecheck:NO];
|
||
} else {
|
||
[self handleFailurePurchase:msg];
|
||
if (code == 1444) {
|
||
// 参数异常,暂不处理
|
||
}
|
||
}
|
||
// NSLog(@" ------------.------------ 后端验单结果:%@ ",msg);
|
||
}
|
||
chooseEnv:@"true"
|
||
chargeRecordId:orderID
|
||
transcationId:tID
|
||
uid:[AccountInfoStorage instance].getUid
|
||
ticket:[AccountInfoStorage instance].getTicket];
|
||
}
|
||
|
||
// 通过苹果收据与后端订单进行验单与发货,此方法是对本地未删除的订单进行检测
|
||
- (void)backgroundCheckReceiptWithTransactionID:(NSString *)tID
|
||
orderID:(NSString *)orderID
|
||
next:(void(^)(BOOL isSuccess))next {
|
||
|
||
// 创建后台任务标识
|
||
UIBackgroundTaskIdentifier backgroundTask = [[UIApplication sharedApplication] beginBackgroundTaskWithName:@"VerifyReceipt"
|
||
expirationHandler:^{
|
||
// 超时处理
|
||
if (next) {
|
||
next(NO);
|
||
}
|
||
[[UIApplication sharedApplication] endBackgroundTask:backgroundTask];
|
||
}];
|
||
|
||
// 原验证代码...
|
||
|
||
// 完成后务必结束后台任务
|
||
@kWeakify(self);
|
||
[Api checkReceipt:^(BaseModel * _Nullable data, NSInteger code, NSString * _Nullable msg) {
|
||
@kStrongify(self);
|
||
// 原有验证代码...
|
||
|
||
// 结束后台任务
|
||
[[UIApplication sharedApplication] endBackgroundTask:backgroundTask];
|
||
}
|
||
chooseEnv:@"true"
|
||
chargeRecordId:orderID
|
||
transcationId:tID
|
||
uid:[AccountInfoStorage instance].getUid
|
||
ticket:[AccountInfoStorage instance].getTicket];
|
||
}
|
||
|
||
// 查找在缓存中的 transactionID 并告知 apple 订单已完成
|
||
- (void)handleCheckReceiptSuccess:(NSString *)tID
|
||
isFromRecheck:(BOOL)isFromRecheck {
|
||
if (@available(iOS 15.0, *)) {
|
||
@kWeakify(self);
|
||
[[PIIAPRegulate shared] verifyBusinessAccomplishWithTransactionID:tID
|
||
completionHandler:^(BOOL success, NSError * _Nullable error) {
|
||
@kStrongify(self);
|
||
if (success) {
|
||
// NSLog(@" ------------.------------ apple 验单成功");
|
||
// 流程完成,移除本地缓存账单
|
||
[RechargeStorage delegateTransactionId:tID
|
||
uid:[AccountInfoStorage instance].getUid];
|
||
// 成功后移除重试记录
|
||
[self removeRetryCountForTransaction:tID];
|
||
} else {
|
||
// 出现异常
|
||
// NSLog(@" ------------.------------ apple 验单成功:%@ ",error);
|
||
if (error == nil) {
|
||
// 该订单在 appstore 已无法找到,不必再重试
|
||
[RechargeStorage delegateTransactionId:tID
|
||
uid:[AccountInfoStorage instance].getUid];
|
||
// 清理不存在的交易记录
|
||
[self removeRetryCountForTransaction:tID];
|
||
} else {
|
||
[self retryCheckAllReceipt];
|
||
}
|
||
}
|
||
|
||
if (!isFromRecheck) {
|
||
// 正常购买情况,重置内存订单数据
|
||
self.orderID = @"";
|
||
self.transactionID = @"";
|
||
}
|
||
}];
|
||
}
|
||
}
|
||
|
||
- (void)addValueIfNotNil:(id)value
|
||
forKey:(NSString *)key
|
||
toDictionary:(NSMutableDictionary *)dictionary {
|
||
if (value != nil && key != nil) {
|
||
dictionary[key] = value;
|
||
}
|
||
}
|
||
|
||
// 添加 dealloc 方法确保定时器释放
|
||
- (void)dealloc {
|
||
if (self.recheckTimer) {
|
||
[self.recheckTimer invalidate];
|
||
self.recheckTimer = nil;
|
||
}
|
||
}
|
||
|
||
// 在应用进入后台时暂停定时器
|
||
- (void)applicationDidEnterBackground {
|
||
if (self.recheckTimer) {
|
||
[self.recheckTimer invalidate];
|
||
self.recheckTimer = nil;
|
||
}
|
||
}
|
||
|
||
// 在应用恢复活动时重新启动定时器
|
||
- (void)applicationWillEnterForeground {
|
||
if (self.isLogin) {
|
||
[self retryCheckAllReceipt];
|
||
}
|
||
}
|
||
|
||
// 清理长时间未处理的交易记录
|
||
- (void)cleanupStaleTransactions {
|
||
NSArray *receipts = [RechargeStorage getAllReceiptsWithUid:[AccountInfoStorage instance].getUid];
|
||
NSDate *now = [NSDate date];
|
||
|
||
for (NSDictionary *receipt in receipts) {
|
||
// 检查交易时间,如果超过7天还未成功,则清理
|
||
NSString *timestamp = receipt[@"timestamp"];
|
||
if (timestamp) {
|
||
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
|
||
[dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss Z"]; // 根据实际时间格式调整
|
||
NSDate *transactionDate = [dateFormatter dateFromString:timestamp];
|
||
|
||
if (transactionDate && [now timeIntervalSinceDate:transactionDate] > 70 * 24 * 60 * 60) {
|
||
NSString *tID = receipt[@"transactionId"];
|
||
[RechargeStorage delegateTransactionId:tID uid:[AccountInfoStorage instance].getUid];
|
||
[self _logToBugly:tID oID:receipt[@"orderId"] status:5]; // 新状态:过期清理
|
||
|
||
// 清理过期交易的重试记录
|
||
[self removeRetryCountForTransaction:tID];
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// 获取交易的重试次数
|
||
- (NSInteger)getRetryCountForTransaction:(NSString *)transactionId {
|
||
NSNumber *countNumber = self.retryCountMap[transactionId];
|
||
return countNumber ? [countNumber integerValue] : 0;
|
||
}
|
||
|
||
// 增加交易的重试次数
|
||
- (void)incrementRetryCountForTransaction:(NSString *)transactionId {
|
||
NSInteger currentCount = [self getRetryCountForTransaction:transactionId];
|
||
self.retryCountMap[transactionId] = @(currentCount + 1);
|
||
}
|
||
|
||
// 移除交易的重试记录
|
||
- (void)removeRetryCountForTransaction:(NSString *)transactionId {
|
||
[self.retryCountMap removeObjectForKey:transactionId];
|
||
}
|
||
|
||
// 清理所有重试记录
|
||
- (void)cleanAllRetryCount {
|
||
[self.retryCountMap removeAllObjects];
|
||
}
|
||
|
||
@end
|
||
|