// // QXIAPManager.m // QXLive // // Created by 启星 on 2025/12/24. // #import "QXIAPManager.h" #import #import #import #import #import "QXMineNetwork.h" @interface QXIAPManager() @property (nonatomic,strong)NSString*orderNo; @end @implementation QXIAPManager + (instancetype)sharedInstance{ static dispatch_once_t pred; static QXIAPManager *manager = nil; dispatch_once(&pred, ^{ manager = [[self alloc] init]; }); return manager; } /* 购买 */ -(void)buyGoodsWithId:(NSString*)productId orderNo:(NSString*)orderNo{ self.orderNo = orderNo; //productId要跟服务端的关键字对应 [[SKPaymentQueue defaultQueue] addTransactionObserver:self]; if ([SKPaymentQueue canMakePayments]) { //用户允许app内购 if (productId.length) { showLoadingInView(KEYWINDOW); NSLog(@"%@商品正在请求中...",productId); NSArray *product = [[NSArray alloc] initWithObjects:productId, nil]; NSSet *set = [NSSet setWithArray:product]; SKProductsRequest *productsRequest = [[SKProductsRequest alloc] initWithProductIdentifiers:set]; productsRequest.delegate = self; [productsRequest start]; } } else { //没有权限 NSLog(@"没有购买权限"); } } /* 恢复购买 */ - (void)resumeInAppPurchase { [[SKPaymentQueue defaultQueue] addTransactionObserver:self]; [[SKPaymentQueue defaultQueue] restoreCompletedTransactions]; } #pragma mark SKProductsRequestDelegate 查询成功后的回调 - (void)productsRequest:(nonnull SKProductsRequest *)request didReceiveResponse:(nonnull SKProductsResponse *)response { NSArray *product = response.products; if (response.invalidProductIdentifiers.count) { dispatch_async(dispatch_get_main_queue(), ^{ hideLoadingInView(KEYWINDOW); }); NSLog(@"商品请求错误,error:%@", response.invalidProductIdentifiers); showToast(@"商品请求错误"); if (self.subscriptionFailurreCompletionHandler) { self.subscriptionFailurreCompletionHandler(); } return; } else { SKPayment *payment = [SKPayment paymentWithProduct:product[0]]; [[SKPaymentQueue defaultQueue] addPayment:payment]; } } - (void)paymentQueue:(nonnull SKPaymentQueue *)queue updatedTransactions:(nonnull NSArray *)transactions { dispatch_async(dispatch_get_main_queue(), ^{ hideLoadingInView(KEYWINDOW); }); // NSInteger i = 0; for (SKPaymentTransaction *tran in transactions) { // if(i != transactions.count - 1){ // i++; // continue; // } switch (tran.transactionState) { case SKPaymentTransactionStatePurchasing://正在交易 break; case SKPaymentTransactionStatePurchased://交易完成 { [[SKPaymentQueue defaultQueue] finishTransaction:tran]; if (tran.originalTransaction) { // 如果是自动续费的订单,originalTransaction会有内容 if (tran.originalTransaction.transactionIdentifier) { [self saveOrderId:tran.originalTransaction.transactionIdentifier]; } } else { // 第一次购买自动订阅 if (tran.transactionIdentifier) { [self saveOrderId:tran.transactionIdentifier]; } } [self vertifyReceipt:^(BOOL success) { if(success){ if (self.subscriptionSuccessCompletionHandler) { self.subscriptionSuccessCompletionHandler(); } [[NSNotificationCenter defaultCenter] postNotificationName:noticeAlipayResult object:nil]; [QXMineNetwork getMineInfoSuccessBlock:^(QXUserModel * _Nonnull userModel) { } failBlock:^(NSError * _Nonnull error, NSString * _Nonnull msg) { }]; }else{ if (self.subscriptionFailurreCompletionHandler) { self.subscriptionFailurreCompletionHandler(); } } }]; //获取交易成功后的购买凭证 NSLog(@"交易完成,正在校验凭证...."); } break; case SKPaymentTransactionStateFailed://交易失败 [[SKPaymentQueue defaultQueue] finishTransaction:tran]; if (self.subscriptionFailurreCompletionHandler) { self.subscriptionFailurreCompletionHandler(); } break; case SKPaymentTransactionStateRestored://已经购买过该商品 NSLog(@"已经购买过该商品"); [[SKPaymentQueue defaultQueue] finishTransaction:tran]; if (tran.originalTransaction) { if (tran.originalTransaction.transactionIdentifier) { [self saveOrderId:tran.originalTransaction.transactionIdentifier]; } } else { if (tran.transactionIdentifier) { [self saveOrderId:tran.transactionIdentifier]; } } self.subscriptionFailurreCompletionHandler(); break; default: break; } } } // 恢复购买成功后的回调 - (void)paymentQueueRestoreCompletedTransactionsFinished:(SKPaymentQueue *)queue { if (queue.transactions.count > 0) { for (SKPaymentTransaction *tran in queue.transactions) { NSString *originalTransactionID = tran.originalTransaction.transactionIdentifier; if (originalTransactionID) { [self saveOrderId:originalTransactionID]; break; } } [self getReceiptState:^(BOOL success) { if(success){ self.restoreSuccessCompletionHandler(); }else{ self.restoreFailurreCompletionHandler(); } }]; } else { self.restoreFailurreCompletionHandler(); } } // 恢复购买失败后的回调 - (void)paymentQueue:(SKPaymentQueue *)queue restoreCompletedTransactionsFailedWithError:(NSError *)error { self.restoreFailurreCompletionHandler(); } /* 保存订单编号到本地 */ - (void)saveOrderId:(NSString*)orderId{ NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; [defaults setObject:orderId forKey:@"orderId"]; [defaults synchronize]; } - (Boolean)getWhetherSubscrid{ NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; NSString *orderId = [defaults objectForKey:@"orderId"]; return orderId != nil; } /* 获取订单凭证 */ - (NSString *)getReceipt { NSURL *receiptURL = [[NSBundle mainBundle] appStoreReceiptURL]; if ([[NSFileManager defaultManager] fileExistsAtPath:[receiptURL path]]){ NSData *receiptData = [NSData dataWithContentsOfURL:receiptURL]; NSString *encodeReceiptStr = [receiptData base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithLineFeed]; return encodeReceiptStr; } else { return nil; } } /* 校验订单 */ - (void)vertifyReceipt:(void (^)(BOOL success))completion { NSLog(@"~~~正在检验。。。"); NSString *payment_token = [self getReceipt]; // NSString *password = @"秘钥"; // NSString *urlString = [NSString stringWithFormat:@"https://sandbox.itunes.apple.com/verifyReceipt"]; // AFHTTPSessionManager *manager = [AFHTTPSessionManager manager]; // manager.responseSerializer = [AFHTTPResponseSerializer serializer]; // // NSDictionary *parameters = @{ // @"apple_receipt": receipt, // @"password": @"a24591f9614b4814b1a77f8ffda41afc" // }; // // [manager POST:urlString parameters:parameters headers:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) { // // 请求成功,处理返回的数据 // NSLog(@"弹窗提示用户请求成功"); // if (responseObject) { // NSString *string = [[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding]; // if ([string isEqualToString:@"success"] || [string isEqualToString:@"订单已存在"]) { // dispatch_async(dispatch_get_main_queue(), ^{ // completion(YES); // }); // }else if ([string isEqualToString:@"failure"] || [string isEqualToString:@"fail"]){ // dispatch_async(dispatch_get_main_queue(), ^{ // completion(NO); // }); // } // } // // } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) { // // 请求失败,处理错误信息 // NSLog(@"请求失败:%@", error.localizedDescription); // dispatch_async(dispatch_get_main_queue(), ^{ // completion(NO); // }); // }]; showLoadingInView(KEYWINDOW) [[QXRequset shareInstance] postWithUrl:@"api/Payment/notify_apple" parameters:@{@"order_no":self.orderNo?:@"",@"payment_token":payment_token?:@""} needCache:NO success:^(id responseObject) { dispatch_async(dispatch_get_main_queue(), ^{ hideLoadingInView(KEYWINDOW); completion(YES); }); } fail:^(NSError *error, NSString *msg, NSURLSessionDataTask *task) { dispatch_async(dispatch_get_main_queue(), ^{ hideLoadingInView(KEYWINDOW); completion(NO); showToast(msg); }); }]; } - (void)getReceiptState:(void (^)(BOOL success))completion { NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; NSString *order_id = [defaults objectForKey:@"orderId"]; if(!order_id){ dispatch_async(dispatch_get_main_queue(), ^{ completion(NO); }); return; } NSString *urlString = [NSString stringWithFormat:@"https://订单状态地址"]; NSString *bundleID = [[NSBundle mainBundle] bundleIdentifier]; AFHTTPSessionManager *manager = [AFHTTPSessionManager manager]; manager.responseSerializer = [AFHTTPResponseSerializer serializer]; NSDictionary *parameters = @{ @"bundle_id": bundleID, @"order_id": order_id }; [manager GET:urlString parameters:parameters headers:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) { NSLog(@"订单状态获取"); if (responseObject) { NSError *error = nil; NSDictionary *dictionary = [NSJSONSerialization JSONObjectWithData:responseObject options:0 error:&error]; if([dictionary[@"status"] boolValue]){ dispatch_async(dispatch_get_main_queue(), ^{ completion(YES); }); }else{ dispatch_async(dispatch_get_main_queue(), ^{ completion(NO); }); } } } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) { // 请求失败,处理错误信息 NSLog(@"请求失败:%@", error.localizedDescription); dispatch_async(dispatch_get_main_queue(), ^{ completion(NO); }); }]; } @end