恢复购买
This commit is contained in:
parent
c73ae42733
commit
5814d4f434
@ -14,3 +14,6 @@ let kSPLoginUserInfoDefaultsKey = "kSPLoginUserInfoDefaultsKey"
|
|||||||
|
|
||||||
///首页搜索记录
|
///首页搜索记录
|
||||||
let kSPHomeSearchHistoryDefaultsKey = "kSPHomeSearchHistoryDefaultsKey"
|
let kSPHomeSearchHistoryDefaultsKey = "kSPHomeSearchHistoryDefaultsKey"
|
||||||
|
|
||||||
|
///待恢复数据
|
||||||
|
let kSPWaitRestoreIAPDefaultsKey = "kSPWaitRestoreIAPDefaultsKey"
|
||||||
|
@ -86,7 +86,7 @@ class SPPlayerDetailViewController: SPPlayerListViewController {
|
|||||||
//解锁视频需要的金币
|
//解锁视频需要的金币
|
||||||
let videoCoin = videoInfo.coins ?? 0
|
let videoCoin = videoInfo.coins ?? 0
|
||||||
|
|
||||||
if myCoin < videoCoin {
|
if myCoin < videoCoin {//金币不够时打开充值页面
|
||||||
self.onPlayBuy()
|
self.onPlayBuy()
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
|
@ -49,6 +49,7 @@ class SPPlayBuyView: HWPanModalContentView {
|
|||||||
button.setTitle("Restore".localized, for: .normal)
|
button.setTitle("Restore".localized, for: .normal)
|
||||||
button.setTitleColor(.colorFFFFFF(alpha: 0.5), for: .normal)
|
button.setTitleColor(.colorFFFFFF(alpha: 0.5), for: .normal)
|
||||||
button.titleLabel?.font = .fontRegular(ofSize: 14)
|
button.titleLabel?.font = .fontRegular(ofSize: 14)
|
||||||
|
button.addTarget(self, action: #selector(handleRestoreButton), for: .touchUpInside)
|
||||||
return button
|
return button
|
||||||
}()
|
}()
|
||||||
|
|
||||||
@ -121,7 +122,13 @@ extension SPPlayBuyView {
|
|||||||
guard let self = self else { return }
|
guard let self = self else { return }
|
||||||
self.rechargeView.userInfo = SPLoginManager.manager.userInfo
|
self.rechargeView.userInfo = SPLoginManager.manager.userInfo
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc private func handleRestoreButton() {
|
||||||
|
SPIAPManager.manager.restore { [weak self] isFinish in
|
||||||
|
guard let self = self else { return }
|
||||||
|
self.handleBuyFinish()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,7 +84,10 @@ class SPStoreViewController: SPViewController {
|
|||||||
extension SPStoreViewController {
|
extension SPStoreViewController {
|
||||||
|
|
||||||
@objc private func handelRightBarButton() {
|
@objc private func handelRightBarButton() {
|
||||||
|
SPIAPManager.manager.restore { [weak self] isFinish in
|
||||||
|
guard let self = self else { return }
|
||||||
|
self.buyFinish()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc private func buyFinish() {
|
@objc private func buyFinish() {
|
||||||
|
@ -141,7 +141,6 @@ extension SPCoinRechargeView: UICollectionViewDelegate, UICollectionViewDataSour
|
|||||||
|
|
||||||
SPIAPManager.manager.startRecharge(model: model, shortPlayId: shortPlayId, videoId: videoId) { [weak self] finish in
|
SPIAPManager.manager.startRecharge(model: model, shortPlayId: shortPlayId, videoId: videoId) { [weak self] finish in
|
||||||
if finish {
|
if finish {
|
||||||
SPToast.show(text: "success".localized)
|
|
||||||
self?.rechargeFinishHandle?()
|
self?.rechargeFinishHandle?()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -106,7 +106,6 @@ extension SPMemberRechargeView: UICollectionViewDelegate, UICollectionViewDataSo
|
|||||||
|
|
||||||
SPIAPManager.manager.startRecharge(model: model, shortPlayId: shortPlayId, videoId: videoId) { [weak self] finish in
|
SPIAPManager.manager.startRecharge(model: model, shortPlayId: shortPlayId, videoId: videoId) { [weak self] finish in
|
||||||
if finish {
|
if finish {
|
||||||
SPToast.show(text: "success".localized)
|
|
||||||
self?.buyFinishHandle?()
|
self?.buyFinishHandle?()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,13 +27,25 @@ class SPIAPManager: NSObject {
|
|||||||
private var orderCode: String?
|
private var orderCode: String?
|
||||||
private var payId: String?
|
private var payId: String?
|
||||||
|
|
||||||
|
///恢复购买使用
|
||||||
|
///等待恢复的数据
|
||||||
|
private var waitRestoreModel: SPWaitRestoreModel? = UserDefaults.jx_object(forKey: kSPWaitRestoreIAPDefaultsKey, class: SPWaitRestoreModel.self) as? SPWaitRestoreModel
|
||||||
|
|
||||||
///开始内购
|
///开始内购
|
||||||
func startRecharge(model: SPPayTemplateItem, shortPlayId: String? = nil, videoId: String? = nil, handler: CompletionHandler? = nil) {
|
func startRecharge(model: SPPayTemplateItem, shortPlayId: String? = nil, videoId: String? = nil, handler: CompletionHandler? = nil) {
|
||||||
|
|
||||||
|
if let waitRestoreModel = self.waitRestoreModel {
|
||||||
|
SPToast.show(text: "kToastMessage_02".localized)
|
||||||
|
handler?(false)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
guard let payId = model.id else {
|
guard let payId = model.id else {
|
||||||
handler?(false)
|
handler?(false)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
self.completionHandler = handler
|
self.completionHandler = handler
|
||||||
|
self.waitRestoreModel = SPWaitRestoreModel()
|
||||||
|
|
||||||
let productId = SPIAPManager.IAPPrefix + (model.ios_template_id ?? "")
|
let productId = SPIAPManager.IAPPrefix + (model.ios_template_id ?? "")
|
||||||
|
|
||||||
@ -42,11 +54,14 @@ class SPIAPManager: NSObject {
|
|||||||
SPWalletAPI.requestCreateOrder(payId: payId, shortPlayId: shortPlayId ?? "0", videoId: videoId ?? "0") { orderModel in
|
SPWalletAPI.requestCreateOrder(payId: payId, shortPlayId: shortPlayId ?? "0", videoId: videoId ?? "0") { orderModel in
|
||||||
guard let orderModel = orderModel else {
|
guard let orderModel = orderModel else {
|
||||||
SPHUD.dismiss()
|
SPHUD.dismiss()
|
||||||
|
self.waitRestoreModel = nil
|
||||||
self.completionHandler?(false)
|
self.completionHandler?(false)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
self.orderCode = orderModel.order_code
|
self.orderCode = orderModel.order_code
|
||||||
self.payId = payId
|
self.payId = payId
|
||||||
|
self.waitRestoreModel?.payId = payId
|
||||||
|
self.waitRestoreModel?.orderCode = orderModel.order_code
|
||||||
|
|
||||||
self.iapManager.start(productId: productId, orderId: self.orderCode ?? "")
|
self.iapManager.start(productId: productId, orderId: self.orderCode ?? "")
|
||||||
|
|
||||||
@ -54,6 +69,42 @@ class SPIAPManager: NSObject {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func restore(isLoding: Bool = true, completer: ((_ isFinish: Bool) -> Void)?) {
|
||||||
|
guard let waitRestoreModel = self.waitRestoreModel,
|
||||||
|
let orderCode = waitRestoreModel.orderCode,
|
||||||
|
let payId = waitRestoreModel.payId,
|
||||||
|
let productId = waitRestoreModel.productId,
|
||||||
|
let receipt = waitRestoreModel.receipt
|
||||||
|
else {
|
||||||
|
if isLoding {
|
||||||
|
SPToast.show(text: "kToastMessage_01".localized)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if isLoding {
|
||||||
|
SPHUD.show()
|
||||||
|
}
|
||||||
|
SPWalletAPI.requestVerifyOrder(orderCode: orderCode, payId: payId, productId: productId, purchaseToken: receipt) { model in
|
||||||
|
if model?.status == "success" {
|
||||||
|
self.waitRestoreModel = nil
|
||||||
|
UserDefaults.jx_setObject(self.waitRestoreModel, forKey: kSPWaitRestoreIAPDefaultsKey)
|
||||||
|
if isLoding {
|
||||||
|
SPToast.show(text: "success".localized)
|
||||||
|
}
|
||||||
|
completer?(true)
|
||||||
|
} else {
|
||||||
|
// SPToast.show(text: "failure".localized)
|
||||||
|
completer?(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
if isLoding {
|
||||||
|
SPHUD.dismiss()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -61,15 +112,29 @@ class SPIAPManager: NSObject {
|
|||||||
extension SPIAPManager: JXIAPManagerDelegate {
|
extension SPIAPManager: JXIAPManagerDelegate {
|
||||||
|
|
||||||
func jx_iapPaySuccess(productId: String, receipt: String, transactionIdentifier: String?) {
|
func jx_iapPaySuccess(productId: String, receipt: String, transactionIdentifier: String?) {
|
||||||
guard let orderCode = self.orderCode, let payId = self.payId else { return }
|
guard let orderCode = self.orderCode, let payId = self.payId else {
|
||||||
|
self.orderCode = nil
|
||||||
|
self.payId = nil
|
||||||
|
self.waitRestoreModel = nil
|
||||||
|
self.completionHandler?(false)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
self.waitRestoreModel?.productId = productId
|
||||||
|
self.waitRestoreModel?.receipt = receipt
|
||||||
|
|
||||||
|
UserDefaults.jx_setObject(self.waitRestoreModel, forKey: kSPWaitRestoreIAPDefaultsKey)
|
||||||
|
|
||||||
SPWalletAPI.requestVerifyOrder(orderCode: orderCode, payId: payId, productId: productId, purchaseToken: receipt) { model in
|
SPWalletAPI.requestVerifyOrder(orderCode: orderCode, payId: payId, productId: productId, purchaseToken: receipt) { model in
|
||||||
SPHUD.dismiss()
|
SPHUD.dismiss()
|
||||||
|
|
||||||
if model?.status == "success" {
|
|
||||||
self.orderCode = nil
|
self.orderCode = nil
|
||||||
self.payId = nil
|
self.payId = nil
|
||||||
|
|
||||||
|
if model?.status == "success" {
|
||||||
|
self.waitRestoreModel = nil
|
||||||
|
UserDefaults.jx_setObject(self.waitRestoreModel, forKey: kSPWaitRestoreIAPDefaultsKey)
|
||||||
|
SPToast.show(text: "success".localized)
|
||||||
self.completionHandler?(true)
|
self.completionHandler?(true)
|
||||||
} else {
|
} else {
|
||||||
self.completionHandler?(false)
|
self.completionHandler?(false)
|
||||||
@ -81,6 +146,8 @@ extension SPIAPManager: JXIAPManagerDelegate {
|
|||||||
func jx_iapPayFailed(productId: String, code: JXIAPManagerCode) {
|
func jx_iapPayFailed(productId: String, code: JXIAPManagerCode) {
|
||||||
self.orderCode = nil
|
self.orderCode = nil
|
||||||
self.payId = nil
|
self.payId = nil
|
||||||
|
self.waitRestoreModel = nil
|
||||||
|
|
||||||
SPHUD.dismiss()
|
SPHUD.dismiss()
|
||||||
|
|
||||||
if code == .noProduct {
|
if code == .noProduct {
|
||||||
|
44
MoviaBox/Libs/SPIAPManager/SPWaitRestoreModel.swift
Normal file
44
MoviaBox/Libs/SPIAPManager/SPWaitRestoreModel.swift
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
//
|
||||||
|
// SPWaitRestoreModel.swift
|
||||||
|
// MoviaBox
|
||||||
|
//
|
||||||
|
// Created by 佳尔 on 2025/5/7.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
|
||||||
|
class SPWaitRestoreModel: SPModel, NSSecureCoding {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
var orderCode: String?
|
||||||
|
var payId: String?
|
||||||
|
var productId: String?
|
||||||
|
var receipt: String?
|
||||||
|
|
||||||
|
|
||||||
|
required init() { }
|
||||||
|
|
||||||
|
static var supportsSecureCoding: Bool {
|
||||||
|
get {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func encode(with coder: NSCoder) {
|
||||||
|
coder.encode(orderCode, forKey: "orderCode")
|
||||||
|
coder.encode(payId, forKey: "payId")
|
||||||
|
coder.encode(productId, forKey: "productId")
|
||||||
|
coder.encode(receipt, forKey: "receipt")
|
||||||
|
}
|
||||||
|
|
||||||
|
required init?(coder: NSCoder) {
|
||||||
|
super.init()
|
||||||
|
orderCode = coder.decodeObject(of: NSString.self, forKey: "orderCode") as? String
|
||||||
|
payId = coder.decodeObject(of: NSString.self, forKey: "payId") as? String
|
||||||
|
productId = coder.decodeObject(of: NSString.self, forKey: "productId") as? String
|
||||||
|
receipt = coder.decodeObject(of: NSString.self, forKey: "receipt") as? String
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
"Home" = "Home";
|
"Home" = "Home";
|
||||||
"success" = "success";
|
"success" = "success";
|
||||||
|
"failure" = "failure";
|
||||||
"For You" = "For You";
|
"For You" = "For You";
|
||||||
"Error" = "Error";
|
"Error" = "Error";
|
||||||
"Profile" = "Profile";
|
"Profile" = "Profile";
|
||||||
@ -91,11 +92,17 @@
|
|||||||
"Unlock the previous episode" = "Unlock the previous episode";
|
"Unlock the previous episode" = "Unlock the previous episode";
|
||||||
"Purchase Single Episode" = "Purchase Single Episode";
|
"Purchase Single Episode" = "Purchase Single Episode";
|
||||||
|
|
||||||
|
///没有可恢复购买
|
||||||
|
"kToastMessage_01" = "There are no recoverable in-app purchases.";
|
||||||
|
///还有未完成的内购
|
||||||
|
"kToastMessage_02" = "You still have unfinished in-app purchases. Please restore them first.";
|
||||||
|
|
||||||
///请购买上一集提示
|
///请购买上一集提示
|
||||||
"kAlertMessage_01" = "The previous episode of this series has not been unlocked yet. Please unlock the previous episode first.";
|
"kAlertMessage_01" = "The previous episode of this series has not been unlocked yet. Please unlock the previous episode first.";
|
||||||
///没有找到视频提示
|
///没有找到视频提示
|
||||||
"kAlertMessage_02" = "Purchase failed, please try again later!";
|
"kAlertMessage_02" = "Purchase failed, please try again later!";
|
||||||
|
|
||||||
|
|
||||||
"kLoginAgreementText" = "By continuing, you agree to the User Agreement and Privacy Policy";
|
"kLoginAgreementText" = "By continuing, you agree to the User Agreement and Privacy Policy";
|
||||||
"kBuyMemberTipText" = "Auto renew · Cancel anytime";
|
"kBuyMemberTipText" = "Auto renew · Cancel anytime";
|
||||||
"kStoreTipTitle" = "Related terms and conditions:";
|
"kStoreTipTitle" = "Related terms and conditions:";
|
||||||
|
Loading…
x
Reference in New Issue
Block a user