How to get local currency for SKProduct | Show IAP price in Swift

I'm trying to display the purchase price of the application in local currency, so the correct dollar is displayed for both the USA and the USA, as well as for the euro, GBP, etc.

I know that every SKProduct has a price that appears during the transaction as a warning, this appears when the purchase is confirmed.

However, I want to show the price before confirmation.

I was thinking of doing something like this:

//Products Array var productsArray: Array<SKProduct!> = [] //Request Products func productsRequest(request: SKProductsRequest, didReceiveResponse response: SKProductsResponse) { if response.products.count != 0 { for product in response.products { print("\(product.localizedTitle)") productsArray.append(product) } } else { print("There are no products.") } if response.invalidProductIdentifiers.count != 0 { print("\(response.invalidProductIdentifiers.description)") } } let item = SKProduct for i in productsArray { if i.localizedTitle == "com.Company.App.item1" item = i } } 

But this does not work as i It seems that it does not have a price property.

Does anyone know how I can set the label text to the iAP price using the correct local currency?

For example, £ 1.49 GBP is $ 1.99 using an apple-based pricing matrix, and the output should match the product price values ​​when confirming the transaction.

+14
source share
5 answers

Swift 5 and version 2019:

Creating an extension for SKProduct so that you can access it conveniently, for example, like this: fetchedProduct.localizedPrice . Here is the code

 extension SKProduct { fileprivate static var formatter: NumberFormatter { let formatter = NumberFormatter() formatter.numberStyle = .currency return formatter } var localizedPrice: String { if self.price == 0.00 { return "Get" } else { let formatter = SKProduct.formatter formatter.locale = self.priceLocale guard let formattedPrice = formatter.string(from: self.price)else { return "Unknown Price" } return formattedPrice } } } 

Original Anser:

Swift 4.2 Olivier answer version

 func priceStringForProduct(item: SKProduct) -> String? { let price = item.price if price == NSDecimalNumber(decimal: 0.00) { return "GET" //or whatever you like really... maybe 'Free' } else { let numberFormatter = NumberFormatter() let locale = item.priceLocale numberFormatter.numberStyle = .currency numberFormatter.locale = locale return numberFormatter.string(from: price) } } 
+4
source

you must use NSNumberFormatter with product values ​​for price and priceLocale to output a string that is formatted correctly regardless of the user's location. product.price returns the price in local currency as NSDecimalNumber, and product.productLocale returns NSLocale for the price value.

eg,

 var item = SKProduct() for i in productsArray { if i.productIdentifier == "com.Company.App.item1" { item = i if let formattedPrice = priceStringForProduct(item) { //update ui with price } } } 

where priceStringForProduct is a function defined elsewhere: -

 func priceStringForProduct(item: SKProduct) -> String? { let numberFormatter = NSNumberFormatter() let price = item.price let locale = item.priceLocale numberFormatter.numberStyle = .CurrencyStyle numberFormatter.locale = locale return numberFormatter.stringFromNumber(price) } 

You can also handle a special case when the price is 0.0 (free level). In this case, change the priceStringForProduct function to:

 func priceStringForProduct(item: SKProduct) -> String? { let price = item.price if price == NSDecimalNumber(float: 0.0) { return "GET" //or whatever you like really... maybe 'Free' } else { let numberFormatter = NSNumberFormatter() let locale = item.priceLocale numberFormatter.numberStyle = .CurrencyStyle numberFormatter.locale = locale return numberFormatter.stringFromNumber(price) } } 

Edit: add other things when you specify your product array in a more “faster” way:

 var productsArray = [SKProduct]() 

and then in your didRecieveResponse, instead of iterating over products, you can simply specify productsArray as response.products

 var productsArray = [SKProduct]() if response.products.count != 0 { print("\(response.products.map {p -> String in return p.localizedTitle})") productsArray = response.products } 

Edit: to test several different locales, I usually make an array of NSLocales, and then print the result cyclically. There is a repo with all the localeIdentifiers here

So:

 let testPrice = NSDecimalNumber(float: 1.99) let localeArray = [NSLocale(localeIdentifier: "uz_Latn"), NSLocale(localeIdentifier: "en_BZ"), NSLocale(localeIdentifier: "nyn_UG"), NSLocale(localeIdentifier: "ebu_KE"), NSLocale(localeIdentifier: "en_JM"), NSLocale(localeIdentifier: "en_US")] /*I got these at random from the link above, pick the countries you expect to operate in*/ for locale in localeArray { let numberFormatter = NSNumberFormatter() numberFormatter.numberStyle = .CurrencyStyle numberFormatter.locale = locale print(numberFormatter.stringFromNumber(testPrice)) } 
+18
source

The StoreKit Programming Guide provides a code snippet for displaying prices in App Store currency:

 NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init]; [numberFormatter setFormatterBehavior:NSNumberFormatterBehavior10_4]; [numberFormatter setNumberStyle:NSNumberFormatterCurrencyStyle]; [numberFormatter setLocale:product.priceLocale]; NSString *formattedPrice = [numberFormatter stringFromNumber:product.price]; 

https://developer.apple.com/library/content/documentation/NetworkingInternet/Conceptual/StoreKitGuide/Chapters/ShowUI.html Listing 2-3

+6
source

You MUST NOT display the price in local currency. You must display it in the currency provided by the store. If we say that a French user buys from a French application store, then the price appears in euros, and this is what the user pays. If this user travels to New Zealand and changes their language to New Zealand but stays with the French app store, they are still paid in euros. So what should you display.

You say, "1.49 pounds is $ 1.99 per Apple pricing matrix." But 1.49 pounds is not $ 1.99. If I, as a British user, travel to the United States and buy from an app store in the UK, I pay £ 1.49, even if I'm in the United States. And "£ 1.49" is what the store tells you.

+4
source

Swift 3 version Olivier priceStringForProduct:item

 func priceStringForProduct(item: SKProduct) -> String? { let price = item.price if price == 0 { return "Free!" //or whatever you like } else { let numberFormatter = NumberFormatter() let locale = item.priceLocale numberFormatter.numberStyle = .currency numberFormatter.locale = locale return numberFormatter.string(from: price) } } 
+1
source

Source: https://habr.com/ru/post/1247721/


All Articles