1
This commit is contained in:
@@ -24,6 +24,9 @@
|
||||
#import "KBVipPay.h"
|
||||
#import "KBUserSessionManager.h"
|
||||
#import "KBLoginVC.h"
|
||||
#import "KBConfig.h"
|
||||
|
||||
static NSTimeInterval const kKBSubscriptionPrefillTTL = 10 * 60.0;
|
||||
|
||||
// 注意:用于判断系统已启用本输入法扩展的 bundle id 需与扩展 target 的
|
||||
// PRODUCT_BUNDLE_IDENTIFIER 完全一致。
|
||||
@@ -199,8 +202,36 @@
|
||||
if ([action isEqualToString:@"autopay"]) {
|
||||
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];
|
||||
[vc configureWithProductId:productId autoPurchase:autoPay];
|
||||
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];
|
||||
}
|
||||
[KB_CURRENT_NAV pushViewController:vc animated:true];
|
||||
return YES;
|
||||
}
|
||||
@@ -209,6 +240,23 @@
|
||||
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 {
|
||||
if (!url) { return @{}; }
|
||||
NSURLComponents *components = [NSURLComponents componentsWithURL:url resolvingAgainstBaseURL:NO];
|
||||
|
||||
@@ -15,6 +15,12 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
/// 通过键盘深链配置初始商品及是否自动发起购买
|
||||
- (void)configureWithProductId:(nullable NSString *)productId
|
||||
autoPurchase:(BOOL)autoPurchase;
|
||||
|
||||
/// 通过键盘扩展预填充商品列表(免二次请求)
|
||||
- (void)configureWithProductId:(nullable NSString *)productId
|
||||
autoPurchase:(BOOL)autoPurchase
|
||||
prefillProductsJSON:(nullable NSArray *)productsJSON
|
||||
selectedIndex:(NSInteger)selectedIndex;
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#import "KBPayProductModel.h"
|
||||
#import "KBBizCode.h"
|
||||
#import "keyBoard-Swift.h"
|
||||
#import <MJExtension/MJExtension.h>
|
||||
|
||||
static NSString * const kKBVipHeaderId = @"kKBVipHeaderId";
|
||||
static NSString * const kKBVipSubscribeCellId = @"kKBVipSubscribeCellId";
|
||||
@@ -37,6 +38,9 @@ static NSString * const kKBVipReviewListCellId = @"kKBVipReviewListCellId";
|
||||
@property (nonatomic, assign) BOOL pendingAutoPurchase;
|
||||
@property (nonatomic, assign) BOOL hasTriggeredAutoPurchase;
|
||||
@property (nonatomic, assign) BOOL viewVisible;
|
||||
@property (nonatomic, copy, nullable) NSArray *prefillProductsJSON;
|
||||
@property (nonatomic, assign) NSInteger prefillSelectedIndex;
|
||||
@property (nonatomic, assign) BOOL didApplyPrefillPlans;
|
||||
|
||||
@end
|
||||
|
||||
@@ -59,6 +63,7 @@ static NSString * const kKBVipReviewListCellId = @"kKBVipReviewListCellId";
|
||||
self.payVM = [PayVM new];
|
||||
self.plans = @[];
|
||||
self.selectedIndex = NSNotFound;
|
||||
self.prefillSelectedIndex = NSNotFound;
|
||||
|
||||
// 组装主列表
|
||||
[self.view addSubview:self.collectionView];
|
||||
@@ -101,9 +106,12 @@ static NSString * const kKBVipReviewListCellId = @"kKBVipReviewListCellId";
|
||||
|
||||
// 预计算 Header 高度(由内部约束决定)
|
||||
self.headerHeight = [self kb_calcHeaderHeightForWidth:KB_SCREEN_WIDTH];
|
||||
BOOL appliedPrefill = [self kb_applyPrefillPlansIfPossible];
|
||||
[self.collectionView reloadData];
|
||||
|
||||
[self fetchSubscriptionPlans];
|
||||
[self selectCurrentPlanAnimated:NO];
|
||||
if (!appliedPrefill) {
|
||||
[self fetchSubscriptionPlans];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)viewDidAppear:(BOOL)animated {
|
||||
@@ -128,6 +136,26 @@ static NSString * const kKBVipReviewListCellId = @"kKBVipReviewListCellId";
|
||||
[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
|
||||
- (void)fetchSubscriptionPlans {
|
||||
__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 {
|
||||
if (![plans isKindOfClass:NSArray.class] || plans.count == 0) { return; }
|
||||
NSMutableArray<NSString *> *ids = [NSMutableArray array];
|
||||
|
||||
Reference in New Issue
Block a user