StoreKit2的currencyCode獲取問題
我們在內購的時候,需要將countryCode、currencyCode、price這幾個參數(shù)讀取后發(fā)給后臺,用于貨幣校驗、價格校驗及統(tǒng)計。
StoreKit2有個坑爹的地方,就是在21年出來的時候,蘋果沒有提供currencyCode的API。
新的API可以直接獲取currencyCode
22年的時候終于出了一個API,可以通過下面的方式讀取countryCode
let products = try await Product.products(for: [productId])
let currencyCode = products.last?.priceFormatStyle.currencyCode
但是,這個新出的API并不能在Xcode13上編譯通過,只能在Xcode14及以上版本編譯通過。而目前開發(fā)使用的是Xcode13。
并且,蘋果提示這個API如果在iOS16之前使用(就是iOS15)在某些情況下可能出現(xiàn)一些問題(主要是StoreKit Testing和出現(xiàn)嚴重的服務器錯誤時)。
Product {
/// The format style to use when formatting numbers derived from the price for the product.
///
/// Use `displayPrice` when possible. Use `priceFormatStyle` only for localizing numbers
/// derived from the `price` property, such as "2 products for $(`price * 2`)".
/// - Important: When using `priceFormatStyle` on systems earlier than iOS 16.0,
/// macOS 13.0, tvOS 16.0 or watchOS 9.0, the property may return a format style
/// with a sentinel locale with identifier "xx\_XX" in some uncommon cases:
/// (1) StoreKit Testing in Xcode (workaround: test your app on a device running a
/// more recent OS) or (2) a critical server error.
@available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *)
public var priceFormatStyle: Decimal.FormatStyle.Currency { get }
總的來說,因為目前開發(fā)的Xcode版本較低導致的編譯無法通過,所以我們需要嘗試尋找另外的方法來獲取currencyCode。
從Product的jsonRepresentation里面獲取currencyCode
其實蘋果本身是可以拿到currencyCode的,因為獲取商品信息成功之后,我們直接打印可以看到一個json,里面有我們需要的currencyCode。
let products = try await Product.products(for: [productId])
print("product=\(products.last!)")
以下為打印出來的內容(已脫敏處理):
product={
"attributes" : {
"description" : {
"standard" : "????,800?? ??"
},
"icuLocale" : "en_TW@currency=TWD",
"isFamilyShareable" : 0,
"isMerchandisedEnabled" : 0,
"isMerchandisedVisibleByDefault" : 0,
"isSubscription" : 0,
"kind" : "Consumable",
"name" : "800??",
"offerName" : "kr.app.gold1",
"offers" : [
{
"assets" : [
],
"buyParams" : "productType=A&price=330000&salableAdamId=1531111111&pricingParameters=STDQ&pg=default",
"currencyCode" : "TWD",
"price" : 330,
"priceFormatted" : "NT$330.00",
"type" : "buy"
}
],
"releaseDate" : "2009-06-17",
"url" : "https://sandbox.itunes.apple.com/tw/app/800%EC%9B%90%EB%B3%B4/id1531111111?l=en"
},
"href" : "/v1/catalog/tw/in-apps/153111111?l=en-GB",
"id" : "153111111",
"type" : "in-apps"
}
可以看到1. icuLocale的值里面有currency相關內容,2. offers數(shù)組里面也有一個currencyCode參數(shù)。
那么,我們拿到這個json之后,再去讀取里面相關的內容,不就可以獲取到我們想要的currencyCode了?
這個json其實在product的jsonRepresentation屬性里面,我們轉化一下就可以拿到。
于是,我們通過下面的代碼可以拿到我們想要的currencyCode
let products = try await Product.products(for: [productId])
let product = products.last
// data->JSON->Dictionry
let decoded = try? JSONSerialization.jsonObject(with: product!.jsonRepresentation, options: [])
let jsonDict = decoded as? [String: Any] ?? [:]
let attributes = jsonDict["attributes"] as? [String: Any]
let offers = attributes?["offers"] as? [[String: Any]]
// 直接獲取currencyCode(目前采用了這種方案)
let currencyCode = offers?.first?["currencyCode"] as? String
print("currencyCode=\(currencyCode)")
// 獲取icuLocale字符串,然后截取字符串拿到currencyCode(略,目前未采用這種方案)
let icuLocale = attributes?["icuLocale"]
print("icuLocale=\(icuLocale)")
目前我們就是使用這種方案來獲取currencyCode的。目前已上線,并沒有出現(xiàn)什么問題,后續(xù)會繼續(xù)進行觀察。
但是這種方案畢竟不是官方提供的,里面的JSON格式可能會出現(xiàn)改變,所以,這種方案其實是有風險的。但是,以目前的情況來說,不失為一種好方案。
使用Storekit1來獲取currencyCode
StoreKit2獲取不到,但是StoreKit1肯定是可以拿到的,所以,有些人會使用StoreKit1來獲取currencyCode。
這種不失為一個好方案,但是這個API需要走一個網(wǎng)絡請求,相對較為耗時。
//獲取商品信息
NSSet *pidSets = [NSSet setWithObject:productId];
SKProductsRequest *request = [[SKProductsRequest alloc] initWithProductIdentifiers:pidSets];
request.delegate = self;
[request start];
#pragma mark - 獲取商品信息成功后回調
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response
{
SKProduct *product = [response.products lastObject];
NSLocale *priceLocale = product.priceLocale;
//獲取本地貨幣簡碼
NSString *currencyCode = nil;
if (@available(iOS 10.0,*)) {
currencyCode = priceLocale.currencyCode;
} else {
currencyCode = [[priceLocale.localeIdentifier componentsSeparatedByString:@"="] lastObject];
}
NSLog(@"currencyCode=%@",currencyCode);
}
總結
總的來說,StoreKit2獲取貨幣碼currencyCode的方案有3個:
1.使用priceFormatStyle.currencyCode進行獲取。官方API,但是需要Xcode14才能編譯通過。在2023.4之后推薦使用(那時候最低使用Xcode14)。
2.使用product的jsonRepresentation屬性,通過解析json的方式獲取。適配Xcode13和iOS15,如果未更新Xcode到14及以上,是較好的方案。缺點是非官方推薦方式,后續(xù)json里面的內容可能會有改動導致出錯。
3.使用StoreKit1的API獲取。好處是方案比較成熟,缺點是較為耗時,而且在StoreKit2里面使用,不太和諧。
推薦方案:
使用Xcode14的開發(fā)建議直接使用方案一。
目前不少開發(fā)仍在使用Xcode13,所以使用Xcode13的開發(fā)建議使用方案二。
另外可以嘗試iOS15使用方案二,iOS16及以上使用方案一(對于這樣做是否更好,未驗證過)。