// // ApplePayService.m // Meet // // Created by mambaxie on 2021/3/1. // #import "ApplePayService.h" #import #import "MTCacheManager.h" //#import "AppConifgService.h" #import "AFHTTPSessionManager.h" //#import static NSString * const kDidReportPayActionCacheKey = @"kDidReportPayActionCacheKey"; @interface ApplePayService() @property (nonatomic, strong) NSMutableSet *userStartProductIds; @property (nonatomic, assign) BOOL restoreProduct; @property (nonatomic, assign) BOOL isFastBuy; @property (nonatomic, assign) BOOL isPurchasing; // 正在购买 @property (nonatomic, assign) NSTimeInterval buyStartTime; @property (nonatomic, copy) NSString *purchasingID; // 正在购买的产品id @property (nonatomic, strong) SKPaymentTransaction *purchasingTransaction; @property (nonatomic, strong) NSString *orderId; @end @implementation ApplePayService + (instancetype)sharedInstance { static dispatch_once_t onceToken; static ApplePayService *service; dispatch_once(&onceToken, ^{ service = [ApplePayService new]; }); return service; } - (void)autoHandleUpdatedTransactions { [[SKPaymentQueue defaultQueue] addTransactionObserver:self]; } + (BOOL)showNoPayToastIfNeed { if ([SKPaymentQueue canMakePayments]) { if ([UserService currentUser].ID == 0) { [SVProgressHUD showErrorWithStatus:@"请先登录..."]; return YES; } return NO; } [SVProgressHUD showErrorWithStatus:@"您没有允许程序内付费..."]; return YES; } + (void)startVipPay:(NSString *)ID isFastBuy:(BOOL)isFastBuy source:(NSString *)source { [self startPay:ID isFastBuy:isFastBuy extInfo:@{ @"vip_source": source }]; } + (void)sendStartVipPay:(NSString *)ID isFastBuy:(BOOL)isFastBuy source:(NSString *)source UserID:(NSString *)userID { [self SendStartPay:ID UserID:userID isFastBuy:isFastBuy extInfo:@{ @"vip_source": source }]; } + (void)startBottlePay:(NSString *)ID isFastBuy:(BOOL)isFastBuy bottleID:(int)bottleID { //sell_bottle_id 里也要标记下这个是写真瓶(为以后连麦房购买酒币做准备) [self startPay:ID isFastBuy:isFastBuy extInfo:@{ @"sell_bottle_id": [NSString stringWithFormat:@"sell_bottle_%d", bottleID]}]; } + (void)startPay:(NSString *)ID isFastBuy:(BOOL)isFastBuy extInfo:(NSDictionary *)extInfo { NSNumber *extraTotalDay = @(0); NSNumber *storeExtraDay = [[NSUserDefaults standardUserDefaults] objectForKey:@"extraVipDaysAppStore"]; if (storeExtraDay != nil) { extraTotalDay = storeExtraDay; } NSNumber *exExtraDay = [[NSUserDefaults standardUserDefaults] objectForKey:@"extraVipDaysWxGzh"]; if (exExtraDay != nil) { extraTotalDay = @(exExtraDay.intValue + storeExtraDay.intValue); } [PYHTTPManager postWithPath:@"wxgoodprepay" params:@{ @"vip_good_id": @([ID intValue]),@"vip_source":@"",@"extra_vip_day":extraTotalDay } callback:^(id _Nullable rsp, NSError * _Nullable error) { if (error) { [SVProgressHUD showErrorWithStatus:@"创建订单失败"]; return; } [PYAppService payByWetChatPayWithOrderId:rsp[@"trade_no"] payInfo:rsp]; }]; // NSString *goodsID = ID; // NSMutableDictionary *paramsM = [@{ // @"apple_good_id": goodsID, // @"extra_vip_day": extraTotalDay // } mutableCopy]; // // [paramsM addEntriesFromDictionary:extInfo]; // // [PYHTTPManager postWithPath:@"iaporder" params:paramsM callback:^(id _Nullable rsp, NSError * _Nullable error) { // if (error) { // [SVProgressHUD showSuccessWithStatus:error.userInfo[@"message"]]; // return; // } // [ApplePayService payProductWithId:goodsID orderId:rsp[@"trade_uuid"] restoreProduct:NO isFastBuy:isFastBuy]; // }]; } + (void)SendStartPay:(NSString *)ID UserID:(NSString *)userID isFastBuy:(BOOL)isFastBuy extInfo:(NSDictionary *)extInfo { NSNumber *extraTotalDay = @(0); NSNumber *storeExtraDay = [[NSUserDefaults standardUserDefaults] objectForKey:@"extraVipDaysAppStore"]; if (storeExtraDay != nil) { extraTotalDay = storeExtraDay; } NSNumber *exExtraDay = [[NSUserDefaults standardUserDefaults] objectForKey:@"extraVipDaysWxGzh"]; if (exExtraDay != nil) { extraTotalDay = @(exExtraDay.intValue + storeExtraDay.intValue); } // [PYHTTPManager postWithPath:@"wxgoodprepay" params:@{ // @"vip_good_id": ID // } callback:^(id _Nullable rsp, NSError * _Nullable error) { // if (error) { // [SVProgressHUD showErrorWithStatus:@"创建订单失败"]; // return; // } // [PYAppService payByWetChatPayWithOrderId:rsp[@"trade_no"] payInfo:rsp]; // }]; int VuserID = [userID intValue]; NSString *goodsID = ID; NSDictionary *infoDictionary = [[NSBundle mainBundle] infoDictionary];//获取app版本信息 NSMutableDictionary *paramsM = [@{ @"vip_good_id": @([goodsID intValue]), @"give_user_id": @(VuserID), @"extra_vip_day": extraTotalDay, // @"device_platform" :@"iOS", // @"app_version_name" : infoDictionary[@"CFBundleShortVersionString"] ?: @"Unknown", // } mutableCopy]; [paramsM addEntriesFromDictionary:extInfo]; [PYHTTPManager postWithPath:@"android/givevip" params:paramsM callback:^(id _Nullable rsp1, NSError * _Nullable error) { NSLog(@"rsp===%@,goodsID===%@",rsp1,paramsM); NSString *vipType ; if ([goodsID containsString:@"1"]) { vipType = @"赠送你一个月会员"; }else if ([goodsID containsString:@"13"]) { vipType = @"赠送你三个月会员"; }else{ vipType = @"赠送你年会员"; } if (!error) { // [SVProgressHUD showSuccessWithStatus:error.userInfo[@"message"]]; [SVProgressHUD showSuccessWithStatus:error.userInfo[@"message"]]; NSLog(@"message===%@",error.userInfo[@"message"]); int code = [error.userInfo[@"code"] intValue]; if (code==0) { [PYAppService payByWetChatPayWithOrderId:rsp1[@"trade_no"] payInfo:rsp1 userId:vipType]; // [ApplePayService payProductWithId:goodsID orderId:rsp1[@"trade_uuid"] restoreProduct:NO isFastBuy:isFastBuy]; // }else if (code==1100) { [SVProgressHUD showSuccessWithStatus:error.userInfo[@"message"]]; return; }else{ // [SVProgressHUD showSuccessWithStatus:@"未成功"]; return; } } // [[NSNotificationCenter defaultCenter] postNotificationName:@"receivedVipMsgnotifi" object:vipType]; }]; } + (void)payProductWithId:(NSString *)ID orderId:(NSString *)orderId restoreProduct:(BOOL)restoreProduct isFastBuy:(BOOL)isFastBuy { if ([self showNoPayToastIfNeed]) { return; } //只有id没用,之前购买过这个商品的tran还会回来,还需要和购买时间对其 if ([ApplePayService sharedInstance].userStartProductIds == nil) { [ApplePayService sharedInstance].userStartProductIds = [NSMutableSet setWithCapacity:6]; } [ApplePayService sharedInstance].restoreProduct = restoreProduct; [ApplePayService sharedInstance].isFastBuy = isFastBuy; [ApplePayService sharedInstance].isPurchasing = YES; [ApplePayService sharedInstance].purchasingID = ID; [ApplePayService sharedInstance].orderId = orderId; [ApplePayService sharedInstance].buyStartTime = [[NSDate date] timeIntervalSince1970]; if (restoreProduct) { [ToastUtil showToast:@"正在检查恢复购买"]; [[SKPaymentQueue defaultQueue] restoreCompletedTransactions];//这句代码就是恢复购买 return; } if (isFastBuy) { [SVProgressHUD showWithStatus:@""]; }else{ [SVProgressHUD showWithStatus:@"请求订阅商品中..."]; } ApplePayService *service = [ApplePayService sharedInstance]; [service requestProductDataWithId:ID]; NSLog(@"【applePay】开始购买商品 productIdentifier : %@", ID); } - (void)requestProductDataWithId:(NSString *)ID { NSSet *set = [NSSet setWithObject:ID]; SKProductsRequest *request = [[SKProductsRequest alloc] initWithProductIdentifiers:set]; request.delegate = self; [request start]; } #pragma mark - SKProductsRequestDelegate - (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response { if ([UserService currentUser].ID == 0) { return; } NSArray *myProducts = response.products; if ([myProducts count] > 0) { //requestProductDataWithId 一次只会发起一个请求 SKProduct *selectedProduct = [myProducts objectAtIndex:0]; SKMutablePayment *payment = [SKMutablePayment paymentWithProduct:selectedProduct]; //orderId 会在apple iap notification里回传给app service payment.applicationUsername = self.orderId; [self.userStartProductIds addObject:selectedProduct.productIdentifier]; [[SKPaymentQueue defaultQueue] addPayment:payment]; if (self.isFastBuy) { [SVProgressHUD showWithStatus:@""]; }else{ [SVProgressHUD showWithStatus:@"请求订阅商品成功"]; } }else{ [SVProgressHUD showErrorWithStatus:@"未找到订阅商品"]; } } - (void)requestDidFinish:(SKRequest *)request NS_AVAILABLE_IOS(3_0) { } - (void)request:(SKRequest *)request didFailWithError:(NSError *)error NS_AVAILABLE_IOS(3_0) { [SVProgressHUD showErrorWithStatus:[NSString stringWithFormat:@"请求订阅商品失败%@", error]]; } #pragma mark - SKPaymentTransactionObserver - (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions NS_AVAILABLE_IOS(3_0) { for (SKPaymentTransaction *transaction in queue.transactions) { NSLog(@"【applePay】updatedTransactions productIdentifier %@ state : %ld oldProductIdentifier : %@", transaction.payment.productIdentifier, (long)transaction.transactionState, transaction.originalTransaction.payment.productIdentifier); switch (transaction.transactionState) { case SKPaymentTransactionStatePurchased://交易完成 { [self validateApplePay:transaction]; [[SKPaymentQueue defaultQueue] finishTransaction:transaction]; break; } case SKPaymentTransactionStateFailed://交易失败 NSLog(@"Transaction error: %@ %ld", transaction.error.localizedDescription,(long)transaction.error.code); if (self.userStartProductIds.count > 0 && [self.userStartProductIds containsObject:transaction.payment.productIdentifier]) { [self.userStartProductIds removeObject:transaction.payment.productIdentifier]; if (self.userStartProductIds.count == 0) { [SVProgressHUD dismiss]; [SVProgressHUD showSuccessWithStatus:[NSString stringWithFormat: @"订阅失败%@", transaction.payment.productIdentifier]]; }else{ [SVProgressHUD showWithStatus:[NSString stringWithFormat: @"订阅失败%@", transaction.payment.productIdentifier]]; } } [self finishTransaction:transaction]; break; case SKPaymentTransactionStateRestored: //已经购买过该商品 if (self.userStartProductIds.count > 0 && [self.userStartProductIds containsObject:transaction.payment.productIdentifier]) { [SVProgressHUD showWithStatus:@"恢复购买成功,正在同步服务器"]; } if (self.restoreProduct == YES) { //恢复购买只需要处理一次,因为服务器那边会拿到最近购买的所有信息 [self validateApplePay:transaction]; self.restoreProduct = NO; } break; case SKPaymentTransactionStatePurchasing: //商品添加进列表 if (self.userStartProductIds.count > 0 && [self.userStartProductIds containsObject:transaction.payment.productIdentifier]) { if (self.isFastBuy) { [SVProgressHUD showWithStatus:@""]; }else{ [SVProgressHUD showWithStatus:@"正在连接苹果服务器"]; } } self.purchasingTransaction = transaction; break; case SKPaymentTransactionStateDeferred: //需要额外操作 if (self.userStartProductIds.count > 0 && [self.userStartProductIds containsObject:transaction.payment.productIdentifier]) { [SVProgressHUD showWithStatus:@"等待确认..."]; } self.purchasingTransaction = transaction; break; default: break; } } } // Sent when transactions are removed from the queue (via finishTransaction:). - (void)paymentQueue:(SKPaymentQueue *)queue removedTransactions:(NSArray *)transactions{ //人工发起的iap for (SKPaymentTransaction *transaction in queue.transactions) { if(![[ApplePayService sharedInstance].userStartProductIds containsObject:transaction.payment.productIdentifier]){ [[ApplePayService sharedInstance].userStartProductIds removeObject:transaction.payment.productIdentifier]; } } } // Sent when all transactions from the user's purchase history have successfully been added back to the queue. - (void)paymentQueue:(SKPaymentQueue *)queue restoreCompletedTransactionsFailedWithError:(nonnull NSError *)error { [ToastUtil showToast:[NSString stringWithFormat:@"恢复购买失败%@", error]]; } // Sent when all transactions from the user's purchase history have successfully been added back to the queue. - (void)paymentQueueRestoreCompletedTransactionsFinished:(SKPaymentQueue *)queue { if (queue.transactions.count > 0) { [ToastUtil showToast:@"之前的恢复购买已经加入到队列"]; }else{ [ToastUtil showToast:@"没有需要恢复购买的项目"]; } } - (void)finishTransaction:(SKPaymentTransaction *)transaction { self.isPurchasing = NO; self.purchasingID = nil; self.orderId = nil; [[SKPaymentQueue defaultQueue] finishTransaction:transaction]; } #pragma mark - Pay - (void)validateApplePay:(SKPaymentTransaction *)transaction { NSData *receiptData; NSURL *url = [[NSBundle mainBundle] appStoreReceiptURL]; bool fileExist = [[NSFileManager defaultManager] fileExistsAtPath:url.path]; if (fileExist) { receiptData = [NSData dataWithContentsOfFile:url.path options:NSDataReadingMappedAlways error:nil]; } // receiptData = transaction.transactionReceipt; if (receiptData == nil) { if (self.userStartProductIds.count > 0 && [self.userStartProductIds containsObject:transaction.payment.productIdentifier]) { [self.userStartProductIds removeObject:transaction.payment.productIdentifier]; if (self.userStartProductIds.count == 0) { [SVProgressHUD dismiss]; [SVProgressHUD showSuccessWithStatus:[NSString stringWithFormat: @"同步失败%@", @"receiptData为空"]]; }else{ [SVProgressHUD showWithStatus:[NSString stringWithFormat: @"同步失败%@", @"receiptData为空"]]; } } return; } if (self.userStartProductIds.count > 0 && [self.userStartProductIds containsObject:transaction.payment.productIdentifier]) { [SVProgressHUD showWithStatus:@"内购商品购买成功\n正在处理"]; } NSLog(@"【applePay】validateApplePay 发送请求到后台"); NSString *reciptString = [receiptData base64EncodedStringWithOptions:0]; NSLog(@"%@", self.orderId); NSLog(@"%@", reciptString); NSLog(@"%@", transaction.payment.productIdentifier); [PYHTTPManager postWithPath:@"iapcheckorder" params:@{ @"receipt_data": reciptString ?: @"", // 票据 @"order_uuid": self.orderId ?: @"" } callback:^(id _Nullable rsp, NSError * _Nullable error) { if (!error) { // 成功 NSLog(@"【applePay】validateApplePay 后台回包 %@", rsp); if (self.restoreProduct) { [ToastUtil showToast:@"恢复购买成功"]; } else { //??? } [self finishTransaction:transaction]; NSString *goodKind = rsp[@"pay_good_kind"]; if ([goodKind isEqualToString:@"buy_bottle"]) { // 写真 [[NSNotificationCenter defaultCenter] postNotificationName:BuyBottleSuccessNotification object:nil]; return; }else if ([goodKind isEqualToString:@"buy_jiubi"]) { // 购买酒币 [[NSNotificationCenter defaultCenter] postNotificationName:BuyCoinSuccessNotification object:nil]; return; } if (self.userStartProductIds.count > 0 && [self.userStartProductIds containsObject:transaction.payment.productIdentifier]) { //用户主动请求的订单 [[NSNotificationCenter defaultCenter] postNotificationName:BuyVIPSuccessNotification object:nil]; /* [BaiduAction logAction:BaiduSDKActionNamePurchase actionParam: @{BaiduSDKActionParamKeyOuterActionId:[NSString stringWithFormat:@"%d", [UserService currentUserID]], BaiduSDKActionParamKeyPurchaseMoney:rsp[@"amount"] }]; */ //更新用户信息. [UserService getUserInfoWithCompletion:^(User * _Nonnull user) {}]; [MTAlertView showWithSetupBlcok:^(MTAlertViewConfig *config) { config.title = @"VIP购买成功"; config.message = @"你现在是我们小酒馆最尊贵的客人"; config.otherTitle = @"确定"; }]; [self.userStartProductIds removeObject:transaction.payment.productIdentifier]; if (self.userStartProductIds.count == 0) { [SVProgressHUD dismiss]; } } if (![[MTCacheManager defaultCacheManager] boolForKey:kDidReportPayActionCacheKey]) { // [BaiduAction logAction:BaiduSDKActionNamePurchase actionParam:nil]; [[MTCacheManager defaultCacheManager] setBool:YES forKey:kDidReportPayActionCacheKey];; } } else { if (self.userStartProductIds.count > 0 && [self.userStartProductIds containsObject:transaction.payment.productIdentifier]) { [self.userStartProductIds removeObject:transaction.payment.productIdentifier]; if (self.userStartProductIds.count == 0) { [SVProgressHUD dismiss]; [SVProgressHUD showSuccessWithStatus:[NSString stringWithFormat: @"同步失败%@", error]]; }else{ [SVProgressHUD showWithStatus:[NSString stringWithFormat: @"同步失败%@", error]]; } } [self finishTransaction:transaction]; NSLog(@"【applePay】validateApplePay 后台回包 %@", error.localizedDescription); } }]; } //- (void)loadProducts:(NSString *)recieptStr { // // NSMutableDictionary *payLoad = [NSMutableDictionary dictionaryWithObject:recieptStr forKey:@"receipt-data"]; // [payLoad setObject:@"3165a051bb5c437ea6efdc90033586ab" forKey:@"password"]; // NSError *error; // NSData *requestData = [NSJSONSerialization dataWithJSONObject:payLoad options:0 error:&error]; // // NSMutableURLRequest *sandBoxReq = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"https://sandbox.itunes.apple.com/verifyReceipt"]]; // [sandBoxReq setHTTPMethod:@"POST"]; // [sandBoxReq setHTTPBody:requestData]; // // NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]]; // [[session dataTaskWithRequest:sandBoxReq completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { // dispatch_async(dispatch_get_main_queue(), ^{ // if(!error){ // NSDictionary *jsonResponse = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil]; // if ([jsonResponse[@"code"] intValue] == 0) { // NSDictionary *info = [jsonResponse objectForKey:@"latest_receipt_info"]; // NSTimeInterval expires_date = [[info valueForKey:@"expires_date"] doubleValue]; // if (expires_date <= 0) { // NSDictionary *info = [jsonResponse objectForKey:@"receipt"]; // expires_date = [[info valueForKey:@"expires_date"] doubleValue]; // } // if (expires_date > 0) { // // [[NSUserDefaults standardUserDefaults] setObject:@(expires_date / 1000.0) forKey:AppReviewVipTimeKey]; // if (self.restoreProduct) { // [SVProgressHUD showSuccessWithStatus:@"恢复购买成功"]; // } else { // [SVProgressHUD showSuccessWithStatus:@"订阅成功"]; // } // [[PYAppService currentViewController] dismissViewControllerAnimated:YES completion:nil]; // } else { // [SVProgressHUD showSuccessWithStatus:@"订阅失败"]; // } // } else { // [SVProgressHUD showSuccessWithStatus:@"订阅失败"]; // } // } // }); // // }] resume]; //} // @end