iOS內購

- 消耗型項目?

就像你玩游戲需要買金幣,買鉆石等,只要花錢就可以無限次的購買

- 非消耗型項目?

就像你在App Store購買App,買了一次之后就不用再買第二次,你擁有永久使用權。

充值會員選擇的是第一種,可以無限次購買。


需要填寫商品名稱,產品ID以及價格等級,簡單說明一下

1. 商品名稱根據你的消費道具的實際意義來說明,比如“100顆寶石”,“100金幣”等。

2. 產品ID是比較重要的,由項目自定義,只要唯一即可,在實際應用中,一定要認真填寫。

3. 價格等級的話“查看價格表”中有對應的說明,可以對照著表中每個國家的貨幣價格與等級來選擇

申請沙盒測試賬號(用來測試購買項目)

這個賬號,是利用蘋果的沙盒測試環境來模擬AppStore的購買流程

回到iTunes Connect中,在這里我們選擇用戶和職能。

然后在沙箱技術測試員中點擊加號,添加測試員。

所有信息都可以隨意填寫,不用管是否真實。

App Store地區選擇,一定要選對,它對應的是你創建的App的地區, 你App是中國的話, 在這里我們依然選擇中國。

此賬號只能用來測試,不要在正式的appstore上使用

填寫完畢,點擊保存后,我們則生成一個測試賬號,當然這個賬號是可以隨時刪除和添加的。


#import "ViewController.h"

#import <StoreKit/StoreKit.h>

#import "SVProgressHUD.h"

@interface ViewController ()

@property (nonatomic,copy) NSString *currentProId;

@end

@implementation ViewController

- (void)viewDidLoad {

[super viewDidLoad];

UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];

button.frame = CGRectMake(100, 100, 100, 100);

button.backgroundColor = [UIColor greenColor];

[button setTitle:@"6元" forState:UIControlStateNormal];

[button addTarget:self action:@selector(btnClick:) forControlEvents:UIControlEventTouchDown];

[self.view addSubview:button];

}

- (void)btnClick:(UIButton *)button

{

[[SKPaymentQueue defaultQueue] addTransactionObserver:self];

_currentProId = @"123";

if([SKPaymentQueue canMakePayments]){

[self requestProductData:product];

}else{

NSLog(@"不允許程序內付費");

}

}

//去蘋果服務器請求商品

- (void)requestProductData:(NSString *)type{

NSLog(@"-------------請求對應的產品信息----------------");

[SVProgressHUD showWithStatus:nil maskType:SVProgressHUDMaskTypeBlack];

NSArray *product = [[NSArray alloc] initWithObjects:type,nil];

NSSet *nsset = [NSSet setWithArray:product];

SKProductsRequest *request = [[SKProductsRequest alloc] initWithProductIdentifiers:nsset];

request.delegate = self;

[request start];

}

//收到產品返回信息

- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response{

NSLog(@"--------------收到產品反饋消息---------------------");

NSArray *product = response.products;

if([product count] == 0){

[SVProgressHUD dismiss];

NSLog(@"--------------沒有商品------------------");

return;

}

NSLog(@"productID:%@", response.invalidProductIdentifiers);

NSLog(@"產品付費數量:%lu",(unsigned long)[product count]);

SKProduct *p = nil;

for (SKProduct *pro in product) {

NSLog(@"%@", [pro description]);

NSLog(@"%@", [pro localizedTitle]);

NSLog(@"%@", [pro localizedDescription]);

NSLog(@"%@", [pro price]);

NSLog(@"%@", [pro productIdentifier]);

if([pro.productIdentifier isEqualToString:_currentProId]){

p = pro;

}

}

SKPayment *payment = [SKPayment paymentWithProduct:p];

NSLog(@"發送購買請求");

[[SKPaymentQueue defaultQueue] addPayment:payment];

}

//請求失敗

- (void)request:(SKRequest *)request didFailWithError:(NSError *)error{

[SVProgressHUD showErrorWithStatus:@"支付失敗"];

NSLog(@"------------------錯誤-----------------:%@", error);

}

- (void)requestDidFinish:(SKRequest *)request{

[SVProgressHUD dismiss];

NSLog(@"------------反饋信息結束-----------------");

}

//沙盒測試環境驗證

#define SANDBOX @"https://sandbox.itunes.apple.com/verifyReceipt"

//正式環境驗證

#define AppStore @"https://buy.itunes.apple.com/verifyReceipt"

/**

* ?驗證購買,避免越獄軟件模擬蘋果請求達到非法購買問題

*

*/

-(void)verifyPurchaseWithPaymentTransaction{

//從沙盒中獲取交易憑證并且拼接成請求體數據

NSURL *receiptUrl=[[NSBundle mainBundle] appStoreReceiptURL];

NSData *receiptData=[NSData dataWithContentsOfURL:receiptUrl];

NSString *receiptString=[receiptData base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithLineFeed];//轉化為base64字符串

NSString *bodyString = [NSString stringWithFormat:@"{\"receipt-data\" : \"%@\"}", receiptString];//拼接請求數據

NSData *bodyData = [bodyString dataUsingEncoding:NSUTF8StringEncoding];

//創建請求到蘋果官方進行購買驗證

NSURL *url=[NSURL URLWithString:SANDBOX];

NSMutableURLRequest *requestM=[NSMutableURLRequest requestWithURL:url];

requestM.HTTPBody=bodyData;

requestM.HTTPMethod=@"POST";

//創建連接并發送同步請求

NSError *error=nil;

NSData *responseData=[NSURLConnection sendSynchronousRequest:requestM returningResponse:nil error:&error];

if (error) {

NSLog(@"驗證購買過程中發生錯誤,錯誤信息:%@",error.localizedDescription);

return;

}

NSDictionary *dic=[NSJSONSerialization JSONObjectWithData:responseData options:NSJSONReadingAllowFragments error:nil];

NSLog(@"%@",dic);

if([dic[@"status"] intValue]==0){

NSLog(@"購買成功!");

NSDictionary *dicReceipt= dic[@"receipt"];

NSDictionary *dicInApp=[dicReceipt[@"in_app"] firstObject];

NSString *productIdentifier= dicInApp[@"product_id"];//讀取產品標識

//如果是消耗品則記錄購買數量,非消耗品則記錄是否購買過

NSUserDefaults *defaults=[NSUserDefaults standardUserDefaults];

if ([productIdentifier isEqualToString:@"123"]) {

int purchasedCount=[defaults integerForKey:productIdentifier];//已購買數量

[[NSUserDefaults standardUserDefaults] setInteger:(purchasedCount+1) forKey:productIdentifier];

}else{

[defaults setBool:YES forKey:productIdentifier];

}

//在此處對購買記錄進行存儲,可以存儲到開發商的服務器端

}else{

NSLog(@"購買失敗,未通過驗證!");

}

}

//監聽購買結果

- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transaction{

for(SKPaymentTransaction *tran in transaction){

switch (tran.transactionState) {

case SKPaymentTransactionStatePurchased:{

NSLog(@"交易完成");

// 發送到蘋果服務器驗證憑證

[self verifyPurchaseWithPaymentTransaction];

[[SKPaymentQueue defaultQueue] finishTransaction:tran];

}

break;

case SKPaymentTransactionStatePurchasing:

NSLog(@"商品添加進列表");

break;

case SKPaymentTransactionStateRestored:{

NSLog(@"已經購買過商品");

[[SKPaymentQueue defaultQueue] finishTransaction:tran];

}

break;

case SKPaymentTransactionStateFailed:{

NSLog(@"交易失敗");

[[SKPaymentQueue defaultQueue] finishTransaction:tran];

[SVProgressHUD showErrorWithStatus:@"購買失敗"];

}

break;

default:

break;

}

}

}

//交易結束

- (void)completeTransaction:(SKPaymentTransaction *)transaction{

NSLog(@"交易結束");

[[SKPaymentQueue defaultQueue] finishTransaction:transaction];

}

- (void)dealloc{

[[SKPaymentQueue defaultQueue] removeTransactionObserver:self];

}

- (void)didReceiveMemoryWarning {

[super didReceiveMemoryWarning];

// Dispose of any resources that can be recreated.

}

@end

在這里需要注意幾點,

代碼中的_currentProId所填寫的是你的購買項目的的ID,這個和第二步創建的內購的productID要一致;本例中是 123。

在監聽購買結果后,一定要調用[[SKPaymentQueue defaultQueue] finishTransaction:tran];來允許你從支付隊列中移除交易。

沙盒環境測試appStore內購流程的時候,請使用沒越獄的設備。

請務必使用真機來測試,一切以真機為準。

項目的Bundle identifier需要與您申請AppID時填寫的bundleID一致,不然會無法請求到商品信息。

真機測試的時候,一定要退出原來的賬號,才能用沙盒測試賬號

二次驗證,請注意區分宏, 測試用沙盒驗證,App Store審核的時候也使用的是沙盒購買,所以驗證購買憑證的時候需要判斷返回Status Code決定是否去沙盒進行二次驗證,為了線上用戶的使用,驗證的順序肯定是先驗證正式環境,此時若返回值為21007,就需要去沙盒二次驗證,因為此購買的是在沙盒進行的。

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,001評論 6 537
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,786評論 3 423
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 176,986評論 0 381
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,204評論 1 315
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,964評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,354評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,410評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,554評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,106評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,918評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,093評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,648評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,342評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,755評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,009評論 1 289
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,839評論 3 395
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,107評論 2 375

推薦閱讀更多精彩內容

  • 自己開發的視頻直播項目,牽涉到充值金幣,用到了蘋果公司的內購,趴坑了兩天,這里總結下實現蘋果內購。 一. 創建測試...
    Leo丶Dicaprio閱讀 3,418評論 8 7
  • 內購的前提: 有個人開發者賬號;開通了銀行業務;在開發者后臺添加了內購產品;創建了相應的Bundle id 和證書...
    無wu閱讀 810評論 0 0
  • iOS應用如果涉及到支付功能,分為兩類:第三方支付和蘋果內購。那么什么情況下選擇使用第三方支付,又在什么情況下選擇...
    ZfRee閱讀 38,962評論 36 66
  • #import "ViewController.h"#import@interface ViewControlle...
    清蘂翅膀的技術閱讀 258評論 0 0
  • 游戲框架的搭建 1.游戲背景2.飛機和噴氣動畫 一、添加游戲背景 首先要注意的是self.size和self.vi...
    H小凡閱讀 423評論 0 0