iOS 應(yīng)用內(nèi)購(gòu)買的推介優(yōu)惠翼虫、促銷優(yōu)惠屑柔、優(yōu)惠代碼的處理

蘋(píng)果應(yīng)用內(nèi)購(gòu)買的自動(dòng)續(xù)訂訂閱,主要有三種優(yōu)惠方式珍剑,三種可以同時(shí)提供掸宛。

  • 推介優(yōu)惠(Introductory Offers)
  • 促銷優(yōu)惠(Promotional Offers)
  • 優(yōu)惠代碼(Offer Codes)

其中促銷優(yōu)惠(Promotional Offer)是蘋(píng)果在 2019 年出的一種促銷優(yōu)惠方案。

最近開(kāi)發(fā)的時(shí)候發(fā)現(xiàn)招拙,網(wǎng)上幾乎沒(méi)有相關(guān)的文章唧瘾,所以記錄一下,方便其他人更快地實(shí)現(xiàn)别凤。
文章中提到的一些文檔和鏈接都可以在最后一章“附錄”中找到饰序。
關(guān)于應(yīng)用內(nèi)購(gòu)買,可以查看我另一篇文章 iOS In-App Purchase(IAP) 流程與實(shí)現(xiàn)规哪。

一求豫、三種優(yōu)惠的區(qū)別

蘋(píng)果在文檔中介紹了幾種優(yōu)惠的區(qū)別:

優(yōu)惠對(duì)比中英.jpg

跟產(chǎn)品溝通時(shí),需要了解產(chǎn)品想要的是哪種優(yōu)惠。網(wǎng)上對(duì)三種優(yōu)惠的翻譯都各不相同蝠嘉。

二最疆、實(shí)現(xiàn)

下面主要講下客戶端的實(shí)現(xiàn),服務(wù)端可以參考其他文檔蚤告。

2.1 配置

蘋(píng)果官方文檔已經(jīng)詳細(xì)說(shuō)明了如何配置和各種配置的注意點(diǎn)努酸,這里就不再贅述和截圖說(shuō)明了。

對(duì)于促銷優(yōu)惠杜恰,需要生成購(gòu)買項(xiàng)目密鑰(文檔中有說(shuō)明)获诈,然后下載私有密鑰,后續(xù)需要用到心褐。只能下載一次烙荷,請(qǐng)妥善保管已下載的密鑰。

2.2 客戶端開(kāi)發(fā)

2.2.1 推介優(yōu)惠

是否享有推介優(yōu)惠檬寂,是由蘋(píng)果根據(jù) Apple 賬號(hào)決定的终抽。
不同產(chǎn)品希望的享有邏輯會(huì)不同,根據(jù)產(chǎn)品策略不同桶至,會(huì)有不一樣的開(kāi)發(fā)流程昼伴。

我們是最簡(jiǎn)單的場(chǎng)景,新用戶都可以享受到推介優(yōu)惠镣屹,不處理用戶切換 Apple 賬號(hào)的場(chǎng)景圃郊。
客戶端不用開(kāi)發(fā),配置后女蜈,點(diǎn)擊購(gòu)買持舆,系統(tǒng)的購(gòu)買彈窗上就會(huì)顯示出優(yōu)惠信息。復(fù)雜的業(yè)務(wù)邏輯在后端伪窖。

試用三天

2.2.2 促銷優(yōu)惠

購(gòu)買商品時(shí)可以傳入商品支持的訂閱優(yōu)惠逸寓,在支付彈窗中就會(huì)顯示相關(guān)信息。

2.2.2.1 生成優(yōu)惠 SKPaymentDiscount

購(gòu)買商品時(shí)覆山,需要先生成一個(gè)優(yōu)惠 SKPaymentDiscount竹伸。我們看下 SKPaymentDiscount 的初始化方法:

public init(identifier: String, keyIdentifier: String, nonce: UUID, signature: String, timestamp: NSNumber)

初始化方法中需要幾個(gè)字段:

  1. identifier
    A string used to uniquely identify a discount offer for a product.
    優(yōu)惠 ID,蘋(píng)果后臺(tái)新建的優(yōu)惠最后的字段
    在 APP - 分發(fā) - 營(yíng)利(訂閱)- 點(diǎn)擊訂閱組 - 點(diǎn)擊某個(gè)訂閱 - 訂閱價(jià)格(有效的訂閱優(yōu)惠)- 點(diǎn)擊優(yōu)惠

  2. keyIdentifier
    A string that identifies the key used to generate the signature.
    密鑰ID簇宽,蘋(píng)果后臺(tái)新建的密鑰的ID
    在 用戶和訪問(wèn) - 集成 - 密鑰(APP 內(nèi)購(gòu)買項(xiàng)目)- 密鑰 ID

  3. nonce
    A universally unique ID (UUID) value that you define.
    UUID勋篓,服務(wù)器生成
    這種格式 58780c93-31e0-4a21-af9c-a34fec006c73。python 里是調(diào)用 uuid.uuid4()魏割。

  4. signature
    A string representing the properties of a specific promotional offer, cryptographically signed.
    簽名譬嚣,服務(wù)器生成

  5. timestamp
    The date and time of the signature's creation in milliseconds, formatted in Unix epoch time.
    服務(wù)器時(shí)間戳,單位毫秒

let discount = SKPaymentDiscount(identifier: xxx, keyIdentifier: xxx, nonce: xxx, signature: xxx, timestamp: NSNumber(integerLiteral: xxx))
  • 使用 python 生成簽名進(jìn)行自測(cè)

先將上一章提到的“私有密鑰”(SubscriptionKey_XXXXXXXXXX.p8)從 .p8 格式轉(zhuǎn)成 .der 格式:

openssl pkcs8 -nocrypt -in SubscriptionKey_xxxxxxxx.p8 -out cert.der -outform der

再將以下 python 腳本保存在同個(gè)目錄中钞它,修改其中的 bundle_id拜银、key_id殊鞭、productoffer盐股、application_username 并執(zhí)行。

腳本來(lái)自參考的文章耻卡,新增和修改了部分注釋

# pip3 install ecdsa

import json
import uuid
import time
import hashlib
import base64

from ecdsa import SigningKey
from ecdsa.util import sigencode_der

bundle_id = 'com.xxx.xxx' # bundle ID
key_id = 'XXXXXXXXXX' # 私鑰 ID
product = 'sp_3' # 訂閱商品 ID
offer = '3day_test' # 優(yōu)惠 ID
application_username = '' # Should be the same you use when making purchases
nonce = uuid.uuid4()
timestamp = int(round(time.time() * 1000))

payload = '\u2063'.join([bundle_id,
                        key_id,
                        product,
                        offer,
                        application_username,
                        str(nonce), # Should be lower case
                        str(timestamp)])

# Read the key file
with open('cert.der', 'rb') as myfile:
  der = myfile.read()
signing_key = SigningKey.from_der(der)
signature = signing_key.sign(payload.encode('utf-8'),
                            hashfunc=hashlib.sha256,
                            sigencode=sigencode_der)
encoded_signature = base64.b64encode(signature)
print(str(encoded_signature, 'utf-8'), str(nonce), str(timestamp), key_id)

控制臺(tái)打印結(jié)果中疯汁,第一個(gè)為簽名,第二個(gè)為 nonce卵酪,第三個(gè)為 timestamp幌蚊,第四個(gè)為 私鑰 ID。此時(shí)將所有信息寫(xiě)死在代碼中就可以自測(cè)購(gòu)買流程了溃卡。

2.2.2.2 使用優(yōu)惠購(gòu)買

/// StoreKit
let payment = SKMutablePayment(product: product)
payment.applicationUsername = usernameHash
payment.paymentDiscount = discountOffer

SKPaymentQueue.default().add(payment)

/// SwiftyStoreKit
SwiftyStoreKit.purchaseProduct(product, quantity: 1, paymentDiscount: paymentDiscount, completion: { [weak self] result in
                                   
})

其中 product 需要自行去獲取溢豆,下面是使用 StoreKit 和 SwiftyStoreKit 去獲取的代碼:

/// StoreKit
let productRequest = SKProductsRequest(productIdentifiers: Set<String>(arrayLiteral: productId))
productRequest.delegate = self
productRequest.start()

extension XXX: SKProductsRequestDelegate {
    func productsRequest(request: SKProductsRequest, didReceiveResponse response: SKProductsResponse) {
        if let product = response.products.first { /// 獲取返回的商品

        }
    }
}

/// SwiftyStoreKit
SwiftyStoreKit.retrieveProductsInfo([productId], completion: { result in

    if let product = result.retrievedProducts.first {

    }
})

2.2.3 優(yōu)惠代碼

優(yōu)惠代碼比較簡(jiǎn)單,就不贅述瘸羡,附錄中有官方的相關(guān)文檔可以查閱漩仙。

三、附錄

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末犹赖,一起剝皮案震驚了整個(gè)濱河市队他,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌峻村,老刑警劉巖麸折,帶你破解...
    沈念sama閱讀 219,427評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異粘昨,居然都是意外死亡垢啼,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,551評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門张肾,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)芭析,“玉大人,你說(shuō)我怎么就攤上這事吞瞪》排伲” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,747評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵尸饺,是天一觀的道長(zhǎng)进统。 經(jīng)常有香客問(wèn)我,道長(zhǎng)浪听,這世上最難降的妖魔是什么螟碎? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,939評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮迹栓,結(jié)果婚禮上掉分,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好酥郭,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,955評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布华坦。 她就那樣靜靜地躺著,像睡著了一般不从。 火紅的嫁衣襯著肌膚如雪惜姐。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,737評(píng)論 1 305
  • 那天椿息,我揣著相機(jī)與錄音歹袁,去河邊找鬼。 笑死寝优,一個(gè)胖子當(dāng)著我的面吹牛条舔,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播乏矾,決...
    沈念sama閱讀 40,448評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼孟抗,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了钻心?” 一聲冷哼從身側(cè)響起夸浅,我...
    開(kāi)封第一講書(shū)人閱讀 39,352評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎扔役,沒(méi)想到半個(gè)月后帆喇,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,834評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡亿胸,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,992評(píng)論 3 338
  • 正文 我和宋清朗相戀三年坯钦,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片侈玄。...
    茶點(diǎn)故事閱讀 40,133評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡婉刀,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出序仙,到底是詐尸還是另有隱情突颊,我是刑警寧澤,帶...
    沈念sama閱讀 35,815評(píng)論 5 346
  • 正文 年R本政府宣布潘悼,位于F島的核電站律秃,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏治唤。R本人自食惡果不足惜棒动,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,477評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望宾添。 院中可真熱鬧船惨,春花似錦柜裸、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,022評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至怜浅,卻和暖如春铐然,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背海雪。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,147評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工锦爵, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留舱殿,地道東北人奥裸。 一個(gè)月前我還...
    沈念sama閱讀 48,398評(píng)論 3 373
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像沪袭,于是被迫代替她去往敵國(guó)和親湾宙。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,077評(píng)論 2 355