2026-02-24 13:38:51 +08:00
|
|
|
|
//
|
|
|
|
|
|
// KeyboardViewController+Subscription.m
|
|
|
|
|
|
// CustomKeyboard
|
|
|
|
|
|
//
|
|
|
|
|
|
// Created by Codex on 2026/02/22.
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
|
|
#import "KeyboardViewController+Private.h"
|
|
|
|
|
|
|
|
|
|
|
|
#import "KBAuthManager.h"
|
|
|
|
|
|
#import "KBFullAccessManager.h"
|
2026-03-05 14:30:07 +08:00
|
|
|
|
#import "../Utils/KBExtensionAppLauncher.h"
|
2026-02-24 13:38:51 +08:00
|
|
|
|
#import "KBKeyboardSubscriptionProduct.h"
|
|
|
|
|
|
#import "KBKeyboardSubscriptionView.h"
|
|
|
|
|
|
|
|
|
|
|
|
@implementation KeyboardViewController (Subscription)
|
|
|
|
|
|
|
|
|
|
|
|
- (void)showSubscriptionPanel {
|
|
|
|
|
|
// 1) 先判断权限:未开启“完全访问”则走引导逻辑
|
|
|
|
|
|
if (![[KBFullAccessManager shared] hasFullAccess]) {
|
|
|
|
|
|
// 未开启完全访问:保持原有引导路径
|
2026-03-07 13:29:29 +08:00
|
|
|
|
// [KBHUD showInfo:KBLocalized(@"Processing...")];
|
2026-02-24 13:38:51 +08:00
|
|
|
|
[[KBFullAccessManager shared] ensureFullAccessOrGuideInView:self.view];
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
// 点击充值要先判断是否登录
|
|
|
|
|
|
// 2) 权限没问题,再判断是否登录:未登录 -> 直接拉起主 App,由主 App 负责完成登录
|
|
|
|
|
|
if (!KBAuthManager.shared.isLoggedIn) {
|
2026-03-05 14:30:07 +08:00
|
|
|
|
NSURL *ul = [NSURL URLWithString:[NSString stringWithFormat:@"%@?src=keyboard", KB_UL_LOGIN]];
|
|
|
|
|
|
NSURL *scheme =
|
|
|
|
|
|
[NSURL URLWithString:[NSString stringWithFormat:@"%@://login?src=keyboard", KB_APP_SCHEME]];
|
|
|
|
|
|
__weak typeof(self) weakSelf = self;
|
|
|
|
|
|
[KBExtensionAppLauncher openPrimaryURL:ul
|
|
|
|
|
|
fallbackURL:scheme
|
|
|
|
|
|
usingInputController:self
|
|
|
|
|
|
source:(self.view ?: (UIResponder *)weakSelf)
|
|
|
|
|
|
completion:nil];
|
2026-02-24 13:38:51 +08:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
[self kb_setPanelMode:KBKeyboardPanelModeSubscription animated:YES];
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
- (void)hideSubscriptionPanel {
|
|
|
|
|
|
if (self.kb_panelMode != KBKeyboardPanelModeSubscription) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
[self kb_setPanelMode:KBKeyboardPanelModeMain animated:YES];
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#pragma mark - KBKeyboardSubscriptionViewDelegate
|
|
|
|
|
|
|
|
|
|
|
|
- (void)subscriptionViewDidTapClose:(KBKeyboardSubscriptionView *)view {
|
|
|
|
|
|
[[KBMaiPointReporter sharedReporter]
|
|
|
|
|
|
reportClickWithEventName:@"click_keyboard_subscription_close_btn"
|
|
|
|
|
|
pageId:@"keyboard_subscription_panel"
|
|
|
|
|
|
elementId:@"close_btn"
|
|
|
|
|
|
extra:nil
|
|
|
|
|
|
completion:nil];
|
|
|
|
|
|
[self hideSubscriptionPanel];
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
- (void)subscriptionView:(KBKeyboardSubscriptionView *)view
|
|
|
|
|
|
didTapPurchaseForProduct:(KBKeyboardSubscriptionProduct *)product {
|
|
|
|
|
|
NSMutableDictionary *extra = [NSMutableDictionary dictionary];
|
|
|
|
|
|
if ([product.productId isKindOfClass:NSString.class] &&
|
|
|
|
|
|
product.productId.length > 0) {
|
|
|
|
|
|
extra[@"product_id"] = product.productId;
|
|
|
|
|
|
}
|
|
|
|
|
|
[[KBMaiPointReporter sharedReporter]
|
|
|
|
|
|
reportClickWithEventName:@"click_keyboard_subscription_product_btn"
|
|
|
|
|
|
pageId:@"keyboard_subscription_panel"
|
|
|
|
|
|
elementId:@"product_btn"
|
|
|
|
|
|
extra:extra.copy
|
|
|
|
|
|
completion:nil];
|
|
|
|
|
|
[self hideSubscriptionPanel];
|
|
|
|
|
|
[self kb_openRechargeForProduct:product];
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-08 21:29:10 +08:00
|
|
|
|
- (void)subscriptionViewDidTapAgreement:(KBKeyboardSubscriptionView *)view {
|
|
|
|
|
|
(void)view;
|
|
|
|
|
|
[self hideSubscriptionPanel];
|
|
|
|
|
|
NSString *query = [NSString stringWithFormat:@"type=%@&src=keyboard",
|
|
|
|
|
|
@"membership"];
|
|
|
|
|
|
NSString *ulString = [NSString stringWithFormat:@"%@?%@", KB_UL_LEGAL, query];
|
|
|
|
|
|
NSString *schemeString =
|
|
|
|
|
|
[NSString stringWithFormat:@"%@://legal?%@", KB_APP_SCHEME, query];
|
|
|
|
|
|
NSURL *ul = [NSURL URLWithString:ulString];
|
|
|
|
|
|
NSURL *scheme = [NSURL URLWithString:schemeString];
|
|
|
|
|
|
__weak typeof(self) weakSelf = self;
|
|
|
|
|
|
[KBExtensionAppLauncher openPrimaryURL:ul
|
|
|
|
|
|
fallbackURL:scheme
|
|
|
|
|
|
usingInputController:self
|
|
|
|
|
|
source:(self.view ?: (UIResponder *)weakSelf)
|
|
|
|
|
|
completion:^(BOOL success) {
|
|
|
|
|
|
if (success) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
dispatch_async(dispatch_get_main_queue(), ^{
|
|
|
|
|
|
[KBHUD showInfo:KBLocalized(@"Please open the App to view the agreement")];
|
|
|
|
|
|
});
|
|
|
|
|
|
}];
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-02-24 13:38:51 +08:00
|
|
|
|
#pragma mark - Actions
|
|
|
|
|
|
|
|
|
|
|
|
- (void)kb_openRechargeForProduct:(KBKeyboardSubscriptionProduct *)product {
|
|
|
|
|
|
if (![product isKindOfClass:KBKeyboardSubscriptionProduct.class] ||
|
|
|
|
|
|
product.productId.length == 0) {
|
|
|
|
|
|
[KBHUD showInfo:KBLocalized(@"Product unavailable")];
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
NSString *encodedId = [self.class kb_urlEncodedString:product.productId];
|
|
|
|
|
|
NSString *title = [product displayTitle];
|
|
|
|
|
|
NSString *encodedTitle = [self.class kb_urlEncodedString:title];
|
|
|
|
|
|
NSMutableArray<NSString *> *params =
|
|
|
|
|
|
[NSMutableArray arrayWithObjects:@"autoPay=1", @"prefill=1", nil];
|
|
|
|
|
|
if (encodedId.length) {
|
|
|
|
|
|
[params addObject:[NSString stringWithFormat:@"productId=%@", encodedId]];
|
|
|
|
|
|
}
|
|
|
|
|
|
if (encodedTitle.length) {
|
|
|
|
|
|
[params
|
|
|
|
|
|
addObject:[NSString stringWithFormat:@"productTitle=%@", encodedTitle]];
|
|
|
|
|
|
}
|
|
|
|
|
|
NSString *query = [params componentsJoinedByString:@"&"];
|
|
|
|
|
|
NSString *urlString = [NSString
|
|
|
|
|
|
stringWithFormat:@"%@://recharge?src=keyboard&%@", KB_APP_SCHEME, query];
|
|
|
|
|
|
NSURL *scheme = [NSURL URLWithString:urlString];
|
2026-03-05 14:30:07 +08:00
|
|
|
|
NSString *ulString = [NSString stringWithFormat:@"%@?src=keyboard&%@", KB_UL_RECHARGE, query];
|
|
|
|
|
|
NSURL *ul = [NSURL URLWithString:ulString];
|
|
|
|
|
|
__weak typeof(self) weakSelf = self;
|
|
|
|
|
|
[KBExtensionAppLauncher openPrimaryURL:ul
|
|
|
|
|
|
fallbackURL:scheme
|
|
|
|
|
|
usingInputController:self
|
|
|
|
|
|
source:(self.view ?: (UIResponder *)weakSelf)
|
|
|
|
|
|
completion:^(BOOL success) {
|
|
|
|
|
|
if (success) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
dispatch_async(dispatch_get_main_queue(), ^{
|
|
|
|
|
|
[KBHUD showInfo:KBLocalized(@"Please open the App to finish purchase")];
|
|
|
|
|
|
});
|
|
|
|
|
|
}];
|
2026-02-24 13:38:51 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
+ (NSString *)kb_urlEncodedString:(NSString *)value {
|
|
|
|
|
|
if (value.length == 0) {
|
|
|
|
|
|
return @"";
|
|
|
|
|
|
}
|
|
|
|
|
|
NSString *reserved = @"!*'();:@&=+$,/?%#[]";
|
|
|
|
|
|
NSMutableCharacterSet *allowed =
|
|
|
|
|
|
[[NSCharacterSet URLQueryAllowedCharacterSet] mutableCopy];
|
|
|
|
|
|
[allowed removeCharactersInString:reserved];
|
|
|
|
|
|
return [value stringByAddingPercentEncodingWithAllowedCharacters:allowed]
|
|
|
|
|
|
?: @"";
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@end
|