// // KBPayMainVC.m // keyBoard // // Created by Mac on 2026/2/3. // #import "KBPayMainVC.h" #import "JXPagerView.h" #import "KBShopHeadView.h" #import #import "KBCategoryTitleView.h" #import #import //#import "KBShopItemVC.h" #import "KBVipPay.h" #import "KBPaySvipVC.h" #import "KBSearchVC.h" #import "MySkinVC.h" #import "JXPagerView.h" #import "PagingViewTableHeaderView.h" #import "JXCategoryTitleView.h" #import "keyBoard-Swift.h" static const CGFloat JXTableHeaderViewHeight = 224; static const CGFloat JXheightForHeaderInSection = 39; @interface KBPayMainVC () @property (nonatomic, strong) JXPagerView *pagerView; @property (nonatomic, strong) PagingViewTableHeaderView *userHeaderView; //@property (nonatomic, strong, readonly) JXCategoryTitleView *categoryView; @property (nonatomic, strong) UIView *categoryContainer; // categoryView 容器 @property (nonatomic, strong) JXCategoryImageView *myCategoryView; @property (nonatomic, assign) BOOL isNeedFooter; @property (nonatomic, assign) BOOL isNeedHeader; - (JXPagerView *)preferredPagingView; //@property (nonatomic, strong) NSArray *titles; @property (nonatomic, strong) NSArray *imageNames; @property (nonatomic, strong) UIView *naviBGView; @property (nonatomic, strong) UIButton *closeButton; // 当前选中的方案索引 @property (nonatomic, strong) UIButton *restoreButton; /// 底部固定区域 @property (nonatomic, strong) UIView *bottomContainer; @property (nonatomic, strong) UIButton *payButton; @property (nonatomic, strong) UILabel *agreementLabel; @property (nonatomic, strong) UIButton *agreementButton; /// Deep link pending config (透传给 VIP 页面) @property (nonatomic, copy, nullable) NSString *pendingProductId; @property (nonatomic, assign) BOOL pendingAutoPurchase; @property (nonatomic, copy, nullable) NSArray *pendingPrefillProductsJSON; @property (nonatomic, assign) NSInteger pendingPrefillSelectedIndex; @end @implementation KBPayMainVC #pragma mark - Deep Link Support - (void)configureWithProductId:(nullable NSString *)productId autoPurchase:(BOOL)autoPurchase { self.pendingProductId = productId.length ? [productId copy] : nil; self.pendingAutoPurchase = autoPurchase; self.pendingPrefillProductsJSON = nil; self.pendingPrefillSelectedIndex = NSNotFound; [self kb_applyPendingConfigToVipIfPossible]; } - (void)configureWithProductId:(nullable NSString *)productId autoPurchase:(BOOL)autoPurchase prefillProductsJSON:(nullable NSArray *)productsJSON selectedIndex:(NSInteger)selectedIndex { self.pendingProductId = productId.length ? [productId copy] : nil; self.pendingAutoPurchase = autoPurchase; self.pendingPrefillProductsJSON = ([productsJSON isKindOfClass:NSArray.class] ? [productsJSON copy] : nil); self.pendingPrefillSelectedIndex = selectedIndex; [self kb_applyPendingConfigToVipIfPossible]; } - (void)kb_applyPendingConfigToVipIfPossible { if (!self.isViewLoaded) { return; } BOOL hasPrefill = ([self.pendingPrefillProductsJSON isKindOfClass:NSArray.class] && self.pendingPrefillProductsJSON.count > 0); BOOL hasProductId = (self.pendingProductId.length > 0); if (!hasPrefill && !hasProductId && !self.pendingAutoPurchase) { return; } // 仅透传给 VIP 页面,确保深链/键盘入口不依赖子 VC 类型 NSInteger vipIndex = 0; if (self.myCategoryView && self.myCategoryView.selectedIndex != vipIndex) { [self.myCategoryView selectItemAtIndex:vipIndex]; } KBVipPay *vipVC = (KBVipPay *)[self.pagerView.listContainerView.validListDict objectForKey:@(vipIndex)]; if (![vipVC isKindOfClass:KBVipPay.class]) { return; } [self kb_applyPendingConfigToVipList:vipVC]; } - (void)kb_applyPendingConfigToVipList:(KBVipPay *)vipVC { if (![vipVC isKindOfClass:KBVipPay.class]) { return; } BOOL hasPrefill = ([self.pendingPrefillProductsJSON isKindOfClass:NSArray.class] && self.pendingPrefillProductsJSON.count > 0); BOOL hasProductId = (self.pendingProductId.length > 0); if (!hasPrefill && !hasProductId && !self.pendingAutoPurchase) { return; } if (hasPrefill) { [vipVC configureWithProductId:self.pendingProductId autoPurchase:self.pendingAutoPurchase prefillProductsJSON:self.pendingPrefillProductsJSON selectedIndex:self.pendingPrefillSelectedIndex]; } else { [vipVC configureWithProductId:self.pendingProductId autoPurchase:self.pendingAutoPurchase]; } } - (void)viewDidLoad { [super viewDidLoad]; self.view.backgroundColor = [UIColor whiteColor]; // self.navigationController.navigationBar.translucent = false; // self.edgesForExtendedLayout = UIRectEdgeNone; NSInteger initialIndex = (self.initialSelectedIndex == 1) ? 1 : 0; self.imageNames = @[@"VIP_Normal_icon", @"SVIP_Normal_icon"]; NSArray *selectedImageNames = @[@"VIP_Selected_icon", @"SVIP_Selected_icon"]; _userHeaderView = [[PagingViewTableHeaderView alloc] init]; // 创建容器视图 self.categoryContainer = [[UIView alloc] initWithFrame:CGRectMake(0, 0, KB_SCREEN_WIDTH, JXheightForHeaderInSection)]; self.categoryContainer.backgroundColor = [UIColor clearColor]; // categoryView 放在容器内 self.myCategoryView = [[JXCategoryImageView alloc] init]; self.myCategoryView.backgroundColor = [UIColor whiteColor]; self.myCategoryView.layer.cornerRadius = JXheightForHeaderInSection * 0.5; self.myCategoryView.layer.masksToBounds = true; [self.categoryContainer addSubview:self.myCategoryView]; [self.myCategoryView mas_makeConstraints:^(MASConstraintMaker *make) { make.left.equalTo(self.categoryContainer).offset(KBFit(24)); make.right.equalTo(self.categoryContainer).offset(-KBFit(24)); make.top.bottom.equalTo(self.categoryContainer); }]; self.myCategoryView.imageInfoArray = self.imageNames; self.myCategoryView.selectedImageInfoArray = selectedImageNames; self.myCategoryView.defaultSelectedIndex = initialIndex; self.myCategoryView.loadImageBlock = ^(UIImageView *imageView, id info) { NSString *imageName = info; imageView.image = [UIImage imageNamed:imageName]; }; // self.myCategoryView.imageZoomEnabled = YES; self.myCategoryView.imageCornerRadius = 0; self.myCategoryView.contentEdgeInsetLeft = 0; self.myCategoryView.contentEdgeInsetRight = 0; self.myCategoryView.cellSpacing = 4; self.myCategoryView.imageSize = CGSizeMake(160, JXheightForHeaderInSection); // JXCategoryIndicatorLineView *lineView = [[JXCategoryIndicatorLineView alloc] init]; // lineView.indicatorWidth = 20; // self.myCategoryView.indicators = @[lineView]; _pagerView = [self preferredPagingView]; self.pagerView.defaultSelectedIndex = initialIndex; self.pagerView.mainTableView.gestureDelegate = self; [self.view addSubview:self.pagerView]; self.myCategoryView.listContainer = (id)self.pagerView.listContainerView; //导航栏隐藏的情况,处理扣边返回,下面的代码要加上 // [self.pagerView.listContainerView.scrollView.panGestureRecognizer requireGestureRecognizerToFail:self.navigationController.interactivePopGestureRecognizer]; // [self.pagerView.mainTableView.panGestureRecognizer requireGestureRecognizerToFail:self.navigationController.interactivePopGestureRecognizer]; self.automaticallyAdjustsScrollViewInsets = NO; CGFloat naviHeight = KB_NAV_TOTAL_HEIGHT; self.pagerView.pinSectionHeaderVerticalOffset = naviHeight + 16; self.naviBGView = [[UIView alloc] init]; self.naviBGView.alpha = 0; self.naviBGView.backgroundColor = [UIColor whiteColor]; self.naviBGView.frame = CGRectMake(0, 0, self.view.bounds.size.width, naviHeight); [self.view addSubview:self.naviBGView]; UILabel *naviTitleLabel = [[UILabel alloc] init]; naviTitleLabel.text = KBLocalized(@"Member recharge"); naviTitleLabel.textAlignment = NSTextAlignmentCenter; naviTitleLabel.frame = CGRectMake(0, KB_STATUSBAR_HEIGHT, self.view.bounds.size.width, 44); [self.naviBGView addSubview:naviTitleLabel]; [self.view addSubview:self.closeButton]; [self.closeButton mas_makeConstraints:^(MASConstraintMaker *make) { make.top.equalTo(self.view).offset(KB_NAV_TOTAL_HEIGHT - 40); make.left.equalTo(self.view).offset(15); make.width.height.mas_equalTo(36); }]; [self.view addSubview:self.restoreButton]; [self.restoreButton mas_makeConstraints:^(MASConstraintMaker *make) { make.centerY.equalTo(self.closeButton); make.right.equalTo(self.view).offset(-15); make.width.mas_equalTo(90); make.height.mas_equalTo(32); }]; self.pagerView.mainTableView.backgroundColor = [UIColor colorWithHex:0xF6F7FB]; // 底部固定区域 [self.view addSubview:self.bottomContainer]; [self.bottomContainer addSubview:self.payButton]; [self.bottomContainer addSubview:self.agreementLabel]; [self.bottomContainer addSubview:self.agreementButton]; [self.bottomContainer mas_makeConstraints:^(MASConstraintMaker *make) { make.left.right.bottom.equalTo(self.view); }]; [self.agreementButton mas_makeConstraints:^(MASConstraintMaker *make) { make.centerX.equalTo(self.bottomContainer); make.bottom.equalTo(self.bottomContainer).offset(-KB_SAFE_BOTTOM - 15); }]; [self.agreementLabel mas_makeConstraints:^(MASConstraintMaker *make) { make.centerX.equalTo(self.bottomContainer); make.bottom.equalTo(self.agreementButton.mas_top).offset(0); }]; [self.payButton mas_makeConstraints:^(MASConstraintMaker *make) { make.left.equalTo(self.bottomContainer).offset(24); make.right.equalTo(self.bottomContainer).offset(-24); make.bottom.equalTo(self.agreementLabel.mas_top).offset(-14); make.top.equalTo(self.bottomContainer).offset(16); make.height.mas_equalTo(51); }]; } - (void)viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; self.navigationController.interactivePopGestureRecognizer.enabled = (self.myCategoryView.selectedIndex == 0); } - (void)viewWillDisappear:(BOOL)animated { [super viewWillDisappear:animated]; self.navigationController.interactivePopGestureRecognizer.enabled = YES; } - (JXPagerView *)preferredPagingView { return [[JXPagerView alloc] initWithDelegate:self]; } - (void)viewDidLayoutSubviews { [super viewDidLayoutSubviews]; // pagerView 底部留出底部按钮区域的空间 CGFloat bottomHeight = self.bottomContainer.bounds.size.height; self.pagerView.frame = CGRectMake(0, 0, self.view.bounds.size.width, self.view.bounds.size.height - bottomHeight); } #pragma mark - JXPagerViewDelegate - (UIView *)tableHeaderViewInPagerView:(JXPagerView *)pagerView { return self.userHeaderView; } - (NSUInteger)tableHeaderViewHeightInPagerView:(JXPagerView *)pagerView { return JXTableHeaderViewHeight; } - (NSUInteger)heightForPinSectionHeaderInPagerView:(JXPagerView *)pagerView { return JXheightForHeaderInSection; } - (UIView *)viewForPinSectionHeaderInPagerView:(JXPagerView *)pagerView { return self.categoryContainer; } - (NSInteger)numberOfListsInPagerView:(JXPagerView *)pagerView { //和categoryView的item数量一致 return 2; } - (id)pagerView:(JXPagerView *)pagerView initListAtIndex:(NSInteger)index { if (index == 0) { KBVipPay *list = [[KBVipPay alloc] init]; [self kb_applyPendingConfigToVipList:list]; return list; } KBPaySvipVC *list = [[KBPaySvipVC alloc] init]; return list; } #pragma mark - JXCategoryViewDelegate - (void)categoryView:(JXCategoryBaseView *)categoryView didSelectedItemAtIndex:(NSInteger)index { self.navigationController.interactivePopGestureRecognizer.enabled = (index == 0); } #pragma mark - JXPagerMainTableViewGestureDelegate - (BOOL)mainTableViewGestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer { //禁止categoryView左右滑动的时候,上下和左右都可以滚动 if (otherGestureRecognizer == self.myCategoryView.collectionView.panGestureRecognizer) { return NO; } return [gestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]] && [otherGestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]]; } - (void)pagerView:(JXPagerView *)pagerView mainTableViewDidScroll:(UIScrollView *)scrollView { CGFloat thresholdDistance = 100; CGFloat percent = scrollView.contentOffset.y/thresholdDistance; percent = MAX(0, MIN(1, percent)); self.naviBGView.alpha = percent; } #pragma mark - Action - (void)onTapClose{ [[KBMaiPointReporter sharedReporter] reportClickWithEventName:@"click_vip_close_btn" pageId:@"vip_pay" elementId:@"close_btn" extra:nil completion:nil]; [self.navigationController popViewControllerAnimated:true]; } - (void)onTapPayButton { // 获取当前选中的子 VC,调用其支付方法 NSInteger index = self.myCategoryView.selectedIndex; if (index == 0) { // VIP 页面 KBVipPay *vipVC = (KBVipPay *)[self.pagerView.listContainerView.validListDict objectForKey:@(index)]; if ([vipVC respondsToSelector:@selector(onTapPayButton)]) { [vipVC onTapPayButton]; } } else { // SVIP 页面 KBPaySvipVC *svipVC = (KBPaySvipVC *)[self.pagerView.listContainerView.validListDict objectForKey:@(index)]; if ([svipVC respondsToSelector:@selector(onTapPayButton)]) { [svipVC onTapPayButton]; } } } - (void)onTapAgreementButton { [KBHUD showInfo:KBLocalized(@"Open agreement")]; } - (void)onTapRestoreButton { [[KBMaiPointReporter sharedReporter] reportClickWithEventName:@"click_vip_restore_btn" pageId:@"vip_pay" elementId:@"restore_btn" extra:nil completion:nil]; [KBHUD show]; __weak typeof(self) weakSelf = self; [[KBStoreKitBridge shared] restorePurchasesWithCompletion:^(BOOL success, NSString * _Nullable message) { dispatch_async(dispatch_get_main_queue(), ^{ __strong typeof(weakSelf) self = weakSelf; (void)self; [KBHUD dismiss]; NSString *tip = message.length ? message : (success ? KBLocalized(@"Success") : KBLocalized(@"Failed")); [KBHUD showInfo:tip]; }); }]; } #pragma mark - lazy - (UIButton *)closeButton { if (!_closeButton) { _closeButton = [UIButton buttonWithType:UIButtonTypeCustom]; [_closeButton setImage:[UIImage imageNamed:@"close_white2_icon"] forState:UIControlStateNormal]; [_closeButton addTarget:self action:@selector(onTapClose) forControlEvents:UIControlEventTouchUpInside]; } return _closeButton; } - (UIButton *)restoreButton { if (!_restoreButton) { _restoreButton = [UIButton buttonWithType:UIButtonTypeCustom]; _restoreButton.backgroundColor = [[UIColor colorWithHex:0xF6F7FB] colorWithAlphaComponent:0.72]; _restoreButton.layer.cornerRadius = 8; _restoreButton.layer.masksToBounds = YES; UIImage *icon = [UIImage imageNamed:@"pay_resh_icon"]; [_restoreButton setImage:icon forState:UIControlStateNormal]; [_restoreButton setTitle:KBLocalized(@"Resume Purchase") forState:UIControlStateNormal]; [_restoreButton setTitleColor:[UIColor colorWithHex:0x02BEAC] forState:UIControlStateNormal]; _restoreButton.titleLabel.font = [KBFont medium:10]; _restoreButton.contentEdgeInsets = UIEdgeInsetsMake(0, 12, 0, 12); _restoreButton.imageEdgeInsets = UIEdgeInsetsMake(0, -4, 0, 4); _restoreButton.titleEdgeInsets = UIEdgeInsetsMake(0, 6, 0, -6); [_restoreButton addTarget:self action:@selector(onTapRestoreButton) forControlEvents:UIControlEventTouchUpInside]; } return _restoreButton; } - (UIView *)bottomContainer { if (!_bottomContainer) { _bottomContainer = [UIView new]; _bottomContainer.backgroundColor = [UIColor colorWithHex:0xF6F7FB]; } return _bottomContainer; } - (UIButton *)payButton { if (!_payButton) { _payButton = [UIButton buttonWithType:UIButtonTypeCustom]; [_payButton setTitle:KBLocalized(@"Recharge Now") forState:UIControlStateNormal]; _payButton.titleLabel.font = [KBFont medium:15]; _payButton.layer.cornerRadius = 10; _payButton.clipsToBounds = YES; _payButton.backgroundColor = [UIColor colorWithHex:0x222222]; [_payButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; [_payButton addTarget:self action:@selector(onTapPayButton) forControlEvents:UIControlEventTouchUpInside]; } return _payButton; } - (UILabel *)agreementLabel { if (!_agreementLabel) { _agreementLabel = [UILabel new]; _agreementLabel.text = KBLocalized(@"By Clicking \"pay\", You Indicate Your Agreement To The"); _agreementLabel.font = [KBFont regular:12]; _agreementLabel.textColor = [UIColor colorWithHex:KBBlackValue]; } return _agreementLabel; } - (UIButton *)agreementButton { if (!_agreementButton) { _agreementButton = [UIButton buttonWithType:UIButtonTypeCustom]; [_agreementButton setTitle:KBLocalized(@"《Embership Agreement》") forState:UIControlStateNormal]; [_agreementButton setTitleColor:[UIColor colorWithHex:KBColorValue] forState:UIControlStateNormal]; _agreementButton.titleLabel.font = [KBFont regular:12]; [_agreementButton addTarget:self action:@selector(onTapAgreementButton) forControlEvents:UIControlEventTouchUpInside]; } return _agreementButton; } @end