SDK接入(3)之iOS內(nèi)支付(In-App Purchase)接入

SDK接入(3)之iOS內(nèi)支付(In-App Purchase)接入

繼整理了Android平臺的SDK接入過程谱煤。再來分享下iOS平臺的內(nèi)支付(In-App Purchase)接入,作為筆者在游戲開發(fā)中實際遇到的兴使,覺得有必要分享下赃磨,同時也當作是對工作的總結(jié)瞬浓,就放在該SDK接入系列文章中了惠遏。

作為SDK接入系列舀武,同時也是Android平臺的SDK接入有:
SDK接入(2)之Android Google Play內(nèi)支付(in-app Billing)接入
SDK接入(1)之Android Facebook SDK接入

這里提一點拄养,SDK的接入,官方文檔肯定最詳細,最準確瘪匿,而且有時效性跛梗,接入流程變化,API修改更新棋弥,肯定最終都以官方的為準核偿。那么,蘋果官方內(nèi)支付(IAP)接入文檔地址為:

In-App Purchase Programming Guide

iOS內(nèi)支付流程

1.商品種類

在了解蘋果IAP內(nèi)支付之前顽染,有必要先了解下蘋果的商品種類漾岳。在蘋果In-App Purchase Programming Guide文檔上寫明了,商品種類分為如下幾種粉寞。接過GooglePlay支付的會發(fā)現(xiàn)尼荆,這點還是很相似的。
(1)消耗類商品
每次使用都須從新購買唧垦。
(2)非消耗類商品
購買一次即可捅儒。系統(tǒng)會自己購買狀態(tài),且會同步所有用戶設(shè)備都一直保持可用狀態(tài)振亮。
(3)自動再生訂閱
例如:一本書的章節(jié)內(nèi)容巧还。
(4)非自動再生訂閱
例如:一個航班表。
(5)免費訂閱
例如:報刊雜志等双炕。

消耗類與非消耗類商品的區(qū)別:

訂閱類商品的區(qū)別:

2.支付流程

對于IAP整個下單到支付過程狞悲,下圖很形象的說明了該步驟:


(1) 應(yīng)用向服務(wù)器發(fā)送請求,獲得一份產(chǎn)品列表妇斤。
(2) 服務(wù)器返回包含商品標識符的列表摇锋。
(3) 應(yīng)用向App Store發(fā)送請求,得到商品的信息站超。
(4) App Store返回商品信息荸恕。
(5) 應(yīng)用把返回的商品信息顯示在UI界面上。
(6) 用戶選擇某個商品死相。
(7) 應(yīng)用向App Store發(fā)送支付請求融求。
(8) App Store處理支付請求并返回交易完成信息。
(9) 應(yīng)用從信息中獲得數(shù)據(jù)算撮,并發(fā)送至服務(wù)器生宛。
(10) 服務(wù)器紀錄數(shù)據(jù),并進行校驗肮柜。
(11) 服務(wù)器將數(shù)據(jù)發(fā)給App Store來驗證該交易的有效性陷舅。
(12) App Store對收到的數(shù)據(jù)進行解析,返回該數(shù)據(jù)和說明其是否有效的標識审洞。
(13) 服務(wù)器讀取返回的數(shù)據(jù)莱睁,確定用戶購買的內(nèi)容。
(14) 服務(wù)器將購買的內(nèi)容傳遞給程序。

3.配置商品

(1)打開iTunes Connect后臺
用開發(fā)者帳號仰剿,登錄iTunes Connect,企業(yè)級用戶需用主開發(fā)者帳號创淡。

(2)配置iTunes Connect
在iTunes Connect后臺添加應(yīng)用,并配置App內(nèi)購買項目南吮,由于我們游戲中的鉆石琳彩、金幣等都屬于消耗型商品,因此旨袒,直接選的這個汁针。需注意下配置的Bundle id須和項目plist中的Bundle id一致术辐。并添加沙箱測試帳號砚尽。

注意:商品Id不可重復(fù),如果刪除某個商品辉词,以后這個商品的ID也不可用必孤,即使它已經(jīng)被刪除了;另外類型也不能改瑞躺,選錯了只能重新增加一個商品敷搪。

iOS內(nèi)支付接入

1. 項目工程引入StoreKit.framework
2. 這里推薦一個叫IAPHelper的開源封裝,有效的封裝支付流程幢哨,進一步簡化了接入的效率赡勘。所以,下面也是基于該項目進行的接入捞镰。IAPHelper可自行Github搜索闸与。

(1)InAppRageIAPHelper.m。在init中初始化商品id列表岸售。

#import "InAppRageIAPHelper.h"
#import "InAppRageIAPHelper.h"

@implementation InAppRageIAPHelper
@synthesize orderInfo = _orderInfo;

static InAppRageIAPHelper * _sharedHelper;

+ (InAppRageIAPHelper *) sharedHelper {
    if (_sharedHelper != nil) {
        return _sharedHelper;
    }

    _sharedHelper = [[InAppRageIAPHelper alloc] init];
    return _sharedHelper;
}

- (void)dealloc
{
    [_orderInfo release];
    _orderInfo = nil;
    [super dealloc];
}

- (id)init {
    NSSet *productIdentifiers = [NSSet setWithObjects:
                                 @"com.game.test.10001",
                                 @"com.game.test.10002",
                                 @"com.game.test.10003",
                                 @"com.game.test.10004",
                                 @"com.game.test.10005",
                                 nil];
    
    if ((self = [super initWithProductIdentifiers:productIdentifiers])) {                
        
    }
    
    return self;
}

@end

(2)注冊本地通知践樱。一般在應(yīng)用啟動時,添加如下代碼:(productsLoaded凸丸、productPurchased拷邢、productPurchaseFailed分別對應(yīng)支付過程中三種加載中,支付完成屎慢,支付失敗狀態(tài)回調(diào)瞭稼,可根據(jù)實際情況作對應(yīng)的處理)

    [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(productsLoaded:) name:kProductsLoadedNotification object:nil];
    [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(productPurchased:) name:kProductPurchasedNotification object:nil];
    [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(productPurchaseFailed:) name:kProductPurchaseFailedNotification object:nil];
    [[InAppRageIAPHelper sharedHelper]requestProducts];

(3)發(fā)起支付。

    if ([SKPaymentQueue canMakePayments]) {
        [[InAppRageIAPHelper sharedHelper]buyProductIdentifier:[self getItemId] game_order:[self getOrderId]];
    } else {
        // 不允許程序內(nèi)付費購買
        
    }

(4)支付成功的回調(diào)腻惠。這里將AppStore返回的數(shù)據(jù)环肘,進行Base64加密,然后再發(fā)送給游戲服務(wù)器進行校驗妖枚。同時廷臼,本地也會存儲返回的票據(jù)receipt,防止在發(fā)送給服務(wù)器過程中請求失敗,造成的充值成功但不到賬的漏單現(xiàn)象荠商。

-(NSData*)receiptWithTransation:(SKPaymentTransaction*) transcation {
    NSData *receipt = nil;
    if ([[NSBundle mainBundle]respondsToSelector:@selector(appStoreReceiptURL)]) {
        NSURL *receiptUrl = [[NSBundle mainBundle]appStoreReceiptURL];
        receipt = [NSData dataWithContentsOfURL:receiptUrl];
    } else {
        if ([transcation respondsToSelector:@selector(transactionReceipt)]) {
            receipt = [transcation transactionReceipt];
        }
    }
    
    return receipt;
}

-(void)productPurchased:(NSNotification*) notification {
    [NSObject cancelPreviousPerformRequestsWithTarget:self];
    SKPaymentTransaction *transaction = (SKPaymentTransaction*)notification.object;
    
    NSData *receipt = [self receiptWithTransation:transaction];
    NSString *base64Receipt = [receipt base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithLineFeed];
    [[InAppRageIAPHelper sharedHelper].orderInfo setObject:[NSString stringWithFormat:@"%@", base64Receipt] forKey:@"originReceipt"];
    
    NSString *m_params = [self makeHttpParams:base64Receipt];
    if (m_params != nil) {
        [self saveReceipt:m_params];
        [self postGameServer:[self getPayUrl] params:m_params];
    }
}

(5)漏單檢測寂恬。下次,啟動時莱没,會進行漏單檢測初肉。若存在本地票據(jù)receipt,就向游戲服務(wù)器發(fā)起請求饰躲。直到游戲服務(wù)器返回成功牙咏,再刪除本地的票據(jù)receipt。

    NSUserDefaults *userDefalut = [NSUserDefaults standardUserDefaults];
    NSMutableDictionary *receiptDict = [NSMutableDictionary dictionaryWithDictionary:[userDefalut objectForKey:@"receipts"]];
    NSEnumerator *enumerator = [receiptDict objectEnumerator];
    for (NSObject *obj in enumerator) {
        [self postGameServer:[self getPayUrl] params:[NSString stringWithFormat:@"orderdata=%@",obj]];
    }

(6)由于嘹裂,我們的校驗是放在服務(wù)器進行的妄壶,所以,這里就不進行過多的介紹了寄狼。簡單說下丁寄,App Store正式環(huán)境校驗地址是https://buy.itunes.apple.com/verifyReceipt ,測試環(huán)境校驗地址是:https://sandbox.itunes.apple.com/verifyReceipt泊愧。

iOS支付安全問題

對于某些越獄設(shè)備來說伊磺,如果校驗流程有漏洞的話,使用某些神器删咱,就能繞過Appstore的付費流程,偽造訂單屑埋,達到免支付體驗各種付費功能。
其中列舉如下神器:
(1)ap cracker:越獄軟件可以截獲付費請求痰滋,并直接返回付費成功摘能。
(2)iap free: 截獲付費請求的同時,還能截獲客戶端發(fā)起的驗證請求 即寡,返回驗證成功的數(shù)據(jù) 徊哑,返回的數(shù)據(jù)和官方的數(shù)據(jù)并不是完全一樣,可以識別出來是否作弊聪富,但是不保證永久有效莺丑。

因此,首先在支付成功之后墩蔓,要將支付成功返回的票據(jù)發(fā)送給服務(wù)器梢莽,在服務(wù)器端作驗證,根據(jù)服務(wù)器的驗證結(jié)果來做相應(yīng)的處理奸披。其次昏名,本地對應(yīng)偽造的票據(jù)進行過濾。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末阵面,一起剝皮案震驚了整個濱河市轻局,隨后出現(xiàn)的幾起案子洪鸭,更是在濱河造成了極大的恐慌,老刑警劉巖仑扑,帶你破解...
    沈念sama閱讀 211,639評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件览爵,死亡現(xiàn)場離奇詭異,居然都是意外死亡镇饮,警方通過查閱死者的電腦和手機蜓竹,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,277評論 3 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來储藐,“玉大人俱济,你說我怎么就攤上這事「撇” “怎么了蛛碌?”我有些...
    開封第一講書人閱讀 157,221評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長肺缕。 經(jīng)常有香客問我左医,道長,這世上最難降的妖魔是什么同木? 我笑而不...
    開封第一講書人閱讀 56,474評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮跛十,結(jié)果婚禮上彤路,老公的妹妹穿的比我還像新娘。我一直安慰自己芥映,他們只是感情好洲尊,可當我...
    茶點故事閱讀 65,570評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著奈偏,像睡著了一般坞嘀。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上惊来,一...
    開封第一講書人閱讀 49,816評論 1 290
  • 那天丽涩,我揣著相機與錄音,去河邊找鬼裁蚁。 笑死矢渊,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的枉证。 我是一名探鬼主播矮男,決...
    沈念sama閱讀 38,957評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼室谚!你這毒婦竟也來了毡鉴?” 一聲冷哼從身側(cè)響起崔泵,我...
    開封第一講書人閱讀 37,718評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎猪瞬,沒想到半個月后管削,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,176評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡撑螺,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,511評論 2 327
  • 正文 我和宋清朗相戀三年含思,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片甘晤。...
    茶點故事閱讀 38,646評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡含潘,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出线婚,到底是詐尸還是另有隱情遏弱,我是刑警寧澤,帶...
    沈念sama閱讀 34,322評論 4 330
  • 正文 年R本政府宣布塞弊,位于F島的核電站漱逸,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏游沿。R本人自食惡果不足惜饰抒,卻給世界環(huán)境...
    茶點故事閱讀 39,934評論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望诀黍。 院中可真熱鬧袋坑,春花似錦、人聲如沸眯勾。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,755評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春秦爆,著一層夾襖步出監(jiān)牢的瞬間娩怎,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,987評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 46,358評論 2 360
  • 正文 我出身青樓故觅,卻偏偏與公主長得像,于是被迫代替她去往敵國和親渠啊。 傳聞我的和親對象是個殘疾皇子输吏,可洞房花燭夜當晚...
    茶點故事閱讀 43,514評論 2 348

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,770評論 25 707
  • 一、清潔 1替蛉、如果有的牙縫會經(jīng)常塞東西贯溅,那就一定要用牙線拄氯。因為頻繁塞東西很容易出現(xiàn)齲齒。并且一旦出現(xiàn)齲齒就要去補它浅,...
    瀟湘妃子JC閱讀 190評論 0 0
  • 早起準備行李在爸媽催促下很早很早去了北京南站十一真的不是一般的人多A大——北京南(轉(zhuǎn)悠了很久商店)——天津西——公...
    dq920813閱讀 139評論 0 0
  • 我感覺我被它盯上了译柏。 暗處的那雙眼睛,帶著幽藍的瞳色姐霍,眼神里仿佛是一種誘惑鄙麦,一種告訴你前面就是無底的深淵,卻還是自...
    寫手李文優(yōu)閱讀 291評論 0 5