修复上传图片失败问题
This commit is contained in:
parent
261c75c8b7
commit
54aeb47fd9
@ -8,12 +8,12 @@
|
|||||||
import Cocoa
|
import Cocoa
|
||||||
|
|
||||||
class APUploadIAPListVC: NSViewController {
|
class APUploadIAPListVC: NSViewController {
|
||||||
|
|
||||||
@IBOutlet weak var tableView: NSTableView!
|
@IBOutlet weak var tableView: NSTableView!
|
||||||
@IBOutlet weak var enterBtn: NSButton!
|
@IBOutlet weak var enterBtn: NSButton!
|
||||||
@IBOutlet weak var preserveCurrentPriceBtn: NSButton!
|
@IBOutlet weak var preserveCurrentPriceBtn: NSButton!
|
||||||
@IBOutlet weak var showApiRateLimitLogsBtn: NSButton!
|
@IBOutlet weak var showApiRateLimitLogsBtn: NSButton!
|
||||||
|
|
||||||
public var currentApp: App? {
|
public var currentApp: App? {
|
||||||
didSet {
|
didSet {
|
||||||
setupUI()
|
setupUI()
|
||||||
@ -24,22 +24,22 @@ class APUploadIAPListVC: NSViewController {
|
|||||||
self.tableView.reloadData()
|
self.tableView.reloadData()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private var screenshotPaths = [String: String]()
|
private var screenshotPaths = [String: String]()
|
||||||
|
|
||||||
override func viewDidLoad() {
|
override func viewDidLoad() {
|
||||||
super.viewDidLoad()
|
super.viewDidLoad()
|
||||||
|
|
||||||
self.tableView.columnAutoresizingStyle = .uniformColumnAutoresizingStyle
|
self.tableView.columnAutoresizingStyle = .uniformColumnAutoresizingStyle
|
||||||
self.tableView.selectionHighlightStyle = .none
|
self.tableView.selectionHighlightStyle = .none
|
||||||
self.tableView.sizeToFit()
|
self.tableView.sizeToFit()
|
||||||
}
|
}
|
||||||
|
|
||||||
func setupUI() {
|
func setupUI() {
|
||||||
self.view.window?.title = "批量内购买项目上传 - " + (currentApp?.appName ?? "")
|
self.view.window?.title = "批量内购买项目上传 - " + (currentApp?.appName ?? "")
|
||||||
self.tableView.reloadData()
|
self.tableView.reloadData()
|
||||||
}
|
}
|
||||||
|
|
||||||
func showUploadView() {
|
func showUploadView() {
|
||||||
// 不能同时 present 出来
|
// 不能同时 present 出来
|
||||||
DispatchQueue.main.asyncAfter(deadline: .now() + 0.25) {
|
DispatchQueue.main.asyncAfter(deadline: .now() + 0.25) {
|
||||||
@ -58,36 +58,36 @@ class APUploadIAPListVC: NSViewController {
|
|||||||
self.presentAsSheet(upVC!)
|
self.presentAsSheet(upVC!)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@IBAction func clickedUploadShotBtn(_ sender: Any) {
|
@IBAction func clickedUploadShotBtn(_ sender: Any) {
|
||||||
showUploadView()
|
showUploadView()
|
||||||
}
|
}
|
||||||
|
|
||||||
@IBAction func clickedSPasswordBtn(_ sender: Any) {
|
@IBAction func clickedSPasswordBtn(_ sender: Any) {
|
||||||
let vc = APASCKeysSettingVC()
|
let vc = APASCKeysSettingVC()
|
||||||
presentAsSheet(vc)
|
presentAsSheet(vc)
|
||||||
}
|
}
|
||||||
|
|
||||||
@IBAction func createIAP(_ sender: Any) {
|
@IBAction func createIAP(_ sender: Any) {
|
||||||
let list = self.iaps
|
let list = self.iaps
|
||||||
guard list.count > 0 else {
|
guard list.count > 0 else {
|
||||||
APHUD.hide(message: "当前 App 无上传的内购商品!", delayTime: 1)
|
APHUD.hide(message: "当前 App 无上传的内购商品!", delayTime: 1)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
guard let appid = currentApp?.appId else {
|
guard let appid = currentApp?.appId else {
|
||||||
APHUD.hide(message: "当前 App 的 appleid 为空!", delayTime: 1)
|
APHUD.hide(message: "当前 App 的 appleid 为空!", delayTime: 1)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
enterBtn.isEnabled = false
|
enterBtn.isEnabled = false
|
||||||
APHUD.show(message: "上传中", view: self.view)
|
APHUD.show(message: "上传中", view: self.view)
|
||||||
let uploadIAPs: ((AppStoreConnectKey) -> Void) = { [weak self] ascKey in
|
let uploadIAPs: ((AppStoreConnectKey) -> Void) = { [weak self] ascKey in
|
||||||
// 上传数据
|
// 上传数据
|
||||||
self?.updateInAppPurchse(iaps: list, appId: appid, ascKey: ascKey)
|
self?.updateInAppPurchse(iaps: list, appId: appid, ascKey: ascKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
guard let ascKey = InfoCenter.shared.currentASCKey else {
|
guard let ascKey = InfoCenter.shared.currentASCKey else {
|
||||||
let vc = APASCKeysSettingVC()
|
let vc = APASCKeysSettingVC()
|
||||||
vc.updateCompletion = { password in
|
vc.updateCompletion = { password in
|
||||||
@ -98,7 +98,7 @@ class APUploadIAPListVC: NSViewController {
|
|||||||
presentAsSheet(vc)
|
presentAsSheet(vc)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
uploadIAPs(ascKey)
|
uploadIAPs(ascKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -106,7 +106,7 @@ class APUploadIAPListVC: NSViewController {
|
|||||||
|
|
||||||
// MARK: - 网络请求
|
// MARK: - 网络请求
|
||||||
extension APUploadIAPListVC {
|
extension APUploadIAPListVC {
|
||||||
|
|
||||||
func updateInAppPurchse(iaps: [IAPProduct], appId: String, ascKey: AppStoreConnectKey) {
|
func updateInAppPurchse(iaps: [IAPProduct], appId: String, ascKey: AppStoreConnectKey) {
|
||||||
let showApiRateLimit = showApiRateLimitLogsBtn.state.rawValue == 1
|
let showApiRateLimit = showApiRateLimitLogsBtn.state.rawValue == 1
|
||||||
let ascAPI = APASCAPI.init(issuerID: ascKey.issuerID,
|
let ascAPI = APASCAPI.init(issuerID: ascKey.issuerID,
|
||||||
@ -114,7 +114,7 @@ extension APUploadIAPListVC {
|
|||||||
privateKey: ascKey.privateKey,
|
privateKey: ascKey.privateKey,
|
||||||
showApiRateLimit: showApiRateLimit)
|
showApiRateLimit: showApiRateLimit)
|
||||||
ascAPI.addMessage("密钥信息:\(ascKey.issuerID), \(ascKey.privateKeyID), \(ascKey.privateKey)")
|
ascAPI.addMessage("密钥信息:\(ascKey.issuerID), \(ascKey.privateKeyID), \(ascKey.privateKey)")
|
||||||
|
|
||||||
Task {
|
Task {
|
||||||
// 1、获取当前账号下 app,判断是否包含当前 提交商品的 app
|
// 1、获取当前账号下 app,判断是否包含当前 提交商品的 app
|
||||||
guard let apps = await ascAPI.apps() else {
|
guard let apps = await ascAPI.apps() else {
|
||||||
@ -130,7 +130,7 @@ extension APUploadIAPListVC {
|
|||||||
APHUD.hide(message: "当前的密钥没有查到App: \(appId),请检查~", delayTime: 2)
|
APHUD.hide(message: "当前的密钥没有查到App: \(appId),请检查~", delayTime: 2)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. 同步显示进度日志
|
// 2. 同步显示进度日志
|
||||||
let sb = NSStoryboard(name: "APDebugVC", bundle: Bundle(for: self.classForCoder))
|
let sb = NSStoryboard(name: "APDebugVC", bundle: Bundle(for: self.classForCoder))
|
||||||
let newWC = sb.instantiateController(withIdentifier: "APDebugWC") as? NSWindowController
|
let newWC = sb.instantiateController(withIdentifier: "APDebugWC") as? NSWindowController
|
||||||
@ -141,11 +141,11 @@ extension APUploadIAPListVC {
|
|||||||
ascAPI.updateMsg = { messages in
|
ascAPI.updateMsg = { messages in
|
||||||
logVC?.debugLog = messages.joined(separator: "\n")
|
logVC?.debugLog = messages.joined(separator: "\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
ascAPI.addMessage("开始处理内购商品,获取现有商品中...")
|
ascAPI.addMessage("开始处理内购商品,获取现有商品中...")
|
||||||
// 3、获取所有的内购商品,如果存在的商品就直接修改,如果不存在就创建
|
// 3、获取所有的内购商品,如果存在的商品就直接修改,如果不存在就创建
|
||||||
let oldIAPs = await ascAPI.fetchInAppPurchasesList(appId: appId)
|
let oldIAPs = await ascAPI.fetchInAppPurchasesList(appId: appId)
|
||||||
|
|
||||||
// 4、遍历所有要上传的商品
|
// 4、遍历所有要上传的商品
|
||||||
for product in iaps {
|
for product in iaps {
|
||||||
// 订阅类型与非订单类型不一样的处理逻辑
|
// 订阅类型与非订单类型不一样的处理逻辑
|
||||||
@ -155,15 +155,15 @@ extension APUploadIAPListVC {
|
|||||||
await createInAppPurchase(appId: appId, product: product, oldIAPs: oldIAPs, ascAPI: ascAPI)
|
await createInAppPurchase(appId: appId, product: product, oldIAPs: oldIAPs, ascAPI: ascAPI)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.enterBtn.isEnabled = true
|
self.enterBtn.isEnabled = true
|
||||||
APHUD.hide()
|
APHUD.hide()
|
||||||
ascAPI.addMessage("完成全部内购商品,可稍后在苹果后台查看!✅✅✅")
|
ascAPI.addMessage("完成全部内购商品,可稍后在苹果后台查看!✅✅✅")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - 上传内购类型商品
|
// MARK: - 上传内购类型商品
|
||||||
|
|
||||||
/// 创建内购商品
|
/// 创建内购商品
|
||||||
func createInAppPurchase(appId: String, product: IAPProduct, oldIAPs: [ASCInAppPurchaseV2], ascAPI: APASCAPI) async {
|
func createInAppPurchase(appId: String, product: IAPProduct, oldIAPs: [ASCInAppPurchaseV2], ascAPI: APASCAPI) async {
|
||||||
ascAPI.addMessage("开始上传内购商品:\(product.productId),\(product.name) ")
|
ascAPI.addMessage("开始上传内购商品:\(product.productId),\(product.name) ")
|
||||||
@ -172,7 +172,7 @@ extension APUploadIAPListVC {
|
|||||||
if let iap = iaps.first {
|
if let iap = iaps.first {
|
||||||
ascAPI.addMessage("订阅商品已经存在:\(product.productId) ,跳过更新信息...")
|
ascAPI.addMessage("订阅商品已经存在:\(product.productId) ,跳过更新信息...")
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ascAPI.addMessage("内购已经存在:\(product.productId) ,开始更新信息中...")
|
ascAPI.addMessage("内购已经存在:\(product.productId) ,开始更新信息中...")
|
||||||
// 0. 审核备注如果原来有值,而新字段无值,则使用原值
|
// 0. 审核备注如果原来有值,而新字段无值,则使用原值
|
||||||
var product = product
|
var product = product
|
||||||
@ -185,8 +185,8 @@ extension APUploadIAPListVC {
|
|||||||
ascAPI.addMessage("内购已经存在:\(product.productId) ,更新信息失败!❌ ")
|
ascAPI.addMessage("内购已经存在:\(product.productId) ,更新信息失败!❌ ")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// 3. 商品本地化语言
|
// 3. 商品本地化语言
|
||||||
ascAPI.addMessage("开始更新内购本地化版本:\(product.productId)")
|
ascAPI.addMessage("开始更新内购本地化版本:\(product.productId)")
|
||||||
let localizations = await ascAPI.fetchInAppPurchasesLocalizations(iapId: iap.id)
|
let localizations = await ascAPI.fetchInAppPurchasesLocalizations(iapId: iap.id)
|
||||||
@ -208,16 +208,16 @@ extension APUploadIAPListVC {
|
|||||||
await createIAPLocalization(iapId: iap.id, localization: localization, product: product, ascAPI: ascAPI)
|
await createIAPLocalization(iapId: iap.id, localization: localization, product: product, ascAPI: ascAPI)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4. 商品截图
|
// 4. 商品截图
|
||||||
await createIAPScreenshot(iapId: iap.id, product: product, ascAPI: ascAPI)
|
await createIAPScreenshot(iapId: iap.id, product: product, ascAPI: ascAPI)
|
||||||
|
|
||||||
// 5. 销售国家或地区
|
// 5. 销售国家或地区
|
||||||
await updateIAPAvailableTerritories(iapId: iap.id, product: product, ascAPI: ascAPI)
|
await updateIAPAvailableTerritories(iapId: iap.id, product: product, ascAPI: ascAPI)
|
||||||
|
|
||||||
// 2. 商品价格档位
|
// 2. 商品价格档位
|
||||||
await updateIAPPricePoint(iapId: iap.id, product: product, ascAPI: ascAPI)
|
await updateIAPPricePoint(iapId: iap.id, product: product, ascAPI: ascAPI)
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// 1. 创建新的商品
|
// 1. 创建新的商品
|
||||||
guard let iap = await ascAPI.createInAppPurchases(appId: appId, product: product) else {
|
guard let iap = await ascAPI.createInAppPurchases(appId: appId, product: product) else {
|
||||||
@ -225,48 +225,48 @@ extension APUploadIAPListVC {
|
|||||||
ascAPI.addMessage("内购商品:\(product.productId) ,创建失败!❌ ")
|
ascAPI.addMessage("内购商品:\(product.productId) ,创建失败!❌ ")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// 3. 商品本地化语言
|
// 3. 商品本地化语言
|
||||||
for localization in product.localizations {
|
for localization in product.localizations {
|
||||||
await createIAPLocalization(iapId: iap.id, localization: localization, product: product, ascAPI: ascAPI)
|
await createIAPLocalization(iapId: iap.id, localization: localization, product: product, ascAPI: ascAPI)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4. 商品截图
|
// 4. 商品截图
|
||||||
await createIAPScreenshot(iapId: iap.id, product: product, ascAPI: ascAPI)
|
await createIAPScreenshot(iapId: iap.id, product: product, ascAPI: ascAPI)
|
||||||
|
|
||||||
// 5. 销售国家或地区
|
// 5. 销售国家或地区
|
||||||
await updateIAPAvailableTerritories(iapId: iap.id, product: product, ascAPI: ascAPI)
|
await updateIAPAvailableTerritories(iapId: iap.id, product: product, ascAPI: ascAPI)
|
||||||
|
|
||||||
// 2. 商品价格档位
|
// 2. 商品价格档位
|
||||||
await updateIAPPricePoint(iapId: iap.id, product: product, ascAPI: ascAPI)
|
await updateIAPPricePoint(iapId: iap.id, product: product, ascAPI: ascAPI)
|
||||||
}
|
}
|
||||||
|
|
||||||
ascAPI.addMessage("内购商品:\(product.productId),\(product.name) ,上传完成!\n")
|
ascAPI.addMessage("内购商品:\(product.productId),\(product.name) ,上传完成!\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 创建内购商品价格档位
|
/// 创建内购商品价格档位
|
||||||
func updateIAPPricePoint(iapId: String, product: IAPProduct, ascAPI: APASCAPI) async {
|
func updateIAPPricePoint(iapId: String, product: IAPProduct, ascAPI: APASCAPI) async {
|
||||||
guard let schedule = product.priceSchedules else {
|
guard let schedule = product.priceSchedules else {
|
||||||
ascAPI.addMessage("无价格计划表:\(product.productId) ,请确认!❌ ")
|
ascAPI.addMessage("无价格计划表:\(product.productId) ,请确认!❌ ")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
let baseTerritory = schedule.baseTerritory
|
let baseTerritory = schedule.baseTerritory
|
||||||
let baseCustomerPrice = schedule.baseCustomerPrice.normalizePrice()
|
let baseCustomerPrice = schedule.baseCustomerPrice.normalizePrice()
|
||||||
|
|
||||||
ascAPI.addMessage("开始更新价格计划表:\(product.productId),\(baseTerritory),\(baseCustomerPrice) \n")
|
ascAPI.addMessage("开始更新价格计划表:\(product.productId),\(baseTerritory),\(baseCustomerPrice) \n")
|
||||||
|
|
||||||
let points = await ascAPI.fetchPricePoints(iapId: iapId, territory: [baseTerritory])
|
let points = await ascAPI.fetchPricePoints(iapId: iapId, territory: [baseTerritory])
|
||||||
if let point = points.filter({ $0.attributes?.customerPrice!.normalizePrice() == baseCustomerPrice }).first {
|
if let point = points.filter({ $0.attributes?.customerPrice!.normalizePrice() == baseCustomerPrice }).first {
|
||||||
var manualPrices: [Any] = []
|
var manualPrices: [Any] = []
|
||||||
var included: [Any] = []
|
var included: [Any] = []
|
||||||
|
|
||||||
ascAPI.addMessage("开始构建基准国家和自定价格:")
|
ascAPI.addMessage("开始构建基准国家和自定价格:")
|
||||||
// base Territory
|
// base Territory
|
||||||
manualPrices.append(["id": "${\(baseTerritory)-\(included.count)}", "type": "inAppPurchasePrices"])
|
manualPrices.append(["id": "${\(baseTerritory)-\(included.count)}", "type": "inAppPurchasePrices"])
|
||||||
included.append(ascAPI.fetchInAppPurchasePriceSchedule(scheduleId: baseTerritory, pricePointId: point.id, iapId: iapId, index: included.count))
|
included.append(ascAPI.fetchInAppPurchasePriceSchedule(scheduleId: baseTerritory, pricePointId: point.id, iapId: iapId, index: included.count))
|
||||||
|
|
||||||
// customerPrice
|
// customerPrice
|
||||||
for pricePoint in schedule.manualPrices {
|
for pricePoint in schedule.manualPrices {
|
||||||
let territory = pricePoint.territory
|
let territory = pricePoint.territory
|
||||||
@ -279,9 +279,9 @@ extension APUploadIAPListVC {
|
|||||||
ascAPI.addMessage("自定价格的内购价格点:\(territory),\(customerPrice) ,未找到此档位!❌ ")
|
ascAPI.addMessage("自定价格的内购价格点:\(territory),\(customerPrice) ,未找到此档位!❌ ")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ascAPI.saveLogs(log: "内购的基准国家和自定价格:\(manualPrices),\(included)")
|
ascAPI.saveLogs(log: "内购的基准国家和自定价格:\(manualPrices),\(included)")
|
||||||
|
|
||||||
if (await ascAPI.updateInAppPurchasePricePoint(iapId: iapId, baseTerritoryId: baseTerritory, manualPrices: manualPrices, included: included)) != nil {
|
if (await ascAPI.updateInAppPurchasePricePoint(iapId: iapId, baseTerritoryId: baseTerritory, manualPrices: manualPrices, included: included)) != nil {
|
||||||
// 价格档位配置成功
|
// 价格档位配置成功
|
||||||
ascAPI.addMessage("内购价格点:\(baseTerritory),\(baseCustomerPrice) ,更新价格成功!✅ ")
|
ascAPI.addMessage("内购价格点:\(baseTerritory),\(baseCustomerPrice) ,更新价格成功!✅ ")
|
||||||
@ -294,8 +294,8 @@ extension APUploadIAPListVC {
|
|||||||
ascAPI.addMessage("基准国家的内购价格点:\(baseTerritory),\(baseCustomerPrice) ,未找到此档位!❌ ")
|
ascAPI.addMessage("基准国家的内购价格点:\(baseTerritory),\(baseCustomerPrice) ,未找到此档位!❌ ")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// 创建内购商品本地化信息
|
/// 创建内购商品本地化信息
|
||||||
func createIAPLocalization(iapId: String, localization: IAPLocalization, product: IAPProduct, ascAPI: APASCAPI) async {
|
func createIAPLocalization(iapId: String, localization: IAPLocalization, product: IAPProduct, ascAPI: APASCAPI) async {
|
||||||
ascAPI.addMessage("开始更新本地化版本:\(product.productId),\(localization.locale)")
|
ascAPI.addMessage("开始更新本地化版本:\(product.productId),\(localization.locale)")
|
||||||
@ -307,7 +307,7 @@ extension APUploadIAPListVC {
|
|||||||
ascAPI.addMessage("内购本地化版本:\(localization.locale) ,更新语言失败!❌ ")
|
ascAPI.addMessage("内购本地化版本:\(localization.locale) ,更新语言失败!❌ ")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 更新内购商品的送审截图
|
/// 更新内购商品的送审截图
|
||||||
func createIAPScreenshot(iapId: String, product: IAPProduct, ascAPI: APASCAPI) async {
|
func createIAPScreenshot(iapId: String, product: IAPProduct, ascAPI: APASCAPI) async {
|
||||||
ascAPI.addMessage("开始更新内购商品的送审截图:\(product.productId),\(product.reviewScreenshot)")
|
ascAPI.addMessage("开始更新内购商品的送审截图:\(product.productId),\(product.reviewScreenshot)")
|
||||||
@ -316,8 +316,9 @@ extension APUploadIAPListVC {
|
|||||||
ascAPI.addMessage("内购商品:\(product.productId) 无送审截图或未上传截图~")
|
ascAPI.addMessage("内购商品:\(product.productId) 无送审截图或未上传截图~")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
let imaUrl = URL.init(fileURLWithPath: imgPath)
|
let imaUrl = URL.init(fileURLWithPath: imgPath)
|
||||||
|
let uploadFileName = imaUrl.lastPathComponent.isEmpty ? imgName : imaUrl.lastPathComponent
|
||||||
guard let fileMD5 = URL.init(fileURLWithPath: imgPath).fileMD5() else {
|
guard let fileMD5 = URL.init(fileURLWithPath: imgPath).fileMD5() else {
|
||||||
ascAPI.addMessage("内购商品截图文件错误:\(imgPath) ,无法生成 md5 值~")
|
ascAPI.addMessage("内购商品截图文件错误:\(imgPath) ,无法生成 md5 值~")
|
||||||
return
|
return
|
||||||
@ -332,16 +333,20 @@ extension APUploadIAPListVC {
|
|||||||
ascAPI.addMessage("内购商品截图创建失败:\(imgName) ,无法删除旧截图~")
|
ascAPI.addMessage("内购商品截图创建失败:\(imgName) ,无法删除旧截图~")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ascAPI.addMessage("创建新的送审截图:\(product.reviewScreenshot)")
|
ascAPI.addMessage("创建新的送审截图:\(uploadFileName)")
|
||||||
// 创建截图
|
// 创建截图
|
||||||
let imaSize = imaUrl.fileSizeInt()
|
let imaSize = imaUrl.fileSizeInt()
|
||||||
guard let shot = await ascAPI.createInAppPurchasesScreenshot(iapId: iapId, fileName: imgName, fileSize: imaSize) else {
|
guard imaSize > 0 else {
|
||||||
|
ascAPI.addMessage("内购商品截图文件错误:\(imgPath) ,文件大小为 0~")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
guard let shot = await ascAPI.createInAppPurchasesScreenshot(iapId: iapId, fileName: uploadFileName, fileSize: imaSize) else {
|
||||||
// 创建失败
|
// 创建失败
|
||||||
ascAPI.addMessage("内购商品:\(product.productId) ,创建送审截图失败!❌ ")
|
ascAPI.addMessage("内购商品:\(product.productId) ,创建送审截图失败!❌ ")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// 根据苹果接口返回的上传接口上传
|
// 根据苹果接口返回的上传接口上传
|
||||||
guard let method = shot.attributes?.uploadOperations?.first?.method,
|
guard let method = shot.attributes?.uploadOperations?.first?.method,
|
||||||
let url = shot.attributes?.uploadOperations?.first?.url,
|
let url = shot.attributes?.uploadOperations?.first?.url,
|
||||||
@ -350,14 +355,14 @@ extension APUploadIAPListVC {
|
|||||||
ascAPI.addMessage("内购商品:\(product.productId) ,创建送审截图失败!苹果参数异常~ ❌ ")
|
ascAPI.addMessage("内购商品:\(product.productId) ,创建送审截图失败!苹果参数异常~ ❌ ")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var request = URLRequest(url: baseURL)
|
var request = URLRequest(url: baseURL)
|
||||||
request.httpMethod = method
|
request.httpMethod = method
|
||||||
for header in requestHeaders {
|
for header in requestHeaders {
|
||||||
request.headers[header.name ?? ""] = header.value ?? ""
|
request.headers[header.name ?? ""] = header.value ?? ""
|
||||||
}
|
}
|
||||||
|
|
||||||
ascAPI.addMessage("上传新的送审截图:\(product.reviewScreenshot)")
|
ascAPI.addMessage("上传新的送审截图:\(uploadFileName)")
|
||||||
// 上传图片
|
// 上传图片
|
||||||
guard let response = try? await URLSession.shared.upload(for: request, fromFile: imaUrl) else {
|
guard let response = try? await URLSession.shared.upload(for: request, fromFile: imaUrl) else {
|
||||||
ascAPI.addMessage("内购商品:\(product.productId) ,创建送审截图失败!上传图片异常~ ❌ ")
|
ascAPI.addMessage("内购商品:\(product.productId) ,创建送审截图失败!上传图片异常~ ❌ ")
|
||||||
@ -367,8 +372,8 @@ extension APUploadIAPListVC {
|
|||||||
ascAPI.addMessage("内购商品:\(product.productId) ,创建送审截图失败!上传图片异常 \(response.1.description)~ ❌ ")
|
ascAPI.addMessage("内购商品:\(product.productId) ,创建送审截图失败!上传图片异常 \(response.1.description)~ ❌ ")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
ascAPI.addMessage("提交新的送审截图:\(product.reviewScreenshot)")
|
ascAPI.addMessage("提交新的送审截图:\(uploadFileName)")
|
||||||
// 确认图片
|
// 确认图片
|
||||||
if ((await ascAPI.updateInAppPurchasesScreenshot(iapShotId: shot.id, fileMD5: fileMD5)) != nil) {
|
if ((await ascAPI.updateInAppPurchasesScreenshot(iapShotId: shot.id, fileMD5: fileMD5)) != nil) {
|
||||||
ascAPI.addMessage("内购商品:\(product.productId) ,送审截图上传成功!✅ ")
|
ascAPI.addMessage("内购商品:\(product.productId) ,送审截图上传成功!✅ ")
|
||||||
@ -376,7 +381,7 @@ extension APUploadIAPListVC {
|
|||||||
ascAPI.addMessage("内购商品:\(product.productId) ,送审截图可能上传失败! ")
|
ascAPI.addMessage("内购商品:\(product.productId) ,送审截图可能上传失败! ")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 销售国家或地区
|
/// 销售国家或地区
|
||||||
func updateIAPAvailableTerritories(iapId: String, product: IAPProduct, ascAPI: APASCAPI) async {
|
func updateIAPAvailableTerritories(iapId: String, product: IAPProduct, ascAPI: APASCAPI) async {
|
||||||
let inAll = product.territories.availableInAllTerritories
|
let inAll = product.territories.availableInAllTerritories
|
||||||
@ -384,7 +389,7 @@ extension APUploadIAPListVC {
|
|||||||
let summary = territoryInfo(product: product)
|
let summary = territoryInfo(product: product)
|
||||||
let newTerritory = inNew ? "将来新国家(地区)时自动提供!" : "将来新国家(地区)时不自动提供!"
|
let newTerritory = inNew ? "将来新国家(地区)时自动提供!" : "将来新国家(地区)时不自动提供!"
|
||||||
ascAPI.addMessage("开始更新内购商品的销售国家/地区:\(summary)")
|
ascAPI.addMessage("开始更新内购商品的销售国家/地区:\(summary)")
|
||||||
|
|
||||||
guard !inAll else {
|
guard !inAll else {
|
||||||
var allTerritories: [[String: String]] = []
|
var allTerritories: [[String: String]] = []
|
||||||
if let territories = await ascAPI.territories() {
|
if let territories = await ascAPI.territories() {
|
||||||
@ -405,7 +410,7 @@ extension APUploadIAPListVC {
|
|||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 选择销售的国家或地区
|
/// 选择销售的国家或地区
|
||||||
var territories: [[String: String]] = []
|
var territories: [[String: String]] = []
|
||||||
product.territories.territories?.forEach({ territory in
|
product.territories.territories?.forEach({ territory in
|
||||||
@ -414,7 +419,7 @@ extension APUploadIAPListVC {
|
|||||||
"id": territory.id
|
"id": territory.id
|
||||||
])
|
])
|
||||||
})
|
})
|
||||||
|
|
||||||
let customerTerritory = product.territories.territories?.map({ $0.id }).joined(separator: ",") ?? "无"
|
let customerTerritory = product.territories.territories?.map({ $0.id }).joined(separator: ",") ?? "无"
|
||||||
if (await ascAPI.updateInAppPurchasesAvailabilityTerritories(iapId: iapId, availableTerritories: territories, availableInNewTerritories: inNew)) != nil {
|
if (await ascAPI.updateInAppPurchasesAvailabilityTerritories(iapId: iapId, availableTerritories: territories, availableInNewTerritories: inNew)) != nil {
|
||||||
ascAPI.addMessage("内购商品的销售国家/地区:\(customerTerritory) ,更新成功!✅ ")
|
ascAPI.addMessage("内购商品的销售国家/地区:\(customerTerritory) ,更新成功!✅ ")
|
||||||
@ -422,10 +427,10 @@ extension APUploadIAPListVC {
|
|||||||
ascAPI.addMessage("内购商品的销售国家/地区:\(customerTerritory) ,更新失败!❌ ")
|
ascAPI.addMessage("内购商品的销售国家/地区:\(customerTerritory) ,更新失败!❌ ")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// MARK: - 上传订阅商品
|
// MARK: - 上传订阅商品
|
||||||
|
|
||||||
/// 订阅商品创建或更新
|
/// 订阅商品创建或更新
|
||||||
func createRenewSubscription(appId: String, product: IAPProduct, ascAPI: APASCAPI) async {
|
func createRenewSubscription(appId: String, product: IAPProduct, ascAPI: APASCAPI) async {
|
||||||
let groupName = product.groupName
|
let groupName = product.groupName
|
||||||
@ -434,46 +439,46 @@ extension APUploadIAPListVC {
|
|||||||
var subGroups = await ascAPI.fetchSubscriptionGroups(appId: appId)
|
var subGroups = await ascAPI.fetchSubscriptionGroups(appId: appId)
|
||||||
// if subGroups.isEmpty {
|
// if subGroups.isEmpty {
|
||||||
// }
|
// }
|
||||||
|
|
||||||
for subGroup in subGroups {
|
for subGroup in subGroups {
|
||||||
if subGroup.attributes?.referenceName == groupName {
|
if subGroup.attributes?.referenceName == groupName {
|
||||||
currentSubGroup = subGroup
|
currentSubGroup = subGroup
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 创建订阅组
|
// 创建订阅组
|
||||||
if currentSubGroup == nil, let group = await ascAPI.createSubscriptionGroups(appId: appId, groupName: groupName) {
|
if currentSubGroup == nil, let group = await ascAPI.createSubscriptionGroups(appId: appId, groupName: groupName) {
|
||||||
currentSubGroup = group
|
currentSubGroup = group
|
||||||
subGroups.append(group)
|
subGroups.append(group)
|
||||||
|
|
||||||
for localization in product.localizations {
|
for localization in product.localizations {
|
||||||
let _ = await ascAPI.createSubscriptionGroupLocalizations(iapGroupId: group.id, name: localization.name, locale: localization.locale, customAppName: nil)
|
let _ = await ascAPI.createSubscriptionGroupLocalizations(iapGroupId: group.id, name: localization.name, locale: localization.locale, customAppName: nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//订阅组设置国际化
|
//订阅组设置国际化
|
||||||
if let group = currentSubGroup {
|
if let group = currentSubGroup {
|
||||||
if let localization = product.groupLocalization {
|
if let localization = product.groupLocalization {
|
||||||
let _ = await ascAPI.createSubscriptionGroupLocalizations(iapGroupId: group.id, name: localization.name, locale: localization.locale, customAppName: nil)
|
let _ = await ascAPI.createSubscriptionGroupLocalizations(iapGroupId: group.id, name: localization.name, locale: localization.locale, customAppName: nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2、有订阅组,获取所有订阅组的所有订阅商品
|
// 2、有订阅组,获取所有订阅组的所有订阅商品
|
||||||
var subscriptions = [ASCSubscription]()
|
var subscriptions = [ASCSubscription]()
|
||||||
for subGroup in subGroups {
|
for subGroup in subGroups {
|
||||||
let subs = await ascAPI.fetchSubscriptionGroupSubscriptions(iapGroupId: subGroup.id)
|
let subs = await ascAPI.fetchSubscriptionGroupSubscriptions(iapGroupId: subGroup.id)
|
||||||
subscriptions.append(contentsOf: subs)
|
subscriptions.append(contentsOf: subs)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// 3、查看是否存在订阅商品,不存在就创建,存在就更新
|
// 3、查看是否存在订阅商品,不存在就创建,存在就更新
|
||||||
let subs = subscriptions.filter({ $0.attributes?.productID == product.productId })
|
let subs = subscriptions.filter({ $0.attributes?.productID == product.productId })
|
||||||
if let sub = subs.first {
|
if let sub = subs.first {
|
||||||
///不做更新
|
///不做更新
|
||||||
ascAPI.addMessage("订阅商品已经存在:\(product.productId) ,跳过更新信息...")
|
ascAPI.addMessage("订阅商品已经存在:\(product.productId) ,跳过更新信息...")
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ascAPI.addMessage("订阅商品已经存在:\(product.productId) ,开始更新信息中...")
|
ascAPI.addMessage("订阅商品已经存在:\(product.productId) ,开始更新信息中...")
|
||||||
// 0. 审核备注如果原来有值,而新字段无值,则使用原值
|
// 0. 审核备注如果原来有值,而新字段无值,则使用原值
|
||||||
var product = product
|
var product = product
|
||||||
@ -486,7 +491,7 @@ extension APUploadIAPListVC {
|
|||||||
ascAPI.addMessage("订阅商品已经存在:\(product.productId) ,更新信息失败!❌ ")
|
ascAPI.addMessage("订阅商品已经存在:\(product.productId) ,更新信息失败!❌ ")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. 商品本地化语言
|
// 2. 商品本地化语言
|
||||||
ascAPI.addMessage("开始更新订阅商品本地化版本:\(product.productId)")
|
ascAPI.addMessage("开始更新订阅商品本地化版本:\(product.productId)")
|
||||||
let localizations = await ascAPI.fetchSubscriptionLocalizations(iapId: iap.id)
|
let localizations = await ascAPI.fetchSubscriptionLocalizations(iapId: iap.id)
|
||||||
@ -508,16 +513,16 @@ extension APUploadIAPListVC {
|
|||||||
await createSubscriptionLocalization(iapId: iap.id, localization: localization, product: product, ascAPI: ascAPI)
|
await createSubscriptionLocalization(iapId: iap.id, localization: localization, product: product, ascAPI: ascAPI)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4. 商品截图
|
// 4. 商品截图
|
||||||
await createSubscriptionScreenshot(iapId: iap.id, product: product, ascAPI: ascAPI)
|
await createSubscriptionScreenshot(iapId: iap.id, product: product, ascAPI: ascAPI)
|
||||||
|
|
||||||
// 5. 销售国家或地区
|
// 5. 销售国家或地区
|
||||||
await updateSubscriptionAvailableTerritories(iapId: iap.id, product: product, ascAPI: ascAPI)
|
await updateSubscriptionAvailableTerritories(iapId: iap.id, product: product, ascAPI: ascAPI)
|
||||||
|
|
||||||
// 3. 商品价格档位
|
// 3. 商品价格档位
|
||||||
await updateSubscriptionPricePoint(iapId: iap.id, product: product, ascAPI: ascAPI)
|
await updateSubscriptionPricePoint(iapId: iap.id, product: product, ascAPI: ascAPI)
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// 1. 创建新的商品
|
// 1. 创建新的商品
|
||||||
guard let iapGroupId = currentSubGroup?.id, let iap = await ascAPI.createSubscription(iapGroupId: iapGroupId, product: product) else {
|
guard let iapGroupId = currentSubGroup?.id, let iap = await ascAPI.createSubscription(iapGroupId: iapGroupId, product: product) else {
|
||||||
@ -525,7 +530,7 @@ extension APUploadIAPListVC {
|
|||||||
ascAPI.addMessage("订阅商品:\(product.productId) ,创建失败!❌ ")
|
ascAPI.addMessage("订阅商品:\(product.productId) ,创建失败!❌ ")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. 商品本地化语言
|
// 2. 商品本地化语言
|
||||||
if let localization = product.subscriptionLocalization {
|
if let localization = product.subscriptionLocalization {
|
||||||
await createSubscriptionLocalization(iapId: iap.id, localization: localization, product: product, ascAPI: ascAPI)
|
await createSubscriptionLocalization(iapId: iap.id, localization: localization, product: product, ascAPI: ascAPI)
|
||||||
@ -533,41 +538,41 @@ extension APUploadIAPListVC {
|
|||||||
// for localization in product.localizations {
|
// for localization in product.localizations {
|
||||||
// await createSubscriptionLocalization(iapId: iap.id, localization: localization, product: product, ascAPI: ascAPI)
|
// await createSubscriptionLocalization(iapId: iap.id, localization: localization, product: product, ascAPI: ascAPI)
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// 4. 商品截图
|
// 4. 商品截图
|
||||||
await createSubscriptionScreenshot(iapId: iap.id, product: product, ascAPI: ascAPI)
|
await createSubscriptionScreenshot(iapId: iap.id, product: product, ascAPI: ascAPI)
|
||||||
|
|
||||||
// 5. 销售国家或地区
|
// 5. 销售国家或地区
|
||||||
await updateSubscriptionAvailableTerritories(iapId: iap.id, product: product, ascAPI: ascAPI)
|
await updateSubscriptionAvailableTerritories(iapId: iap.id, product: product, ascAPI: ascAPI)
|
||||||
|
|
||||||
// 3. 商品价格档位
|
// 3. 商品价格档位
|
||||||
await updateSubscriptionPricePoint(iapId: iap.id, product: product, ascAPI: ascAPI)
|
await updateSubscriptionPricePoint(iapId: iap.id, product: product, ascAPI: ascAPI)
|
||||||
}
|
}
|
||||||
|
|
||||||
ascAPI.addMessage("订阅商品:\(product.productId),\(product.name) ,上传完成!\n")
|
ascAPI.addMessage("订阅商品:\(product.productId),\(product.name) ,上传完成!\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// 更新订阅商品的价格档位
|
/// 更新订阅商品的价格档位
|
||||||
func updateSubscriptionPricePoint(iapId: String, product: IAPProduct, ascAPI: APASCAPI) async {
|
func updateSubscriptionPricePoint(iapId: String, product: IAPProduct, ascAPI: APASCAPI) async {
|
||||||
guard let schedule = product.priceSchedules else {
|
guard let schedule = product.priceSchedules else {
|
||||||
ascAPI.addMessage("无价格计划表:\(product.productId) ,请确认!❌ ")
|
ascAPI.addMessage("无价格计划表:\(product.productId) ,请确认!❌ ")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
let baseTerritory = schedule.baseTerritory
|
let baseTerritory = schedule.baseTerritory
|
||||||
let baseCustomerPrice = schedule.baseCustomerPrice.normalizePrice()
|
let baseCustomerPrice = schedule.baseCustomerPrice.normalizePrice()
|
||||||
|
|
||||||
ascAPI.addMessage("开始更新订阅商品价格点,基准国家:\(product.productId),\(baseTerritory),\(baseCustomerPrice) \n")
|
ascAPI.addMessage("开始更新订阅商品价格点,基准国家:\(product.productId),\(baseTerritory),\(baseCustomerPrice) \n")
|
||||||
|
|
||||||
let isPreservePrice = preserveCurrentPriceBtn.state.rawValue == 1
|
let isPreservePrice = preserveCurrentPriceBtn.state.rawValue == 1
|
||||||
ascAPI.addMessage("保留自动续期订阅者现有定价:\(isPreservePrice ? "是" : "否")")
|
ascAPI.addMessage("保留自动续期订阅者现有定价:\(isPreservePrice ? "是" : "否")")
|
||||||
|
|
||||||
let points = await ascAPI.fetchSubscriptionPricePoints(iapId: iapId, territory: [baseTerritory])
|
let points = await ascAPI.fetchSubscriptionPricePoints(iapId: iapId, territory: [baseTerritory])
|
||||||
if let point = points.filter({ $0.attributes?.customerPrice!.normalizePrice() == baseCustomerPrice }).first {
|
if let point = points.filter({ $0.attributes?.customerPrice!.normalizePrice() == baseCustomerPrice }).first {
|
||||||
|
|
||||||
ascAPI.addMessage("开始更新自定价格:")
|
ascAPI.addMessage("开始更新自定价格:")
|
||||||
// 自定价格的国家或地区, 基准国家也算是自定价格
|
// 自定价格的国家或地区, 基准国家也算是自定价格
|
||||||
var customerPriceSchedules = schedule.manualPrices
|
var customerPriceSchedules = schedule.manualPrices
|
||||||
@ -588,7 +593,7 @@ extension APUploadIAPListVC {
|
|||||||
ascAPI.addMessage("自定价格的订阅商品价格点:\(territory),\(customerPrice) ,未找到此档位!❌ ")
|
ascAPI.addMessage("自定价格的订阅商品价格点:\(territory),\(customerPrice) ,未找到此档位!❌ ")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ascAPI.addMessage("开始更新全球均衡价格:")
|
ascAPI.addMessage("开始更新全球均衡价格:")
|
||||||
// 剩余的所有的国家地区的订阅价格点,然后一个一个设置。API不支持全部国家一次配置
|
// 剩余的所有的国家地区的订阅价格点,然后一个一个设置。API不支持全部国家一次配置
|
||||||
let allPoints = await ascAPI.fetchSubscriptionPricePointsEqualizations(pointId: point.id, territory: nil)
|
let allPoints = await ascAPI.fetchSubscriptionPricePointsEqualizations(pointId: point.id, territory: nil)
|
||||||
@ -612,8 +617,8 @@ extension APUploadIAPListVC {
|
|||||||
ascAPI.addMessage("基准国家的订阅商品价格点:\(baseTerritory),\(baseCustomerPrice) ,未找到此档位!❌ ")
|
ascAPI.addMessage("基准国家的订阅商品价格点:\(baseTerritory),\(baseCustomerPrice) ,未找到此档位!❌ ")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// 更新订阅商品的本地化信息
|
/// 更新订阅商品的本地化信息
|
||||||
func createSubscriptionLocalization(iapId: String, localization: IAPLocalization, product: IAPProduct, ascAPI: APASCAPI) async {
|
func createSubscriptionLocalization(iapId: String, localization: IAPLocalization, product: IAPProduct, ascAPI: APASCAPI) async {
|
||||||
ascAPI.addMessage("开始更新订阅商品本地化版本:\(product.productId),\(localization.locale)")
|
ascAPI.addMessage("开始更新订阅商品本地化版本:\(product.productId),\(localization.locale)")
|
||||||
@ -625,7 +630,7 @@ extension APUploadIAPListVC {
|
|||||||
ascAPI.addMessage("订阅商品本地化版本:\(localization.locale) ,更新语言失败!❌ ")
|
ascAPI.addMessage("订阅商品本地化版本:\(localization.locale) ,更新语言失败!❌ ")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 更新订阅商品的送审截图
|
/// 更新订阅商品的送审截图
|
||||||
func createSubscriptionScreenshot(iapId: String, product: IAPProduct, ascAPI: APASCAPI) async {
|
func createSubscriptionScreenshot(iapId: String, product: IAPProduct, ascAPI: APASCAPI) async {
|
||||||
ascAPI.addMessage("开始更新订阅商品的送审截图:\(product.productId),\(product.reviewScreenshot)")
|
ascAPI.addMessage("开始更新订阅商品的送审截图:\(product.productId),\(product.reviewScreenshot)")
|
||||||
@ -634,8 +639,9 @@ extension APUploadIAPListVC {
|
|||||||
ascAPI.addMessage("订阅商品:\(product.productId) 无送审截图或未上传截图~")
|
ascAPI.addMessage("订阅商品:\(product.productId) 无送审截图或未上传截图~")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
let imaUrl = URL.init(fileURLWithPath: imgPath)
|
let imaUrl = URL.init(fileURLWithPath: imgPath)
|
||||||
|
let uploadFileName = imaUrl.lastPathComponent.isEmpty ? imgName : imaUrl.lastPathComponent
|
||||||
guard let fileMD5 = URL.init(fileURLWithPath: imgPath).fileMD5() else {
|
guard let fileMD5 = URL.init(fileURLWithPath: imgPath).fileMD5() else {
|
||||||
ascAPI.addMessage("订阅商品截图文件错误:\(imgPath) ,无法生成 md5 值~")
|
ascAPI.addMessage("订阅商品截图文件错误:\(imgPath) ,无法生成 md5 值~")
|
||||||
return
|
return
|
||||||
@ -650,16 +656,20 @@ extension APUploadIAPListVC {
|
|||||||
ascAPI.addMessage("订阅商品截图创建失败:\(imgName) ,无法删除旧截图~")
|
ascAPI.addMessage("订阅商品截图创建失败:\(imgName) ,无法删除旧截图~")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ascAPI.addMessage("创建新的送审截图:\(product.reviewScreenshot)")
|
ascAPI.addMessage("创建新的送审截图:\(uploadFileName)")
|
||||||
// 创建截图
|
// 创建截图
|
||||||
let imaSize = imaUrl.fileSizeInt()
|
let imaSize = imaUrl.fileSizeInt()
|
||||||
guard let shot = await ascAPI.createSubscriptionScreenshot(iapId: iapId, fileName: imgName, fileSize: imaSize) else {
|
guard imaSize > 0 else {
|
||||||
|
ascAPI.addMessage("订阅商品截图文件错误:\(imgPath) ,文件大小为 0~")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
guard let shot = await ascAPI.createSubscriptionScreenshot(iapId: iapId, fileName: uploadFileName, fileSize: imaSize) else {
|
||||||
// 创建失败
|
// 创建失败
|
||||||
ascAPI.addMessage("订阅商品:\(product.productId) ,创建送审截图失败!❌ ")
|
ascAPI.addMessage("订阅商品:\(product.productId) ,创建送审截图失败!❌ ")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// 根据苹果接口返回的上传接口上传
|
// 根据苹果接口返回的上传接口上传
|
||||||
guard let method = shot.attributes?.uploadOperations?.first?.method,
|
guard let method = shot.attributes?.uploadOperations?.first?.method,
|
||||||
let url = shot.attributes?.uploadOperations?.first?.url,
|
let url = shot.attributes?.uploadOperations?.first?.url,
|
||||||
@ -668,14 +678,14 @@ extension APUploadIAPListVC {
|
|||||||
ascAPI.addMessage("订阅商品:\(product.productId) ,创建送审截图失败!苹果参数异常~ ❌ ")
|
ascAPI.addMessage("订阅商品:\(product.productId) ,创建送审截图失败!苹果参数异常~ ❌ ")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var request = URLRequest(url: baseURL)
|
var request = URLRequest(url: baseURL)
|
||||||
request.httpMethod = method
|
request.httpMethod = method
|
||||||
for header in requestHeaders {
|
for header in requestHeaders {
|
||||||
request.headers[header.name ?? ""] = header.value ?? ""
|
request.headers[header.name ?? ""] = header.value ?? ""
|
||||||
}
|
}
|
||||||
|
|
||||||
ascAPI.addMessage("上传新的送审截图:\(product.reviewScreenshot)")
|
ascAPI.addMessage("上传新的送审截图:\(uploadFileName)")
|
||||||
// 上传图片
|
// 上传图片
|
||||||
guard let response = try? await URLSession.shared.upload(for: request, fromFile: imaUrl) else {
|
guard let response = try? await URLSession.shared.upload(for: request, fromFile: imaUrl) else {
|
||||||
ascAPI.addMessage("订阅商品:\(product.productId) ,创建送审截图失败!上传图片异常~ ❌ ")
|
ascAPI.addMessage("订阅商品:\(product.productId) ,创建送审截图失败!上传图片异常~ ❌ ")
|
||||||
@ -685,8 +695,8 @@ extension APUploadIAPListVC {
|
|||||||
ascAPI.addMessage("订阅商品:\(product.productId) ,创建送审截图失败!上传图片异常 \(response.1.description)~ ❌ ")
|
ascAPI.addMessage("订阅商品:\(product.productId) ,创建送审截图失败!上传图片异常 \(response.1.description)~ ❌ ")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
ascAPI.addMessage("提交新的送审截图:\(product.reviewScreenshot)")
|
ascAPI.addMessage("提交新的送审截图:\(uploadFileName)")
|
||||||
// 确认图片
|
// 确认图片
|
||||||
if ((await ascAPI.updateSubscriptionScreenshot(iapShotId: shot.id, fileMD5: fileMD5)) != nil) {
|
if ((await ascAPI.updateSubscriptionScreenshot(iapShotId: shot.id, fileMD5: fileMD5)) != nil) {
|
||||||
ascAPI.addMessage("订阅商品:\(product.productId) ,送审截图上传成功!✅ ")
|
ascAPI.addMessage("订阅商品:\(product.productId) ,送审截图上传成功!✅ ")
|
||||||
@ -694,7 +704,7 @@ extension APUploadIAPListVC {
|
|||||||
ascAPI.addMessage("订阅商品:\(product.productId) ,送审截图可能上传失败! ")
|
ascAPI.addMessage("订阅商品:\(product.productId) ,送审截图可能上传失败! ")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 销售国家或地区
|
/// 销售国家或地区
|
||||||
func updateSubscriptionAvailableTerritories(iapId: String, product: IAPProduct, ascAPI: APASCAPI) async {
|
func updateSubscriptionAvailableTerritories(iapId: String, product: IAPProduct, ascAPI: APASCAPI) async {
|
||||||
let inAll = product.territories.availableInAllTerritories
|
let inAll = product.territories.availableInAllTerritories
|
||||||
@ -702,7 +712,7 @@ extension APUploadIAPListVC {
|
|||||||
let summary = territoryInfo(product: product)
|
let summary = territoryInfo(product: product)
|
||||||
let newTerritory = inNew ? "将来新国家(地区)时自动提供!" : "将来新国家(地区)时不自动提供!"
|
let newTerritory = inNew ? "将来新国家(地区)时自动提供!" : "将来新国家(地区)时不自动提供!"
|
||||||
ascAPI.addMessage("开始更新订阅商品的销售国家/地区:\(summary)")
|
ascAPI.addMessage("开始更新订阅商品的销售国家/地区:\(summary)")
|
||||||
|
|
||||||
guard !inAll else {
|
guard !inAll else {
|
||||||
var allTerritories: [[String: String]] = []
|
var allTerritories: [[String: String]] = []
|
||||||
if let territories = await ascAPI.territories() {
|
if let territories = await ascAPI.territories() {
|
||||||
@ -723,7 +733,7 @@ extension APUploadIAPListVC {
|
|||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 选择销售的国家或地区
|
/// 选择销售的国家或地区
|
||||||
var territories: [[String: String]] = []
|
var territories: [[String: String]] = []
|
||||||
product.territories.territories?.forEach({ territory in
|
product.territories.territories?.forEach({ territory in
|
||||||
@ -732,7 +742,7 @@ extension APUploadIAPListVC {
|
|||||||
"id": territory.id
|
"id": territory.id
|
||||||
])
|
])
|
||||||
})
|
})
|
||||||
|
|
||||||
let customerTerritory = product.territories.territories?.map({ $0.id }).joined(separator: ",") ?? "无"
|
let customerTerritory = product.territories.territories?.map({ $0.id }).joined(separator: ",") ?? "无"
|
||||||
if (await ascAPI.updateSubscriptionAvailabilityTerritories(iapId: iapId, availableTerritories: territories, availableInNewTerritories: inNew)) != nil {
|
if (await ascAPI.updateSubscriptionAvailabilityTerritories(iapId: iapId, availableTerritories: territories, availableInNewTerritories: inNew)) != nil {
|
||||||
ascAPI.addMessage("订阅商品的销售国家/地区:\(customerTerritory) ,更新成功!✅ ")
|
ascAPI.addMessage("订阅商品的销售国家/地区:\(customerTerritory) ,更新成功!✅ ")
|
||||||
@ -744,7 +754,7 @@ extension APUploadIAPListVC {
|
|||||||
|
|
||||||
// MARK: - Privacy Method
|
// MARK: - Privacy Method
|
||||||
extension APUploadIAPListVC {
|
extension APUploadIAPListVC {
|
||||||
|
|
||||||
func territoryInfo(product: IAPProduct) -> String {
|
func territoryInfo(product: IAPProduct) -> String {
|
||||||
let inAll = product.territories.availableInAllTerritories
|
let inAll = product.territories.availableInAllTerritories
|
||||||
let inNew = product.territories.availableInNewTerritories
|
let inNew = product.territories.availableInNewTerritories
|
||||||
@ -762,7 +772,7 @@ extension APUploadIAPListVC: NSTableViewDelegate, NSTableViewDataSource {
|
|||||||
func numberOfRows(in tableView: NSTableView) -> Int {
|
func numberOfRows(in tableView: NSTableView) -> Int {
|
||||||
return iaps.count
|
return iaps.count
|
||||||
}
|
}
|
||||||
|
|
||||||
func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
|
func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
|
||||||
let iap = iaps[row]
|
let iap = iaps[row]
|
||||||
switch tableColumn?.identifier.enumValue() {
|
switch tableColumn?.identifier.enumValue() {
|
||||||
@ -815,7 +825,7 @@ extension APUploadIAPListVC: NSTableViewDelegate, NSTableViewDataSource {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func tableView(_ tableView: NSTableView, heightOfRow row: Int) -> CGFloat {
|
func tableView(_ tableView: NSTableView, heightOfRow row: Int) -> CGFloat {
|
||||||
let prices = iaps[row].priceSchedules?.manualPrices.count ?? 0
|
let prices = iaps[row].priceSchedules?.manualPrices.count ?? 0
|
||||||
let count = max(prices + 2, 3)
|
let count = max(prices + 2, 3)
|
||||||
|
|||||||
@ -34,14 +34,14 @@ typealias ASCSubscriptionAvailability = AppStoreConnect_Swift_SDK.SubscriptionAv
|
|||||||
|
|
||||||
|
|
||||||
class APASCAPI {
|
class APASCAPI {
|
||||||
|
|
||||||
public var updateMsg: (([String])->Void)?
|
public var updateMsg: (([String])->Void)?
|
||||||
private var message = [String]() {
|
private var message = [String]() {
|
||||||
didSet {
|
didSet {
|
||||||
updateMsg?(message)
|
updateMsg?(message)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 日志文件保存路径
|
// 日志文件保存路径
|
||||||
private let date = Date()
|
private let date = Date()
|
||||||
var logPath: String {
|
var logPath: String {
|
||||||
@ -52,14 +52,14 @@ class APASCAPI {
|
|||||||
return "/AppleParty/ASCAPI/log_\(currentDate).txt"
|
return "/AppleParty/ASCAPI/log_\(currentDate).txt"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Go to https://appstoreconnect.apple.com/access/api and create your own key. This is also the page to find the private key ID and the issuer ID.
|
/// Go to https://appstoreconnect.apple.com/access/api and create your own key. This is also the page to find the private key ID and the issuer ID.
|
||||||
/// Download the private key and open it in a text editor. Remove the enters and copy the contents over to the private key parameter.
|
/// Download the private key and open it in a text editor. Remove the enters and copy the contents over to the private key parameter.
|
||||||
//private let configuration = APIConfiguration(issuerID: "<YOUR ISSUER ID>", privateKeyID: "<YOUR PRIVATE KEY ID>", privateKey: "<YOUR PRIVATE KEY>")
|
//private let configuration = APIConfiguration(issuerID: "<YOUR ISSUER ID>", privateKeyID: "<YOUR PRIVATE KEY ID>", privateKey: "<YOUR PRIVATE KEY>")
|
||||||
//private lazy var provider: APIProvider = APIProvider(configuration: configuration)
|
//private lazy var provider: APIProvider = APIProvider(configuration: configuration)
|
||||||
private var provider: APIProvider?
|
private var provider: APIProvider?
|
||||||
private var rateLimitPublisher: AnyCancellable?
|
private var rateLimitPublisher: AnyCancellable?
|
||||||
|
|
||||||
init(issuerID: String, privateKeyID: String, privateKey: String, showApiRateLimit: Bool) {
|
init(issuerID: String, privateKeyID: String, privateKey: String, showApiRateLimit: Bool) {
|
||||||
do {
|
do {
|
||||||
let configuration = try APIConfiguration(issuerID: issuerID, privateKeyID: privateKeyID, privateKey: privateKey)
|
let configuration = try APIConfiguration(issuerID: issuerID, privateKeyID: privateKeyID, privateKey: privateKey)
|
||||||
@ -73,7 +73,7 @@ class APASCAPI {
|
|||||||
handleError("初始化失败: \(error.localizedDescription)")
|
handleError("初始化失败: \(error.localizedDescription)")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 获取所有 app
|
/// 获取所有 app
|
||||||
/// - Returns: apps
|
/// - Returns: apps
|
||||||
func apps() async -> [ASCApp]? {
|
func apps() async -> [ASCApp]? {
|
||||||
@ -97,7 +97,7 @@ class APASCAPI {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 获取所有 App Store 支持的国家或地区
|
/// 获取所有 App Store 支持的国家或地区
|
||||||
/// - Returns: apps
|
/// - Returns: apps
|
||||||
func territories() async -> [ASCTerritory]? {
|
func territories() async -> [ASCTerritory]? {
|
||||||
@ -117,9 +117,9 @@ class APASCAPI {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - 非续期订阅类型内购 API
|
// MARK: - 非续期订阅类型内购 API
|
||||||
|
|
||||||
/// 获取 app 所有的商品信息
|
/// 获取 app 所有的商品信息
|
||||||
/// - Parameter appId: apple id
|
/// - Parameter appId: apple id
|
||||||
/// - Returns: 商品列表
|
/// - Returns: 商品列表
|
||||||
@ -141,9 +141,9 @@ class APASCAPI {
|
|||||||
handleError("获取内购列表失败: \(error.localizedDescription)")
|
handleError("获取内购列表失败: \(error.localizedDescription)")
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 创建内购商品
|
/// 创建内购商品
|
||||||
/// - Parameters:
|
/// - Parameters:
|
||||||
/// - appId: apple id
|
/// - appId: apple id
|
||||||
@ -172,7 +172,7 @@ class APASCAPI {
|
|||||||
"type": "inAppPurchases"
|
"type": "inAppPurchases"
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
|
|
||||||
do {
|
do {
|
||||||
guard let provider = provider else {
|
guard let provider = provider else {
|
||||||
return nil
|
return nil
|
||||||
@ -190,7 +190,7 @@ class APASCAPI {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// 修改内购商品
|
/// 修改内购商品
|
||||||
/// - Parameters:
|
/// - Parameters:
|
||||||
/// - iapId: 内购商品 id
|
/// - iapId: 内购商品 id
|
||||||
@ -209,7 +209,7 @@ class APASCAPI {
|
|||||||
"type": "inAppPurchases"
|
"type": "inAppPurchases"
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
|
|
||||||
do {
|
do {
|
||||||
guard let provider = provider else {
|
guard let provider = provider else {
|
||||||
return nil
|
return nil
|
||||||
@ -227,7 +227,7 @@ class APASCAPI {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// 删除内购商品
|
/// 删除内购商品
|
||||||
/// - Parameters:
|
/// - Parameters:
|
||||||
/// - iapId: 内购商品 id
|
/// - iapId: 内购商品 id
|
||||||
@ -248,8 +248,8 @@ class APASCAPI {
|
|||||||
}
|
}
|
||||||
return 400
|
return 400
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// 获取内购商品价格档位
|
/// 获取内购商品价格档位
|
||||||
/// - Parameters:
|
/// - Parameters:
|
||||||
/// - iapId: 内购商品 id
|
/// - iapId: 内购商品 id
|
||||||
@ -276,8 +276,8 @@ class APASCAPI {
|
|||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// 构建一个价格计划表
|
/// 构建一个价格计划表
|
||||||
/// - Parameters:
|
/// - Parameters:
|
||||||
/// - scheduleId: 价格计划表 id
|
/// - scheduleId: 价格计划表 id
|
||||||
@ -308,8 +308,8 @@ class APASCAPI {
|
|||||||
]
|
]
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// 修改内购商品价格档位
|
/// 修改内购商品价格档位
|
||||||
/// - Parameters:
|
/// - Parameters:
|
||||||
/// - iapId: 内购商品 id
|
/// - iapId: 内购商品 id
|
||||||
@ -371,7 +371,7 @@ class APASCAPI {
|
|||||||
// ]
|
// ]
|
||||||
// ]
|
// ]
|
||||||
]
|
]
|
||||||
|
|
||||||
do {
|
do {
|
||||||
guard let provider = provider else {
|
guard let provider = provider else {
|
||||||
return nil
|
return nil
|
||||||
@ -388,8 +388,8 @@ class APASCAPI {
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// 获取内购商品本地化信息
|
/// 获取内购商品本地化信息
|
||||||
/// - Parameters:
|
/// - Parameters:
|
||||||
/// - iapId: 内购商品 id
|
/// - iapId: 内购商品 id
|
||||||
@ -413,8 +413,8 @@ class APASCAPI {
|
|||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// 创建内购商品本地化
|
/// 创建内购商品本地化
|
||||||
/// - Parameters:
|
/// - Parameters:
|
||||||
/// - iapId: 内购商品 id
|
/// - iapId: 内购商品 id
|
||||||
@ -439,7 +439,7 @@ class APASCAPI {
|
|||||||
"type": "inAppPurchaseLocalizations"
|
"type": "inAppPurchaseLocalizations"
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
|
|
||||||
do {
|
do {
|
||||||
guard let provider = provider else {
|
guard let provider = provider else {
|
||||||
return nil
|
return nil
|
||||||
@ -457,7 +457,7 @@ class APASCAPI {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// 修改内购商品本地化信息
|
/// 修改内购商品本地化信息
|
||||||
/// - Parameters:
|
/// - Parameters:
|
||||||
/// - iapLocaleId: 内购商品本地化语言 id
|
/// - iapLocaleId: 内购商品本地化语言 id
|
||||||
@ -491,7 +491,7 @@ class APASCAPI {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// 删除内购商品本地化
|
/// 删除内购商品本地化
|
||||||
/// - Parameters:
|
/// - Parameters:
|
||||||
/// - iapLocaleId: 内购商品本地化语言 id
|
/// - iapLocaleId: 内购商品本地化语言 id
|
||||||
@ -512,8 +512,8 @@ class APASCAPI {
|
|||||||
}
|
}
|
||||||
return 400
|
return 400
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// 获取内购商品的送审截屏
|
/// 获取内购商品的送审截屏
|
||||||
/// - Parameter iapId: 内购商品 id
|
/// - Parameter iapId: 内购商品 id
|
||||||
/// - Returns: 返回内购商品的截图信息
|
/// - Returns: 返回内购商品的截图信息
|
||||||
@ -530,7 +530,7 @@ class APASCAPI {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 创建内购商品的送审截屏
|
/// 创建内购商品的送审截屏
|
||||||
/// - Parameters:
|
/// - Parameters:
|
||||||
/// - iapId: 内购商品 id
|
/// - iapId: 内购商品 id
|
||||||
@ -555,7 +555,7 @@ class APASCAPI {
|
|||||||
"type": "inAppPurchaseAppStoreReviewScreenshots"
|
"type": "inAppPurchaseAppStoreReviewScreenshots"
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
|
|
||||||
do {
|
do {
|
||||||
guard let provider = provider else {
|
guard let provider = provider else {
|
||||||
return nil
|
return nil
|
||||||
@ -572,8 +572,8 @@ class APASCAPI {
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// 确认内购商品的送审截屏
|
/// 确认内购商品的送审截屏
|
||||||
/// - Parameters:
|
/// - Parameters:
|
||||||
/// - iapShotId: 内购商品截屏 id
|
/// - iapShotId: 内购商品截屏 id
|
||||||
@ -590,7 +590,7 @@ class APASCAPI {
|
|||||||
"type": "inAppPurchaseAppStoreReviewScreenshots"
|
"type": "inAppPurchaseAppStoreReviewScreenshots"
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
|
|
||||||
do {
|
do {
|
||||||
guard let provider = provider else {
|
guard let provider = provider else {
|
||||||
return nil
|
return nil
|
||||||
@ -607,7 +607,7 @@ class APASCAPI {
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 删除内购商品的送审截屏
|
/// 删除内购商品的送审截屏
|
||||||
/// - Parameters:
|
/// - Parameters:
|
||||||
/// - iapShotId: 内购商品截屏 id
|
/// - iapShotId: 内购商品截屏 id
|
||||||
@ -628,8 +628,8 @@ class APASCAPI {
|
|||||||
}
|
}
|
||||||
return 400
|
return 400
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// 修改内购商品的销售范围
|
/// 修改内购商品的销售范围
|
||||||
/// - Parameters:
|
/// - Parameters:
|
||||||
/// - iapId: 内购商品 id
|
/// - iapId: 内购商品 id
|
||||||
@ -662,7 +662,7 @@ class APASCAPI {
|
|||||||
]
|
]
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
|
|
||||||
do {
|
do {
|
||||||
guard let provider = provider else {
|
guard let provider = provider else {
|
||||||
return nil
|
return nil
|
||||||
@ -679,11 +679,11 @@ class APASCAPI {
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// MARK: - 续期订阅类商品 API
|
// MARK: - 续期订阅类商品 API
|
||||||
|
|
||||||
|
|
||||||
/// 获取所有订阅组
|
/// 获取所有订阅组
|
||||||
/// - Parameters:
|
/// - Parameters:
|
||||||
/// - appId: apple id
|
/// - appId: apple id
|
||||||
@ -707,8 +707,8 @@ class APASCAPI {
|
|||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// 创建订阅组
|
/// 创建订阅组
|
||||||
/// - Parameters:
|
/// - Parameters:
|
||||||
/// - appId: apple id
|
/// - appId: apple id
|
||||||
@ -731,7 +731,7 @@ class APASCAPI {
|
|||||||
"type": "subscriptionGroups"
|
"type": "subscriptionGroups"
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
|
|
||||||
do {
|
do {
|
||||||
guard let provider = provider else {
|
guard let provider = provider else {
|
||||||
return nil
|
return nil
|
||||||
@ -748,8 +748,8 @@ class APASCAPI {
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// 获取所有订阅组的本地化信息
|
/// 获取所有订阅组的本地化信息
|
||||||
/// - Parameters:
|
/// - Parameters:
|
||||||
/// - iapGroupId: 订阅组 id
|
/// - iapGroupId: 订阅组 id
|
||||||
@ -773,8 +773,8 @@ class APASCAPI {
|
|||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// 创建订阅组本地化信息
|
/// 创建订阅组本地化信息
|
||||||
/// - Parameters:
|
/// - Parameters:
|
||||||
/// - iapGroupId: 订阅组 id
|
/// - iapGroupId: 订阅组 id
|
||||||
@ -801,7 +801,7 @@ class APASCAPI {
|
|||||||
"type": "subscriptionGroupLocalizations"
|
"type": "subscriptionGroupLocalizations"
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
|
|
||||||
do {
|
do {
|
||||||
guard let provider = provider else {
|
guard let provider = provider else {
|
||||||
return nil
|
return nil
|
||||||
@ -818,8 +818,8 @@ class APASCAPI {
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// 获取订阅组下所有内购商品
|
/// 获取订阅组下所有内购商品
|
||||||
/// - Parameters:
|
/// - Parameters:
|
||||||
/// - appId: apple id
|
/// - appId: apple id
|
||||||
@ -843,8 +843,8 @@ class APASCAPI {
|
|||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// 创建订阅商品
|
/// 创建订阅商品
|
||||||
/// - Parameters:
|
/// - Parameters:
|
||||||
/// - iapGroupId: apple id
|
/// - iapGroupId: apple id
|
||||||
@ -873,7 +873,7 @@ class APASCAPI {
|
|||||||
"type": "subscriptions"
|
"type": "subscriptions"
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
|
|
||||||
do {
|
do {
|
||||||
guard let provider = provider else {
|
guard let provider = provider else {
|
||||||
return nil
|
return nil
|
||||||
@ -890,8 +890,8 @@ class APASCAPI {
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func updateSubscription(iapId: String, product: IAPProduct) async -> ASCSubscription? {
|
func updateSubscription(iapId: String, product: IAPProduct) async -> ASCSubscription? {
|
||||||
let body = [
|
let body = [
|
||||||
"data": [
|
"data": [
|
||||||
@ -923,8 +923,8 @@ class APASCAPI {
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// 获取订阅商品本地化信息
|
/// 获取订阅商品本地化信息
|
||||||
/// - Parameters:
|
/// - Parameters:
|
||||||
/// - iapId: 内购商品 id
|
/// - iapId: 内购商品 id
|
||||||
@ -949,8 +949,8 @@ class APASCAPI {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// 创建订阅商品本地化
|
/// 创建订阅商品本地化
|
||||||
/// - Parameters:
|
/// - Parameters:
|
||||||
/// - iapId: 内购商品 id
|
/// - iapId: 内购商品 id
|
||||||
@ -975,7 +975,7 @@ class APASCAPI {
|
|||||||
"type": "subscriptionLocalizations"
|
"type": "subscriptionLocalizations"
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
|
|
||||||
do {
|
do {
|
||||||
guard let provider = provider else {
|
guard let provider = provider else {
|
||||||
return nil
|
return nil
|
||||||
@ -993,7 +993,7 @@ class APASCAPI {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// 修改订阅商品本地化信息
|
/// 修改订阅商品本地化信息
|
||||||
/// - Parameters:
|
/// - Parameters:
|
||||||
/// - iapLocaleId: 内购商品本地化语言 id
|
/// - iapLocaleId: 内购商品本地化语言 id
|
||||||
@ -1027,8 +1027,8 @@ class APASCAPI {
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// 获取订阅商品价格档位
|
/// 获取订阅商品价格档位
|
||||||
/// - Parameters:
|
/// - Parameters:
|
||||||
/// - iapId: 内购商品 id
|
/// - iapId: 内购商品 id
|
||||||
@ -1055,8 +1055,8 @@ class APASCAPI {
|
|||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// 获取订阅商品价格档位的等价价格
|
/// 获取订阅商品价格档位的等价价格
|
||||||
/// - Parameters:
|
/// - Parameters:
|
||||||
/// - pointId: 内购价格档位 id
|
/// - pointId: 内购价格档位 id
|
||||||
@ -1083,8 +1083,8 @@ class APASCAPI {
|
|||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// 修改订阅商品价格档位
|
/// 修改订阅商品价格档位
|
||||||
/// - Parameters:
|
/// - Parameters:
|
||||||
/// - iapId: 内购商品 id
|
/// - iapId: 内购商品 id
|
||||||
@ -1115,7 +1115,7 @@ class APASCAPI {
|
|||||||
]
|
]
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
|
|
||||||
do {
|
do {
|
||||||
guard let provider = provider else {
|
guard let provider = provider else {
|
||||||
return nil
|
return nil
|
||||||
@ -1132,8 +1132,8 @@ class APASCAPI {
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// 获取订阅商品的送审截屏
|
/// 获取订阅商品的送审截屏
|
||||||
func fetchSubscriptionScreenshot(iapId: String) async -> ASCSubscriptionScreenshot? {
|
func fetchSubscriptionScreenshot(iapId: String) async -> ASCSubscriptionScreenshot? {
|
||||||
let request = APIEndpoint.v1.subscriptions.id(iapId).appStoreReviewScreenshot.get()
|
let request = APIEndpoint.v1.subscriptions.id(iapId).appStoreReviewScreenshot.get()
|
||||||
@ -1143,12 +1143,23 @@ class APASCAPI {
|
|||||||
}
|
}
|
||||||
let shot = try await provider.request(request).data
|
let shot = try await provider.request(request).data
|
||||||
return shot
|
return shot
|
||||||
|
} catch APIProvider.Error.decodingError(let decodeError, let data) {
|
||||||
|
if let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any],
|
||||||
|
json["data"] is NSNull {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
let err = APIProvider.Error.decodingError(decodeError, data)
|
||||||
|
handleError("获取订阅商品的送审截图异常: \(err.localizedDescription)")
|
||||||
|
return nil
|
||||||
|
} catch APIProvider.Error.requestFailure(let statusCode, let errorResponse, _) {
|
||||||
|
handleRequestFailure(statusCode, errorResponse)
|
||||||
|
return nil
|
||||||
} catch {
|
} catch {
|
||||||
handleError("获取订阅商品的送审截图异常: \(error.localizedDescription)")
|
handleError("获取订阅商品的送审截图异常: \(error.localizedDescription)")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 创建订阅商品的送审截屏
|
/// 创建订阅商品的送审截屏
|
||||||
func createSubscriptionScreenshot(iapId: String, fileName: String, fileSize: Int) async -> ASCSubscriptionScreenshot? {
|
func createSubscriptionScreenshot(iapId: String, fileName: String, fileSize: Int) async -> ASCSubscriptionScreenshot? {
|
||||||
let body = [
|
let body = [
|
||||||
@ -1203,7 +1214,7 @@ class APASCAPI {
|
|||||||
"type": "subscriptionAppStoreReviewScreenshots"
|
"type": "subscriptionAppStoreReviewScreenshots"
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
|
|
||||||
do {
|
do {
|
||||||
guard let provider = provider else {
|
guard let provider = provider else {
|
||||||
return nil
|
return nil
|
||||||
@ -1220,7 +1231,7 @@ class APASCAPI {
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 删除订阅商品的送审截屏
|
/// 删除订阅商品的送审截屏
|
||||||
/// - Parameters:
|
/// - Parameters:
|
||||||
/// - iapShotId: 内购商品截屏 id
|
/// - iapShotId: 内购商品截屏 id
|
||||||
@ -1241,8 +1252,8 @@ class APASCAPI {
|
|||||||
}
|
}
|
||||||
return 400
|
return 400
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// 修改订阅商品的销售范围
|
/// 修改订阅商品的销售范围
|
||||||
/// - Parameters:
|
/// - Parameters:
|
||||||
/// - iapId: 内购商品 id
|
/// - iapId: 内购商品 id
|
||||||
@ -1275,7 +1286,7 @@ class APASCAPI {
|
|||||||
]
|
]
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
|
|
||||||
do {
|
do {
|
||||||
guard let provider = provider else {
|
guard let provider = provider else {
|
||||||
return nil
|
return nil
|
||||||
@ -1297,30 +1308,30 @@ class APASCAPI {
|
|||||||
|
|
||||||
// MARK: - handle log
|
// MARK: - handle log
|
||||||
extension APASCAPI {
|
extension APASCAPI {
|
||||||
|
|
||||||
func handleRequestFailure(_ statusCode: Int, _ errorResponse: ErrorResponse?) {
|
func handleRequestFailure(_ statusCode: Int, _ errorResponse: ErrorResponse?) {
|
||||||
print("Request failed with statuscode: \(statusCode) and the following errors:")
|
print("Request failed with statuscode: \(statusCode) and the following errors:")
|
||||||
errorResponse?.errors?.forEach({ error in
|
errorResponse?.errors?.forEach({ error in
|
||||||
handleError("Error code: \(error.code), title: \(error.title), detail: \(String(describing: error.detail))")
|
handleError("Error code: \(error.code), title: \(error.title), detail: \(String(describing: error.detail))")
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleError(_ msg: String) {
|
func handleError(_ msg: String) {
|
||||||
addMessage(msg)
|
addMessage(msg)
|
||||||
print(msg)
|
print(msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
func addMessage(_ msg: String) {
|
func addMessage(_ msg: String) {
|
||||||
let dateFormatter : DateFormatter = DateFormatter()
|
let dateFormatter : DateFormatter = DateFormatter()
|
||||||
dateFormatter.dateFormat = "[MM-dd HH:mm:ss] "
|
dateFormatter.dateFormat = "[MM-dd HH:mm:ss] "
|
||||||
let currentDateString = dateFormatter.string(from: Date())
|
let currentDateString = dateFormatter.string(from: Date())
|
||||||
let log = currentDateString + msg
|
let log = currentDateString + msg
|
||||||
message.append(log)
|
message.append(log)
|
||||||
|
|
||||||
// 本地保存
|
// 本地保存
|
||||||
saveLogs(log: log)
|
saveLogs(log: log)
|
||||||
}
|
}
|
||||||
|
|
||||||
func saveLogs(log: String, retry: Int = 3) {
|
func saveLogs(log: String, retry: Int = 3) {
|
||||||
do {
|
do {
|
||||||
try log.appendLine(to: logPath.createFilePath)
|
try log.appendLine(to: logPath.createFilePath)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user