From 6800864866f7118ba2d05f0d9aa377ecff9a6cc5 Mon Sep 17 00:00:00 2001 From: CodeST <694468528@qq.com> Date: Tue, 16 Dec 2025 16:25:50 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E6=81=A2=E5=A4=8D=E8=B4=AD?= =?UTF-8?q?=E4=B9=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Localization/en.lproj/Localizable.strings | 1 + .../zh-Hans.lproj/Localizable.strings | 1 + .../Pay/pay_resh_icon.imageset/Contents.json | 22 ++++++++++ .../pay_resh_icon@2x.png | Bin 0 -> 1021 bytes .../pay_resh_icon@3x.png | Bin 0 -> 1836 bytes .../StoreKit2Manager/KBStoreKitBridge.swift | 15 +++++++ keyBoard/Class/Pay/V/KBVipPayHeaderView.m | 2 +- keyBoard/Class/Pay/VC/KBVipPay.m | 41 ++++++++++++++++++ 8 files changed, 81 insertions(+), 1 deletion(-) create mode 100644 keyBoard/Assets.xcassets/Pay/pay_resh_icon.imageset/Contents.json create mode 100644 keyBoard/Assets.xcassets/Pay/pay_resh_icon.imageset/pay_resh_icon@2x.png create mode 100644 keyBoard/Assets.xcassets/Pay/pay_resh_icon.imageset/pay_resh_icon@3x.png diff --git a/Shared/Localization/en.lproj/Localizable.strings b/Shared/Localization/en.lproj/Localizable.strings index 246079c..c637836 100644 --- a/Shared/Localization/en.lproj/Localizable.strings +++ b/Shared/Localization/en.lproj/Localizable.strings @@ -266,3 +266,4 @@ "Purchase cancelled." = "Purchase cancelled."; "Purchase pending approval." = "Purchase pending approval."; "Unable to obtain transaction payload." = "Unable to obtain transaction payload."; +"Resume Purchase" = "Resume Purchase"; diff --git a/Shared/Localization/zh-Hans.lproj/Localizable.strings b/Shared/Localization/zh-Hans.lproj/Localizable.strings index f930300..bc036a5 100644 --- a/Shared/Localization/zh-Hans.lproj/Localizable.strings +++ b/Shared/Localization/zh-Hans.lproj/Localizable.strings @@ -264,3 +264,4 @@ "Purchase cancelled." = "已取消购买"; "Purchase pending approval." = "购买等待确认"; "Unable to obtain transaction payload." = "无法获取交易凭据"; +"Resume Purchase" = "恢复购买"; diff --git a/keyBoard/Assets.xcassets/Pay/pay_resh_icon.imageset/Contents.json b/keyBoard/Assets.xcassets/Pay/pay_resh_icon.imageset/Contents.json new file mode 100644 index 0000000..1f445cc --- /dev/null +++ b/keyBoard/Assets.xcassets/Pay/pay_resh_icon.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "pay_resh_icon@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "pay_resh_icon@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/keyBoard/Assets.xcassets/Pay/pay_resh_icon.imageset/pay_resh_icon@2x.png b/keyBoard/Assets.xcassets/Pay/pay_resh_icon.imageset/pay_resh_icon@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..2c012c093994eff6a283262a16dc1e5f8bd0fc98 GIT binary patch literal 1021 zcmV71Q{000BBNklTQ7eXyuv?yp%tBiti zVHCbMRFpX`-uDy~6%`b9AqXlX=)#5Ygn7)2_xL;C_r7m@&U@p`^K$>3d(OG%_nmw1 zckWTFrX1KmistlJ64wq&T%Xmrz94aJ&S`1X|8*H$XBDAH`QX?eQ0yi5AYEW>81@9n>p@yYiz?4rRDH(j0BojgFZB{|Uqhq+A+Eng z-m*&BGG5A%)&UyY1G7Ja>H1Kv>_D{j7)q1vRDr$IQRNV2lL12;==o`KS!GyZe-%nY7;ER?nnjKV#j?GaXLnX|L(f>6^8W(A-_< z%+@~eBTeqSZ@^WsaC6HM# zkyTI&--0)k^x&1}N-s~i0oolyJpG!}-crD@@oNg`zO%UZ66mSZgEte)ZK&9IW=RqM z^Snyfl`(u2$T*s{uDy5un%aV$%=LqHoB>p@z%P-mo8*dW_;I!23cbn@JTN2@6B$hi zc4|@O)eu#9wm6JV2{Qk5h^ixaXIs9gBYODo|GqJ0oK@2snX&-m8rMzY`tkG(U1E02 zhosGG{zb`rE#2E6Uk`#Wv8-6zFf@?^isC}9^Z3xFoF0TIRev!cxux0iAo>j$9CE;5 zIGPE?LM5XI9o-v%F_;Dzea-^se*Z8@N8G57{x3%yM)5m^Nq;y6&UF1ds;QXymbm*mb5mS=ym82R-1csetvx$HK{Wqzl*%(#vYhnmk6sEeUSg<#9y%WuvNH+r)li6u}){zz2ga4z+^CaJmXpsR|s<|=EW!J+`p+;U2TXR5z z<(*J`fw57i{2MyxrRj_7tba>kRU~d{v0K+-5BlHZ}vc zIiST**-E_9gcl44;M}cF@F7ENwR`o@9jug|~1N!$P2OxNuZM;U_Pu}T@?jqNh`aTlLzaY_n6l>QOX|E@5>l-+P zp5!a8XYfvE`Yui#EO~k6hgy zL@w5X`#RF;0FhD;h7Q35R;cPQel@}c5b-{pD#1F@9f19*F0G*-omgIHqf!sFGk6<= zZ=rpuhW0&-rnyN|YZWE>|LL6F8A*Q*Pq9SA#@%tsVy5cc7X`SqWD;AhBCEm8zNEM6 z(Kob*Ti<9+`Z)LHZsbR}&sMF~9?g$j2a(TKs!A)7K=tB_Dz+90$~yp4SLUjiyqkIh zpubGNQ{gtUasj!P-Vsdd4{HsrkVD`_K>Qw!H_F=~uJaAK^isT>ZqqRM3Z@)7H*K*wH>ymN!#3dCZe}gGy>kpthnAVg$+dLS1@a~IruKPbJ<#}x|A^ovUr}ahSI7-z zxrI*-Ex;iz4K>Qeun8aRf2OQ}`{T-s{P~&31XX(&vsP|tq}N0<6@Q`c$ew!};B9}?f z2FO=~^Uhk)Qn0*Cqc8OvT#=eUq-aDht5*&jU@v}!CsXZayx26@su!HSK6+Oy2Q~T3 zKhn-=^a1`Cbs6&cSd&qa#Z(g&E_6=-vJ*TNXZnLkpq5#HjT zP#jv@>tT6 zgtjg|uHlrp4I=k&sXkzk2O;>bw~0x=_aW1b&ng{d{dVlHzlT<<>!sO&dVdeLCwZ?E zy@IVhN7H}FjmR&K4ub3eB#!CDXgbEJGp6PS!`|d$;4VYktkfLPsWgd!m&17bb?l`L z5ZOg@=^W;}8S=i5iL*7~}nSx3CMO6 zd6wO^4}O<0a{%^H|2 Void) { + Task { + do { + try await self.manager.restorePurchases() + await MainActor.run { + completion(true, nil) + } + } catch { + await MainActor.run { + completion(false, error.localizedDescription) + } + } + } + } + // MARK: - Private Helpers @MainActor diff --git a/keyBoard/Class/Pay/V/KBVipPayHeaderView.m b/keyBoard/Class/Pay/V/KBVipPayHeaderView.m index d2ff5cf..3d73c90 100644 --- a/keyBoard/Class/Pay/V/KBVipPayHeaderView.m +++ b/keyBoard/Class/Pay/V/KBVipPayHeaderView.m @@ -38,7 +38,7 @@ [self.containerView addSubview:self.vipImageView]; [self.vipImageView mas_makeConstraints:^(MASConstraintMaker *make) { make.right.left.equalTo(self.containerView).inset(KBFit(27)); - make.top.equalTo(self.containerView).offset(KB_NAV_TOTAL_HEIGHT + 10); + make.top.equalTo(self.containerView).offset(KB_NAV_TOTAL_HEIGHT + 25); make.height.mas_equalTo((269)); }]; [self.containerView addSubview:self.wanImageView]; diff --git a/keyBoard/Class/Pay/VC/KBVipPay.m b/keyBoard/Class/Pay/VC/KBVipPay.m index 77bd25f..1e51b41 100644 --- a/keyBoard/Class/Pay/VC/KBVipPay.m +++ b/keyBoard/Class/Pay/VC/KBVipPay.m @@ -23,6 +23,7 @@ static NSString * const kKBVipReviewListCellId = @"kKBVipReviewListCellId"; @property (nonatomic, strong) NSArray *plans; // 订阅方案数组 @property (nonatomic, assign) NSInteger selectedIndex; // 当前选中的方案索引 @property (nonatomic, strong) UIButton *closeButton; // 当前选中的方案索引 +@property (nonatomic, strong) UIButton *restoreButton; @property (nonatomic, strong) UIImageView *bgImageView; // 全屏背景图 // Header 自适应测量 @property (nonatomic, strong) KBVipPayHeaderView *sizingHeader; @@ -86,6 +87,13 @@ static NSString * const kKBVipReviewListCellId = @"kKBVipReviewListCellId"; 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(123); + make.height.mas_equalTo(32); + }]; // 预计算 Header 高度(由内部约束决定) self.headerHeight = [self kb_calcHeaderHeightForWidth:KB_SCREEN_WIDTH]; @@ -217,6 +225,20 @@ static NSString * const kKBVipReviewListCellId = @"kKBVipReviewListCellId"; [KBHUD showInfo:KBLocalized(@"Open agreement")]; } +- (void)onTapRestoreButton { + [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 - UICollectionView DataSource - (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView { @@ -351,6 +373,25 @@ static NSString * const kKBVipReviewListCellId = @"kKBVipReviewListCellId"; 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; +} + - (UIButton *)payButton { if (!_payButton) { _payButton = [UIButton buttonWithType:UIButtonTypeCustom];