From c898d16688ebdf67b09e4f61123a525506d490bb Mon Sep 17 00:00:00 2001 From: CodeST <694468528@qq.com> Date: Tue, 16 Dec 2025 14:29:47 +0800 Subject: [PATCH] =?UTF-8?q?=E5=88=A0=E9=99=A4storkit=201?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- keyBoard.xcodeproj/project.pbxproj | 36 --- keyBoard/AppDelegate.m | 9 - keyBoard/Class/Login/VM/KBLoginVM.m | 12 - .../Class/Pay/M/IAPVerifyTransactionObj.h | 4 +- .../Class/Pay/M/IAPVerifyTransactionObj.m | 114 --------- .../Class/Vender/FGIAPService/FGIAPManager.h | 27 -- .../Class/Vender/FGIAPService/FGIAPManager.m | 26 -- .../Vender/FGIAPService/FGIAPProductsFilter.h | 24 -- .../Vender/FGIAPService/FGIAPProductsFilter.m | 41 --- .../Class/Vender/FGIAPService/FGIAPService.h | 46 ---- .../Class/Vender/FGIAPService/FGIAPService.m | 235 ------------------ .../Vender/FGIAPService/FGIAPServiceUtility.h | 22 -- .../FGIAPService/FGIAPVerifyTransaction.h | 58 ----- .../FGIAPService/NSObject+FGIsNullOrEmpty.h | 19 -- .../FGIAPService/NSObject+FGIsNullOrEmpty.m | 55 ---- 15 files changed, 1 insertion(+), 727 deletions(-) delete mode 100644 keyBoard/Class/Vender/FGIAPService/FGIAPManager.h delete mode 100644 keyBoard/Class/Vender/FGIAPService/FGIAPManager.m delete mode 100644 keyBoard/Class/Vender/FGIAPService/FGIAPProductsFilter.h delete mode 100644 keyBoard/Class/Vender/FGIAPService/FGIAPProductsFilter.m delete mode 100644 keyBoard/Class/Vender/FGIAPService/FGIAPService.h delete mode 100644 keyBoard/Class/Vender/FGIAPService/FGIAPService.m delete mode 100644 keyBoard/Class/Vender/FGIAPService/FGIAPServiceUtility.h delete mode 100644 keyBoard/Class/Vender/FGIAPService/FGIAPVerifyTransaction.h delete mode 100644 keyBoard/Class/Vender/FGIAPService/NSObject+FGIsNullOrEmpty.h delete mode 100644 keyBoard/Class/Vender/FGIAPService/NSObject+FGIsNullOrEmpty.m diff --git a/keyBoard.xcodeproj/project.pbxproj b/keyBoard.xcodeproj/project.pbxproj index d213eaa..ecff023 100644 --- a/keyBoard.xcodeproj/project.pbxproj +++ b/keyBoard.xcodeproj/project.pbxproj @@ -132,10 +132,6 @@ 0498BDDE2EE81508006CC1D5 /* KBShopVM.m in Sources */ = {isa = PBXBuildFile; fileRef = 0498BDDD2EE81508006CC1D5 /* KBShopVM.m */; }; 0498BDE12EEA87C9006CC1D5 /* KBShopStyleModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 0498BDE02EEA87C8006CC1D5 /* KBShopStyleModel.m */; }; 0498BDE42EEA885D006CC1D5 /* KBShopThemeModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 0498BDE32EEA885D006CC1D5 /* KBShopThemeModel.m */; }; - 0498BDF02EEC0E56006CC1D5 /* FGIAPManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 0498BDE72EEC0E56006CC1D5 /* FGIAPManager.m */; }; - 0498BDF12EEC0E56006CC1D5 /* FGIAPProductsFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 0498BDE92EEC0E56006CC1D5 /* FGIAPProductsFilter.m */; }; - 0498BDF22EEC0E56006CC1D5 /* NSObject+FGIsNullOrEmpty.m in Sources */ = {isa = PBXBuildFile; fileRef = 0498BDEF2EEC0E56006CC1D5 /* NSObject+FGIsNullOrEmpty.m */; }; - 0498BDF32EEC0E56006CC1D5 /* FGIAPService.m in Sources */ = {isa = PBXBuildFile; fileRef = 0498BDEB2EEC0E56006CC1D5 /* FGIAPService.m */; }; 0498BDF52EEC50EE006CC1D5 /* emoji_categories.json in Resources */ = {isa = PBXBuildFile; fileRef = 0498BDF42EEC50EE006CC1D5 /* emoji_categories.json */; }; 049FB20B2EC1C13800FAB05D /* KBSkinBottomActionView.m in Sources */ = {isa = PBXBuildFile; fileRef = 049FB20A2EC1C13800FAB05D /* KBSkinBottomActionView.m */; }; 049FB20E2EC1CD2800FAB05D /* KBAlert.m in Sources */ = {isa = PBXBuildFile; fileRef = 049FB20D2EC1CD2800FAB05D /* KBAlert.m */; }; @@ -449,16 +445,6 @@ 0498BDE02EEA87C8006CC1D5 /* KBShopStyleModel.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBShopStyleModel.m; sourceTree = ""; }; 0498BDE22EEA885D006CC1D5 /* KBShopThemeModel.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBShopThemeModel.h; sourceTree = ""; }; 0498BDE32EEA885D006CC1D5 /* KBShopThemeModel.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBShopThemeModel.m; sourceTree = ""; }; - 0498BDE62EEC0E56006CC1D5 /* FGIAPManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FGIAPManager.h; sourceTree = ""; }; - 0498BDE72EEC0E56006CC1D5 /* FGIAPManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FGIAPManager.m; sourceTree = ""; }; - 0498BDE82EEC0E56006CC1D5 /* FGIAPProductsFilter.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FGIAPProductsFilter.h; sourceTree = ""; }; - 0498BDE92EEC0E56006CC1D5 /* FGIAPProductsFilter.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FGIAPProductsFilter.m; sourceTree = ""; }; - 0498BDEA2EEC0E56006CC1D5 /* FGIAPService.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FGIAPService.h; sourceTree = ""; }; - 0498BDEB2EEC0E56006CC1D5 /* FGIAPService.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FGIAPService.m; sourceTree = ""; }; - 0498BDEC2EEC0E56006CC1D5 /* FGIAPServiceUtility.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FGIAPServiceUtility.h; sourceTree = ""; }; - 0498BDED2EEC0E56006CC1D5 /* FGIAPVerifyTransaction.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FGIAPVerifyTransaction.h; sourceTree = ""; }; - 0498BDEE2EEC0E56006CC1D5 /* NSObject+FGIsNullOrEmpty.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NSObject+FGIsNullOrEmpty.h"; sourceTree = ""; }; - 0498BDEF2EEC0E56006CC1D5 /* NSObject+FGIsNullOrEmpty.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "NSObject+FGIsNullOrEmpty.m"; sourceTree = ""; }; 0498BDF42EEC50EE006CC1D5 /* emoji_categories.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = emoji_categories.json; sourceTree = ""; }; 049FB2092EC1C13800FAB05D /* KBSkinBottomActionView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBSkinBottomActionView.h; sourceTree = ""; }; 049FB20A2EC1C13800FAB05D /* KBSkinBottomActionView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBSkinBottomActionView.m; sourceTree = ""; }; @@ -693,23 +679,6 @@ path = VM; sourceTree = ""; }; - 04122F6C2EC5F40800EF7AB3 /* FGIAPService */ = { - isa = PBXGroup; - children = ( - 0498BDE62EEC0E56006CC1D5 /* FGIAPManager.h */, - 0498BDE72EEC0E56006CC1D5 /* FGIAPManager.m */, - 0498BDE82EEC0E56006CC1D5 /* FGIAPProductsFilter.h */, - 0498BDE92EEC0E56006CC1D5 /* FGIAPProductsFilter.m */, - 0498BDEA2EEC0E56006CC1D5 /* FGIAPService.h */, - 0498BDEB2EEC0E56006CC1D5 /* FGIAPService.m */, - 0498BDEC2EEC0E56006CC1D5 /* FGIAPServiceUtility.h */, - 0498BDED2EEC0E56006CC1D5 /* FGIAPVerifyTransaction.h */, - 0498BDEE2EEC0E56006CC1D5 /* NSObject+FGIsNullOrEmpty.h */, - 0498BDEF2EEC0E56006CC1D5 /* NSObject+FGIsNullOrEmpty.m */, - ); - path = FGIAPService; - sourceTree = ""; - }; 04122F7D2EC5FC5500EF7AB3 /* V */ = { isa = PBXGroup; children = ( @@ -988,7 +957,6 @@ isa = PBXGroup; children = ( 04122F862EC6198C00EF7AB3 /* WMDragView */, - 04122F6C2EC5F40800EF7AB3 /* FGIAPService */, 049FB2162EC20A6600FAB05D /* BMLongPressDragCellCollectionView */, 048908D92EBF61AF00FABA60 /* UICollectionViewLeftAlignedLayout */, 047920592EDEE1FC004E8522 /* CRBoxInputView */, @@ -2000,10 +1968,6 @@ 0479205F2EDEE1FC004E8522 /* CRBoxInputCellProperty.m in Sources */, 047920602EDEE1FC004E8522 /* CRLineView.m in Sources */, 047C65502EBCBA9E0035E841 /* KBShopVC.m in Sources */, - 0498BDF02EEC0E56006CC1D5 /* FGIAPManager.m in Sources */, - 0498BDF12EEC0E56006CC1D5 /* FGIAPProductsFilter.m in Sources */, - 0498BDF22EEC0E56006CC1D5 /* NSObject+FGIsNullOrEmpty.m in Sources */, - 0498BDF32EEC0E56006CC1D5 /* FGIAPService.m in Sources */, 0477BE042EBC83130055D639 /* HomeMainVC.m in Sources */, 0477BDFD2EBC6A170055D639 /* HomeHotVC.m in Sources */, 04122FAA2EC73C0100EF7AB3 /* KBVipPayHeaderView.m in Sources */, diff --git a/keyBoard/AppDelegate.m b/keyBoard/AppDelegate.m index 7be9980..d5a2b03 100644 --- a/keyBoard/AppDelegate.m +++ b/keyBoard/AppDelegate.m @@ -19,8 +19,6 @@ #import "KBULBridgeNotification.h" // Darwin 通知常量:用于通知扩展“UL已处理” #import "LSTPopView.h" #import "KBLoginPopView.h" -#import "IAPVerifyTransactionObj.h" -#import "FGIAPManager.h" #import "KBSexSelVC.h" #import "KBKeyboardPermissionManager.h" #import "KBVipPay.h" @@ -41,13 +39,6 @@ /// 2 : 处理token问题(包括卸载重装场景下的 token 清理) [[KBUserSessionManager shared] bootstrapIfNeeded]; - /// 3:如果当前已经是登录状态,则在启动时初始化一次内购服务。 - /// 对于“首次登录”的场景,会在登录成功(见 KBLoginVM)后再进行一次配置。 - if ([KBUserSessionManager shared].isLoggedIn) { -// [[FGIAPManager shared] setConfigureWith:[IAPVerifyTransactionObj new]]; - } - - // 首次安装/升级:重置“完全访问”记录,避免继承旧安装遗留在 Keychain 中的状态 static NSString *const kKBFullAccessRecordInitializedKey = @"KBFullAccessRecordInitialized"; NSUserDefaults *ud = [NSUserDefaults standardUserDefaults]; diff --git a/keyBoard/Class/Login/VM/KBLoginVM.m b/keyBoard/Class/Login/VM/KBLoginVM.m index 2dfa45d..6b0c159 100644 --- a/keyBoard/Class/Login/VM/KBLoginVM.m +++ b/keyBoard/Class/Login/VM/KBLoginVM.m @@ -6,8 +6,6 @@ #import "AppleSignInManager.h" #import "KBNetworkManager.h" #import "KBAuthManager.h" -#import "FGIAPManager.h" -#import "IAPVerifyTransactionObj.h" #import "KBAPI.h" #import "KBUser.h" #import "KBMyVM.h" @@ -19,14 +17,6 @@ @implementation KBLoginVM -/// 统一初始化内购(只执行一次)。既可以在“启动时已登录”的场景调用,也可以在“登录成功回调”里调用。 -+ (void)kb_configureIAPIfNeeded { - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ -// [[FGIAPManager shared] setConfigureWith:[IAPVerifyTransactionObj new]]; - }); -} - + (instancetype)shared { static KBLoginVM *vm; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ vm = [KBLoginVM new]; }); return vm; @@ -76,7 +66,6 @@ return; } [[KBUserSessionManager shared] handleLoginSuccessWithUser:user]; - [KBLoginVM kb_configureIAPIfNeeded]; [self kb_syncKeyboardCharactersAfterLogin]; if (completion) completion(YES, nil); // 保存登录态到共享钥匙串;供 App 与扩展共享 @@ -113,7 +102,6 @@ return; } [[KBUserSessionManager shared] handleLoginSuccessWithUser:user]; - [KBLoginVM kb_configureIAPIfNeeded]; [self kb_syncKeyboardCharactersAfterLogin]; if (completion) completion(YES, nil); }]; diff --git a/keyBoard/Class/Pay/M/IAPVerifyTransactionObj.h b/keyBoard/Class/Pay/M/IAPVerifyTransactionObj.h index b2ddddc..56fc9cc 100644 --- a/keyBoard/Class/Pay/M/IAPVerifyTransactionObj.h +++ b/keyBoard/Class/Pay/M/IAPVerifyTransactionObj.h @@ -4,14 +4,12 @@ // #import -#import -#import "FGIAPVerifyTransaction.h" NS_ASSUME_NONNULL_BEGIN FOUNDATION_EXPORT NSNotificationName const KBIAPDidCompletePurchaseNotification; -@interface IAPVerifyTransactionObj : NSObject +@interface IAPVerifyTransactionObj : NSObject /// 校验票据(StoreKit 2 入口) /// - Parameters: diff --git a/keyBoard/Class/Pay/M/IAPVerifyTransactionObj.m b/keyBoard/Class/Pay/M/IAPVerifyTransactionObj.m index 9496869..68e24ed 100644 --- a/keyBoard/Class/Pay/M/IAPVerifyTransactionObj.m +++ b/keyBoard/Class/Pay/M/IAPVerifyTransactionObj.m @@ -4,9 +4,6 @@ #import "IAPVerifyTransactionObj.h" #import "PayVM.h" -#import "KBAuthManager.h" -#import "KBHUD.h" -//#import "KBLoginSheetViewController.h" #import "KBBizCode.h" NSNotificationName const KBIAPDidCompletePurchaseNotification = @"KBIAPDidCompletePurchaseNotification"; @@ -69,115 +66,4 @@ NSNotificationName const KBIAPDidCompletePurchaseNotification = @"KBIAPDidComple }]; } -#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 diff --git a/keyBoard/Class/Vender/FGIAPService/FGIAPManager.h b/keyBoard/Class/Vender/FGIAPService/FGIAPManager.h deleted file mode 100644 index cbe74f2..0000000 --- a/keyBoard/Class/Vender/FGIAPService/FGIAPManager.h +++ /dev/null @@ -1,27 +0,0 @@ -// -// FGIAPManager.h -// MaltBaby -// -// Created by FoneG on 2020/5/11. -// - -#import -#import "FGIAPService.h" - -NS_ASSUME_NONNULL_BEGIN - -@interface FGIAPManager : NSObject - -/// FGIAPService -@property (nonatomic, strong, readonly) FGIAPService *iap; - -/// Initialize -+ (FGIAPManager *)shared; - -/// Configure a server validation object -/// @param verifyTransaction a server validation object -- (void)setConfigureWith:(id)verifyTransaction; - -@end - -NS_ASSUME_NONNULL_END diff --git a/keyBoard/Class/Vender/FGIAPService/FGIAPManager.m b/keyBoard/Class/Vender/FGIAPService/FGIAPManager.m deleted file mode 100644 index cbdcada..0000000 --- a/keyBoard/Class/Vender/FGIAPService/FGIAPManager.m +++ /dev/null @@ -1,26 +0,0 @@ -// -// FGIAPManager.m -// MaltBaby -// -// Created by FoneG on 2020/5/11. -// - -#import "FGIAPManager.h" - -@implementation FGIAPManager - -+ (FGIAPManager *)shared{ - static FGIAPManager *manager = nil; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - manager = [[FGIAPManager alloc] init]; - }); - return manager; -} - -- (void)setConfigureWith:(id)verifyTransaction{ - self->_iap = [[FGIAPService alloc] initWithTransaction:verifyTransaction]; -} - - -@end diff --git a/keyBoard/Class/Vender/FGIAPService/FGIAPProductsFilter.h b/keyBoard/Class/Vender/FGIAPService/FGIAPProductsFilter.h deleted file mode 100644 index c45ca5b..0000000 --- a/keyBoard/Class/Vender/FGIAPService/FGIAPProductsFilter.h +++ /dev/null @@ -1,24 +0,0 @@ -// -// FGIAPProductsFilter.h -// MaltBaby -// -// Created by FoneG on 2021/5/8. -// - -#import -#import - -NS_ASSUME_NONNULL_BEGIN - -typedef void(^FGIAPManagerResponseBlock)(NSArray * products); - -@interface FGIAPProductsFilter : NSObject - -/// 获取苹果内购商品列表 -/// @param productIdentifiers 商品id列表 -/// @param completion completion -- (void)requestProductsWith:(NSSet *)productIdentifiers completion:(nonnull FGIAPManagerResponseBlock)completion; - -@end - -NS_ASSUME_NONNULL_END diff --git a/keyBoard/Class/Vender/FGIAPService/FGIAPProductsFilter.m b/keyBoard/Class/Vender/FGIAPService/FGIAPProductsFilter.m deleted file mode 100644 index a529e19..0000000 --- a/keyBoard/Class/Vender/FGIAPService/FGIAPProductsFilter.m +++ /dev/null @@ -1,41 +0,0 @@ -// -// FGIAPProductsFilter.m -// MaltBaby -// -// Created by FoneG on 2021/5/8. -// - -#import "FGIAPProductsFilter.h" -#import "FGIAPServiceUtility.h" - -@interface FGIAPProductsFilter () -@property (nonatomic,strong) SKProductsRequest *request; -@property (nonatomic, copy) FGIAPManagerResponseBlock requestProductsBlock; -@end - -@implementation FGIAPProductsFilter - -- (void)requestProductsWith:(NSSet *)productIdentifiers completion:(nonnull FGIAPManagerResponseBlock)completion{ - - if (productIdentifiers.count==0) { - if (completion) completion([NSArray array]); - return; - } - self.request = [[SKProductsRequest alloc] initWithProductIdentifiers:productIdentifiers]; - self.request.delegate = self; - self.requestProductsBlock = completion; - [self.request start]; -} - -#pragma mark - SKProductsRequestDelegate - -- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response { - NSArray *products = [response.products sortedArrayUsingComparator:^NSComparisonResult(SKProduct *obj1, SKProduct *obj2) { - return obj1.price.doubleValue < obj2.price.doubleValue ? NSOrderedAscending : NSOrderedDescending; - }]; - if(_requestProductsBlock) { - _requestProductsBlock(products); - } -} - -@end diff --git a/keyBoard/Class/Vender/FGIAPService/FGIAPService.h b/keyBoard/Class/Vender/FGIAPService/FGIAPService.h deleted file mode 100644 index ce99cc1..0000000 --- a/keyBoard/Class/Vender/FGIAPService/FGIAPService.h +++ /dev/null @@ -1,46 +0,0 @@ -// -// FGIAPManager.h -// MaltBaby -// -// Created by FoneG on 2020/5/7. -// - -#import -#import -#import "FGIAPVerifyTransaction.h" - -NS_ASSUME_NONNULL_BEGIN - -typedef NS_ENUM(NSInteger, FGIAPManagerPurchaseRusult) { - FGIAPManagerPurchaseRusultSuccess = 0, //内购成功 - FGIAPManagerPurchaseRusultHalfSuccess, //苹果扣款成功,但是验签接口失败了 - FGIAPManagerPurchaseRusultFail, //内购失败 - FGIAPManagerPurchaseRusultCancel //用户取消 -}; -typedef void(^FGIAPManagerBuyBlock)(NSString *message, FGIAPManagerPurchaseRusult result); - -@interface FGIAPService : NSObject - -/** - * 初始化支付对象 - * @param verifyTransaction 一般得到苹果服务器返回的支付结果后,需要通过再次向服务器进行二次确认,来保证整个支付链路闭环 - */ -- (instancetype)initWithTransaction:(id)verifyTransaction; - -/** - * iap支付 - * @param product 对应的商品 - * @param completion 支付回调 - */ -- (void)buyProduct:(SKProduct *)product onCompletion:(FGIAPManagerBuyBlock)completion; - - -/** - * 在合适的时间处理从App Store下载页面触发的内购行为 - */ -- (void)tryShouldAddStorePayments; - -@end - - -NS_ASSUME_NONNULL_END diff --git a/keyBoard/Class/Vender/FGIAPService/FGIAPService.m b/keyBoard/Class/Vender/FGIAPService/FGIAPService.m deleted file mode 100644 index 1d96f3b..0000000 --- a/keyBoard/Class/Vender/FGIAPService/FGIAPService.m +++ /dev/null @@ -1,235 +0,0 @@ -// -// FGIAPManager.m -// MaltBaby -// -// Created by FoneG on 2020/5/7. -// - -#import "FGIAPService.h" -#import "FGIAPServiceUtility.h" -#import "NSObject+FGIsNullOrEmpty.h" - -static NSMutableDictionary *FGIAPServiceErrorMapsFromTransaction (SKPaymentTransaction *transaction) { - NSMutableDictionary *errorMaps = [NSMutableDictionary dictionary]; - [errorMaps setValue:transaction.transactionIdentifier?:@"" forKey:@"transactionIdentifier"]; - [errorMaps setValue:transaction.originalTransaction.transactionIdentifier?:@"" forKey:@"originalTransaction.transactionIdentifier"]; - [errorMaps setValue:transaction.payment.applicationUsername?:@"" forKey:@"applicationUsername"]; - [errorMaps setValue:transaction.payment.productIdentifier?:@"" forKey:@"productIdentifier"]; - return errorMaps; -} - -@interface FGIAPService () -@property (nonatomic, strong) id verifyTransaction; -@property (nonatomic, copy) FGIAPManagerBuyBlock buyProductCompleteBlock; -@property (nonatomic, strong) NSString *productIdentifier; -@property (nonatomic, strong) SKPayment *APPStorePayment; -@end - -@implementation FGIAPService - -- (instancetype)initWithTransaction:(id)verifyTransaction{ - if (self = [super init]) { - - _verifyTransaction = verifyTransaction; - - if ([SKPaymentQueue defaultQueue]) { - [[SKPaymentQueue defaultQueue] addTransactionObserver:self]; - } - } - return self; -} - - -- (void)buyProduct:(SKProduct *)product onCompletion:(nonnull FGIAPManagerBuyBlock)completion{ - - if (![SKPaymentQueue canMakePayments]) { - completion(@"Failed to obtain the internal purchase permission", FGIAPManagerPurchaseRusultFail); - return; - } - if ([product.productIdentifier isNSStringAndNotEmpty]) { - _productIdentifier = product.productIdentifier; - _buyProductCompleteBlock = completion; - SKMutablePayment *payment = [SKMutablePayment paymentWithProduct:product]; - if ([SKPaymentQueue defaultQueue]) { - [[SKPaymentQueue defaultQueue] addPayment:payment]; - } - }else{ - completion(@"The selected payment does not exist", FGIAPManagerPurchaseRusultFail); - } -} - -- (void)tryShouldAddStorePayments{ - if (_APPStorePayment && [SKPaymentQueue defaultQueue]) { - [[SKPaymentQueue defaultQueue] addPayment:self.APPStorePayment]; - } -} - -#pragma mark - SKPaymentTransactionObserver - -- (void)paymentQueue:(SKPaymentQueue *)queue removedTransactions:(NSArray *)transactions{ - FGLog(@"%s %ld", __func__, [SKPaymentQueue defaultQueue].transactions.count); - if (![[SKPaymentQueue defaultQueue].transactions isNSArrayAndNotEmpty]) { - /// all transactions finished - } -} - -- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions -{ - for (SKPaymentTransaction *transaction in transactions) - { - switch (transaction.transactionState) - { - case SKPaymentTransactionStatePurchasing: - FGLog(@"Add an payment to the list"); - break; - case SKPaymentTransactionStatePurchased: - FGLog(@"Customer paid successfully"); - [self completeTransaction:transaction retryWhenreceiptURLisEmpty:YES]; - break; - case SKPaymentTransactionStateRestored: - FGLog(@"The transaction has been recovered from the user's purchase history"); - [self completeTransaction:transaction retryWhenreceiptURLisEmpty:YES]; - break; - case SKPaymentTransactionStateFailed: - FGLog(@"Failure of commodity transaction"); - [self failedTransaction:transaction withError:FGIAPServiceErrorTypeNone]; - break; - case SKPaymentTransactionStateDeferred: - FGLog(@"Merchandise is suspended"); - break; - default: - /// - break; - } - } -} - -- (BOOL)paymentQueue:(SKPaymentQueue *)queue shouldAddStorePayment:(SKPayment *)payment forProduct:(SKProduct *)product API_AVAILABLE(ios(11.0)){ - BOOL shouldAddStorePayment = NO; - if (_verifyTransaction && [_verifyTransaction respondsToSelector:@selector(paymentQueue:shouldAddStorePayment:forProduct:)]) { - shouldAddStorePayment = [_verifyTransaction paymentQueue:queue shouldAddStorePayment:payment forProduct:product]; - } - if (shouldAddStorePayment == NO) { - _APPStorePayment = payment; - } - return shouldAddStorePayment; -} - - -#pragma mark - SKRequestDelegate - -- (void)requestDidFinish:(SKRequest *)request{ - if ([request isKindOfClass:[SKReceiptRefreshRequest class]]) { - SKReceiptRefreshRequest *RefreshRequest = (SKReceiptRefreshRequest *)request; - SKPaymentTransaction *transaction = [RefreshRequest.receiptProperties valueForKey:@"transaction"]; - if (transaction) { - [self completeTransaction:transaction retryWhenreceiptURLisEmpty:NO]; - }else{ - [self failedTransaction:transaction withError:FGIAPServiceErrorTypeReceiptNotExist]; - } - } -} - -- (void)request:(SKRequest *)request didFailWithError:(nonnull NSError *)error{ - if ([request isKindOfClass:[SKReceiptRefreshRequest class]]) { - SKReceiptRefreshRequest *RefreshRequest = (SKReceiptRefreshRequest *)request; - SKPaymentTransaction *transaction = [RefreshRequest.receiptProperties valueForKey:@"transaction"]; - [self failedTransaction:transaction withError:FGIAPServiceErrorTypeReceiptNotExist]; - } -} - - -#pragma mark - private method - -- (void)completeTransaction:(SKPaymentTransaction *)transaction retryWhenreceiptURLisEmpty:(BOOL)retry{ - FGLog(@"%s %@ %@", __func__, transaction.transactionIdentifier, transaction.originalTransaction.transactionIdentifier); - - if (![transaction.transactionIdentifier isNSStringAndNotEmpty]) { - [self failedTransaction:transaction withError:FGIAPServiceErrorTypeTransactionIdentifierNotExist]; - return; - } - - NSURL *receiptURL = [[NSBundle mainBundle] appStoreReceiptURL]; - if ([[NSFileManager defaultManager] fileExistsAtPath:receiptURL.path]) { - - NSData *receiptData = [NSData dataWithContentsOfURL:receiptURL]; - NSString *receiptDataText = [receiptData base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithLineFeed]; - [self checkReceipt:receiptDataText withTransaction:transaction handler:nil]; - - }else if (retry){ - - SKReceiptRefreshRequest *receiptRefreshRequest = [[SKReceiptRefreshRequest alloc] initWithReceiptProperties:@{@"transaction":transaction}]; - receiptRefreshRequest.delegate = self; - [receiptRefreshRequest start]; - - }else{ - [self failedTransaction:transaction withError:FGIAPServiceErrorTypeReceiptNotExist]; - } -} - - -- (void)failedTransaction:(SKPaymentTransaction *)transaction withError:(FGIAPServiceErrorType)error{ - FGLog(@"%s Transaction error:%@ code:%ld", __func__, transaction.error.localizedDescription, transaction.error.code); - - BOOL finish = error == FGIAPServiceErrorTypeNone; - - if (finish && [SKPaymentQueue defaultQueue]) { - [[SKPaymentQueue defaultQueue] finishTransaction: transaction]; - } - - NSMutableDictionary *logStatistics = [NSMutableDictionary dictionaryWithDictionary:FGIAPServiceErrorMapsFromTransaction(transaction)]; - if (self.verifyTransaction && [self.verifyTransaction respondsToSelector:@selector(pushServiceErrorLogStatistics:error:)]) { - [logStatistics setValue:@(error) forKey:@"error"]; - [self.verifyTransaction pushServiceErrorLogStatistics:logStatistics error:error]; - } - - if (_buyProductCompleteBlock) { - FGIAPManagerPurchaseRusult result = FGIAPManagerPurchaseRusultHalfSuccess; - if (error == FGIAPServiceErrorTypeNone) { - result = transaction.error.code == SKErrorPaymentCancelled ? FGIAPManagerPurchaseRusultCancel : FGIAPManagerPurchaseRusultFail; - } - _buyProductCompleteBlock(transaction.error.localizedDescription, result); - } -} - - - -- (void)checkReceipt:(NSString *)receipt withTransaction:(SKPaymentTransaction *)transaction handler:(FGIAPVerifyTransactionBlock)handler{ - - WS(wSelf); - if (_verifyTransaction && [_verifyTransaction respondsToSelector:@selector(pushSuccessTradeReultToServer:transaction:complete:)]) { - [_verifyTransaction pushSuccessTradeReultToServer:receipt transaction:transaction complete:^(NSString * _Nonnull message, NSError * _Nullable requestErr) { - - //polling verify transaction - if (requestErr && requestErr.code != FGIAPServerOverdueErrorCode) { - dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(10.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ - [wSelf checkReceipt:receipt withTransaction:transaction handler:handler]; - }); - return; - } - - [wSelf finishTransaction:transaction result: FGIAPManagerPurchaseRusultSuccess message:message]; - }]; - }else{ - NSAssert(NO, @"You must configure the method: - pushSuccessTradeReultToServer:transaction:complete:"); - } -} - - -- (void)finishTransaction:(SKPaymentTransaction *)transaction result:(FGIAPManagerPurchaseRusult)result message:(NSString *)msg{ - - FGLog(@"%s finishTransaction:%@", __func__, transaction.transactionIdentifier); - - if ([SKPaymentQueue defaultQueue]) { - [[SKPaymentQueue defaultQueue] finishTransaction:transaction]; - } - - if (transaction.originalTransaction == nil && [transaction.payment.productIdentifier isEqualToString:self.productIdentifier]) { - self.productIdentifier = nil; - if (_buyProductCompleteBlock) { - _buyProductCompleteBlock(msg, result); - } - } -} - -@end diff --git a/keyBoard/Class/Vender/FGIAPService/FGIAPServiceUtility.h b/keyBoard/Class/Vender/FGIAPService/FGIAPServiceUtility.h deleted file mode 100644 index 4e2b509..0000000 --- a/keyBoard/Class/Vender/FGIAPService/FGIAPServiceUtility.h +++ /dev/null @@ -1,22 +0,0 @@ -// -// FGIAPServiceUtility.h -// Pods -// -// Created by FoneG on 2021/5/10. -// - -#ifndef FGIAPServiceUtility_h -#define FGIAPServiceUtility_h - -#define FGDEBUG - -#if defined (FGDEBUG) && defined (DEBUG) - #define FGLog(...) NSLog(__VA_ARGS__) -#else - #define FGLog(...) -#endif - -#define WS(wSelf) __weak typeof(self) wSelf = self -#define FGIAPServerOverdueErrorCode 11000007 //预留code:订单提交无效,需要删除本地的订单 - -#endif /* FGIAPServiceUtility_h */ diff --git a/keyBoard/Class/Vender/FGIAPService/FGIAPVerifyTransaction.h b/keyBoard/Class/Vender/FGIAPService/FGIAPVerifyTransaction.h deleted file mode 100644 index 34d3e55..0000000 --- a/keyBoard/Class/Vender/FGIAPService/FGIAPVerifyTransaction.h +++ /dev/null @@ -1,58 +0,0 @@ -// -// FGIAPVerifyTransaction.h -// MaltBaby -// -// Created by FoneG on 2021/5/8. -// - -#import -#import - -NS_ASSUME_NONNULL_BEGIN - -typedef NS_ENUM(NSInteger, FGIAPVerifyTransactionRusult) { - FGIAPManagerVerifyRusultCREATED = 0, - FGIAPManagerVerifyRusultFail, - FGIAPManagerVerifyRusultSuccess, -}; - -typedef NS_ENUM(NSInteger, FGIAPServiceErrorType) { - FGIAPServiceErrorTypeNone, - ///Failed to validate receipt - FGIAPServiceErrorTypeTransactionIdentifierNotExist, - ///No matching receipt data was found - FGIAPServiceErrorTypeReceiptNotExist, - ///Failed to validate receipt - FGIAPServiceErrorTypeVerifyTradeFail, -}; - -typedef void(^FGIAPVerifyTransactionBlock)(NSString *message, FGIAPVerifyTransactionRusult result); -typedef void(^FGIAPVerifyTransactionPushCallBack)(NSString *message, NSError * _Nullable result); - -@protocol FGIAPVerifyTransaction - -/// 苹果支付流程结束后,需要根据返回的票据等数据去自己的服务器校验 -/// @param receipt 票据 -/// @param transaction 支付事务 -/// @param handler 检验回调 -- (void)pushSuccessTradeReultToServer:(NSString *)receipt transaction:(SKPaymentTransaction *)transaction complete:(FGIAPVerifyTransactionPushCallBack)handler; - - -@optional - -/// 推送失败日志 -/// @param logStatistics 日志 -- (void)pushServiceErrorLogStatistics:(NSDictionary *)logStatistics error:(FGIAPServiceErrorType)error; - -/** -Promoting In-App Purchases - - 用户如果在 App下载页面点击购买你推广的内购商品,如果用户已经安装过你的 App 则会直接跳转你的App并调用上述代理方法;如果用户还没有安装你的 App 那么就会去下载你的 App,下载完成之后系统会推送一个通知,如果用户点击该通知就会跳转到你的App并且调用上面的代理方法 - - 上面的代理方法返回 true 则表示跳转到你的 App,IAP 继续完成交易,如果返回 false 则表示推迟或者取消购买,实际开发中因为可能还需要用户登录自己的账号、生成订单等,一般都是返回 false,之后通过 FGIAPService 的. -tryShouldAddStorePayments 在合适的时机触发。 - */ -- (BOOL)paymentQueue:(SKPaymentQueue *)queue shouldAddStorePayment:(SKPayment *)payment forProduct:(SKProduct *)product API_AVAILABLE(ios(11.0)); - -@end - -NS_ASSUME_NONNULL_END diff --git a/keyBoard/Class/Vender/FGIAPService/NSObject+FGIsNullOrEmpty.h b/keyBoard/Class/Vender/FGIAPService/NSObject+FGIsNullOrEmpty.h deleted file mode 100644 index e29e9b5..0000000 --- a/keyBoard/Class/Vender/FGIAPService/NSObject+FGIsNullOrEmpty.h +++ /dev/null @@ -1,19 +0,0 @@ -// -// NSObject+FGIsNullOrEmpty.h -// FGIAPService -// -// Created by FoneG on 2021/5/10. -// - -#import - -NS_ASSUME_NONNULL_BEGIN - -@interface NSObject (FGIsNullOrEmpty) - -- (BOOL)isNSStringAndNotEmpty; -- (BOOL)isNSArrayAndNotEmpty; - -@end - -NS_ASSUME_NONNULL_END diff --git a/keyBoard/Class/Vender/FGIAPService/NSObject+FGIsNullOrEmpty.m b/keyBoard/Class/Vender/FGIAPService/NSObject+FGIsNullOrEmpty.m deleted file mode 100644 index 18bd24c..0000000 --- a/keyBoard/Class/Vender/FGIAPService/NSObject+FGIsNullOrEmpty.m +++ /dev/null @@ -1,55 +0,0 @@ -// -// NSObject+FGIsNullOrEmpty.m -// FGIAPService -// -// Created by FoneG on 2021/5/10. -// - -#import "NSObject+FGIsNullOrEmpty.h" - -@implementation NSObject (FGIsNullOrEmpty) - -- (BOOL)isNSStringAndNotEmpty -{ - if (nil == self) { - return false; - } - if ([self isKindOfClass:[NSString class]]) { - NSString *str = (NSString*)self; - str = [str stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; - if ([str isEqualToString:@""]) { - return false; - } - if ([str isEqualToString:@"(null)"]) { - return false; - } - if (str.length == 0) { - return false; - } - return true; - } else if ([self isKindOfClass:[NSAttributedString class]]) { - NSString *str = ((NSAttributedString *)self).string; - str = [str stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; - if (str.length > 0) { - return true; - }else{ - return false; - } - } else{ - return false; - } -} - - -- (BOOL)isNSArrayAndNotEmpty -{ - if ([self isKindOfClass:[NSArray class]]) { - NSArray *temp = (NSArray *)self; - if (temp.count > 0) { - return true; - } - } - return false; -} - -@end