最近一年的工作重心都在海外订阅项目上。ROI数据还不错,所以AB测试越做越多。
近期要实现一个根据国家和地区来下发不同的SKU的需求。记录一下。
判断用户的国家和地区可以简化为判断用户Apple ID的地区,也就是App Store地区。
上次和Apple交流,问了这个为问题。告知并没有提供相关API,原因是你App所选的销售地区就是你内购提供的地区,用户可以转区,转区后所订阅的项目也能在新地区提供。
但是我记得WWDC 2019中,介绍了一个iOS13新增的API,可以监听App Store地区的变化。
WWDC详见:
《In-App Purchases and Using Server-to-Server Notifications》
新增的API是SKStorefront
SKStorefront
官方文档见:
https://developer.apple.com/documentation/storekit/skstorefront
获取地区代码
if |
注意有可能为nil
countryCode使用的是ISO 3166-1 Alpha-3代码
SKStorefront还可以通过paymentQueueDidChangeStorefront
监听App Store地区的变化
func paymentQueueDidChangeStorefront(_ queue: SKPaymentQueue) { |
Apple官方文档说SKStorefront随时可能变化,甚至是在购买过程中,因此新增了一个代理方法paymentQueue:shouldContinueTransaction:inStorefront:
此方法的作用是在购买时候发生SKStorefront变化,可以判断要不要继续执行这个Transaction。
SKPaymentQueue.default().delegate = self // Set your object as the SKPaymentQueue delegate. |
如果此地区不支持购买paymentQueue:shouldContinueTransaction:inStorefront:
返回false
。在Transaction回调中就会收到一个SKErrorStoreProductNotAvailable
的Error信息
func paymentQueue(_ queue: SKPaymentQueue, |
但是SKStorefront
只支持iOS13+,并不满足我们的需求。因此还要想别的办法。
通用做法
我们的需求是根据国家和地区,下发不同比例的SKU,不存在这个SKU只在这个地区销售的情况。因为订阅类型的SKU,用户可以在订阅管理里面切换套餐
我的做法是从SKU价格处理入手,因为我们是海外项目,在全球销售。所以要要呈现用户所在地区的价格和货币。可以通过NumberFormatter
进行转换
let formatter = NumberFormatter.init()
formatter.formatterBehavior = NumberFormatter.Behavior.behavior10_4
formatter.numberStyle = NumberFormatter.Style.currency
//SKProduct中有priceLocale
formatter.locale = product!.priceLocale
let price :String = formatter.string(from: self.product!.price) ?? "$4.99"
从上述代码可以看到,SKProduct中有个priceLocale
属性,赋值给NumberFormatter后可以对价格进行处理。
priceLocale是Local类型(OC中是NSLocal)
Local中有identifier
、regionCode
等属性。regionCode
代表的就是地区,可能为nil,identifier
是标识符,是一个字符串。
下图是App Store切换到澳大利亚地区,打印的结果
下图是美国
但是regionCode可能为nil,所以要做下判断,当regionCode为nil时候使用identifier,或者跟着业务逻辑调整。
identifier的格式一般是都是固定的,可以根据@符分割,拿到前面的语言_地区
的值。
如何快速切换App Store地区可以看我之前写的这篇文章《iOS开发中一些小工具》 使用Switcher这个工具。安装地址:http://switchr.imagility.io/
这个办法必须先获取一个可用的SKProduct
,并不能在请求SKProduct
之前拿到地区。所以还是有一定的局限性。
我一般是在productsRequest:didReceiveResponse:
回调中,拿到一个SKProduct
获取到地区后就存起来。有个这个参数也可以在埋点上报中用到,标明用户的App Store地区。