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