diff --git a/MoviaBox/AppDelegate/AppDelegate+Config.swift b/MoviaBox/AppDelegate/AppDelegate+Config.swift index 7d80b20..64abb53 100644 --- a/MoviaBox/AppDelegate/AppDelegate+Config.swift +++ b/MoviaBox/AppDelegate/AppDelegate+Config.swift @@ -17,6 +17,8 @@ extension AppDelegate { SPToast.config() SPHUD.config() + + UIBarButtonItem.appearance().sp_setTitleTextAttributes() } @@ -70,8 +72,6 @@ extension AppDelegate { if #available(iOS 15.0, *) { tabBar.scrollEdgeAppearance = appearance } - - } } diff --git a/MoviaBox/Base/Extension/UIBarButtonItem+SPAdd.swift b/MoviaBox/Base/Extension/UIBarButtonItem+SPAdd.swift new file mode 100644 index 0000000..25dc959 --- /dev/null +++ b/MoviaBox/Base/Extension/UIBarButtonItem+SPAdd.swift @@ -0,0 +1,36 @@ +// +// UIBarButtonItem+SPAdd.swift +// MoviaBox +// +// Created by 佳尔 on 2025/4/29. +// + +import UIKit + +extension UIBarButtonItem { + + static let sp_normalTitleFont = UIFont.fontRegular(ofSize: 14) + static var sp_normalTitleColor: UIColor { + get { + return UIColor.colorFFFFFF(alpha: 0.5) + } + } + + /** + 默认标题样式 + */ + static var sp_normalTitleTextAttributes: [NSAttributedString.Key : Any] { + get { + return [ + NSAttributedString.Key.font : sp_normalTitleFont, + NSAttributedString.Key.foregroundColor : sp_normalTitleColor + ] + } + } + + func sp_setTitleTextAttributes(normalAttributes: [NSAttributedString.Key : Any] = UIBarButtonItem.sp_normalTitleTextAttributes) { + self.setTitleTextAttributes(normalAttributes, for: .normal) + self.setTitleTextAttributes(normalAttributes, for: .highlighted) + } + +} diff --git a/MoviaBox/Class/Mine/View/SPMineWalletView.swift b/MoviaBox/Class/Mine/View/SPMineWalletView.swift index 19da11b..0213a0c 100644 --- a/MoviaBox/Class/Mine/View/SPMineWalletView.swift +++ b/MoviaBox/Class/Mine/View/SPMineWalletView.swift @@ -94,7 +94,7 @@ class SPMineWalletView: UIView { extension SPMineWalletView { @objc private func handleStoreButton() { - let vc = SPWalletViewController() + let vc = SPStoreViewController() self.viewController?.navigationController?.pushViewController(vc, animated: true) } diff --git a/MoviaBox/Class/Wallet/Controller/SPStoreViewController.swift b/MoviaBox/Class/Wallet/Controller/SPStoreViewController.swift new file mode 100644 index 0000000..8981ea5 --- /dev/null +++ b/MoviaBox/Class/Wallet/Controller/SPStoreViewController.swift @@ -0,0 +1,138 @@ +// +// SPStoreViewController.swift +// MoviaBox +// +// Created by 佳尔 on 2025/4/29. +// + +import UIKit + +class SPStoreViewController: SPViewController { + + //MARK: UI属性 + private lazy var scrollView: SPScrollView = { + let scrollView = SPScrollView() + return scrollView + }() + + private lazy var stackView: UIStackView = { + let view = UIStackView() + view.axis = .vertical + view.spacing = 16 + return view + }() + + private lazy var rechargeView: SPCoinRechargeView = { + let view = SPCoinRechargeView() + return view + }() + + private lazy var memberView: SPMemberRechargeView = { + let view = SPMemberRechargeView() + return view + }() + + private lazy var tipTitleLabel: UILabel = { + let label = UILabel() + label.font = .fontMedium(ofSize: 12) + label.textColor = .colorFFFFFF(alpha: 0.7) + return label + }() + + private lazy var tipTextLabel: UILabel = { + let label = UILabel() + label.numberOfLines = 0 + label.textColor = .colorFFFFFF(alpha: 0.5) + label.font = .fontRegular(ofSize: 12) + return label + }() + + override func viewDidLoad() { + super.viewDidLoad() + self.title = "Store".localized + self.edgesForExtendedLayout = .top + setBackgroundView(isShowGradient: false, bgImage: UIImage(named: "buy_bg_image_02")) + + let rightBarButton = UIBarButtonItem(title: "Restore".localized, style: .plain, target: self, action: #selector(handelRightBarButton)) + self.navigationItem.rightBarButtonItem = rightBarButton + + tipTitleLabel.text = "kStoreTipTitle".localized + tipTextLabel.text = "kStoreTipText".localized + + _setupUI() + + requestPayTemplate() + } + + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + self.navigationController?.setNavigationBarHidden(false, animated: true) + setNavigationNormalStyle(backgroundColor: .clear, isTranslucent: true) + } + + + +} + +extension SPStoreViewController { + + @objc private func handelRightBarButton() { + + } + +} + +extension SPStoreViewController { + + private func _setupUI() { + view.addSubview(scrollView) + scrollView.addSubview(stackView) + scrollView.addSubview(tipTitleLabel) + scrollView.addSubview(tipTextLabel) + + scrollView.snp.makeConstraints { make in + make.left.right.bottom.equalToSuperview() + make.top.equalToSuperview().offset(kSPNavBarHeight) + } + + stackView.snp.makeConstraints { make in + make.left.right.top.equalToSuperview() +// make.bottom.equalTo(-(kSPTabbarSafeBottomMargin + 10)) + make.width.equalTo(kSPScreenWidth) + } + + tipTitleLabel.snp.makeConstraints { make in + make.left.equalToSuperview().offset(24) + make.top.equalTo(stackView.snp.bottom).offset(34) + } + + tipTextLabel.snp.makeConstraints { make in + make.left.equalTo(tipTitleLabel) + make.right.lessThanOrEqualTo(stackView).offset(-24) + make.top.equalTo(tipTitleLabel.snp.bottom).offset(4) + make.bottom.equalTo(-(kSPTabbarSafeBottomMargin + 10)) + } + } + +} + +extension SPStoreViewController { + + ///请求支付模版 + private func requestPayTemplate() { + SPWalletAPI.requestPayTemplate { [weak self] templateModel in + guard let self = self else { return } + self.rechargeView.dataArr = templateModel?.list_coins + self.memberView.dataArr = templateModel?.list_sub_vip + + self.stackView.removeAllArrangedSubview() + + self.stackView.addArrangedSubview(self.memberView) + self.stackView.addArrangedSubview(self.rechargeView) + + } + } + + +} + diff --git a/MoviaBox/Source/Assets.xcassets/image/buy_bg_image_02.imageset/Contents.json b/MoviaBox/Source/Assets.xcassets/image/buy_bg_image_02.imageset/Contents.json new file mode 100644 index 0000000..6a0b20a --- /dev/null +++ b/MoviaBox/Source/Assets.xcassets/image/buy_bg_image_02.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "背景.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "背景@2x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MoviaBox/Source/Assets.xcassets/image/buy_bg_image_02.imageset/背景.png b/MoviaBox/Source/Assets.xcassets/image/buy_bg_image_02.imageset/背景.png new file mode 100644 index 0000000..ecde994 Binary files /dev/null and b/MoviaBox/Source/Assets.xcassets/image/buy_bg_image_02.imageset/背景.png differ diff --git a/MoviaBox/Source/Assets.xcassets/image/buy_bg_image_02.imageset/背景@2x.png b/MoviaBox/Source/Assets.xcassets/image/buy_bg_image_02.imageset/背景@2x.png new file mode 100644 index 0000000..795dd3c Binary files /dev/null and b/MoviaBox/Source/Assets.xcassets/image/buy_bg_image_02.imageset/背景@2x.png differ diff --git a/MoviaBox/Source/en.lproj/Localizable.strings b/MoviaBox/Source/en.lproj/Localizable.strings index 987a218..4dd28a6 100644 --- a/MoviaBox/Source/en.lproj/Localizable.strings +++ b/MoviaBox/Source/en.lproj/Localizable.strings @@ -73,4 +73,6 @@ "kLoginAgreementText" = "By continuing, you agree to the User Agreement and Privacy Policy"; "kBuyMemberTipText" = "Auto renew · Cancel anytime"; +"kStoreTipTitle" = "Related terms and conditions:"; +"kStoreTipText" = "1. Coins can only be used within this application.
2. Payment: The purchase will be charged to your iTunes account. 
3. Renewal: Your Apple iTunes account will be charged within 24 hours before the expiration and the subscription period will be extended for another subscription cycle upon successful deduction.
4. Cancellation: To cancel the subscription renewal, please turn off the automatic renewal function in the iTunes/Apple ID settings at least 24 hours before the current subscription period expires. If canceled within the last 24 hours before expiration, a subscription fee will still be charged. 
5. Payment successful but recharge not taking effect for an extended period? Click here to refresh or send an email to: cs.jiaer.developer@icloud.com. 
6. Manage your subscriptions: You can view, change, or cancel your subscriptions. 

Terms of Service | Privacy Policy 
Renewal Agreement"; diff --git a/MoviaBox/Thirdparty/JXIAPManager/JXIAPManager.swift b/MoviaBox/Thirdparty/JXIAPManager/JXIAPManager.swift new file mode 100644 index 0000000..1036e47 --- /dev/null +++ b/MoviaBox/Thirdparty/JXIAPManager/JXIAPManager.swift @@ -0,0 +1,198 @@ +// +// JXIAPManager.swift +// BoJia +// +// Created by 火山传媒 on 2024/6/3. +// + +import UIKit +import StoreKit + +@objc protocol JXIAPManagerDelegate { + /// 获取到可购买商品列表 + @objc optional func jx_iapPayGotProducts(productIds: [String]) + /// 购买成功 + @objc optional func jx_iapPaySuccess(productId: String, receipt: String, transactionIdentifier: String?) + /// 购买失败 + @objc optional func jx_iapPayFailed(productId: String, code: JXIAPManagerCode) + /// 恢复商品(仅限永久有效商品) + @objc optional func iapPayRestore(productIds: [String], transactionIds: [String]) +// /// 加载 +// @objc optional func iapPayShowHud() +// /// 系统错误 +// @objc optional func iapSysWrong() +// /// 验证成功 +// @objc optional func verifySuccess() +// /// 验证失败 +// @objc optional func verifyFailed() +} + +@objc enum JXIAPManagerCode: Int { + ///未知错误 + case unknown + ///取消交易 + case cancelled + ///没有商品 + case noProduct + +} + +class JXIAPManager: NSObject { + + static let manager: JXIAPManager = JXIAPManager() + + weak var delegate: JXIAPManagerDelegate? + + private var payment: SKPayment? + + private var product: SKProduct? + private var productId: String = "" + private var orderId: String? + private var applicationUsername: String? { + get { + let id = "00000000-0000-0000-0000-000000000000" + guard let orderId = orderId else { return nil } + var string = "" + for i in 0.. Bool { +// return true +// } + + /// 恢复购买回调 + func paymentQueueRestoreCompletedTransactionsFinished(_ queue: SKPaymentQueue) { + + } + +} + +extension JXIAPManager { + private func completeTransaction(transaction: SKPaymentTransaction) { + //自动续费 + if let _ = transaction.original, transaction.payment.applicationUsername == nil { + return + } + //重新开通自动续费 + if let _ = transaction.original, transaction.payment.applicationUsername != nil { + self.delegate?.jx_iapPayFailed?(productId: productId, code: .unknown) + return + } + + guard let receiptURL = Bundle.main.appStoreReceiptURL else { return } + let receiptData = NSData(contentsOf: receiptURL) + guard let encodeStr = receiptData?.base64EncodedString(options: .endLineWithLineFeed) else { return } + guard let transactionIdentifier = transaction.transactionIdentifier else { return } + + self.delegate?.jx_iapPaySuccess?(productId: productId, receipt: encodeStr, transactionIdentifier: transactionIdentifier) + } + + private func failedTransaction(transaction: SKPaymentTransaction) { + let error = transaction.error as? SKError + switch error?.code { + case SKError.paymentCancelled: + self.delegate?.jx_iapPayFailed?(productId: productId, code: .cancelled) + default: + self.delegate?.jx_iapPayFailed?(productId: productId, code: .unknown) + } + } +}