内购价格随地区变化

This commit is contained in:
zeng 2025-07-19 13:57:19 +08:00
parent ee36da46d3
commit 01eb1c6c6a
3 changed files with 161 additions and 31 deletions

View File

@ -14,9 +14,71 @@ class SPWalletAPI: NSObject {
}
///
static func requestPayTemplate(completer: ((_ model: SPPayTemplateModel?) -> Void)?) {
static func requestPayTemplate(isLoding: Bool = false, isToast: Bool = true, completer: ((_ model: SPPayTemplateModel?) -> Void)?) {
if isLoding {
SPHUD.show()
}
_requestPayTemplate(isToast: isToast) { model in
guard let model = model else {
if isLoding {
SPHUD.dismiss()
}
completer?(nil)
return
}
var productIdArr: [String] = []
model.list_sub_vip?.forEach { item in
productIdArr.append(SPIAPManager.manager.getProductId(templateId: item.ios_template_id) ?? "")
}
model.list_coins?.forEach { item in
productIdArr.append(SPIAPManager.manager.getProductId(templateId: item.ios_template_id) ?? "")
}
SPIAPManager.manager.requestProductList(productIdArr: productIdArr) { products in
if isLoding {
SPHUD.dismiss()
}
var newCoinList: [SPPayTemplateItem] = []
var newVipList: [SPPayTemplateItem] = []
model.list_coins?.forEach { item in
let productId = SPIAPManager.manager.getProductId(templateId: item.ios_template_id) ?? ""
for product in products {
if productId == product.productIdentifier {
item.price = product.price.stringValue
item.currency = product.priceLocale.currencySymbol
newCoinList.append(item)
break
}
}
}
model.list_sub_vip?.forEach { item in
let productId = SPIAPManager.manager.getProductId(templateId: item.ios_template_id) ?? ""
for product in products {
if productId == product.productIdentifier {
item.price = product.price.stringValue
item.currency = product.priceLocale.currencySymbol
newVipList.append(item)
break
}
}
}
model.list_coins = newCoinList
model.list_sub_vip = newVipList
completer?(model)
}
}
}
private static func _requestPayTemplate(isToast: Bool = true, completer: ((_ model: SPPayTemplateModel?) -> Void)?) {
var param = SPNetworkParameters(path: "/paySettingsV3")
param.method = .get
param.isToast = isToast
SPNetwork.request(parameters: param) { (response: SPNetworkResponse<SPPayTemplateModel>) in
completer?(response.data)

View File

@ -6,6 +6,7 @@
//
import UIKit
import StoreKit
class SPIAPManager: NSObject {
typealias CompletionHandler = ((_ finish: Bool) -> Void)
@ -18,6 +19,8 @@ class SPIAPManager: NSObject {
///
private var completionHandler: CompletionHandler?
private var productListHandler: ((_ products: [SKProduct]) -> Void)?
private lazy var iapManager: JXIAPManager = {
let manager = JXIAPManager()
manager.delegate = self
@ -119,6 +122,17 @@ class SPIAPManager: NSObject {
}
}
func requestProductList(productIdArr: [String], completer: ((_ products: [SKProduct]) -> Void)?) {
self.productListHandler = completer
self.iapManager.requestProductList(productIdArr: productIdArr)
}
func getProductId(templateId: String?) -> String? {
guard let templateId = templateId else { return nil }
return SPIAPManager.IAPPrefix + templateId
}
}
//MARK: -------------- JXIAPManagerDelegate --------------
@ -182,6 +196,13 @@ extension SPIAPManager: JXIAPManagerDelegate {
self.completionHandler?(false)
}
func jx_iapPayGotProducts(products: [SKProduct]) {
self.productListHandler?(products)
self.productListHandler = nil
}
}
extension SPIAPManager {

View File

@ -10,7 +10,7 @@ import StoreKit
@objc protocol JXIAPManagerDelegate {
///
@objc optional func jx_iapPayGotProducts(productIds: [String])
@objc optional func jx_iapPayGotProducts(products: [SKProduct])
///
@objc optional func jx_iapPaySuccess(productId: String, receipt: String, transactionIdentifier: String?)
///
@ -34,19 +34,29 @@ import StoreKit
case cancelled
///
case noProduct
}
class JXIAPManager: NSObject {
enum OperationType {
case idle
case buy
case request
}
static let manager: JXIAPManager = JXIAPManager()
weak var delegate: JXIAPManagerDelegate?
///
private var operationType = OperationType.idle
private var payment: SKPayment?
private var product: SKProduct?
private var productId: String?
private var discount: SKPaymentDiscount?
private var orderId: String?
private var applicationUsername: String? {
get {
@ -80,10 +90,47 @@ class JXIAPManager: NSObject {
SKPaymentQueue.default().add(self)
}
func start(productId: String, orderId: String) {
func showCodeRedemption() {
SKPaymentQueue.default().presentCodeRedemptionSheet()
}
func requestProductList(productIdArr: [String]) {
guard self.operationType == .idle else { return }
self.operationType = .request
let set = Set(productIdArr)
let productsRequest = SKProductsRequest(productIdentifiers: set)
productsRequest.delegate = self
productsRequest.start()
}
// ///
// func buyProduct(product: SKProduct, orderId: String, discount: SKPaymentDiscount? = nil) {
// guard self.operationType == .idle else { return }
// self.operationType = .buy
//
// self.product = product
// self.orderId = orderId
//
// //
// let payment = SKMutablePayment(product: product)
// payment.applicationUsername = applicationUsername
// if let discount = discount {
// payment.paymentDiscount = discount
// }
//
// //
// SKPaymentQueue.default().add(payment)
// }
func start(productId: String, orderId: String, discount: SKPaymentDiscount? = nil) {
guard self.operationType == .idle else { return }
self.operationType = .buy
self.product = nil
self.productId = productId
self.orderId = orderId
self.discount = discount
let set = Set([productId])
let productsRequest = SKProductsRequest(productIdentifiers: set)
@ -98,9 +145,13 @@ class JXIAPManager: NSObject {
//
let payment = SKMutablePayment(product: product)
payment.applicationUsername = applicationUsername
spLog(message: payment.applicationUsername)
if let discount = self.discount {
payment.paymentDiscount = discount
self.discount = nil
}
self.payment = payment
//
SKPaymentQueue.default().add(payment)
}
@ -110,18 +161,27 @@ class JXIAPManager: NSObject {
//MARK: -------------- SKProductsRequestDelegate --------------
extension JXIAPManager: SKProductsRequestDelegate {
func productsRequest(_ request: SKProductsRequest, didReceive response: SKProductsResponse) {
guard let product = response.products.first else {
if self.operationType == .request {
DispatchQueue.main.async {
if let productId = self.productId {
self.productId = nil
self.delegate?.jx_iapPayFailed?(productId: productId, code: .noProduct)
}
self.delegate?.jx_iapPayGotProducts?(products: response.products)
}
return
}
self.product = product
self.operationType = .idle
} else if self.operationType == .buy {
guard let product = response.products.first else {
DispatchQueue.main.async {
if let productId = self.productId {
self.productId = nil
self.delegate?.jx_iapPayFailed?(productId: productId, code: .noProduct)
}
}
return
}
self.product = product
self.buyProduct()
}
self.buyProduct()
}
}
@ -131,7 +191,6 @@ extension JXIAPManager: SKPaymentTransactionObserver {
func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
for transaction in transactions {
spLog(message: "transactionState = \(transaction.transactionState)")
switch transaction.transactionState {
case .purchased:
DispatchQueue.main.async {
@ -171,33 +230,21 @@ extension JXIAPManager: SKPaymentTransactionObserver {
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
// }
spLog(message: "transactionDate = \(String(describing: transaction.transactionDate))")
spLog(message: "nowDate = \(Date())")
spLog(message: "productIdentifier = \(transaction.payment.productIdentifier)")
guard let productId = self.productId, productId == transaction.payment.productIdentifier else { return }
self.productId = nil
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 }
guard let productId = self.productId, productId == transaction.payment.productIdentifier else { return }
self.operationType = .idle
self.productId = nil
self.delegate?.jx_iapPaySuccess?(productId: productId, receipt: encodeStr, transactionIdentifier: transactionIdentifier)
}
private func failedTransaction(transaction: SKPaymentTransaction) {
self.operationType = .idle
let error = transaction.error as? SKError
guard let productId = self.productId else { return }
self.productId = nil