欧美free性护士vide0shd,老熟女,一区二区三区,久久久久夜夜夜精品国产,久久久久久综合网天天,欧美成人护士h版

首頁綜合 正文
目錄

柚子快報(bào)邀請(qǐng)碼778899分享:iOS

柚子快報(bào)邀請(qǐng)碼778899分享:iOS

http://yzkb.51969.com/

iOS蘋果內(nèi)購詳細(xì)步驟

iOS開發(fā)支付的兩種方式1 Apple Pay + 調(diào)取外部支付,例如支付寶、微信、銀聯(lián)等2 蘋果內(nèi)購IAP(In-App Purchase)

1 IAP規(guī)則詳解1.1 適用范圍1.2 IAP類型1.2.1 Consumable products (消耗型商品)1.2.2 Non-consumable products(非消耗型商品)1.2.3 Non-renewable subscriptions(非續(xù)期訂閱)1.2.4 Auto-renewable subscriptions(自動(dòng)續(xù)期訂閱)1.2.4.1 Free subscriptions(免費(fèi)訂閱)

1.3 定價(jià)1.4 分成1.5 結(jié)算

2 IAP設(shè)計(jì)開發(fā)要點(diǎn)2.1 創(chuàng)建和提交IAP項(xiàng)目2.1.1 盡量不要?jiǎng)h除已創(chuàng)建的IAP2.1.2 注意區(qū)分reference name和display name2.1.3 當(dāng)App審核被拒時(shí)

2.2 IAP支付流程2.3 不能忽視的坑2.3.1 延遲返回支付結(jié)果2.3.2 服務(wù)端校驗(yàn)延遲2.3.3 非官方渠道包支付失敗問題2.3.4 貨幣校驗(yàn)2.3.5 未綁定App Store支付方式的用戶支付流程

3 更多IAP實(shí)踐經(jīng)驗(yàn)總結(jié)3.1 匿名購買3.2 跨平臺(tái)同步3.3 虛擬幣3.4 退款問題3.5 支付成功率3.6 作弊行為

4 代碼集成4.1 引入頭文件4.2 遵循兩個(gè)代理4.3 開啟內(nèi)購檢測4.4 設(shè)置內(nèi)購點(diǎn)擊事件4.5 請(qǐng)求商品,獲取商品信息,以及代理4.6 沙盒測試環(huán)境驗(yàn)證以及正式環(huán)境

5 IAP QA測試幫助6 App Store協(xié)議、稅務(wù)和銀行業(yè)務(wù)6.1 登錄iTunes Connect6.2 選擇申請(qǐng)合同類型6.3 申請(qǐng)iOS Paid Application合同6.4 添加銀行賬戶6.5 報(bào)稅(跟咱沒啥關(guān)系,但還是要填)6.5.1 填寫稅務(wù)信息6.5.2 填寫聯(lián)系信息,如果是個(gè)人開發(fā)者就全寫自己

6.6 等待審核

iOS開發(fā)支付的兩種方式

1 Apple Pay + 調(diào)取外部支付,例如支付寶、微信、銀聯(lián)等

什么是Apple Pay?

簡單說是一種“支付工具”。對(duì)于國外流行信用卡,Apple Pay很符合美國的國情。但對(duì)于中國,微信支付、支付寶支付更加便利符合中國的人的行為習(xí)慣。 說到這你可能就理解了,Apple Pay,就是類比支付寶類似的線上線下支付工具。 Apple Pay和 支付寶、微信一樣主要針對(duì)現(xiàn)實(shí)現(xiàn)金交易。當(dāng)然也存在平臺(tái)支持虛擬產(chǎn)品支付。例如淘寶平臺(tái)出售虛擬物品,電話費(fèi)、游戲卡等等。但這不屬于蘋果內(nèi)購范疇。

當(dāng)然對(duì)于我們的自己的App,我們可以接入多種支付方式。

2 蘋果內(nèi)購IAP(In-App Purchase)

什么是內(nèi)購?

如果你購買的商品,是在本app中使用和消耗的,就一定要用內(nèi)購,否則會(huì)被拒絕上線,例如:游戲幣,在線書籍,app中使用的道具等虛擬產(chǎn)品。如果購買的就是普通的商品,例如淘寶買東西等,就不需要用內(nèi)購。內(nèi)購的話,蘋果公司需要抽取30%左右傭金。

蘋果內(nèi)購價(jià)格表中的實(shí)際收入是動(dòng)態(tài)變化的,會(huì)根據(jù)稅收變化而發(fā)生改變,一般蘋果會(huì)收取30%左右的金額。但是表格里邊的價(jià)格和等級(jí)一般是不變的。

當(dāng)然,打賞功能被納入內(nèi)購項(xiàng)目中。所以例如微信打賞功能、直播項(xiàng)目打賞主播都必須采用內(nèi)購。

可以簡單理解成,帶有內(nèi)購功能的項(xiàng)目以后的成本會(huì)比安卓、PC端高出30%成本。 內(nèi)購使用場景:愛奇藝APP購買會(huì)員,QQ斗地主里面的充值QB等。 支付彈窗圖標(biāo)、價(jià)格、詳情等都需要到https://developer.apple.com里面去設(shè)置。具體下面會(huì)講到。

項(xiàng)目積分購買課程需使用內(nèi)購方式,因此本文將按照政策規(guī)則、代碼集成+丟包處理、稅務(wù)填寫銀行賬號(hào)信息等方面詳細(xì)介紹IAP

1 IAP規(guī)則詳解

本文所述IAP(In-App Purchase),特指蘋果App Store的應(yīng)用內(nèi)購買,是蘋果為App內(nèi)購買虛擬商品或服務(wù)提供的一套交易系統(tǒng)。 首先來討論一下IAP的基本規(guī)則以及其中的一些要點(diǎn):

1.1 適用范圍

在App內(nèi)需要付費(fèi)使用的產(chǎn)品功能或虛擬商品/服務(wù),如游戲道具、電子書、音樂、視頻、訂閱會(huì)員、App的高級(jí)功能等。App內(nèi)購買實(shí)體商品(如淘寶買衣服)不適用IAP,不在App內(nèi)使用的虛擬商品(如充話費(fèi))或服務(wù)(如滴滴叫車)也不適用IAP。 那么問題來了,假如在App內(nèi)購買一個(gè)音樂專輯,既能在App里面聽數(shù)字專輯,同時(shí)也能獲得實(shí)體商品cd,適不適用IAP呢? 答案是適用的。因?yàn)锳pp內(nèi)的數(shù)字專輯和實(shí)體商品cd在使用上是可以分離的,數(shù)字專輯符合IAP的適用范圍,購買就要用IAP。否則各種游戲里面賣648的道具,都聲稱商品不僅包含游戲道具,購買后還能獲得一個(gè)5毛錢的實(shí)體紀(jì)念品(舉例),就直接繞過IAP,蘋果豈不完蛋? 蘋果規(guī)定,適用范圍內(nèi)的虛擬商品或服務(wù),必須使用IAP購買支付,不允許使用支付寶、微信支付等其它支付方式(包括Apple Pay),也不允許以任何方式(包括跳出App、提示文案等)引導(dǎo)用戶通過應(yīng)用外部渠道購買。原則上蘋果也不允許通過外部兌換碼等方式在應(yīng)用內(nèi)解鎖虛擬商品或服務(wù),但實(shí)際上兌換碼的限制是有些模糊的,因?yàn)橛行〢pp可以在應(yīng)用內(nèi)獲得兌換碼(比如活動(dòng)發(fā)放優(yōu)惠券或簽到獎(jiǎng)勵(lì)),很難嚴(yán)格界定是一個(gè)外部兌換碼還是內(nèi)容兌換碼。因此,在IAP購買中使用優(yōu)惠券抵扣一般情況下是允許的,但如果很明顯地引導(dǎo)用戶在App外購買兌換碼,再在App內(nèi)兌換成虛擬商品或服務(wù),是會(huì)被蘋果Reject的。另外在App Store Review Guidelines 3.1.4 里面還有這樣一條特殊規(guī)則:

“App features that work in combination with an approved physical product (such as a toy) on an optional basis may unlock functionality without using IAP, provided that an IAP option is available as well.”

意思就是說,用戶在App內(nèi)購買一個(gè)功能,而這個(gè)功能需要和一個(gè)實(shí)體商品結(jié)合起來使用,這種情況下,允許使用IAP之外的方式來解鎖功能,但前提是仍然需要提供IAP購買的選項(xiàng)。比如用戶在一個(gè)健康管理App內(nèi)購買一個(gè)高級(jí)計(jì)步器功能,但這個(gè)計(jì)步器功能需要跟手環(huán)配合使用,要和手環(huán)打包購買。這個(gè)情況下,App可以在IAP購買的選項(xiàng)基礎(chǔ)上,再提供其它的購買方式。但現(xiàn)實(shí)中好像并見過沒有這樣的案例。因?yàn)锳pp完全可以把計(jì)步器變成免費(fèi)功能,只是沒有手環(huán)不起實(shí)際作用,然后把手環(huán)當(dāng)成是一個(gè)在App外使用的實(shí)體商品,這樣跟IAP就沒有半毛錢關(guān)系了。誰沒事找事還把這個(gè)東西做成IAP還要給蘋果分成啊~另外還有一些跨平臺(tái)同步的復(fù)雜案例,在本文的第三部分再進(jìn)一步介紹。

1.2 IAP類型

如前面說的,IAP是一套商品交易系統(tǒng),而非簡單的支付系統(tǒng)。每一個(gè)購買項(xiàng)目都需要在App的itunes connect后臺(tái)創(chuàng)建一個(gè)商品,提交給蘋果審核,審核通過后,購買項(xiàng)目才會(huì)生效。在創(chuàng)建IAP商品時(shí),主要有4種類型可供選擇:

1.2.1 Consumable products (消耗型商品)

該類型適用于可多次購買的消耗型項(xiàng)目,如游戲道具、虛擬幣等。

1.2.2 Non-consumable products(非消耗型商品)

該類型適用于一次購買永久有效的項(xiàng)目,如電子書、游戲關(guān)卡等。該類型項(xiàng)目支持跨設(shè)備同步和本地restore,比如說,用戶在某個(gè)App中購買了一本書,可在所有相同Apple ID設(shè)備的App中免費(fèi)獲取這本書,而不要需要借助App本身的帳號(hào)體系,即使在App中刪除了這本書,也可免費(fèi)重新獲取。

1.2.3 Non-renewable subscriptions(非續(xù)期訂閱)

該類型適用于固定有效期的非自動(dòng)續(xù)費(fèi)項(xiàng)目,如云音樂的會(huì)員和一些視頻App的會(huì)員。沒有跨設(shè)備同步和本地restore機(jī)制,用戶可以多次購買。

1.2.4 Auto-renewable subscriptions(自動(dòng)續(xù)期訂閱)

該類型適用于自動(dòng)續(xù)費(fèi)的訂閱項(xiàng)目,如Apple Music的按月訂閱,用戶購買后會(huì)每月自動(dòng)續(xù)費(fèi),直到用戶手動(dòng)取消或者開發(fā)者下架IAP項(xiàng)目。類似Non-consumable products,該類型也支持跨設(shè)備同步和本地restore機(jī)制。之前這種類型只支持newsstand類別(報(bào)刊雜志)的App,從2016年6月開始支持所有類型的App,但除了newsstand類別之外,國內(nèi)的App很少使用這種類型的內(nèi)購。

1.2.4.1 Free subscriptions(免費(fèi)訂閱)

該類型是Auto-renewable subscriptions的一個(gè)特例,適用于免費(fèi)的訂閱項(xiàng)目,僅支持newsstand類別的App,同樣支持跨設(shè)備同步和本地restore機(jī)制。 《In-App Purchase Programming Guide》詳細(xì)說明了各種類型的適用范圍和特性。

其中需要特別注意的是:

1 針對(duì)Non-consumable products類型的IAP項(xiàng)目,蘋果會(huì)要求App提供一個(gè)“恢復(fù)購買”的功能,以支持跨設(shè)備同步和本地restore。同時(shí),如果App本身有用戶帳號(hào)系統(tǒng),那么用戶只要付費(fèi)一次,就可以通過restore機(jī)制將IAP項(xiàng)目無限復(fù)制到多個(gè)用戶帳號(hào)下。 因此,對(duì)于類似電子書之類的一次購買永久有效的項(xiàng)目,如果希望使用App本身的用戶帳號(hào)系統(tǒng),避開跨設(shè)備同步和本地restore機(jī)制,可以考慮選擇Non-renewable subscriptions類型。同時(shí),考慮到Non-renewable subscriptions一般是有固定有效期的,可以加一個(gè)無限長的有效期(比如9999天),以應(yīng)對(duì)蘋果審核。2 Consumable products和Non-renewable subscriptions都是可以重復(fù)購買的IAP項(xiàng)目,前者更偏向消耗品,后者更偏向訂閱品。另外還有一個(gè)區(qū)別是,針對(duì)Non-renewable subscriptions的IAP項(xiàng)目,用戶如果之前已經(jīng)買過一次,過期后再次購買或者切換App帳號(hào)后購買,支付流程中會(huì)出現(xiàn)一個(gè)系統(tǒng)彈窗提示用戶之前已經(jīng)購買過該項(xiàng)目,是否要再次購買,如果用戶不小心點(diǎn)了取消,支付流程就會(huì)終止。 蘋果設(shè)計(jì)這個(gè)彈窗的本意更多是根據(jù)Apple ID識(shí)別用戶身份,避免用戶重復(fù)購買相同項(xiàng)目。但對(duì)于有用戶帳號(hào)體系的App,這個(gè)提示是有點(diǎn)多余的,雖然影響不大。因此,如果一個(gè)IAP項(xiàng)目既適用于Consumable products也適用于Non-renewable subscriptions,比較建議選擇Consumable products。

1.3 定價(jià)

在創(chuàng)建IAP項(xiàng)目的時(shí)候,需要設(shè)定價(jià)格,這個(gè)價(jià)格只能從蘋果預(yù)設(shè)的價(jià)格等級(jí)中選擇,比如等級(jí)1對(duì)應(yīng)1美元、6元人民幣,等級(jí)2對(duì)應(yīng)2美元、12元人民幣……最高等級(jí)87對(duì)應(yīng)999.99美元、6498元人民幣。另外可能是為了照顧某些貨幣區(qū)的開發(fā)者和用戶,還有一些特殊的等級(jí),比如備用等級(jí)A對(duì)應(yīng)1美元、1元人民幣,備用等級(jí)B對(duì)應(yīng)1美元、3元人民幣這樣。除此之外,IAP項(xiàng)目不能定一個(gè)9.9元人民幣這樣不符合任何等級(jí)的價(jià)格。詳細(xì)價(jià)格等級(jí)表可以看蘋果的官方文檔 蘋果的價(jià)格等級(jí)表通常是不會(huì)調(diào)整的,但也不排除在某些貨幣匯率發(fā)生巨大變化的情況下,對(duì)該貨幣的定價(jià)進(jìn)行調(diào)整,調(diào)整前蘋果會(huì)發(fā)郵件通知開發(fā)者。 另外,價(jià)格等級(jí)表中不同貨幣的匯率關(guān)系與實(shí)際匯率存在差異,淘寶上有部分低價(jià)的iOS游戲內(nèi)購代充就是利用了某些貨幣的匯率差來做生意。 對(duì)于開發(fā)者來說,如果App在中國區(qū)以外發(fā)布,可能需要注意一下匯率的問題。某些地區(qū)的內(nèi)購結(jié)算成人民幣后收入會(huì)低于相應(yīng)價(jià)格等級(jí)的人民幣收入,所以在一些需要嚴(yán)格計(jì)算實(shí)際收入的情況下(比如財(cái)務(wù)統(tǒng)計(jì)營收,或內(nèi)購收入需要進(jìn)一步與平臺(tái)CP方進(jìn)行分成),可能需要根據(jù)內(nèi)購的實(shí)際支付貨幣及金額和還有相應(yīng)匯率來計(jì)算收入,或者也可以用一些辦法來限制某些地區(qū)的內(nèi)購(在本文2.2部分會(huì)講)。 補(bǔ)充說明一下,IAP項(xiàng)目的價(jià)格在商品發(fā)布以后是可以在itunes connect后臺(tái)修改的,也可以設(shè)置限時(shí)優(yōu)惠價(jià)。但是大部分聯(lián)網(wǎng)App的內(nèi)購項(xiàng)目價(jià)格是從自己的服務(wù)端獲取的,如果要修改價(jià)格或設(shè)置限時(shí)優(yōu)惠,需要兩邊一起處理,還是挺麻煩的。

1.4 分成

很多人都知道,App Store上的付費(fèi)App和App內(nèi)購,蘋果與開發(fā)者默認(rèn)是3/7分成。但實(shí)際上,在某些地區(qū)蘋果與開發(fā)者分成之前需要先扣除交易稅,開發(fā)者的實(shí)際分成不一定是70%。從2015年10月開始,蘋果對(duì)中國地區(qū)的App Store購買扣除了2%的交易稅,對(duì)于中國區(qū)帳號(hào)購買的IAP,開發(fā)者的實(shí)際分成在68%~69%之間。而且中國以外不同地區(qū)的交易稅標(biāo)準(zhǔn)也存在差異,如1.3中所述,如果需要嚴(yán)格計(jì)算實(shí)際收入,可能需要把這個(gè)部分也考慮進(jìn)來。針對(duì)不同地區(qū)的內(nèi)購,內(nèi)購價(jià)格和對(duì)應(yīng)的開發(fā)者實(shí)際收入在蘋果的價(jià)格等級(jí)表(1.3中的鏈接)中有詳細(xì)列舉。另外,根據(jù)蘋果在2016年6月的新規(guī)則,針對(duì)Auto-Renewable Subscription類型的IAP,如果用戶購買的訂閱時(shí)間超過1年,那么從第二年開始,開發(fā)者可以獲得85%的分成。詳情可查看: https://developer.apple.com/app-store/subscriptions/

1.5 結(jié)算

針對(duì)IAP的交易收入,蘋果一般以5周(每年1/4/7/10月)或4周(其余月份)作為一個(gè)結(jié)算周期,并在每個(gè)結(jié)算周期結(jié)束后第33天向開發(fā)者付賬。

2 IAP設(shè)計(jì)開發(fā)要點(diǎn)

2.1 創(chuàng)建和提交IAP項(xiàng)目

開發(fā)IAP之前需要先在itunes connect后臺(tái)創(chuàng)建IAP商品,并按規(guī)范填寫product id、商品名稱、價(jià)格、截圖等信息。如果App當(dāng)前版本支持新增的IAP項(xiàng)目,可不用發(fā)版直接提交IAP審核。如果需要App新功能配合,則需要和App版本一起提交。 《In-App Purchase Configuration Guide for iTunes Connect》詳細(xì)介紹了IAP的創(chuàng)建和提交流程:

其中需要特別注意的是:

2.1.1 盡量不要?jiǎng)h除已創(chuàng)建的IAP

已創(chuàng)建的IAP除了product id之外的所有信息都可以修改,如果刪除了一個(gè)IAP,將無法再創(chuàng)建一個(gè)相同product id的IAP,也意味著該product id永久失效。而product id一般有特定的命名規(guī)則,用來標(biāo)示App內(nèi)的購買項(xiàng)目,如果命名規(guī)則下有某個(gè)product id永久失效,可能會(huì)導(dǎo)致整個(gè)product id命名規(guī)則都要修改,掉進(jìn)坑里~

2.1.2 注意區(qū)分reference name和display name

reference name是給開發(fā)者自己看的,display name會(huì)在IAP支付流程的確認(rèn)購買系統(tǒng)彈窗中展示給用戶,而且不能隨意修改(修改需要重新提交IAP審核),所以命名的時(shí)候要弄清楚。

2.1.3 當(dāng)App審核被拒時(shí)

如果IAP隨App版本一起提交審核,有問題時(shí)所有新提交的IAP項(xiàng)目和App版本會(huì)同時(shí)被拒,再次提交App審核時(shí),一定要記得重新提交所有IAP項(xiàng)目(每個(gè)IAP還得要手動(dòng)編輯一下才能重新提交真麻煩),否則蘋果是無法繼續(xù)審核的。

2.2 IAP支付流程

這部分內(nèi)容屬于功能實(shí)現(xiàn)的邏輯,同樣在《In-App Purchase Programming Guide》中有詳細(xì)說明: 具體來說,IAP的支付模式分為 客戶端校驗(yàn) 和 服務(wù)端校驗(yàn) 2種模式,客戶端校驗(yàn)?zāi)J揭驗(yàn)槿菀讉卧熘Ц稇{據(jù),安全性比較低,一般只有非常簡單的單機(jī)App才會(huì)使用,大部分App都會(huì)采用 服務(wù)端校驗(yàn) 模式。

另外不同類型的IAP支付流程也會(huì)有一些小差異(主要是restore機(jī)制),下面就以最常用的Consumable products和Non-renewable subscriptions類型為例,來說明一下IAP的支付流程:

步驟說明:

程序向服務(wù)器發(fā)送請(qǐng)求,獲得一份產(chǎn)品列表。服務(wù)器返回包含產(chǎn)品標(biāo)識(shí)符的列表。程序向App Store發(fā)送請(qǐng)求,得到產(chǎn)品的信息。App Store返回產(chǎn)品信息。程序把返回的產(chǎn)品信息顯示給用戶(App的store界面)用戶選擇某個(gè)產(chǎn)品程序向App Store發(fā)送支付請(qǐng)求App Store處理支付請(qǐng)求并返回交易完成信息。程序從信息中獲得數(shù)據(jù),并發(fā)送至服務(wù)器。服務(wù)器紀(jì)錄數(shù)據(jù),并進(jìn)行審(我們的)查。服務(wù)器將數(shù)據(jù)發(fā)給App Store來驗(yàn)證該交易的有效性。App Store對(duì)收到的數(shù)據(jù)進(jìn)行解析,返回該數(shù)據(jù)和說明其是否有效的標(biāo)識(shí)。服務(wù)器讀取返回的數(shù)據(jù),確定用戶購買的內(nèi)容。服務(wù)器將購買的內(nèi)容傳遞給程序。

以上簡要步驟總結(jié):

用戶進(jìn)入購買虛擬物品頁面,App從后臺(tái)服務(wù)器獲取產(chǎn)品列表然后顯示給用戶用戶點(diǎn)擊購買購買某一個(gè)虛擬物品,APP就發(fā)送該虛擬物品的productionIdentifier到Apple服務(wù)器Apple服務(wù)器根據(jù)APP發(fā)送過來的productionIdentifier返回相應(yīng)的物品的信息(描述,價(jià)格等)用戶點(diǎn)擊確認(rèn)鍵購買該物品,購買請(qǐng)求發(fā)送到Apple服務(wù)器Apple服務(wù)器完成購買后,返回用戶一個(gè)完成購買的憑證APP發(fā)送這個(gè)憑證到后臺(tái)服務(wù)器驗(yàn)證后臺(tái)服務(wù)器把這個(gè)憑證發(fā)送到Apple驗(yàn)證,Apple返回一個(gè)字段給后臺(tái)服務(wù)器表明該憑證是否有效后臺(tái)服務(wù)器把驗(yàn)證結(jié)果在發(fā)送到APP,APP根據(jù)驗(yàn)證結(jié)果做相應(yīng)的處理

2.3 不能忽視的坑

2.3.1 延遲返回支付結(jié)果

在上述流程的步驟6,由于網(wǎng)絡(luò)問題等種種原因,即使用戶已經(jīng)付款成功,客戶端也可能一時(shí)半會(huì)收不到蘋果API的支付成功通知,也無法主動(dòng)向蘋果API請(qǐng)求查詢支付狀態(tài),只能被動(dòng)等待通知。因此有些情況下,客戶端會(huì)延遲收到支付成功的通知(可能是過了幾分鐘,也有可能是下次打開App的時(shí)候),針對(duì)這種情況,需要做好兩件事:1 客戶端本地保存所有支付結(jié)果未確認(rèn)的交易信息,并設(shè)置一個(gè)監(jiān)聽進(jìn)程,在收到支付成功的信息后,繼續(xù)處理這筆交易的后續(xù)流程。極端情況下,用戶在交易結(jié)果未確認(rèn)的情況下刪除App,保存在App本地?cái)?shù)據(jù)庫中的交易信息也會(huì)丟失,因此,更好的方案是 把交易信息存到iOS系統(tǒng)的keychain里面 2 當(dāng)本地存在支付結(jié)果未確認(rèn)的交易信息時(shí),在交互上提示用戶可能需要等待支付結(jié)果,避免用戶重復(fù)付款

2.3.2 服務(wù)端校驗(yàn)延遲

在上述流程6~8的支付憑據(jù)校驗(yàn)過程中,因?yàn)榫W(wǎng)絡(luò)問題等各種原因,客戶端可能無法及時(shí)收到服務(wù)端的校驗(yàn)成功通知,類似的,這種情況需要:

1 客戶端本地保存支付憑據(jù),并持續(xù)向服務(wù)端輪詢校驗(yàn)結(jié)果,直到返回明確的校驗(yàn)成功或校驗(yàn)無效的結(jié)果。支付憑據(jù)最好也保存在 keychain 里面2 在客戶端向服務(wù)端輪詢結(jié)果時(shí),為了避免用戶在支付結(jié)果頁面等待過久,交互層面上可以先結(jié)束支付流程(經(jīng)過一定時(shí)間超時(shí)),同時(shí)提示用戶需要等待支付結(jié)果,避免用戶重復(fù)付款

2.3.3 非官方渠道包支付失敗問題

在上述流程步驟1中,如果用戶安裝的App不是App Store官方渠道包(從PP助手、同步推等第三方應(yīng)用商店下載),蘋果API會(huì)直接返回product id不存在并結(jié)束支付流程,在交互層面上表現(xiàn)為用戶點(diǎn)擊購買后直接提示支付失敗。 類似的,越獄設(shè)備在安裝某些內(nèi)購破解插件后,也會(huì)導(dǎo)致無法進(jìn)行內(nèi)購(返回product id不存在)。不過現(xiàn)在iOS設(shè)備的越獄比例已經(jīng)非常低了,基本可以忽略。 因此,針對(duì)這個(gè)問題的解決辦法是:當(dāng)返回product id不存在時(shí),提示用戶安裝的可能是非官方渠道包,引導(dǎo)用戶到App Store下載官方渠道包。

2.3.4 貨幣校驗(yàn)

如本文1.3部分所述,如果App在中國區(qū)以外發(fā)布,但由于某些原因又希望限制某些地區(qū)帳號(hào)的內(nèi)購,可以在上述流程的步驟4校驗(yàn)用戶支付的貨幣單位,并禁止某些貨幣的購買。同時(shí)在交互上也要給用戶相應(yīng)的提示,類似不支持特殊地區(qū)帳號(hào)購買的彈窗說明。

2.3.5 未綁定App Store支付方式的用戶支付流程

這是一個(gè)巨大的坑!

如果用戶在內(nèi)購前未綁定App Store的支付方式,在上述流程的步驟5,點(diǎn)擊系統(tǒng)彈窗(第1次)的確認(rèn)購買后,會(huì)自動(dòng)跳轉(zhuǎn)到App Store的綁定支付方式界面。接著如果順利完成支付方式的綁定,會(huì)再自動(dòng)跳轉(zhuǎn)跳回App,再次出現(xiàn)系統(tǒng)彈窗(第2次)讓用戶確認(rèn)購買。但是,當(dāng)用戶點(diǎn)擊系統(tǒng)彈窗(第1次)的確認(rèn)購買后,蘋果API會(huì)立即向客戶端返回支付失敗…支付失敗…失敗…一般情況下,客戶端收到支付失敗的返回,理所應(yīng)當(dāng)認(rèn)為支付已經(jīng)取消了,而丟棄本地的交易信息。但萬萬沒想到后面用戶綁定支付方式完成后會(huì)繼續(xù)確認(rèn)購買,這簡直就是蘋果IAP系統(tǒng)設(shè)計(jì)的一個(gè)大bug!如果知道了這個(gè)坑,解決方案也很簡單,就是在蘋果API返回支付失敗時(shí),用類似2.3.1的方式處理,保留待確認(rèn)的交易信息并持續(xù)監(jiān)聽支付結(jié)果返回。

3 更多IAP實(shí)踐經(jīng)驗(yàn)總結(jié)

3.1 匿名購買

很多App在第一次提交IAP時(shí)都會(huì)因?yàn)椴恢С帜涿徺I被拒,原因是App Store Review Guidelines要求App在非必要的情況下,不允許強(qiáng)制用戶注冊/登錄后才能使用某些功能。一般情況下,對(duì)于沒有IAP的App,強(qiáng)制用戶注冊/登錄才能使用是不會(huì)被拒的(除非遇到很苛刻的審核人員),但是對(duì)于IAP,一般都會(huì)要求支持匿名購買。當(dāng)然你也可以嘗試編一堆原因說明為什么強(qiáng)制用戶注冊/登錄是必要的(比如提供的商品或服務(wù)需要獲取用戶手機(jī)號(hào)或郵箱之類的理由),但也不能保證說服審核人員。支持匿名購買,通常需要在用戶未登錄App帳號(hào)的情況下,臨時(shí)保存用戶的購買記錄,并在用戶登錄后合并到App帳號(hào)數(shù)據(jù)。

3.2 跨平臺(tái)同步

雖然在原則上,蘋果不允許通過外部渠道解鎖App內(nèi)需要付費(fèi)才能使用的功能或虛擬商品,比如在web端購買一個(gè)課程,在App內(nèi)觀看,但實(shí)際在某些條件下是可以做跨平臺(tái)同步用戶購買的內(nèi)容:

1 在iOS App內(nèi)也提供相應(yīng)商品IAP購買的前提下,通過App帳號(hào)同步用戶在不同平臺(tái)上購買的內(nèi)容。這條規(guī)則適用到大部分游戲上可能會(huì)比較苛刻,但是一般的內(nèi)容類App都是行的通的。2 針對(duì)電子書、音樂、視頻等項(xiàng)目,App只提供單純的內(nèi)容閱讀/觀看功能,而不提供任何發(fā)現(xiàn)和訂閱內(nèi)容的功能(比如Kindle iOS版),可支持用戶在外部渠道購買內(nèi)容后在App中使用(具體可參考App Store Review Guidelines 3.1.3)。但實(shí)際上是否允許可能也要取決于審核人員的判斷,比如云課堂曾經(jīng)提交過一個(gè)版本,不能購買付費(fèi)課程,但是允許用戶在web端購買付費(fèi)課程后在iOS端觀看,就被拒了,理由是付費(fèi)課程不屬于上述條件的內(nèi)容范疇。

3.3 虛擬幣

由于IAP的價(jià)格等級(jí)機(jī)制,無法支持靈活的商品定價(jià)(如9.9元人民幣)和營銷功能(如優(yōu)惠券抵扣等),很多App會(huì)引入虛擬幣,先通過IAP內(nèi)購充值特定價(jià)格的虛擬幣(如6、12、18、648等),再使用虛擬幣購買具體的商品。類似IAP跨平臺(tái)同步問題,iOS平臺(tái)充值的虛擬幣不允許和其他平臺(tái)(Android、web)流通,外部平臺(tái)充值的虛擬幣不能在iOS平臺(tái)使用,同時(shí)iOS平臺(tái)充值的虛擬幣也不能在外部平臺(tái)使用。但實(shí)際中,我們會(huì)發(fā)現(xiàn)有些App,比如喜馬拉雅和得到,支持用戶在微信公眾號(hào)中充值虛擬幣(雖然微信充值也區(qū)分了iOS平臺(tái)和其他平臺(tái)),再在App內(nèi)使用,并且在App內(nèi)的充值界面,隱晦的提示用戶如果充值遇到問題,可以關(guān)注微信公眾號(hào)獲取客服幫助(實(shí)際上就是引導(dǎo)用戶用微信充值)。這種做法嚴(yán)格意義上是不合規(guī)的,但如果蘋果審核不嚴(yán)也能通過,算是打擦邊球,估計(jì)這招效果還不錯(cuò)~

3.4 退款問題

根據(jù)蘋果政策,用戶在購買IAP后90天內(nèi),能以各種原因申請(qǐng)退款(扣款后購買失敗、買錯(cuò)了、不喜歡等等),但實(shí)際能不能退成功蘋果說了算。如果一個(gè)用戶申請(qǐng)退款成功,蘋果會(huì)在與開發(fā)者結(jié)算時(shí)記一筆退款訂單(當(dāng)然原來購買成功的訂單也在),錢就不給了,而且蘋果也不會(huì)告訴你是哪個(gè)用戶退款的,而且用戶購買的東西還在,簡直就是霸王條件~訂單數(shù)據(jù)可以在itunes connect后臺(tái)的“付款和財(cái)務(wù)報(bào)告”中查看,但沒有詳細(xì)時(shí)間信息和用戶信息,很難定位到相應(yīng)的平臺(tái)訂單。對(duì)于游戲或者一些自營平臺(tái)來說,可能就是少點(diǎn)收入。而對(duì)于需要與平臺(tái)CP方一一分成的產(chǎn)品來說,可能就要虧錢。為了解決這個(gè)問題,可設(shè)計(jì)一套退款訂單分配規(guī)則,根據(jù)IAP訂單的時(shí)間周期、金額,結(jié)合平臺(tái)訂單的一些信息,將IAP退款訂單分配到平臺(tái)訂單,由平臺(tái)和CP方共同承擔(dān)退款。從歷史數(shù)據(jù)來看,一般不遇到大量惡意退款的情況下,IAP的退款率可能在1~3%之間(取決于App內(nèi)容質(zhì)量、用戶心情,還有蘋果的心情)。對(duì)于IAP營收額很大的App,可能需要考慮一下退款的問題。

3.5 支付成功率

云課堂曾經(jīng)對(duì)比過iPhone端使用支付寶/微信支付(注意:繞過IAP使用第三方支付屬于違規(guī)行為,可能導(dǎo)致應(yīng)用下架或開發(fā)者被封號(hào),切勿模仿?。┖虸AP的支付數(shù)據(jù),發(fā)現(xiàn)第三方支付的用戶支付成功率大概是IAP的2~3倍,反映在營收上也差了2倍多。 不難理解,國內(nèi)App Store的用戶支付習(xí)慣肯定不如第三方支付成熟。而經(jīng)過進(jìn)一步的用戶問卷調(diào)研,發(fā)現(xiàn)影響IAP支付成功率的因素有很多方面:1 用戶安裝的App來自第三方應(yīng)用商店或使用越獄設(shè)備,無法使用IAP支付(約5%用戶)2 用戶未綁定App Store支付方式(約75%用戶,數(shù)據(jù)很驚人)3 用戶在IAP支付過程綁定支付方式遇到問題,放棄了(約50%用戶)以上數(shù)據(jù)僅代表云課堂iPhone端的用戶群,某種意義上也說明云課堂的用戶比較小白(產(chǎn)品本身的目標(biāo)用戶很大一部分就是小白),沒接觸過IAP這種支付方式。不同產(chǎn)品的目標(biāo)用戶群的App Store內(nèi)購使用習(xí)慣肯定也存在差異。不過,隨著App Store內(nèi)購的普及(一方面是游戲內(nèi)購帶動(dòng),另一方面也得益于蘋果的推廣,比如經(jīng)常搞一些App一元購活動(dòng),還有從2016年11月開始支持綁定支付寶),用戶的內(nèi)購習(xí)慣也在持續(xù)養(yǎng)成,從數(shù)據(jù)上也能看出IAP支付成功率的上升趨勢,對(duì)于接入IAP的產(chǎn)品是友好的。

3.6 作弊行為

考慮到IAP的分成、退款以及支付成功率等一系列問題,雖然我們有很多種辦法可以偷偷繞過IAP使用第三方支付,比如:

1 通過后臺(tái)開關(guān)控制在某些時(shí)間開啟第三方支付2 根據(jù)用戶信息和行為識(shí)別出明顯不是蘋果審核人員的用戶(特別是其中一些高客單價(jià)用戶),開放第三方支付 等等…… 但是根據(jù)公司企業(yè)發(fā)展部、市場部、法務(wù)部的要求,切勿在IAP的問題上搞事情!好好遵守蘋果規(guī)則,做好產(chǎn)品,爭取App Store推薦。

4 代碼集成

內(nèi)購所需要寫的代碼是非常少的,只有幾百行。

4.1 引入頭文件

import StoreKit

4.2 遵循兩個(gè)代理

SKProductsRequestDelegate, SKPaymentTransactionObserver

4.3 開啟內(nèi)購檢測

func add(_ observer: SKPaymentTransactionObserver)

let paymentQueue: PaymentQueue = SKPaymentQueue.default()

paymentQueue.add(self)

4.4 設(shè)置內(nèi)購點(diǎn)擊事件

private func purchase(

product: SKProduct,

quantity: Int,

atomically: Bool,

applicationUsername: String = "",

completion: @escaping (PurchaseResult) -> Void

) {

guard SwiftyStoreKit.canMakePayments else {

let error = NSError(

domain: SKErrorDomain,

code: SKError.paymentNotAllowed.rawValue,

userInfo: nil

)

completion(.error(error: SKError(_nsError: error)))

return

}

paymentQueueController.startPayment(

Payment(

product: product,

quantity: quantity,

atomically: atomically,

applicationUsername: applicationUsername

) { result in

completion(self.processPurchaseResult(result))

})

}

4.5 請(qǐng)求商品,獲取商品信息,以及代理

private let request: SKProductsRequest

deinit {

request.delegate = nil

}

private init(

productIds: Set,

callback: @escaping RequestCallback

) {

self.callback = callback

request = SKProductsRequest(productIdentifiers: productIds)

super.init()

request.delegate = self

}

class func startQuery(

_ productIds: Set,

callback: @escaping RequestCallback

) -> InAppProductQueryRequest {

let request = InAppProductQueryRequest(productIds: productIds, callback: callback)

request.start()

return request

}

func start() {

request.start()

}

func cancel() {

request.cancel()

}

// MARK: SKProductsRequestDelegate

func productsRequest(

_ request: SKProductsRequest,

didReceive response: SKProductsResponse

) {

let retrievedProducts = Set(response.products)

let invalidProductIDs = Set(response.invalidProductIdentifiers)

performCallback(RetrieveResults(retrievedProducts: retrievedProducts,

invalidProductIDs: invalidProductIDs, error: nil))

}

func requestDidFinish(_ request: SKRequest) {

}

func request(

_ request: SKRequest,

didFailWithError error: Error

) {

performCallback(

RetrieveResults(

retrievedProducts: Set(),

invalidProductIDs: Set(),

error: error

)

)

}

private func performCallback(_ results: RetrieveResults) {

DispatchQueue.main.async {

self.callback(results)

}

}

4.6 沙盒測試環(huán)境驗(yàn)證以及正式環(huán)境

public enum VerifyReceiptURLType: String {

// 正式環(huán)境驗(yàn)證

case production = "https://buy.itunes.apple.com/verifyReceipt"

// 沙盒測試環(huán)境驗(yàn)證

case sandbox = "https://sandbox.itunes.apple.com/verifyReceipt"

}

public init(service: VerifyReceiptURLType = .production) {

self.service = service

}

private let service: VerifyReceiptURLType

public func validate(

receipt: String,

password autoRenewPassword: String? = nil,

completion: @escaping (VerifyReceiptResult) -> Void) {

let storeURL = URL(string: service.rawValue)! // safe (until no more)

let storeRequest = NSMutableURLRequest(url: storeURL)

storeRequest.httpMethod = "POST"

let requestContents: NSMutableDictionary = [ "receipt-data": receipt ]

// password if defined

if let password = autoRenewPassword, !password.isEmpty {

requestContents.setValue(password, forKey: "password")

}

// Encore request body

do {

storeRequest.httpBody = try JSONSerialization.data(withJSONObject: requestContents, options: JSONSerialization.WritingOptions.prettyPrinted)

} catch let e {

completion(.error(error: .requestBodyEncodeError(error: e)))

return

}

// Remote task

let task = URLSession.shared.dataTask(with: storeRequest as URLRequest) { data, _, error -> Void in

// there is an error

if let networkError = error {

completion(.error(error: .networkError(error: networkError)))

return

}

// there is no data

guard let safeData = data else {

completion(.error(error: .noRemoteData))

return

}

// cannot decode data

guard let receiptInfo = try? JSONSerialization.jsonObject(with: data!, options: .mutableLeaves) as? ReceiptInfo ?? [:] else {

let jsonStr = String(data: safeData, encoding: String.Encoding.utf8)

completion(.error(error: .jsonDecodeError(string: jsonStr)))

return

}

// get status from info

if let status = receiptInfo["status"] as? Int {

let receiptStatus = ReceiptStatus(rawValue: status) ?? ReceiptStatus.unknown

if case .testReceipt = receiptStatus {

let sandboxValidator = AppleReceiptValidator(service: .sandbox)

sandboxValidator.validate(receipt: receipt, password: autoRenewPassword, completion: completion)

} else {

if receiptStatus.isValid {

completion(.success(receipt: receiptInfo))

} else {

completion(.error(error: .receiptInvalid(receipt: receiptInfo, status: receiptStatus)))

}

}

} else {

completion(.error(error: .receiptInvalid(receipt: receiptInfo, status: ReceiptStatus.none)))

}

}

task.resume()

}

5 IAP QA測試幫助

IAP沙盒測試賬號(hào)使用

6 App Store協(xié)議、稅務(wù)和銀行業(yè)務(wù)

6.1 登錄iTunes Connect

登錄iTunes Connect 進(jìn)入?yún)f(xié)議、稅務(wù)和銀行業(yè)務(wù)頁面

6.2 選擇申請(qǐng)合同類型

進(jìn)入?yún)f(xié)議、稅務(wù)和銀行業(yè)務(wù)頁面后,會(huì)有3種合同類型,如果你之前沒有主動(dòng)申請(qǐng)過去合同,那么一般你現(xiàn)在激活的合同只有iOS Free Application一種。

頁面內(nèi)容分為兩塊:

Request Contracts(申請(qǐng)合同)Contracts In Effect(已生效合同)。

合同類型分為3種:

iOS Free Application(免費(fèi)應(yīng)用合同)iOS Paid Application(付費(fèi)應(yīng)用合同)iAd App NetNetwork(廣告合同)

6.3 申請(qǐng)iOS Paid Application合同

當(dāng)我們點(diǎn)擊申請(qǐng)iOS Paid Application合同后,該合同的狀態(tài)會(huì)變成如下的樣子,我們可以看到其中Status為Pending Tax, Bank, Contact。意思是聯(lián)系方式、銀行和稅務(wù)信息沒有填寫。

6.4 添加銀行賬戶

填寫銀行CNAPS Code(ABA匯款路線號(hào)碼)

6.5 報(bào)稅(跟咱沒啥關(guān)系,但還是要填)

默認(rèn)美國打勾,其他有的話打勾,一般都沒

選擇美國U.S Tax Forms,選擇后會(huì)問你兩個(gè)問題

第一個(gè)問題如下:詢問你是否是美國居民,有沒有美國伙伴關(guān)系或者美國公司,如果沒有直接選擇No。

第二個(gè)問題如下:詢問你有沒有在美國的商業(yè)性活動(dòng),沒有也直接選No。

6.5.1 填寫稅務(wù)信息

包括以下幾點(diǎn):

Individual or Organization Name:個(gè)人或者組織名稱Country of incorporation: 所在國家Type of Beneficial Owner:受益方式,獨(dú)立開發(fā)者選個(gè)人Permanent Residence:居住地址Mailing address:郵寄地址Name of Person Making this Declaration:聲明人Title:頭銜

填寫完這些信息后就可以提交了

6.5.2 填寫聯(lián)系信息,如果是個(gè)人開發(fā)者就全寫自己

6.6 等待審核

當(dāng)你填寫完所有資料后,合同狀態(tài)就會(huì)變成Processing,大約半天就通過了。

柚子快報(bào)邀請(qǐng)碼778899分享:iOS

http://yzkb.51969.com/

好文閱讀

評(píng)論可見,查看隱藏內(nèi)容

本文內(nèi)容根據(jù)網(wǎng)絡(luò)資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點(diǎn)和立場。

轉(zhuǎn)載請(qǐng)注明,如有侵權(quán),聯(lián)系刪除。

本文鏈接:http://gantiao.com.cn/post/19198831.html

發(fā)布評(píng)論

您暫未設(shè)置收款碼

請(qǐng)?jiān)谥黝}配置——文章設(shè)置里上傳

掃描二維碼手機(jī)訪問

文章目錄