From c9dd6001b4df2af28181d5de296224e1aa550616 Mon Sep 17 00:00:00 2001 From: fengshuo <963787902@qq.com> Date: Sun, 26 Sep 2021 20:42:33 +0800 Subject: [PATCH] =?UTF-8?q?=E5=86=85=E8=B4=AD=E7=9A=84=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Podfile | 5 + Podfile.lock | 14 +- xplan-ios.xcodeproj/project.pbxproj | 46 ++++ xplan-ios/Base/MVP/Api/Api.h | 12 + xplan-ios/Base/MVP/Api/Api.m | 16 ++ .../Base/Tool/IAPHelper/RechargeStorage.h | 30 +++ .../Base/Tool/IAPHelper/RechargeStorage.m | 61 +++++ xplan-ios/Base/Tool/IAPHelper/XPIAPHelper.h | 36 +++ xplan-ios/Base/Tool/IAPHelper/XPIAPHelper.m | 88 +++++++ .../Base/Tool/NSObject/NSObject+JSONString.h | 16 ++ .../Base/Tool/NSObject/NSObject+JSONString.m | 16 ++ xplan-ios/Global/XPHtmlUrl.h | 1 + xplan-ios/Global/XPHtmlUrl.m | 1 + xplan-ios/Main/Mine/Api/Api+Mine.h | 32 +++ xplan-ios/Main/Mine/Api/Api+Mine.m | 26 +++ .../Mine/Model/Recharge/WalletInfoModel.h | 31 +++ .../Mine/Model/Recharge/WalletInfoModel.m | 12 + .../Mine/Presenter/XPMineRechargePresenter.h | 17 ++ .../Mine/Presenter/XPMineRechargePresenter.m | 52 +++++ .../Mine/Protocol/XPMineRechargeProtocol.h | 12 +- .../Recharge/XPMineRechargeTableViewCell.h | 14 +- .../Recharge/XPMineRechargeTableViewCell.m | 4 +- .../Recharge/XPMineRechargeViewController.m | 215 ++++++++++++++++-- .../SubViews/Recharge/XPMineRechageHeadView.h | 5 +- .../SubViews/Recharge/XPMineRechageHeadView.m | 15 +- .../SubViews/Recharge/XPMineRechargeNavView.h | 21 ++ .../SubViews/Recharge/XPMineRechargeNavView.m | 82 +++++++ xplan-ios/Main/Tabbar/Api+Main.m | 2 + xplan-ios/Main/Tabbar/MainPresenter.h | 4 +- xplan-ios/Main/Tabbar/MainPresenter.m | 10 + xplan-ios/Main/Tabbar/MainProtocol.h | 3 +- xplan-ios/Main/Tabbar/TabbarViewController.m | 18 ++ 32 files changed, 879 insertions(+), 38 deletions(-) create mode 100644 xplan-ios/Base/Tool/IAPHelper/RechargeStorage.h create mode 100644 xplan-ios/Base/Tool/IAPHelper/RechargeStorage.m create mode 100644 xplan-ios/Base/Tool/IAPHelper/XPIAPHelper.h create mode 100644 xplan-ios/Base/Tool/IAPHelper/XPIAPHelper.m create mode 100644 xplan-ios/Base/Tool/NSObject/NSObject+JSONString.h create mode 100644 xplan-ios/Base/Tool/NSObject/NSObject+JSONString.m create mode 100644 xplan-ios/Main/Mine/Model/Recharge/WalletInfoModel.h create mode 100644 xplan-ios/Main/Mine/Model/Recharge/WalletInfoModel.m create mode 100644 xplan-ios/Main/Mine/View/SubViews/Recharge/XPMineRechargeNavView.h create mode 100644 xplan-ios/Main/Mine/View/SubViews/Recharge/XPMineRechargeNavView.m diff --git a/Podfile b/Podfile index ffd4bc8e..26c1c388 100644 --- a/Podfile +++ b/Podfile @@ -24,6 +24,11 @@ target 'xplan-ios' do pod 'SDCycleScrollView' #上传图片 pod 'Qiniu' + #内购 + pod 'IAPHelper' + #持久化存储 + pod 'SSKeychain' + pod 'Base64' #登录的 pod 'mob_sharesdk' pod 'mob_sharesdk/ShareSDKPlatforms/QQ' diff --git a/Podfile.lock b/Podfile.lock index b9e3b347..90d927e5 100644 --- a/Podfile.lock +++ b/Podfile.lock @@ -14,8 +14,10 @@ PODS: - AFNetworking/Serialization (4.0.1) - AFNetworking/UIKit (4.0.1): - AFNetworking/NSURLSession + - Base64 (1.1.2) - FFPopup (1.1.5) - HappyDNS (0.3.17) + - IAPHelper (1.1) - Masonry (1.1.0) - MBProgressHUD (1.2.0) - MJExtension (3.3.0) @@ -43,12 +45,15 @@ PODS: - SDWebImage (5.11.1): - SDWebImage/Core (= 5.11.1) - SDWebImage/Core (5.11.1) + - SSKeychain (1.4.1) - SZTextView (1.3.0) - YYText (1.0.7) DEPENDENCIES: - AFNetworking + - Base64 - FFPopup + - IAPHelper - Masonry - MBProgressHUD - MJExtension @@ -61,14 +66,17 @@ DEPENDENCIES: - ReactiveObjC - SDCycleScrollView - SDWebImage + - SSKeychain - SZTextView - YYText SPEC REPOS: trunk: - AFNetworking + - Base64 - FFPopup - HappyDNS + - IAPHelper - Masonry - MBProgressHUD - MJExtension @@ -79,13 +87,16 @@ SPEC REPOS: - ReactiveObjC - SDCycleScrollView - SDWebImage + - SSKeychain - SZTextView - YYText SPEC CHECKSUMS: AFNetworking: 7864c38297c79aaca1500c33288e429c3451fdce + Base64: cecfb41a004124895a7bcee567a89bae5a89d49b FFPopup: a208dcee8db3e54ec4a88fcd6481f6f5d85b7a83 HappyDNS: 848ef73e24f2b0e2752064223ce2dc0dd88900ea + IAPHelper: fd74f53b0ac142eed085777b88b86a11746a2dd4 Masonry: 678fab65091a9290e40e2832a55e7ab731aad201 MBProgressHUD: 3ee5efcc380f6a79a7cc9b363dd669c5e1ae7406 MJExtension: 01704cca2b60a214c10761b6491eab74069d68a9 @@ -96,9 +107,10 @@ SPEC CHECKSUMS: ReactiveObjC: 011caa393aa0383245f2dcf9bf02e86b80b36040 SDCycleScrollView: a0d74c3384caa72bdfc81470bdbc8c14b3e1fbcf SDWebImage: a7f831e1a65eb5e285e3fb046a23fcfbf08e696d + SSKeychain: 55cc80f66f5c73da827e3077f02e43528897db41 SZTextView: 094dc6acc9beec537685c545d6e3e0d4975174e1 YYText: 5c461d709e24d55a182d1441c41dc639a18a4849 -PODFILE CHECKSUM: ad9235b352788673e6e5cf8b0d1b7c840428a840 +PODFILE CHECKSUM: e15982fef9e57d97997b5e561f9e5bd64d3950fc COCOAPODS: 1.10.1 diff --git a/xplan-ios.xcodeproj/project.pbxproj b/xplan-ios.xcodeproj/project.pbxproj index 691a665d..71cd5268 100644 --- a/xplan-ios.xcodeproj/project.pbxproj +++ b/xplan-ios.xcodeproj/project.pbxproj @@ -135,6 +135,11 @@ E88B5CBD26FB3BDF00DA9178 /* XPTeenagerAlertView.m in Sources */ = {isa = PBXBuildFile; fileRef = E88B5CBC26FB3BDF00DA9178 /* XPTeenagerAlertView.m */; }; E88B5CC126FB407B00DA9178 /* XPMineUserInfoViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = E88B5CC026FB407B00DA9178 /* XPMineUserInfoViewController.m */; }; E88B5CC526FB42B000DA9178 /* XPMineUserInfoHeaderView.m in Sources */ = {isa = PBXBuildFile; fileRef = E88B5CC426FB42B000DA9178 /* XPMineUserInfoHeaderView.m */; }; + E89DA66427005932008483C1 /* XPIAPHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = E89DA66327005932008483C1 /* XPIAPHelper.m */; }; + E89DA66727006443008483C1 /* RechargeStorage.m in Sources */ = {isa = PBXBuildFile; fileRef = E89DA66627006443008483C1 /* RechargeStorage.m */; }; + E89DA67227008D59008483C1 /* WalletInfoModel.m in Sources */ = {isa = PBXBuildFile; fileRef = E89DA67127008D59008483C1 /* WalletInfoModel.m */; }; + E89DA67527009ACD008483C1 /* XPMineRechargeNavView.m in Sources */ = {isa = PBXBuildFile; fileRef = E89DA67427009ACD008483C1 /* XPMineRechargeNavView.m */; }; + E89DA67827009F16008483C1 /* NSObject+JSONString.m in Sources */ = {isa = PBXBuildFile; fileRef = E89DA67727009F16008483C1 /* NSObject+JSONString.m */; }; E8AC720D26F435F5007D6E91 /* UIImageView+LoadImage.m in Sources */ = {isa = PBXBuildFile; fileRef = E8AC720C26F435F5007D6E91 /* UIImageView+LoadImage.m */; }; E8AC721026F43955007D6E91 /* UIImageConstant.m in Sources */ = {isa = PBXBuildFile; fileRef = E8AC720F26F43955007D6E91 /* UIImageConstant.m */; }; E8AC721326F46ADD007D6E91 /* XPMineSettingViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = E8AC721226F46ADD007D6E91 /* XPMineSettingViewController.m */; }; @@ -442,6 +447,16 @@ E88B5CC026FB407B00DA9178 /* XPMineUserInfoViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = XPMineUserInfoViewController.m; sourceTree = ""; }; E88B5CC326FB42B000DA9178 /* XPMineUserInfoHeaderView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = XPMineUserInfoHeaderView.h; sourceTree = ""; }; E88B5CC426FB42B000DA9178 /* XPMineUserInfoHeaderView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = XPMineUserInfoHeaderView.m; sourceTree = ""; }; + E89DA66227005931008483C1 /* XPIAPHelper.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = XPIAPHelper.h; sourceTree = ""; }; + E89DA66327005932008483C1 /* XPIAPHelper.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = XPIAPHelper.m; sourceTree = ""; }; + E89DA66527006443008483C1 /* RechargeStorage.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RechargeStorage.h; sourceTree = ""; }; + E89DA66627006443008483C1 /* RechargeStorage.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RechargeStorage.m; sourceTree = ""; }; + E89DA67027008D59008483C1 /* WalletInfoModel.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WalletInfoModel.h; sourceTree = ""; }; + E89DA67127008D59008483C1 /* WalletInfoModel.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = WalletInfoModel.m; sourceTree = ""; }; + E89DA67327009ACD008483C1 /* XPMineRechargeNavView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = XPMineRechargeNavView.h; sourceTree = ""; }; + E89DA67427009ACD008483C1 /* XPMineRechargeNavView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = XPMineRechargeNavView.m; sourceTree = ""; }; + E89DA67627009F16008483C1 /* NSObject+JSONString.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NSObject+JSONString.h"; sourceTree = ""; }; + E89DA67727009F16008483C1 /* NSObject+JSONString.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "NSObject+JSONString.m"; sourceTree = ""; }; E8AC720B26F435F5007D6E91 /* UIImageView+LoadImage.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "UIImageView+LoadImage.h"; sourceTree = ""; }; E8AC720C26F435F5007D6E91 /* UIImageView+LoadImage.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "UIImageView+LoadImage.m"; sourceTree = ""; }; E8AC720E26F43955007D6E91 /* UIImageConstant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = UIImageConstant.h; sourceTree = ""; }; @@ -941,6 +956,8 @@ 189DD5A726DFA09700AB55B1 /* Tool */ = { isa = PBXGroup; children = ( + E89DA66C2700873B008483C1 /* NSObject */, + E89DA6612700590A008483C1 /* IAPHelper */, E8B846B926FD7BE600A777FE /* UploadImage */, E8EEB8EA26FC2050007C6EBA /* SDPhotoBrowser */, E81366E426F0A4820076364C /* NSString */, @@ -1214,6 +1231,26 @@ path = MineInfo; sourceTree = ""; }; + E89DA6612700590A008483C1 /* IAPHelper */ = { + isa = PBXGroup; + children = ( + E89DA66227005931008483C1 /* XPIAPHelper.h */, + E89DA66327005932008483C1 /* XPIAPHelper.m */, + E89DA66527006443008483C1 /* RechargeStorage.h */, + E89DA66627006443008483C1 /* RechargeStorage.m */, + ); + path = IAPHelper; + sourceTree = ""; + }; + E89DA66C2700873B008483C1 /* NSObject */ = { + isa = PBXGroup; + children = ( + E89DA67627009F16008483C1 /* NSObject+JSONString.h */, + E89DA67727009F16008483C1 /* NSObject+JSONString.m */, + ); + path = NSObject; + sourceTree = ""; + }; E8AC720A26F435AF007D6E91 /* UIImageView */ = { isa = PBXGroup; children = ( @@ -1257,6 +1294,8 @@ children = ( E8B846CD26FDD96100A777FE /* XPMineRechageHeadView.h */, E8B846CE26FDD96100A777FE /* XPMineRechageHeadView.m */, + E89DA67327009ACD008483C1 /* XPMineRechargeNavView.h */, + E89DA67427009ACD008483C1 /* XPMineRechargeNavView.m */, ); path = Recharge; sourceTree = ""; @@ -1275,6 +1314,8 @@ children = ( E8B846DA26FDE24300A777FE /* RechargeListModel.h */, E8B846DB26FDE24300A777FE /* RechargeListModel.m */, + E89DA67027008D59008483C1 /* WalletInfoModel.h */, + E89DA67127008D59008483C1 /* WalletInfoModel.m */, ); path = Recharge; sourceTree = ""; @@ -1612,6 +1653,7 @@ E88B5CBA26FB329C00DA9178 /* XPMineTeenagerPwdProtocol.h in Sources */, E88B5CB226FB1CFF00DA9178 /* XPMineTeenagerProtocol.h in Sources */, E824546626F5FF6000BE8163 /* XPMineResetPayPasswordProtocol.h in Sources */, + E89DA66427005932008483C1 /* XPIAPHelper.m in Sources */, E824545E26F5EF2200BE8163 /* XPMineVerifIdentityProtocol.h in Sources */, E824545326F5CEAD00BE8163 /* XPMineModifPayProtocol.h in Sources */, E824544826F5945300BE8163 /* XPMinePayPwdProtocol.h in Sources */, @@ -1651,6 +1693,7 @@ E8AC722F26F49610007D6E91 /* XPMineNotificationItemModel.m in Sources */, E8E70D7A26F2F16600F03460 /* XPMinePresent.m in Sources */, E8EEB8F226FC2050007C6EBA /* SDPhotoBrowser.m in Sources */, + E89DA67827009F16008483C1 /* NSObject+JSONString.m in Sources */, E81C27AB26EF2D920031E639 /* ThirdUserInfo.m in Sources */, E81C279D26EEEC620031E639 /* XPConstant.m in Sources */, 187EEEFE26E8A82C002833B2 /* NSObject+AutoCoding.m in Sources */, @@ -1729,6 +1772,7 @@ E88B5CA526FB088600DA9178 /* XPMineTeenagerViewController.m in Sources */, E8EEB90926FC579A007C6EBA /* XPMineUserInfoEditTableViewCell.m in Sources */, 18C17A5D26F338F300C48E11 /* XplanFBFlutterViewContainer.m in Sources */, + E89DA67527009ACD008483C1 /* XPMineRechargeNavView.m in Sources */, 186A536926FC6F2E00D67B2C /* XCShareView.m in Sources */, 186A534C26FC6ED900D67B2C /* TTAlertView.m in Sources */, E8B825BF26E9E57D009E8E9F /* LoginTicketInfo.m in Sources */, @@ -1762,9 +1806,11 @@ E8B846DC26FDE24300A777FE /* RechargeListModel.m in Sources */, 189DD75926E6003C00AB55B1 /* Api.m in Sources */, E88B5CB826FB325200DA9178 /* XPMineTeenagerPwdPresenter.m in Sources */, + E89DA66727006443008483C1 /* RechargeStorage.m in Sources */, 189DD53F26DE255600AB55B1 /* main.m in Sources */, E872308D26E89DAA00B90D4F /* LoginInputView.m in Sources */, 189DD58F26DF97E700AB55B1 /* LoginPresenter.m in Sources */, + E89DA67227008D59008483C1 /* WalletInfoModel.m in Sources */, 189DD55026DE37F900AB55B1 /* MvpViewController.m in Sources */, E81366F326F0B7C80076364C /* LoginFullInfoViewController.m in Sources */, ); diff --git a/xplan-ios/Base/MVP/Api/Api.h b/xplan-ios/Base/MVP/Api/Api.h index 4629d06c..e9cc1d20 100644 --- a/xplan-ios/Base/MVP/Api/Api.h +++ b/xplan-ios/Base/MVP/Api/Api.h @@ -45,6 +45,18 @@ NS_ASSUME_NONNULL_BEGIN /// @param userInfo 需要更新的用户信息 + (void)complementInfoWithComplection:(HttpRequestHelperCompletion)complection userInfo:(NSDictionary *)userInfo; +/// 获取用户钱包余额信息 +/// @param complection 完成 +/// @param uid 用户uid +/// @param ticket ticketg ++ (void)getUserWalletInfoWithComplection:(HttpRequestHelperCompletion)complection + uid:(NSString *)uid + ticket:(NSString *)ticket; +/// 批量验证 +/// @param complection 完成 +/// @param transcationIdStr 需要验证的数据 ++ (void)requestCheckTranscationIdsWithComplection:(HttpRequestHelperCompletion)complection + transcationIdStr:(NSString *)transcationIdStr; @end NS_ASSUME_NONNULL_END diff --git a/xplan-ios/Base/MVP/Api/Api.m b/xplan-ios/Base/MVP/Api/Api.m index 14f55d82..def525c0 100644 --- a/xplan-ios/Base/MVP/Api/Api.m +++ b/xplan-ios/Base/MVP/Api/Api.m @@ -70,4 +70,20 @@ [HttpRequestHelper request:@"user/v2/update" method:HttpRequestHelperMethodPOST params:userInfo completion:complection]; } + +/// 获取用户钱包余额信息 +/// @param complection 完成 +/// @param uid 用户uid +/// @param ticket ticketg ++ (void)getUserWalletInfoWithComplection:(HttpRequestHelperCompletion)complection uid:(NSString *)uid ticket:(NSString *)ticket { + [self makeRequest:@"purse/query" method:HttpRequestHelperMethodGET completion:complection, __FUNCTION__, uid, ticket,nil]; +} + +/// 批量验证 +/// @param complection 完成 +/// @param transcationIdStr 需要验证的数据 ++ (void)requestCheckTranscationIdsWithComplection:(HttpRequestHelperCompletion)complection + transcationIdStr:(NSString *)transcationIdStr { + [self makeRequest:@"verify/checkIOSChargeRecord" method:HttpRequestHelperMethodPOST completion:complection, __FUNCTION__,transcationIdStr, nil]; +} @end diff --git a/xplan-ios/Base/Tool/IAPHelper/RechargeStorage.h b/xplan-ios/Base/Tool/IAPHelper/RechargeStorage.h new file mode 100644 index 00000000..e49d78a8 --- /dev/null +++ b/xplan-ios/Base/Tool/IAPHelper/RechargeStorage.h @@ -0,0 +1,30 @@ +// +// RechargeStorage.h +// xplan-ios +// +// Created by 冯硕 on 2021/9/26. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface RechargeStorage : NSObject + +/// 根据商品id保存凭证 ++ (BOOL)saveTranscationId:(NSString *)transcationId + recipt:(NSString *)recipt + uid:(NSString *)uid; + +/// 获取所有凭证 ++ (NSArray *)getAllReciptsWithUid:(NSString *)uid; + +/// 根据订单删除凭证 ++ (BOOL)delegateTranscationId:(NSString *)transcationId + uid:(NSString *)uid; + +/// 删除所有凭证 ++ (void)delegateAllTranscationIdsWithUid:(NSString *)uid; +@end + +NS_ASSUME_NONNULL_END diff --git a/xplan-ios/Base/Tool/IAPHelper/RechargeStorage.m b/xplan-ios/Base/Tool/IAPHelper/RechargeStorage.m new file mode 100644 index 00000000..6f1536ab --- /dev/null +++ b/xplan-ios/Base/Tool/IAPHelper/RechargeStorage.m @@ -0,0 +1,61 @@ +// +// RechargeStorage.m +// xplan-ios +// +// Created by 冯硕 on 2021/9/26. +// + +#import "RechargeStorage.h" +#import + +#define kappStoreKey @"kappStoreKey" + +@implementation RechargeStorage + +/// 根据商品id保存凭证 ++ (BOOL)saveTranscationId:(NSString *)transcationId + recipt:(NSString *)recipt + uid:(NSString *)uid { + NSString * key = [NSString stringWithFormat:@"%@_%@", kappStoreKey, uid]; + return [SSKeychain setPassword:recipt forService:key account:transcationId error:nil]; +} + + +/// 获取所有凭证 ++ (NSArray *)getAllReciptsWithUid:(NSString *)uid { + NSArray *transcationIds = [SSKeychain allAccounts]; + NSMutableArray *temArr = [NSMutableArray array]; + [transcationIds enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { + if ([obj[@"svce"] isKindOfClass:[NSString class]]) { + NSString * key = [NSString stringWithFormat:@"%@_%@", kappStoreKey, uid]; + if ([obj[@"svce"] isEqualToString:key]) { + NSString *recipt = [SSKeychain passwordForService:key account:obj[@"acct"] error:nil]; + NSData *data = [recipt dataUsingEncoding:NSUTF8StringEncoding]; + NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil]; + [temArr addObject:json]; + } + } + }]; + return temArr; +} + +/// 根据订单删除凭证 ++ (BOOL)delegateTranscationId:(NSString *)transcationId uid:(NSString *)uid { + NSString * key = [NSString stringWithFormat:@"%@_%@", kappStoreKey, uid]; + return [SSKeychain deletePasswordForService:key account:transcationId error:nil]; +} + +/// 删除所有凭证 ++ (void)delegateAllTranscationIdsWithUid:(NSString *)uid { + NSArray *transcationIds = [SSKeychain allAccounts]; + [transcationIds enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { + if ([obj[@"svce"] isKindOfClass:[NSString class]]) { + NSString * key = [NSString stringWithFormat:@"%@_%@", kappStoreKey, uid]; + if ([obj[@"svce"] isEqualToString:key]) { + [SSKeychain deletePasswordForService:key account:obj[@"acct"]]; + } + } + }]; +} + +@end diff --git a/xplan-ios/Base/Tool/IAPHelper/XPIAPHelper.h b/xplan-ios/Base/Tool/IAPHelper/XPIAPHelper.h new file mode 100644 index 00000000..e897c134 --- /dev/null +++ b/xplan-ios/Base/Tool/IAPHelper/XPIAPHelper.h @@ -0,0 +1,36 @@ +// +// XPIAPHelper.h +// xplan-ios +// +// Created by 冯硕 on 2021/9/26. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +typedef NS_ENUM(NSInteger ,PaymentStatus) { + PaymentStatus_Purchasing = 1,//付款中 + PaymentStatus_Purchased, //付款操作已经完成 + PaymentStatus_Failed, //付款操作失败 + PaymentStatus_Deferred, //未知状态 +}; + +@protocol XPIAPHelperDelegate + +///当前充值的状态 +- (void)rechargeProcessStatus:(PaymentStatus)status; + +///充值成功回调id +- (void)rechargeSuccess:(NSString *)transactionIdentifier; +@end + +@interface XPIAPHelper : NSObject ++ (instancetype)shareHelper; +///代理 +@property (nonatomic,weak) id delegate; +///购买商品 +- (void)buyAppProductWithAppProductId:(NSString *)appProductId; +@end + +NS_ASSUME_NONNULL_END diff --git a/xplan-ios/Base/Tool/IAPHelper/XPIAPHelper.m b/xplan-ios/Base/Tool/IAPHelper/XPIAPHelper.m new file mode 100644 index 00000000..b510e976 --- /dev/null +++ b/xplan-ios/Base/Tool/IAPHelper/XPIAPHelper.m @@ -0,0 +1,88 @@ +// +// XPIAPHelper.m +// xplan-ios +// +// Created by 冯硕 on 2021/9/26. +// + +#import "XPIAPHelper.h" +#import +#import + +@implementation XPIAPHelper + ++ (instancetype)shareHelper { + static dispatch_once_t onceToken; + static XPIAPHelper * helper; + dispatch_once(&onceToken, ^{ + helper = [[XPIAPHelper alloc] init]; + }); + return helper; +} + + +- (void)buyAppProductWithAppProductId:(NSString *)appProductId { + NSSet* dataSet = [[NSSet alloc] initWithObjects:appProductId, nil]; + [IAPShare sharedHelper].iap = [[IAPHelper alloc] initWithProductIdentifiers:dataSet]; + [[IAPShare sharedHelper].iap requestProductsWithCompletion:^(SKProductsRequest *request, SKProductsResponse *response) { + if (response != nil && response.products.count) { + ///有这个内购的产品 + } else if (!response.products.count) { + ///请求内购产品失败,无产品数量 +#warning to do 此处埋点一个 没有内购产品 + return; + } else if (!response) { +#warning to do 此处埋点一个 请求内购没有响应 + ///请求内购产品失败,内购无响应 + return; + } else { +#warning to do 此处埋点一个 异常 发起付款失败 + ///异常 发起付款失败 + return; + } + if (response.products.firstObject) { + [[IAPShare sharedHelper].iap buyProduct:response.products.firstObject onCompletion:^(SKPaymentTransaction *transcation) { + NSLog(@"%@",transcation.error.description); + switch(transcation.transactionState) { + case SKPaymentTransactionStatePurchased: { + NSLog(@"付款完成状态, 要做出相关的处理"); + [[SKPaymentQueue defaultQueue] finishTransaction:transcation]; + if (self.delegate && [self.delegate respondsToSelector:@selector(rechargeProcessStatus:)]) { + [self.delegate rechargeProcessStatus:PaymentStatus_Purchased]; + } + + if (self.delegate && [self.delegate respondsToSelector:@selector(rechargeSuccess:)]) { + [self.delegate rechargeSuccess:transcation.transactionIdentifier]; + } + //同步返回购买成功后,需要请求服务器二次校验 + } + break; + case SKPaymentTransactionStateFailed: { + [[SKPaymentQueue defaultQueue] finishTransaction:transcation]; + if (self.delegate && [self.delegate respondsToSelector:@selector(rechargeProcessStatus:)]) { + [self.delegate rechargeProcessStatus:PaymentStatus_Failed]; + } + } + break; + case SKPaymentTransactionStatePurchasing: { + NSLog(@"正在购买中"); + if (self.delegate && [self.delegate respondsToSelector:@selector(rechargeProcessStatus:)]) { + [self.delegate rechargeProcessStatus:PaymentStatus_Purchasing]; + } + } + break; + default: { + [[SKPaymentQueue defaultQueue] finishTransaction:transcation]; + if (self.delegate && [self.delegate respondsToSelector:@selector(rechargeProcessStatus:)]) { + [self.delegate rechargeProcessStatus:PaymentStatus_Deferred]; + } + NSLog(@"其它"); + } + } + }]; + } + }]; +} + + +@end diff --git a/xplan-ios/Base/Tool/NSObject/NSObject+JSONString.h b/xplan-ios/Base/Tool/NSObject/NSObject+JSONString.h new file mode 100644 index 00000000..f523dce2 --- /dev/null +++ b/xplan-ios/Base/Tool/NSObject/NSObject+JSONString.h @@ -0,0 +1,16 @@ +// +// NSObject+JSONString.h +// xplan-ios +// +// Created by 冯硕 on 2021/9/26. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface NSObject (JSONString) +- (NSString *)objectToJSONString; +@end + +NS_ASSUME_NONNULL_END diff --git a/xplan-ios/Base/Tool/NSObject/NSObject+JSONString.m b/xplan-ios/Base/Tool/NSObject/NSObject+JSONString.m new file mode 100644 index 00000000..78c43b48 --- /dev/null +++ b/xplan-ios/Base/Tool/NSObject/NSObject+JSONString.m @@ -0,0 +1,16 @@ +// +// NSObject+JSONString.m +// xplan-ios +// +// Created by 冯硕 on 2021/9/26. +// + +#import "NSObject+JSONString.h" +#import +@implementation NSObject (JSONString) + +- (NSString *)objectToJSONString { + return [self mj_JSONString]; +} + +@end diff --git a/xplan-ios/Global/XPHtmlUrl.h b/xplan-ios/Global/XPHtmlUrl.h index 641d8f26..f8700b17 100644 --- a/xplan-ios/Global/XPHtmlUrl.h +++ b/xplan-ios/Global/XPHtmlUrl.h @@ -19,6 +19,7 @@ typedef NS_ENUM(NSUInteger, URLType) { kIdentityURL,///实名认证 kGameBindAccountURL, kNurseryURL,///护苗计划 + kRechargePrivacyURL////充值协议 }; NSString * const URLWithType(URLType type); diff --git a/xplan-ios/Global/XPHtmlUrl.m b/xplan-ios/Global/XPHtmlUrl.m index cde8916e..a3edaf8f 100644 --- a/xplan-ios/Global/XPHtmlUrl.m +++ b/xplan-ios/Global/XPHtmlUrl.m @@ -19,6 +19,7 @@ NSString * const URLWithType(URLType type) { @(kIdentityURL):@"modules/identity/new.html",//实人认证 @(kGameBindAccountURL):@"modules/game/bindAccount.html",///绑定账号 @(kNurseryURL):@"activity/cleanNet/index.html", + @(kRechargePrivacyURL) : @"modules/rule/rechargeAgreement.html",//充值协议 }; NSString * url = [dic objectForKey:@(type)]; diff --git a/xplan-ios/Main/Mine/Api/Api+Mine.h b/xplan-ios/Main/Mine/Api/Api+Mine.h index 1d7896e3..ec7c5ffd 100644 --- a/xplan-ios/Main/Mine/Api/Api+Mine.h +++ b/xplan-ios/Main/Mine/Api/Api+Mine.h @@ -99,6 +99,38 @@ NS_ASSUME_NONNULL_BEGIN /// @param channelType channel + (void)getRechargeListWithComplection:(HttpRequestHelperCompletion)complection channelType:(NSString *)channelType; + +/// 苹果下单 +/// @param complection 完成 +/// @param chargeProdId 充值id +/// @param uid 用户的uid +/// @param ticket ticket +/// @param deviceInfo uuid +/// @param clientIp ip地址 ++ (void)requestIAPRechargeWithComplection:(HttpRequestHelperCompletion)complection + chargeProdId:(NSString *)chargeProdId + uid:(NSString *)uid + ticket:(NSString *)ticket + deviceInfo:(NSString *)deviceInfo + clientIp:(NSString *)clientIp; + +/// 验证凭据 +/// @param complection 完成 +/// @param receipt base 64 recepit +/// @param chooseEnv @"true" +/// @param chargeRecordId 服务端生成的订单编号 +/// @param transcationId 内购的唯一标识符 +/// @param uid 用户uid +/// @param ticket ticket ++ (void)checkReceiptWithComplection:(HttpRequestHelperCompletion)complection + receipt:(NSString *)receipt + chooseEnv:(NSString *)chooseEnv + chargeRecordId:(NSString *)chargeRecordId + transcationId:(NSString *)transcationId + uid:(NSString *)uid + ticket:(NSString *)ticket; + + @end NS_ASSUME_NONNULL_END diff --git a/xplan-ios/Main/Mine/Api/Api+Mine.m b/xplan-ios/Main/Mine/Api/Api+Mine.m index 6d47732c..027ccaa7 100644 --- a/xplan-ios/Main/Mine/Api/Api+Mine.m +++ b/xplan-ios/Main/Mine/Api/Api+Mine.m @@ -105,4 +105,30 @@ + (void)getRechargeListWithComplection:(HttpRequestHelperCompletion)complection channelType:(NSString *)channelType { [self makeRequest:@"chargeprod/list" method:HttpRequestHelperMethodGET completion:complection, __FUNCTION__,channelType, nil]; } + +/// 苹果下单 +/// @param complection 完成 +/// @param chargeProdId 充值id +/// @param uid 用户的uid +/// @param ticket ticket +/// @param deviceInfo uuid +/// @param clientIp ip地址 ++ (void)requestIAPRechargeWithComplection:(HttpRequestHelperCompletion)complection chargeProdId:(NSString *)chargeProdId uid:(NSString *)uid ticket:(NSString *)ticket deviceInfo:(NSString *)deviceInfo clientIp:(NSString *)clientIp { + [self makeRequest:@"order/placeV2" method:HttpRequestHelperMethodPOST completion:complection, __FUNCTION__,chargeProdId, uid, ticket, deviceInfo, clientIp, nil]; +} + + +/// 验证凭据 +/// @param complection 完成 +/// @param receipt base 64 recepit +/// @param chooseEnv @"true" +/// @param chargeRecordId 服务端生成的订单编号 +/// @param transcationId 内购的唯一标识符 +/// @param uid 用户uid +/// @param ticket ticket ++ (void)checkReceiptWithComplection:(HttpRequestHelperCompletion)complection receipt:(NSString *)receipt chooseEnv:(NSString *)chooseEnv chargeRecordId:(NSString *)chargeRecordId transcationId:(NSString *)transcationId uid:(NSString *)uid ticket:(NSString *)ticket { + [self makeRequest:@"order/placeV2" method:HttpRequestHelperMethodPOST completion:complection, __FUNCTION__,receipt, chooseEnv, chargeRecordId, transcationId, uid, ticket, nil]; +} + + @end diff --git a/xplan-ios/Main/Mine/Model/Recharge/WalletInfoModel.h b/xplan-ios/Main/Mine/Model/Recharge/WalletInfoModel.h new file mode 100644 index 00000000..ab95e095 --- /dev/null +++ b/xplan-ios/Main/Mine/Model/Recharge/WalletInfoModel.h @@ -0,0 +1,31 @@ +// +// WalletBalanceInfoModel.h +// xplan-ios +// +// Created by 冯硕 on 2021/9/26. +// + +#import "BaseObject.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface WalletInfoModel : BaseObject +/// 用户 uid +@property(nonatomic, assign) NSInteger uid; +/// 钻石数量 +@property(nonatomic, copy)NSString *goldNum; +//钻石数量(音游) +@property(nonatomic, copy)NSString *diamonds; + +@property(nonatomic, copy)NSString *chargeGoldNum; + +@property(nonatomic, assign)NSInteger amount; +/// 钻石数量 +@property(nonatomic, assign) double diamondNum; + +@property(nonatomic, copy)NSString *depositNum; +/// 是否有钻石转增功能 +@property (nonatomic, assign) BOOL sendGold; +@end + +NS_ASSUME_NONNULL_END diff --git a/xplan-ios/Main/Mine/Model/Recharge/WalletInfoModel.m b/xplan-ios/Main/Mine/Model/Recharge/WalletInfoModel.m new file mode 100644 index 00000000..6d7ad06d --- /dev/null +++ b/xplan-ios/Main/Mine/Model/Recharge/WalletInfoModel.m @@ -0,0 +1,12 @@ +// +// WalletBalanceInfoModel.m +// xplan-ios +// +// Created by 冯硕 on 2021/9/26. +// + +#import "WalletInfoModel.h" + +@implementation WalletInfoModel + +@end diff --git a/xplan-ios/Main/Mine/Presenter/XPMineRechargePresenter.h b/xplan-ios/Main/Mine/Presenter/XPMineRechargePresenter.h index 2d85117a..0aba8714 100644 --- a/xplan-ios/Main/Mine/Presenter/XPMineRechargePresenter.h +++ b/xplan-ios/Main/Mine/Presenter/XPMineRechargePresenter.h @@ -10,9 +10,26 @@ NS_ASSUME_NONNULL_BEGIN @interface XPMineRechargePresenter : BaseMvpPresenter + +/// 获取钱包信息 +- (void)getUserWalletInfo; /// 请求内购列表 /// @param channel 目前是8 - (void)requestRechargeListWithChannel:(NSString *)channel; + +/// 获取充值的订单编号 +/// @param chargeProdId 苹果服务器的充值 的id +- (void)requestIAPRechargeOrderWithChargeProdId:(NSString *)chargeProdId; + +/// 充值成功二次验证 +/// @param receipt 凭据 +/// @param orderId 订单编号 +/// @param transcationId 商品id +- (void)checkReceiptWithData:(NSString *)receipt orderId:(NSString *)orderId transcationId:(NSString *)transcationId; + +/// 批量验证内购掉单 +/// @param transcations 凭据的数组 +- (void)checkTranscationIds:(NSArray *)transcations; @end NS_ASSUME_NONNULL_END diff --git a/xplan-ios/Main/Mine/Presenter/XPMineRechargePresenter.m b/xplan-ios/Main/Mine/Presenter/XPMineRechargePresenter.m index 542a465e..dd70facb 100644 --- a/xplan-ios/Main/Mine/Presenter/XPMineRechargePresenter.m +++ b/xplan-ios/Main/Mine/Presenter/XPMineRechargePresenter.m @@ -8,14 +8,30 @@ #import "XPMineRechargePresenter.h" ///Api #import "Api+Mine.h" +///Tool +#import "AccountInfoStorage.h" +#import "YYUtility.h" +#import "NSObject+JSONString.h" ///P #import "XPMineRechargeProtocol.h" ///Model #import "RechargeListModel.h" +#import "WalletInfoModel.h" @implementation XPMineRechargePresenter +/// 获取钱包信息 +- (void)getUserWalletInfo { + NSString * uid = [AccountInfoStorage instance].getUid; + NSString * ticket = [AccountInfoStorage instance].getTicket; + [Api getUserWalletInfoWithComplection:[self createHttpCompletion:^(BaseModel * _Nonnull data) { + WalletInfoModel * model = [WalletInfoModel modelWithDictionary:data.data]; + [[self getView] getUserWalletInfo:model]; + }] uid:uid ticket:ticket]; +} + + /// 请求内购列表 /// @param channel 目前是8 - (void)requestRechargeListWithChannel:(NSString *)channel { @@ -25,4 +41,40 @@ }] channelType:channel]; } +/// 获取充值的订单编号 +/// @param chargeProdId 苹果服务器的充值 的id +- (void)requestIAPRechargeOrderWithChargeProdId:(NSString *)chargeProdId { + NSString * uid = [AccountInfoStorage instance].getUid; + NSString * ticket = [AccountInfoStorage instance].getTicket; + NSString * deviceInfo = [YYUtility deviceID]; + NSString * clientIp= [YYUtility ipAddress]; + [Api requestIAPRechargeWithComplection:[self createHttpCompletion:^(BaseModel * _Nonnull data) { + NSString *orderId = (NSString *)data.data[@"recordId"]; + [[self getView] requestIAPRechargeOrderSuccess:orderId chargeProdId:chargeProdId]; + } showLoading:YES] chargeProdId:chargeProdId uid:uid ticket:ticket deviceInfo:deviceInfo clientIp:clientIp]; +} + + +/// 充值成功二次验证 +/// @param receipt 凭据 +/// @param orderId 订单编号 +/// @param transcationId 商品id +- (void)checkReceiptWithData:(NSString *)receipt orderId:(NSString *)orderId transcationId:(NSString *)transcationId { + NSString * uid = [AccountInfoStorage instance].getUid; + NSString * ticket = [AccountInfoStorage instance].getTicket; + [Api checkReceiptWithComplection:[self createHttpCompletion:^(BaseModel * _Nonnull data) { + [[self getView] checkReceiptSuccess:transcationId]; + } showLoading:YES] receipt:receipt chooseEnv:@"true" chargeRecordId:orderId transcationId:transcationId uid:uid ticket:ticket]; +} + + +/// 批量验证内购掉单 +/// @param transcations 凭据的数组 +- (void)checkTranscationIds:(NSArray *)transcations { + NSString * transcationIdStr = [transcations objectToJSONString]; + [Api requestCheckTranscationIdsWithComplection:[self createHttpCompletion:^(BaseModel * _Nonnull data) { + [[self getView] checkTranscationIdsSuccess]; + }] transcationIdStr:transcationIdStr]; +} + @end diff --git a/xplan-ios/Main/Mine/Protocol/XPMineRechargeProtocol.h b/xplan-ios/Main/Mine/Protocol/XPMineRechargeProtocol.h index e585ea1e..c1b096be 100644 --- a/xplan-ios/Main/Mine/Protocol/XPMineRechargeProtocol.h +++ b/xplan-ios/Main/Mine/Protocol/XPMineRechargeProtocol.h @@ -8,12 +8,18 @@ #import NS_ASSUME_NONNULL_BEGIN - +@class WalletInfoModel; @protocol XPMineRechargeProtocol - +///请求钱包余额信息 +- (void)getUserWalletInfo:(WalletInfoModel *)balanceInfo; ///请求充值列表成功 - (void)requestRechargeListSucccess:(NSArray *)list; - +///请求充值id的状态成功 +- (void)requestIAPRechargeOrderSuccess:(NSString *)orderId chargeProdId:(NSString *)chargeProdId; +///二次校验成功 +- (void)checkReceiptSuccess:(NSString *)transcationId; +///批量验证凭据成功 +- (void)checkTranscationIdsSuccess; @end NS_ASSUME_NONNULL_END diff --git a/xplan-ios/Main/Mine/View/Cell/Recharge/XPMineRechargeTableViewCell.h b/xplan-ios/Main/Mine/View/Cell/Recharge/XPMineRechargeTableViewCell.h index 7f2c90aa..a13cf28e 100644 --- a/xplan-ios/Main/Mine/View/Cell/Recharge/XPMineRechargeTableViewCell.h +++ b/xplan-ios/Main/Mine/View/Cell/Recharge/XPMineRechargeTableViewCell.h @@ -8,10 +8,20 @@ #import NS_ASSUME_NONNULL_BEGIN -@class RechargeListModel; +@class RechargeListModel,XPMineRechargeTableViewCell; + +@protocol XPMineRechargeTableViewCellDelegate + +///点击了某个item +- (void)xPMineRechargeTableViewCell:(XPMineRechargeTableViewCell *)cell didSelectItem:(RechargeListModel *)listModel; + +@end + @interface XPMineRechargeTableViewCell : UITableViewCell -/// +///数据源 @property (nonatomic,strong) RechargeListModel *listModel; +///代理 +@property (nonatomic,weak) id delegate; @end NS_ASSUME_NONNULL_END diff --git a/xplan-ios/Main/Mine/View/Cell/Recharge/XPMineRechargeTableViewCell.m b/xplan-ios/Main/Mine/View/Cell/Recharge/XPMineRechargeTableViewCell.m index 49d04687..1c7de694 100644 --- a/xplan-ios/Main/Mine/View/Cell/Recharge/XPMineRechargeTableViewCell.m +++ b/xplan-ios/Main/Mine/View/Cell/Recharge/XPMineRechargeTableViewCell.m @@ -36,7 +36,9 @@ } #pragma mark - Response - (void)rechargeButtonAction:(UIButton *)sender { - + if (self.delegate && [self.delegate respondsToSelector:@selector(xPMineRechargeTableViewCell:didSelectItem:)]) { + [self.delegate xPMineRechargeTableViewCell:self didSelectItem:self.listModel]; + } } #pragma mark - Private Method diff --git a/xplan-ios/Main/Mine/View/Recharge/XPMineRechargeViewController.m b/xplan-ios/Main/Mine/View/Recharge/XPMineRechargeViewController.m index c1ebaa89..065472e7 100644 --- a/xplan-ios/Main/Mine/View/Recharge/XPMineRechargeViewController.m +++ b/xplan-ios/Main/Mine/View/Recharge/XPMineRechargeViewController.m @@ -8,48 +8,84 @@ #import "XPMineRechargeViewController.h" ///Third #import -#import +#import ///Tool #import "ThemeColor.h" #import "XPMacro.h" +#import "XPHtmlUrl.h" +#import "XPIAPHelper.h" +#import "RechargeStorage.h" +#import "AccountInfoStorage.h" +#import "NSObject+JSONString.h" ///Model #import "RechargeListModel.h" ///View #import "XPMineRechageHeadView.h" #import "XPMineRechargeTableViewCell.h" +#import "XPMineRechargeNavView.h" ///P #import "XPMineRechargePresenter.h" #import "XPMineRechargeProtocol.h" +///VC +#import "XPWebViewController.h" -@interface XPMineRechargeViewController () +@interface XPMineRechargeViewController () ///数据源 @property (nonatomic,strong) NSArray *datasource; ///列表 @property (nonatomic,strong) UITableView *tableView; /// @property (nonatomic,strong) XPMineRechageHeadView *headeView; +///订单编号 +@property (nonatomic,copy) NSString *orderId; +///导航栏 +@property (nonatomic,strong) XPMineRechargeNavView *navView; +/// +@property (nonatomic,strong) UIStackView *stackView; +///同意 +@property (nonatomic,strong) UILabel *agreeLabel; ///充值协议 -@property (nonatomic,strong) YYLabel *rechargeProtocolLabel; +@property (nonatomic,strong) UIButton *protcoloButton; @end @implementation XPMineRechargeViewController +- (void)dealloc { + [XPIAPHelper shareHelper].delegate = nil; +} + +- (BOOL)isHiddenNavBar { + return YES; +} + - (XPMineRechargePresenter *)createPresenter { return [[XPMineRechargePresenter alloc] init]; } - (void)viewDidLoad { - [super viewDidLoad]; - [self getRechargeList]; + [super viewDidLoad]; + [self initHttpData]; [self initSubViews]; [self initSubViewConstraints]; } - +#pragma mark - Response +- (void)protcoloButtonAction:(UIButton *)sender { + XPWebViewController * webVC= [[XPWebViewController alloc] init]; + webVC.url = URLWithType(kRechargePrivacyURL); + [self.navigationController pushViewController:webVC animated:YES]; +} #pragma mark - Private Method - (void)initSubViews { [self.view addSubview:self.tableView]; - [self.view addSubview:self.rechargeProtocolLabel]; + [self.view addSubview:self.navView]; + [self.view addSubview:self.stackView]; + + [self.stackView addArrangedSubview:self.agreeLabel]; + [self.stackView addArrangedSubview:self.protcoloButton]; self.tableView.tableHeaderView = self.headeView; + + [XPIAPHelper shareHelper].delegate = self; + self.automaticallyAdjustsScrollViewInsets = NO; } - (void)initSubViewConstraints { @@ -57,16 +93,65 @@ make.edges.mas_equalTo(self.view); }]; - [self.rechargeProtocolLabel mas_makeConstraints:^(MASConstraintMaker *make) { + [self.stackView mas_makeConstraints:^(MASConstraintMaker *make) { make.centerX.mas_equalTo(self.view); make.bottom.mas_equalTo(self.view).offset(-20 - kSafeAreaBottomHeight); }]; + + [self.navView mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.right.top.mas_equalTo(self.view); + make.height.mas_equalTo(kNavigationHeight); + }]; +} + +- (void)initHttpData { + [self getRechargeList]; + [self getUserWalletBalanceInfo]; + [self checkTranscationIds]; } - (void)getRechargeList { [self.presenter requestRechargeListWithChannel:@"8"]; } +- (void)getUserWalletBalanceInfo { + [self.presenter getUserWalletInfo]; +} + +///批量验证 +- (void)checkTranscationIds { + NSString * uid = [AccountInfoStorage instance].getUid; + NSArray * array = [RechargeStorage getAllReciptsWithUid:uid]; + if (array.count > 0) { + [self.presenter checkTranscationIds:array]; + } +} + +///充值成功之后保存订单到钥匙串 +- (void)saveRechageReciptWithTransactionIdentifier:(NSString *)transactionIdentifier { + NSData *receipt = [NSData dataWithContentsOfURL:[[NSBundle mainBundle] appStoreReceiptURL]]; + NSString *encodeStr = [receipt base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithLineFeed]; + NSMutableDictionary *dictionary = [NSMutableDictionary dictionary]; + [dictionary setObject:transactionIdentifier forKey:@"transcationId"]; + [dictionary setObject:encodeStr forKey:@"recipt"]; + [dictionary setObject:self.orderId forKey:@"orderId"]; + NSString *reciptJson = [dictionary objectToJSONString]; + NSString * uid = [AccountInfoStorage instance].getUid; + BOOL saveSuccess = [RechargeStorage saveTranscationId:transactionIdentifier recipt:reciptJson uid:uid]; + if (!saveSuccess) { +#warning to do 保存失败 需要埋点 + } +} + +///删除本地保存的 +- (void)deleteRechageReciptWithTransactionIdentifier:(NSString *)transactionIdentifier { + NSString * uid = [AccountInfoStorage instance].getUid; + BOOL deleteSuccess = [RechargeStorage delegateTranscationId:transactionIdentifier uid:uid]; + if (deleteSuccess) { +#warning to do 保存失败 需要埋点 + } +} + #pragma mark - UITableViewDelegate And UITableViewDataSource - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return self.datasource.count; @@ -75,6 +160,7 @@ - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { XPMineRechargeTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:NSStringFromClass([XPMineRechargeTableViewCell class]) forIndexPath:indexPath]; cell.listModel = self.datasource[indexPath.row]; + cell.delegate = self; return cell; } @@ -85,12 +171,74 @@ - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{ [tableView deselectRowAtIndexPath:indexPath animated:true]; } + +#pragma mark - XPMineRechargeTableViewCellDelegate +- (void)xPMineRechargeTableViewCell:(XPMineRechargeTableViewCell *)cell didSelectItem:(RechargeListModel *)listModel { + if (listModel.chargeProdId) { + [self.presenter requestIAPRechargeOrderWithChargeProdId:listModel.chargeProdId]; + } +} + +#pragma mark - XPMineRechargeNavViewDelegate +- (void)xPMineRechargeNavView:(XPMineRechargeNavView *)view didClickBackButton:(UIButton *)sender { + [self.navigationController popViewControllerAnimated:YES]; +} + +#pragma mark - XPIAPHelperDelegate +///当前充值的状态 +- (void)rechargeProcessStatus:(PaymentStatus)status { + [self hideHUD]; + if (status == PaymentStatus_Purchased) { + [self showLoading]; + } else if (status == PaymentStatus_Purchasing) { + [self showLoading]; + } else if (status == PaymentStatus_Failed) { + [self showErrorToast:@"购买失败"]; + } else if (status == PaymentStatus_Deferred) { + [self showErrorToast:@"出现未知错误,请重新尝试"]; + } +} + +///充值成功回调id +- (void)rechargeSuccess:(NSString *)transactionIdentifier { + ///保存唯一凭证 + [self saveRechageReciptWithTransactionIdentifier:transactionIdentifier]; + NSData *receiptData = [NSData dataWithContentsOfURL:[[NSBundle mainBundle] appStoreReceiptURL]]; + NSString * receipt = [MF_Base64Codec base64StringFromData:receiptData]; + ///二次验证 + [self.presenter checkReceiptWithData:receipt orderId:self.orderId transcationId:transactionIdentifier]; +} + #pragma mark - XPMineRechargeProtocol - (void)requestRechargeListSucccess:(NSArray *)list { self.datasource = list; [self.tableView reloadData]; } +- (void)requestIAPRechargeOrderSuccess:(NSString *)orderId chargeProdId:(NSString *)chargeProdId { + if (orderId.length > 0) { + self.orderId = orderId; + [[XPIAPHelper shareHelper] buyAppProductWithAppProductId:chargeProdId]; + } +} + +///二次验证成功 +- (void)checkReceiptSuccess:(NSString *)transcationId { + [self deleteRechageReciptWithTransactionIdentifier:transcationId]; + ///刷新一下用户的💎 + [self getUserWalletBalanceInfo]; + self.orderId = nil; +} + +- (void)getUserWalletInfo:(WalletInfoModel *)balanceInfo { + self.headeView.walletInfo = balanceInfo; +} + +- (void)checkTranscationIdsSuccess { + NSString * uid = [AccountInfoStorage instance].getUid; + [RechargeStorage delegateAllTranscationIdsWithUid:uid]; +} +#pragma mark - Getters And Setters - (UITableView *)tableView { if (!_tableView) { _tableView = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStyleGrouped]; @@ -114,21 +262,44 @@ return _headeView; } -- (YYLabel *)rechargeProtocolLabel { - if (!_rechargeProtocolLabel) { - _rechargeProtocolLabel = [[YYLabel alloc] init]; - _rechargeProtocolLabel.font = [UIFont systemFontOfSize:12]; - NSString * name = [NSString stringWithFormat:@"《用户充值协议》"]; - NSString *str = [NSString stringWithFormat:@"%@%@", @"已阅读并同意", name]; - NSRange range1 = [str rangeOfString:@"已阅读并同意"]; - NSRange range = [str rangeOfString:name]; - NSMutableAttributedString *attStr = [[NSMutableAttributedString alloc] initWithString:str]; - [attStr addAttribute:NSForegroundColorAttributeName value:[ThemeColor appMainColor] range:range]; - [attStr addAttribute:NSForegroundColorAttributeName value:[ThemeColor textThirdColor] range:range1]; - _rechargeProtocolLabel.attributedText = attStr; - _rechargeProtocolLabel.textAlignment = NSTextAlignmentCenter; + +- (UIStackView *)stackView { + if (!_stackView) { + _stackView = [[UIStackView alloc] init]; + _stackView.axis = UILayoutConstraintAxisHorizontal; + _stackView.distribution = UIStackViewDistributionFill; + _stackView.alignment = UIStackViewAlignmentFill; + _stackView.spacing = 2; } - return _rechargeProtocolLabel; + return _stackView; +} + +- (UIButton *)protcoloButton { + if (!_protcoloButton) { + _protcoloButton = [UIButton buttonWithType:UIButtonTypeCustom]; + [_protcoloButton setTitle:@"《用户充值协议》" forState:UIControlStateNormal]; + [_protcoloButton setTitleColor:[ThemeColor appMainColor] forState:UIControlStateNormal]; + _protcoloButton.titleLabel.font = [UIFont systemFontOfSize:12]; + [_protcoloButton addTarget:self action:@selector(protcoloButtonAction:) forControlEvents:UIControlEventTouchUpInside]; + } + return _protcoloButton; +} +- (UILabel *)agreeLabel { + if (!_agreeLabel) { + _agreeLabel = [[UILabel alloc] init]; + _agreeLabel.text = @"已阅读并同意"; + _agreeLabel.font = [UIFont systemFontOfSize:12]; + _agreeLabel.textColor = [ThemeColor textThirdColor]; + } + return _agreeLabel; +} + +- (XPMineRechargeNavView *)navView { + if (!_navView) { + _navView = [[XPMineRechargeNavView alloc] init]; + _navView.delegate = self; + } + return _navView; } @end diff --git a/xplan-ios/Main/Mine/View/SubViews/Recharge/XPMineRechageHeadView.h b/xplan-ios/Main/Mine/View/SubViews/Recharge/XPMineRechageHeadView.h index 0574640b..bbfabd2b 100644 --- a/xplan-ios/Main/Mine/View/SubViews/Recharge/XPMineRechageHeadView.h +++ b/xplan-ios/Main/Mine/View/SubViews/Recharge/XPMineRechageHeadView.h @@ -8,9 +8,10 @@ #import NS_ASSUME_NONNULL_BEGIN - +@class WalletInfoModel; @interface XPMineRechageHeadView : UIView - +///钱包信息 +@property (nonatomic,strong) WalletInfoModel *walletInfo; @end NS_ASSUME_NONNULL_END diff --git a/xplan-ios/Main/Mine/View/SubViews/Recharge/XPMineRechageHeadView.m b/xplan-ios/Main/Mine/View/SubViews/Recharge/XPMineRechageHeadView.m index 93a8a1ee..c468d5fa 100644 --- a/xplan-ios/Main/Mine/View/SubViews/Recharge/XPMineRechageHeadView.m +++ b/xplan-ios/Main/Mine/View/SubViews/Recharge/XPMineRechageHeadView.m @@ -11,6 +11,8 @@ ///Tool #import "ThemeColor.h" #import "XPMacro.h" +///Model +#import "WalletInfoModel.h" @interface XPMineRechageHeadView () ///大的背景 @@ -47,11 +49,7 @@ } - (void)initContrations { - [self mas_makeConstraints:^(MASConstraintMaker *make) { - make.width.mas_equalTo(KScreenWidth); - make.height.mas_equalTo(kSafeAreaTopHeight + 190); - }]; - + self.frame = CGRectMake(0, 0, KScreenWidth, 190 + kSafeAreaTopHeight); [self.backImageView mas_makeConstraints:^(MASConstraintMaker *make) { make.edges.mas_equalTo(self); }]; @@ -79,12 +77,19 @@ } #pragma mark - Getters And Setters +- (void)setWalletInfo:(WalletInfoModel *)walletInfo { + _walletInfo = walletInfo; + if (_walletInfo) { + self.amountLabel.text = walletInfo.diamonds; + } +} - (UIImageView *)backImageView { if (!_backImageView) { _backImageView = [[UIImageView alloc] init]; _backImageView.userInteractionEnabled = YES; _backImageView.image = [UIImage imageNamed:@"mine_recharge_header_bg"]; + _backImageView.layer.masksToBounds = YES; _backImageView.contentMode = UIViewContentModeScaleAspectFill; } return _backImageView; diff --git a/xplan-ios/Main/Mine/View/SubViews/Recharge/XPMineRechargeNavView.h b/xplan-ios/Main/Mine/View/SubViews/Recharge/XPMineRechargeNavView.h new file mode 100644 index 00000000..88c744b6 --- /dev/null +++ b/xplan-ios/Main/Mine/View/SubViews/Recharge/XPMineRechargeNavView.h @@ -0,0 +1,21 @@ +// +// XPMineRechargeNavView.h +// xplan-ios +// +// Created by 冯硕 on 2021/9/26. +// + +#import + +NS_ASSUME_NONNULL_BEGIN +@class XPMineRechargeNavView; +@protocol XPMineRechargeNavViewDelegate +///点击了返回按钮 +- (void)xPMineRechargeNavView:(XPMineRechargeNavView *)view didClickBackButton:(UIButton *)sender; +@end +@interface XPMineRechargeNavView : UIView +///代理 +@property (nonatomic,weak) id delegate; +@end + +NS_ASSUME_NONNULL_END diff --git a/xplan-ios/Main/Mine/View/SubViews/Recharge/XPMineRechargeNavView.m b/xplan-ios/Main/Mine/View/SubViews/Recharge/XPMineRechargeNavView.m new file mode 100644 index 00000000..da063446 --- /dev/null +++ b/xplan-ios/Main/Mine/View/SubViews/Recharge/XPMineRechargeNavView.m @@ -0,0 +1,82 @@ +// +// XPMineRechargeNavView.m +// xplan-ios +// +// Created by 冯硕 on 2021/9/26. +// + +#import "XPMineRechargeNavView.h" +///Third +#import +///Tool +#import "ThemeColor.h" +#import "UIButton+EnlargeTouchArea.h" + +@interface XPMineRechargeNavView () +///返回按钮 +@property (nonatomic,strong) UIButton *backButton; +///显示文本 +@property (nonatomic,strong) UILabel *titleLabel; +@end + +@implementation XPMineRechargeNavView + +- (instancetype)initWithFrame:(CGRect)frame { + self = [super initWithFrame:frame]; + if (self) { + [self initSubViews]; + [self initSubViewConstraints]; + } + return self; +} +#pragma mark - Response +- (void)backButtonAction:(UIButton *)sender { + if (self.delegate && [self.delegate respondsToSelector:@selector(xPMineRechargeNavView:didClickBackButton:)]) { + [self.delegate xPMineRechargeNavView:self didClickBackButton:sender]; + } +} + +#pragma mark - Private Method +- (void)initSubViews { + self.backgroundColor = [UIColor clearColor]; + [self addSubview:self.backButton]; + [self addSubview:self.titleLabel]; +} + +- (void)initSubViewConstraints { + [self.backButton mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.mas_equalTo(15); + make.centerY.equalTo(self.mas_bottom).mas_offset(-22); + }]; + + [self.titleLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.centerX.mas_equalTo(self); + make.centerY.equalTo(self.mas_bottom).mas_offset(-22); + }]; +} + +#pragma mark - Getters And Setters +- (UIButton *)backButton { + if (!_backButton) { + _backButton = [UIButton buttonWithType:UIButtonTypeCustom]; + [_backButton setImage:[UIImage imageNamed:@"common_nav_back"] forState:UIControlStateNormal]; + _backButton.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft; + [_backButton addTarget:self action:@selector(backButtonAction:) forControlEvents:UIControlEventTouchUpInside]; + [_backButton setEnlargeEdgeWithTop:10 right:10 bottom:10 left:10]; + } + return _backButton; +} + + +- (UILabel *)titleLabel { + if (!_titleLabel) { + _titleLabel = [[UILabel alloc] init]; + _titleLabel.textAlignment = NSTextAlignmentCenter; + _titleLabel.font = [UIFont systemFontOfSize:15]; + _titleLabel.text = @"账户"; + _titleLabel.textColor = [ThemeColor mainTextColor]; + } + return _titleLabel; +} + +@end diff --git a/xplan-ios/Main/Tabbar/Api+Main.m b/xplan-ios/Main/Tabbar/Api+Main.m index f6916e05..10b1d1e7 100644 --- a/xplan-ios/Main/Tabbar/Api+Main.m +++ b/xplan-ios/Main/Tabbar/Api+Main.m @@ -12,4 +12,6 @@ + (void)requestTicket:(HttpRequestHelperCompletion)completion access_token:(NSString *)accessToken issue_type:(NSString *)issueType { [self makeRequest:@"oauth/ticket" method:HttpRequestHelperMethodPOST completion:completion, __FUNCTION__, accessToken, issueType, nil]; } + + @end diff --git a/xplan-ios/Main/Tabbar/MainPresenter.h b/xplan-ios/Main/Tabbar/MainPresenter.h index 85860bfb..07b15610 100644 --- a/xplan-ios/Main/Tabbar/MainPresenter.h +++ b/xplan-ios/Main/Tabbar/MainPresenter.h @@ -13,7 +13,9 @@ NS_ASSUME_NONNULL_BEGIN - (void)autoLogin; - (void)getUserInfo; - +/// 批量验证内购掉单 +/// @param transcations 凭据的数组 +- (void)checkTranscationIds:(NSArray *)transcations; @end NS_ASSUME_NONNULL_END diff --git a/xplan-ios/Main/Tabbar/MainPresenter.m b/xplan-ios/Main/Tabbar/MainPresenter.m index 47f013a5..c6c4519d 100644 --- a/xplan-ios/Main/Tabbar/MainPresenter.m +++ b/xplan-ios/Main/Tabbar/MainPresenter.m @@ -10,6 +10,7 @@ #import "AccountModel.h" #import "Api+Main.h" #import "MainProtocol.h" +#import "NSObject+JSONString.h" @implementation MainPresenter @@ -36,4 +37,13 @@ }] uid:[[AccountInfoStorage instance] getUid]]; } +/// 批量验证内购掉单 +/// @param transcations 凭据的数组 +- (void)checkTranscationIds:(NSArray *)transcations { + NSString * transcationIdStr = [transcations objectToJSONString]; + [Api requestCheckTranscationIdsWithComplection:[self createHttpCompletion:^(BaseModel * _Nonnull data) { + [[self getView] checkTranscationIdsSuccess]; + }] transcationIdStr:transcationIdStr]; +} + @end diff --git a/xplan-ios/Main/Tabbar/MainProtocol.h b/xplan-ios/Main/Tabbar/MainProtocol.h index 923cfc06..f2d42349 100644 --- a/xplan-ios/Main/Tabbar/MainProtocol.h +++ b/xplan-ios/Main/Tabbar/MainProtocol.h @@ -14,7 +14,8 @@ NS_ASSUME_NONNULL_BEGIN - (void)autoLoginSuccess; - (void)getUserInfoSuccess:(UserInfoModel *)userInfo; - +///批量验证凭据成功 +- (void)checkTranscationIdsSuccess; @end NS_ASSUME_NONNULL_END diff --git a/xplan-ios/Main/Tabbar/TabbarViewController.m b/xplan-ios/Main/Tabbar/TabbarViewController.m index 0de71fbd..7431131e 100644 --- a/xplan-ios/Main/Tabbar/TabbarViewController.m +++ b/xplan-ios/Main/Tabbar/TabbarViewController.m @@ -12,6 +12,8 @@ #import "ThemeColor.h" #import "UIImage+Utils.h" #import "XCHUDTool.h" +#import "RechargeStorage.h" +#import "AccountInfoStorage.h" ///VC #import "TabbarViewController.h" #import "BaseViewController.h" @@ -45,6 +47,7 @@ [super viewWillAppear:animated]; [self.navigationController setNavigationBarHidden:YES animated:YES]; [self.presenter autoLogin]; + [self checkTranscationIds]; } - (MainPresenter *)presenter { @@ -91,6 +94,21 @@ [self.navigationController presentViewController:nav animated:YES completion:nil]; } +///批量验证内购凭据成功 +- (void)checkTranscationIdsSuccess { + NSString * uid = [AccountInfoStorage instance].getUid; + [RechargeStorage delegateAllTranscationIdsWithUid:uid]; +} + +#pragma mark - 批量验证内购凭据 +- (void)checkTranscationIds { + NSString * uid = [AccountInfoStorage instance].getUid; + NSArray * array = [RechargeStorage getAllReciptsWithUid:uid]; + if (array.count > 0) { + [self.presenter checkTranscationIds:array]; + } +} + #pragma mark - 绑定手机号 - (void)bindPhone { LoginBindPhoneViewController * bindPhoneVC = [[LoginBindPhoneViewController alloc] init];