1
This commit is contained in:
@@ -0,0 +1,116 @@
|
||||
//
|
||||
// ProductConverter.swift
|
||||
// StoreKit2Manager
|
||||
//
|
||||
// Created by xiaopin on 2025/12/6.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import StoreKit
|
||||
|
||||
/// Product 转换器
|
||||
/// 将 Product 对象转换为可序列化的基础数据类型(Dictionary/JSON)
|
||||
public struct ProductConverter {
|
||||
|
||||
/// 将 Product 转换为 Dictionary(可序列化为 JSON)
|
||||
/// - Parameter product: Product 对象
|
||||
/// - Returns: Dictionary 对象,包含所有产品信息
|
||||
public static func toDictionary(_ product: Product) -> [String: Any] {
|
||||
var dict: [String: Any] = [:]
|
||||
|
||||
// 基本信息(确保都是字符串类型)
|
||||
dict["id"] = product.id
|
||||
dict["displayName"] = product.displayName
|
||||
dict["description"] = product.description
|
||||
|
||||
// 价格信息
|
||||
let priceDecimal = product.price
|
||||
let priceDouble = NSDecimalNumber(decimal: priceDecimal).doubleValue
|
||||
dict["price"] = Double(String(format: "%.2f", priceDouble)) ?? priceDouble
|
||||
dict["displayPrice"] = product.displayPrice
|
||||
|
||||
// 产品类型
|
||||
dict["type"] = productTypeToString(product.type)
|
||||
|
||||
// 家庭共享
|
||||
dict["isFamilyShareable"] = product.isFamilyShareable
|
||||
|
||||
// JSON 表示(可选,可能很大,通常用于服务器验证)
|
||||
// 注意:jsonRepresentation 是 Data 类型,转换为 Base64 字符串以便 JSON 序列化
|
||||
let jsonData = product.jsonRepresentation
|
||||
if let jsonString = String(data: jsonData, encoding: .utf8) {
|
||||
dict["jsonRepresentation"] = jsonString
|
||||
} else {
|
||||
dict["jsonRepresentation"] = ""
|
||||
}
|
||||
|
||||
// 订阅信息(如果有)
|
||||
if let subscription = product.subscription {
|
||||
dict["subscription"] = SubscriptionConverter.subscriptionInfoToDictionary(subscription, product: product)
|
||||
} else {
|
||||
dict["subscription"] = NSNull()
|
||||
}
|
||||
|
||||
return dict
|
||||
}
|
||||
|
||||
/// 将 Product 数组转换为 Dictionary 数组
|
||||
/// - Parameter products: Product 数组
|
||||
/// - Returns: Dictionary 数组
|
||||
public static func toDictionaryArray(_ products: [Product]) -> [[String: Any]] {
|
||||
return products.map { toDictionary($0) }
|
||||
}
|
||||
|
||||
/// 将 Product 转换为 JSON 字符串
|
||||
/// - Parameter product: Product 对象
|
||||
/// - Returns: JSON 字符串
|
||||
public static func toJSONString(_ product: Product) -> String? {
|
||||
let dict = toDictionary(product)
|
||||
return dictionaryToJSONString(dict)
|
||||
}
|
||||
|
||||
/// 将 Product 数组转换为 JSON 字符串
|
||||
/// - Parameter products: Product 数组
|
||||
/// - Returns: JSON 字符串
|
||||
public static func toJSONString(_ products: [Product]) -> String? {
|
||||
let array = toDictionaryArray(products)
|
||||
return arrayToJSONString(array)
|
||||
}
|
||||
|
||||
// MARK: - 私有方法
|
||||
|
||||
/// 产品类型转字符串
|
||||
private static func productTypeToString(_ type: Product.ProductType) -> String {
|
||||
switch type {
|
||||
case .consumable:
|
||||
return "consumable"
|
||||
case .nonConsumable:
|
||||
return "nonConsumable"
|
||||
case .autoRenewable:
|
||||
return "autoRenewable"
|
||||
case .nonRenewable:
|
||||
return "nonRenewable"
|
||||
default:
|
||||
return "unknown"
|
||||
}
|
||||
}
|
||||
|
||||
/// Dictionary 转 JSON 字符串
|
||||
internal static func dictionaryToJSONString(_ dict: [String: Any]) -> String? {
|
||||
guard let jsonData = try? JSONSerialization.data(withJSONObject: dict, options: .prettyPrinted),
|
||||
let jsonString = String(data: jsonData, encoding: .utf8) else {
|
||||
return nil
|
||||
}
|
||||
return jsonString
|
||||
}
|
||||
|
||||
/// Array 转 JSON 字符串
|
||||
internal static func arrayToJSONString(_ array: [[String: Any]]) -> String? {
|
||||
guard let jsonData = try? JSONSerialization.data(withJSONObject: array, options: .prettyPrinted),
|
||||
let jsonString = String(data: jsonData, encoding: .utf8) else {
|
||||
return nil
|
||||
}
|
||||
return jsonString
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user