// // IAPVerifyTransactionObj.m // #import "IAPVerifyTransactionObj.h" #import "PayVM.h" #import "KBAuthManager.h" #import "KBHUD.h" //#import "KBLoginSheetViewController.h" #import "KBBizCode.h" NSNotificationName const KBIAPDidCompletePurchaseNotification = @"KBIAPDidCompletePurchaseNotification"; @interface IAPVerifyTransactionObj () @property (nonatomic, strong) PayVM *payVM; @end @implementation IAPVerifyTransactionObj - (instancetype)init { if (self = [super init]) { _payVM = [PayVM new]; } return self; } - (void)verifyReceipt:(NSString *)receipt completion:(void (^)(BOOL success, NSString * _Nullable message, NSInteger statusCode))completion { if (![receipt isKindOfClass:NSString.class] || receipt.length == 0) { if (completion) { completion(NO, KBLocalized(@"Receipt missing"), KBBizCodeReceiptError); } return; } NSDictionary *params = @{ @"receipt": receipt ?: @"" }; __weak typeof(self) weakSelf = self; [self.payVM applePayReqWithParams:params needShow:NO completion:^(NSInteger sta, NSString * _Nullable msg) { dispatch_async(dispatch_get_main_queue(), ^{ __strong typeof(weakSelf) self = weakSelf; (void)self; BOOL success = (sta == KBBizCodeSuccess); NSString *tip = msg ?: (success ? KBLocalized(@"Success") : KBLocalized(@"Payment failed")); if (completion) { completion(success, tip, sta); } }); }]; } #pragma mark - FGIAPVerifyTransaction - (void)pushSuccessTradeReultToServer:(NSString *)receipt transaction:(SKPaymentTransaction *)transaction complete:(FGIAPVerifyTransactionPushCallBack)handler { if (![self checkLogin]) { return; } KBLOG(@"receipt = %@", receipt); KBLOG(@"transactionId = %@, originalId = %@", transaction.transactionIdentifier,transaction.originalTransaction.transactionIdentifier); #if DEBUG // [self kb_debugLogReceipt:receipt transaction:transaction]; #endif #if DEBUG // [self kb_debugLogReceipt:receipt transaction:transaction]; #endif __weak typeof(self) weakSelf = self; [KBHUD showWithStatus:@"请稍等..."]; [self verifyReceipt:receipt completion:^(BOOL success, NSString * _Nullable message, NSInteger statusCode) { __strong typeof(weakSelf) self = weakSelf; (void)self; if (success) { [[SKPaymentQueue defaultQueue] finishTransaction:transaction]; [KBHUD showInfo:@"Success"]; [[NSNotificationCenter defaultCenter] postNotificationName:KBIAPDidCompletePurchaseNotification object:nil]; if (handler) handler(KBLocalized(@"Success"), nil); } else if (statusCode == KBBizCodeReceiptError) { [KBHUD dismiss]; [[SKPaymentQueue defaultQueue] finishTransaction:transaction]; } else { [KBHUD showError:message ?: KBLocalized(@"Failed")]; if (handler) handler(message ?: KBLocalized(@"Failed"), nil); } }]; } #pragma mark - Helpers - (BOOL)checkLogin { BOOL loggedIn = [[KBUserSessionManager shared] isLoggedIn]; if (!loggedIn) { [[KBUserSessionManager shared] goLoginVC]; } return YES; } #if DEBUG - (void)kb_debugLogReceipt:(NSString *)receipt transaction:(SKPaymentTransaction *)transaction { if (![receipt isKindOfClass:[NSString class]] || receipt.length == 0) { KBLOG(@"[IAPVerifyTransactionObj] debug receipt empty"); return; } NSURL *url = [NSURL URLWithString:@"https://sandbox.itunes.apple.com/verifyReceipt"]; if (!url) { return; } NSDictionary *payload = @{ @"receipt-data": receipt, @"exclude-old-transactions": @NO }; NSError *jsonError = nil; NSData *body = [NSJSONSerialization dataWithJSONObject:payload options:0 error:&jsonError]; if (jsonError || !body) { KBLOG(@"[IAPVerifyTransactionObj] debug receipt json error: %@", jsonError); return; } NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; request.HTTPMethod = @"POST"; request.HTTPBody = body; [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; request.timeoutInterval = 30; NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) { if (error) { KBLOG(@"[IAPVerifyTransactionObj] debug receipt request error: %@", error); return; } if (data.length == 0) { KBLOG(@"[IAPVerifyTransactionObj] debug receipt empty response"); return; } NSError *parseError = nil; NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:0 error:&parseError]; if (!json || parseError) { KBLOG(@"[IAPVerifyTransactionObj] debug receipt parse error: %@", parseError); return; } NSNumber *status = json[@"status"]; KBLOG(@"[IAPVerifyTransactionObj] receipt status: %@, env transaction: %@ / %@", status, transaction.transactionIdentifier, transaction.originalTransaction.transactionIdentifier); void (^logEntries)(NSArray *entries, NSString *label) = ^(NSArray *entries, NSString *label) { for (NSDictionary *item in entries) { KBLOG(@"[IAPVerifyTransactionObj][%@] product:%@ transaction:%@ original:%@ purchase_date:%@", label, item[@"product_id"], item[@"transaction_id"], item[@"original_transaction_id"], item[@"purchase_date"]); } }; NSArray *latestInfos = json[@"latest_receipt_info"]; if ([latestInfos isKindOfClass:[NSArray class]] && latestInfos.count > 0) { logEntries(latestInfos, @"latest_receipt_info"); } NSDictionary *receiptDict = json[@"receipt"]; NSArray *inAppInfos = receiptDict[@"in_app"]; if ([inAppInfos isKindOfClass:[NSArray class]] && inAppInfos.count > 0) { logEntries(inAppInfos, @"receipt.in_app"); } }]; [task resume]; } #endif @end