This commit is contained in:
2025-12-17 19:45:39 +08:00
parent 8bad475288
commit 886de394d0
10 changed files with 207 additions and 36 deletions

View File

@@ -0,0 +1,22 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "buy_sel_icon@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "buy_sel_icon@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

View File

@@ -359,7 +359,7 @@ static void KBSkinInstallNotificationCallback(CFNotificationCenterRef center,
NSString *encodedId = [self.class kb_urlEncodedString:product.productId]; NSString *encodedId = [self.class kb_urlEncodedString:product.productId];
NSString *title = [product displayTitle]; NSString *title = [product displayTitle];
NSString *encodedTitle = [self.class kb_urlEncodedString:title]; NSString *encodedTitle = [self.class kb_urlEncodedString:title];
NSMutableArray<NSString *> *params = [NSMutableArray arrayWithObject:@"autoPay=1"]; NSMutableArray<NSString *> *params = [NSMutableArray arrayWithObjects:@"autoPay=1", @"prefill=1", nil];
if (encodedId.length) { if (encodedId.length) {
[params addObject:[NSString stringWithFormat:@"productId=%@", encodedId]]; [params addObject:[NSString stringWithFormat:@"productId=%@", encodedId]];
} }

View File

@@ -11,8 +11,7 @@
@property (nonatomic, strong) UILabel *titleLabel; @property (nonatomic, strong) UILabel *titleLabel;
@property (nonatomic, strong) UILabel *priceLabel; @property (nonatomic, strong) UILabel *priceLabel;
@property (nonatomic, strong) UILabel *strikeLabel; @property (nonatomic, strong) UILabel *strikeLabel;
@property (nonatomic, strong) UIView *checkBadge; @property (nonatomic, strong) UIImageView *selectedImageView;
@property (nonatomic, strong) UILabel *checkLabel;
@end @end
@implementation KBKeyboardSubscriptionOptionCell @implementation KBKeyboardSubscriptionOptionCell
- (instancetype)initWithFrame:(CGRect)frame { - (instancetype)initWithFrame:(CGRect)frame {
@@ -22,8 +21,7 @@
[self.cardView addSubview:self.titleLabel]; [self.cardView addSubview:self.titleLabel];
[self.cardView addSubview:self.priceLabel]; [self.cardView addSubview:self.priceLabel];
[self.cardView addSubview:self.strikeLabel]; [self.cardView addSubview:self.strikeLabel];
[self.cardView addSubview:self.checkBadge]; [self.cardView addSubview:self.selectedImageView];
[self.checkBadge addSubview:self.checkLabel];
[self.cardView mas_makeConstraints:^(MASConstraintMaker *make) { [self.cardView mas_makeConstraints:^(MASConstraintMaker *make) {
// make.edges.equalTo(self.contentView); // make.edges.equalTo(self.contentView);
@@ -32,7 +30,7 @@
}]; }];
[self.titleLabel mas_makeConstraints:^(MASConstraintMaker *make) { [self.titleLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.cardView.mas_top).offset(4); make.top.equalTo(self.cardView.mas_top).offset(8);
make.left.equalTo(self.cardView.mas_left).offset(10); make.left.equalTo(self.cardView.mas_left).offset(10);
make.right.equalTo(self.cardView.mas_right).offset(-10); make.right.equalTo(self.cardView.mas_right).offset(-10);
}]; }];
@@ -47,14 +45,11 @@
make.centerY.equalTo(self.priceLabel); make.centerY.equalTo(self.priceLabel);
}]; }];
[self.checkBadge mas_makeConstraints:^(MASConstraintMaker *make) { [self.selectedImageView mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerX.equalTo(self.cardView.mas_centerX); make.centerX.equalTo(self.cardView.mas_centerX);
make.bottom.equalTo(self.cardView.mas_bottom).offset(10); make.bottom.equalTo(self.cardView.mas_bottom).offset(10);
make.width.height.mas_equalTo(20); make.width.mas_equalTo(16);
}]; make.height.mas_equalTo(17);
[self.checkLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.center.equalTo(self.checkBadge);
}]; }];
} }
return self; return self;
@@ -92,13 +87,16 @@
void (^changes)(void) = ^{ void (^changes)(void) = ^{
self.cardView.layer.borderColor = selected ? [UIColor colorWithHex:0x02BEAC].CGColor : [[UIColor blackColor] colorWithAlphaComponent:0.12].CGColor; self.cardView.layer.borderColor = selected ? [UIColor colorWithHex:0x02BEAC].CGColor : [[UIColor blackColor] colorWithAlphaComponent:0.12].CGColor;
self.cardView.layer.borderWidth = selected ? 2.0 : 1.0; self.cardView.layer.borderWidth = selected ? 2.0 : 1.0;
self.checkBadge.backgroundColor = selected ? [UIColor colorWithHex:0x02BEAC] : [[UIColor blackColor] colorWithAlphaComponent:0.15]; self.selectedImageView.alpha = selected ? 1.0 : 0.0;
self.checkLabel.textColor = [UIColor whiteColor];
}; };
if (animated) { if (animated) {
[UIView animateWithDuration:0.18 animations:changes]; self.selectedImageView.hidden = NO;
[UIView animateWithDuration:0.18 animations:changes completion:^(BOOL finished) {
self.selectedImageView.hidden = !selected;
}];
} else { } else {
changes(); changes();
self.selectedImageView.hidden = !selected;
} }
} }
@@ -141,23 +139,13 @@
return _strikeLabel; return _strikeLabel;
} }
- (UIView *)checkBadge { - (UIImageView *)selectedImageView {
if (!_checkBadge) { if (!_selectedImageView) {
_checkBadge = [[UIView alloc] init]; _selectedImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"buy_sel_icon"]];
_checkBadge.layer.cornerRadius = 10; _selectedImageView.contentMode = UIViewContentModeScaleAspectFit;
_checkBadge.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.15]; _selectedImageView.hidden = YES;
_selectedImageView.alpha = 0.0;
} }
return _checkBadge; return _selectedImageView;
}
- (UILabel *)checkLabel {
if (!_checkLabel) {
_checkLabel = [[UILabel alloc] init];
_checkLabel.text = @"✓";
_checkLabel.font = [UIFont systemFontOfSize:12 weight:UIFontWeightBold];
_checkLabel.textColor = [UIColor whiteColor];
_checkLabel.textAlignment = NSTextAlignmentCenter;
}
return _checkLabel;
} }
@end @end

View File

@@ -9,11 +9,39 @@
#import "KBFullAccessManager.h" #import "KBFullAccessManager.h"
#import "KBKeyboardSubscriptionFeatureMarqueeView.h" #import "KBKeyboardSubscriptionFeatureMarqueeView.h"
#import "KBKeyboardSubscriptionOptionCell.h" #import "KBKeyboardSubscriptionOptionCell.h"
#import "KBConfig.h"
#import <MJExtension/MJExtension.h> #import <MJExtension/MJExtension.h>
static NSString * const kKBKeyboardSubscriptionCellId = @"kKBKeyboardSubscriptionCellId"; static NSString * const kKBKeyboardSubscriptionCellId = @"kKBKeyboardSubscriptionCellId";
static id KBKeyboardSubscriptionSanitizeJSON(id obj) {
if (!obj || obj == (id)kCFNull) { return nil; }
if ([obj isKindOfClass:[NSDictionary class]]) {
NSDictionary *dict = (NSDictionary *)obj;
NSMutableDictionary *result = [NSMutableDictionary dictionaryWithCapacity:dict.count];
[dict enumerateKeysAndObjectsUsingBlock:^(id key, id value, BOOL *stop) {
(void)stop;
if (![key isKindOfClass:[NSString class]]) { return; }
id sanitized = KBKeyboardSubscriptionSanitizeJSON(value);
if (!sanitized) { return; }
result[key] = sanitized;
}];
return result;
}
if ([obj isKindOfClass:[NSArray class]]) {
NSArray *arr = (NSArray *)obj;
NSMutableArray *result = [NSMutableArray arrayWithCapacity:arr.count];
for (id item in arr) {
id sanitized = KBKeyboardSubscriptionSanitizeJSON(item);
if (!sanitized) { continue; }
[result addObject:sanitized];
}
return result;
}
return obj;
}
@interface KBKeyboardSubscriptionView () <UICollectionViewDataSource, UICollectionViewDelegateFlowLayout> @interface KBKeyboardSubscriptionView () <UICollectionViewDataSource, UICollectionViewDelegateFlowLayout>
@property (nonatomic, strong) UIImageView *cardView; @property (nonatomic, strong) UIImageView *cardView;
@property (nonatomic, strong) UIButton *closeButton; @property (nonatomic, strong) UIButton *closeButton;
@@ -25,6 +53,7 @@ static NSString * const kKBKeyboardSubscriptionCellId = @"kKBKeyboardSubscriptio
@property (nonatomic, strong) UIActivityIndicatorView *loadingIndicator; @property (nonatomic, strong) UIActivityIndicatorView *loadingIndicator;
@property (nonatomic, strong) UILabel *emptyLabel; @property (nonatomic, strong) UILabel *emptyLabel;
@property (nonatomic, copy) NSArray<KBKeyboardSubscriptionProduct *> *products; @property (nonatomic, copy) NSArray<KBKeyboardSubscriptionProduct *> *products;
@property (nonatomic, copy, nullable) NSArray *productsRawJSON;
@property (nonatomic, assign) NSInteger selectedIndex; @property (nonatomic, assign) NSInteger selectedIndex;
@property (nonatomic, assign) BOOL didLoadOnce; @property (nonatomic, assign) BOOL didLoadOnce;
@property (nonatomic, assign, getter=isLoading) BOOL loading; @property (nonatomic, assign, getter=isLoading) BOOL loading;
@@ -156,6 +185,7 @@ static NSString * const kKBKeyboardSubscriptionCellId = @"kKBKeyboardSubscriptio
return; return;
} }
KBKeyboardSubscriptionProduct *product = self.products[self.selectedIndex]; KBKeyboardSubscriptionProduct *product = self.products[self.selectedIndex];
[self kb_persistPrefillPayloadForProduct:product];
if ([self.delegate respondsToSelector:@selector(subscriptionView:didTapPurchaseForProduct:)]) { if ([self.delegate respondsToSelector:@selector(subscriptionView:didTapPurchaseForProduct:)]) {
[self.delegate subscriptionView:self didTapPurchaseForProduct:product]; [self.delegate subscriptionView:self didTapPurchaseForProduct:product];
} }
@@ -191,6 +221,7 @@ static NSString * const kKBKeyboardSubscriptionCellId = @"kKBKeyboardSubscriptio
NSString *tip = error.localizedDescription ?: KBLocalized(@"Network error"); NSString *tip = error.localizedDescription ?: KBLocalized(@"Network error");
[KBHUD showInfo:tip]; [KBHUD showInfo:tip];
self.products = @[]; self.products = @[];
self.productsRawJSON = nil;
self.selectedIndex = NSNotFound; self.selectedIndex = NSNotFound;
[self.collectionView reloadData]; [self.collectionView reloadData];
self.emptyLabel.hidden = NO; self.emptyLabel.hidden = NO;
@@ -203,12 +234,15 @@ static NSString * const kKBKeyboardSubscriptionCellId = @"kKBKeyboardSubscriptio
} }
if (![dataObj isKindOfClass:[NSArray class]]) { if (![dataObj isKindOfClass:[NSArray class]]) {
self.products = @[]; self.products = @[];
self.productsRawJSON = nil;
self.selectedIndex = NSNotFound; self.selectedIndex = NSNotFound;
[self.collectionView reloadData]; [self.collectionView reloadData];
self.emptyLabel.hidden = NO; self.emptyLabel.hidden = NO;
[self updatePurchaseButtonState]; [self updatePurchaseButtonState];
return; return;
} }
id sanitized = KBKeyboardSubscriptionSanitizeJSON(dataObj);
self.productsRawJSON = [sanitized isKindOfClass:NSArray.class] ? (NSArray *)sanitized : nil;
NSArray *models = [KBKeyboardSubscriptionProduct mj_objectArrayWithKeyValuesArray:(NSArray *)dataObj]; NSArray *models = [KBKeyboardSubscriptionProduct mj_objectArrayWithKeyValuesArray:(NSArray *)dataObj];
self.products = models ?: @[]; self.products = models ?: @[];
self.selectedIndex = self.products.count > 0 ? 0 : NSNotFound; self.selectedIndex = self.products.count > 0 ? 0 : NSNotFound;
@@ -221,6 +255,25 @@ static NSString * const kKBKeyboardSubscriptionCellId = @"kKBKeyboardSubscriptio
}]; }];
} }
- (void)kb_persistPrefillPayloadForProduct:(KBKeyboardSubscriptionProduct *)product {
if (![product isKindOfClass:KBKeyboardSubscriptionProduct.class]) { return; }
if (![self.productsRawJSON isKindOfClass:NSArray.class] || self.productsRawJSON.count == 0) { return; }
NSUserDefaults *ud = [[NSUserDefaults alloc] initWithSuiteName:AppGroup];
if (!ud) { return; }
NSMutableDictionary *payload = [NSMutableDictionary dictionary];
payload[@"ts"] = @((long long)floor([NSDate date].timeIntervalSince1970));
payload[@"src"] = @"keyboard";
if (product.productId.length) {
payload[@"productId"] = product.productId;
}
if (self.selectedIndex != NSNotFound) {
payload[@"selectedIndex"] = @(self.selectedIndex);
}
payload[@"products"] = self.productsRawJSON;
[ud setObject:payload forKey:AppGroup_SubscriptionPrefillPayload];
[ud synchronize];
}
- (void)selectCurrentProductAnimated:(BOOL)animated { - (void)selectCurrentProductAnimated:(BOOL)animated {
if (self.selectedIndex == NSNotFound || self.selectedIndex >= self.products.count) { return; } if (self.selectedIndex == NSNotFound || self.selectedIndex >= self.products.count) { return; }
NSIndexPath *indexPath = [NSIndexPath indexPathForItem:self.selectedIndex inSection:0]; NSIndexPath *indexPath = [NSIndexPath indexPathForItem:self.selectedIndex inSection:0];
@@ -401,4 +454,3 @@ static NSString * const kKBKeyboardSubscriptionCellId = @"kKBKeyboardSubscriptio
} }
@end @end

View File

@@ -24,6 +24,9 @@
/// 键盘JSON数据 /// 键盘JSON数据
#define AppGroup_MyKbJson @"AppGroup_MyKbJson" #define AppGroup_MyKbJson @"AppGroup_MyKbJson"
/// 键盘 -> 主 App 订阅页预填充数据(用于免二次请求)
#define AppGroup_SubscriptionPrefillPayload @"AppGroup_SubscriptionPrefillPayload"
/// 皮肤图标加载模式: /// 皮肤图标加载模式:
/// 0 = 使用本地 Assets 图片名key_icons 的 value 写成图片名,例如 "kb_q_melon" /// 0 = 使用本地 Assets 图片名key_icons 的 value 写成图片名,例如 "kb_q_melon"
/// 1 = 使用远程 Zip 皮肤包skinJSON 中提供 zip_urlkey_icons 的 value 写成 Zip 内图标文件名,例如 "key_a" /// 1 = 使用远程 Zip 皮肤包skinJSON 中提供 zip_urlkey_icons 的 value 写成 Zip 内图标文件名,例如 "key_a"

View File

@@ -24,6 +24,9 @@
#import "KBVipPay.h" #import "KBVipPay.h"
#import "KBUserSessionManager.h" #import "KBUserSessionManager.h"
#import "KBLoginVC.h" #import "KBLoginVC.h"
#import "KBConfig.h"
static NSTimeInterval const kKBSubscriptionPrefillTTL = 10 * 60.0;
// bundle id target // bundle id target
// PRODUCT_BUNDLE_IDENTIFIER // PRODUCT_BUNDLE_IDENTIFIER
@@ -199,8 +202,36 @@
if ([action isEqualToString:@"autopay"]) { if ([action isEqualToString:@"autopay"]) {
autoPay = YES; autoPay = YES;
} }
BOOL wantsPrefill = NO;
NSString *prefillFlag = params[@"prefill"];
if ([prefillFlag respondsToSelector:@selector(boolValue)] && prefillFlag.boolValue) {
wantsPrefill = YES;
}
NSString *src = params[@"src"];
if ([src isKindOfClass:NSString.class] && [src.lowercaseString isEqualToString:@"keyboard"]) {
wantsPrefill = YES;
}
NSDictionary *prefillPayload = wantsPrefill ? [self kb_consumeSubscriptionPrefillPayloadIfValid] : nil;
if ([prefillPayload isKindOfClass:NSDictionary.class]) {
NSString *payloadProductId = prefillPayload[@"productId"];
if (productId.length == 0 && [payloadProductId isKindOfClass:NSString.class]) {
productId = payloadProductId;
}
}
KBVipPay *vc = [[KBVipPay alloc] init]; KBVipPay *vc = [[KBVipPay alloc] init];
if ([prefillPayload isKindOfClass:NSDictionary.class]) {
NSArray *productsJSON = prefillPayload[@"products"];
NSNumber *selectedIndexNumber = prefillPayload[@"selectedIndex"];
NSInteger selectedIndex = [selectedIndexNumber respondsToSelector:@selector(integerValue)] ? selectedIndexNumber.integerValue : NSNotFound;
[vc configureWithProductId:productId
autoPurchase:autoPay
prefillProductsJSON:productsJSON
selectedIndex:selectedIndex];
} else {
[vc configureWithProductId:productId autoPurchase:autoPay]; [vc configureWithProductId:productId autoPurchase:autoPay];
}
[KB_CURRENT_NAV pushViewController:vc animated:true]; [KB_CURRENT_NAV pushViewController:vc animated:true];
return YES; return YES;
} }
@@ -209,6 +240,23 @@
return NO; return NO;
} }
- (nullable NSDictionary *)kb_consumeSubscriptionPrefillPayloadIfValid {
NSUserDefaults *ud = [[NSUserDefaults alloc] initWithSuiteName:AppGroup];
if (!ud) { return nil; }
id obj = [ud objectForKey:AppGroup_SubscriptionPrefillPayload];
[ud removeObjectForKey:AppGroup_SubscriptionPrefillPayload];
[ud synchronize];
if (![obj isKindOfClass:NSDictionary.class]) { return nil; }
NSDictionary *payload = (NSDictionary *)obj;
NSNumber *ts = payload[@"ts"];
if (![ts respondsToSelector:@selector(doubleValue)]) { return nil; }
NSTimeInterval age = [NSDate date].timeIntervalSince1970 - ts.doubleValue;
if (age < 0 || age > kKBSubscriptionPrefillTTL) { return nil; }
id products = payload[@"products"];
if (![products isKindOfClass:NSArray.class] || ((NSArray *)products).count == 0) { return nil; }
return payload;
}
- (NSDictionary<NSString *, NSString *> *)kb_queryParametersFromURL:(NSURL *)url { - (NSDictionary<NSString *, NSString *> *)kb_queryParametersFromURL:(NSURL *)url {
if (!url) { return @{}; } if (!url) { return @{}; }
NSURLComponents *components = [NSURLComponents componentsWithURL:url resolvingAgainstBaseURL:NO]; NSURLComponents *components = [NSURLComponents componentsWithURL:url resolvingAgainstBaseURL:NO];

View File

@@ -15,6 +15,12 @@ NS_ASSUME_NONNULL_BEGIN
/// 通过键盘深链配置初始商品及是否自动发起购买 /// 通过键盘深链配置初始商品及是否自动发起购买
- (void)configureWithProductId:(nullable NSString *)productId - (void)configureWithProductId:(nullable NSString *)productId
autoPurchase:(BOOL)autoPurchase; autoPurchase:(BOOL)autoPurchase;
/// 通过键盘扩展预填充商品列表(免二次请求)
- (void)configureWithProductId:(nullable NSString *)productId
autoPurchase:(BOOL)autoPurchase
prefillProductsJSON:(nullable NSArray *)productsJSON
selectedIndex:(NSInteger)selectedIndex;
@end @end
NS_ASSUME_NONNULL_END NS_ASSUME_NONNULL_END

View File

@@ -13,6 +13,7 @@
#import "KBPayProductModel.h" #import "KBPayProductModel.h"
#import "KBBizCode.h" #import "KBBizCode.h"
#import "keyBoard-Swift.h" #import "keyBoard-Swift.h"
#import <MJExtension/MJExtension.h>
static NSString * const kKBVipHeaderId = @"kKBVipHeaderId"; static NSString * const kKBVipHeaderId = @"kKBVipHeaderId";
static NSString * const kKBVipSubscribeCellId = @"kKBVipSubscribeCellId"; static NSString * const kKBVipSubscribeCellId = @"kKBVipSubscribeCellId";
@@ -37,6 +38,9 @@ static NSString * const kKBVipReviewListCellId = @"kKBVipReviewListCellId";
@property (nonatomic, assign) BOOL pendingAutoPurchase; @property (nonatomic, assign) BOOL pendingAutoPurchase;
@property (nonatomic, assign) BOOL hasTriggeredAutoPurchase; @property (nonatomic, assign) BOOL hasTriggeredAutoPurchase;
@property (nonatomic, assign) BOOL viewVisible; @property (nonatomic, assign) BOOL viewVisible;
@property (nonatomic, copy, nullable) NSArray *prefillProductsJSON;
@property (nonatomic, assign) NSInteger prefillSelectedIndex;
@property (nonatomic, assign) BOOL didApplyPrefillPlans;
@end @end
@@ -59,6 +63,7 @@ static NSString * const kKBVipReviewListCellId = @"kKBVipReviewListCellId";
self.payVM = [PayVM new]; self.payVM = [PayVM new];
self.plans = @[]; self.plans = @[];
self.selectedIndex = NSNotFound; self.selectedIndex = NSNotFound;
self.prefillSelectedIndex = NSNotFound;
// //
[self.view addSubview:self.collectionView]; [self.view addSubview:self.collectionView];
@@ -101,9 +106,12 @@ static NSString * const kKBVipReviewListCellId = @"kKBVipReviewListCellId";
// Header // Header
self.headerHeight = [self kb_calcHeaderHeightForWidth:KB_SCREEN_WIDTH]; self.headerHeight = [self kb_calcHeaderHeightForWidth:KB_SCREEN_WIDTH];
BOOL appliedPrefill = [self kb_applyPrefillPlansIfPossible];
[self.collectionView reloadData]; [self.collectionView reloadData];
[self selectCurrentPlanAnimated:NO];
if (!appliedPrefill) {
[self fetchSubscriptionPlans]; [self fetchSubscriptionPlans];
}
} }
- (void)viewDidAppear:(BOOL)animated { - (void)viewDidAppear:(BOOL)animated {
@@ -128,6 +136,26 @@ static NSString * const kKBVipReviewListCellId = @"kKBVipReviewListCellId";
[self kb_triggerAutoPurchaseIfNeeded]; [self kb_triggerAutoPurchaseIfNeeded];
} }
- (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.hasTriggeredAutoPurchase = NO;
self.prefillProductsJSON = [productsJSON isKindOfClass:NSArray.class] ? [productsJSON copy] : nil;
self.prefillSelectedIndex = selectedIndex;
self.didApplyPrefillPlans = NO;
if (self.isViewLoaded) {
BOOL ok = [self kb_applyPrefillPlansIfPossible];
if (ok) {
[self.collectionView reloadData];
[self selectCurrentPlanAnimated:NO];
}
}
[self kb_triggerAutoPurchaseIfNeeded];
}
#pragma mark - Data #pragma mark - Data
- (void)fetchSubscriptionPlans { - (void)fetchSubscriptionPlans {
__weak typeof(self) weakSelf = self; __weak typeof(self) weakSelf = self;
@@ -154,6 +182,30 @@ static NSString * const kKBVipReviewListCellId = @"kKBVipReviewListCellId";
}]; }];
} }
- (BOOL)kb_applyPrefillPlansIfPossible {
if (self.didApplyPrefillPlans) {
return (self.plans.count > 0);
}
if (![self.prefillProductsJSON isKindOfClass:NSArray.class] || self.prefillProductsJSON.count == 0) {
return NO;
}
NSArray<KBPayProductModel *> *models = [KBPayProductModel mj_objectArrayWithKeyValuesArray:self.prefillProductsJSON];
if (![models isKindOfClass:NSArray.class] || models.count == 0) {
return NO;
}
self.didApplyPrefillPlans = YES;
self.plans = models;
NSInteger idx = self.prefillSelectedIndex;
if (idx != NSNotFound && idx >= 0 && idx < (NSInteger)self.plans.count) {
self.selectedIndex = idx;
} else {
self.selectedIndex = (self.plans.count > 0) ? 0 : NSNotFound;
}
[self prepareStoreKitWithPlans:self.plans];
[self kb_applyPendingPrefillIfNeeded];
return YES;
}
- (void)prepareStoreKitWithPlans:(NSArray<KBPayProductModel *> *)plans { - (void)prepareStoreKitWithPlans:(NSArray<KBPayProductModel *> *)plans {
if (![plans isKindOfClass:NSArray.class] || plans.count == 0) { return; } if (![plans isKindOfClass:NSArray.class] || plans.count == 0) { return; }
NSMutableArray<NSString *> *ids = [NSMutableArray array]; NSMutableArray<NSString *> *ids = [NSMutableArray array];