Files
keyboard/keyBoard/Class/Pay/VC/KBPayMainVC.m
2026-02-04 21:49:28 +08:00

446 lines
18 KiB
Objective-C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
// KBPayMainVC.m
// keyBoard
//
// Created by Mac on 2026/2/3.
//
#import "KBPayMainVC.h"
#import "JXPagerView.h"
#import "KBShopHeadView.h"
#import <JXCategoryView/JXCategoryView.h>
#import "KBCategoryTitleView.h"
#import <JXPagingView/JXPagerView.h>
#import <MJRefresh/MJRefresh.h>
//#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 ()<JXCategoryViewDelegate,JXPagerViewDelegate, JXPagerMainTableViewGestureDelegate>
@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 <NSString *> *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<JXCategoryViewListContainer>)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<JXPagerViewListViewDelegate>)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