iOS開發以內購-AppStore

本文會給你們詳細介紹iOS內購,雖然以前網上也有內購的教程,可是還不夠詳細,我從新整理出一份教程,但願對你們有所幫助。ios

基於Xcode7.1.1版本,模擬器iphone6,9.1系統。
部分地方直接摘自網絡,省時省心省力。
多圖預警!!!
轉載請註明出處@yimouleng
git

一. 建立測試App

建立App-1

首先你須要登陸 App的ItunesConnection,你會看到以下界面github

簡單的介紹一下這幾個選項服務器

  • 1.個人App主要用於管理本身的App應用,例如編輯資料,上架,下架等。
  • 2.銷售和趨勢主要是來查看App在各個平臺的下載量,收入等方面數據,裏面有曲線圖等圖文結合的方式給咱們參考。
  • 3.付款和財務報告顯示的是你的收入以及付款等相關信息。
  • 4.iAd主要是跟廣告有關,開發者能夠登陸到Workbench,經過iAd對應用的廣告進行控制。
  • 5.用戶和職能用於生成相應帳號,例如蘋果沙河測試帳號。
  • 6.協議,稅務和銀行業務則是你銀行相關帳戶的信息設置。

在這裏咱們選擇第一個選項,個人App, 而後點擊左上角的加號,新建一個用來測試用的App。網絡

咱們會看到彈出的窗口併發

在這裏有幾個須要填寫的地方,名稱本身取,平臺IOS,語言選擇了簡體中文,套裝ID也就是你的Bundle Identifier,須要你在Certificates頁面 申請BundleID,在這裏簡單的給你們介紹一下。app

申請BundleID

打開Certificates頁面 ,在左側選擇 Identifiers,並點擊加號,申請一個新的Identifiers。iphone

在這裏Name能夠隨意填寫,我填寫的是TestAppStroeTestDemo,而用來使用的BundleID,咱們在這裏必須選擇第一個選項惟一的,不用選擇通配。在下面的選項中, 咱們只須要勾選一個 Apple Pay便可,其餘選項看本身需求,我在這裏只選擇了它。ide

以後一路Done便可。post

建立App-2

以後咱們回到建立App,選擇好本身剛建立的 BundleID ,填寫SKU, SKU是你App的專用ID,我在這裏隨意填寫,直接複製了App名。點擊建立,咱們的測試App則建立成功。

二.添加內購

App建立好以後,咱們打開建立的App,在左上角選擇功能,會看到左側的App 內購買項目。咱們點擊右下角的加號,爲App添加內購項目。

以後咱們會看到類型的選項,以下圖

官方的註釋寫的很清楚了,只在這裏簡單的說下前兩種

消耗型項目 就像你玩遊戲須要買金幣,買鑽石等,只要花錢就能夠無限次的購買
非消耗型項目 就像你在App Store購買App,買了一次以後就不用再買第二次,你擁有永久使用權。

在這裏爲了方便測試,咱們選擇第一種 消耗型項目 。來到內購項目填寫頁面,以下圖。

這裏有幾個選項,須要填寫商品名稱,產品ID以及價格等級,簡單說明一下

1.商品名稱根據你的消費道具的實際意義來講明,好比「100顆寶石」,「100金幣」等。
2.產品ID是比較重要的,由項目自定義,只要惟一便可,由於測試,我在這裏隨便填寫的123,在實際應用中,必定要認真填寫。
3.價格等級的話「查看價格表」中有對應的說明,能夠對照着表中每一個國家的貨幣價格與等級來選擇

接下來是語言選擇,和上傳快照以下圖

點擊添加語言,填寫名稱和描述,這裏咱們依然選擇簡體中文,以下

審覈備註,根據實際狀況填寫,能夠不填。而下面的屏幕快照,則是商品圖片,以像素爲單位,最低尺寸爲321,390,尺寸需求以下圖,上傳便可。

到這裏爲止, 咱們的內購項目則添加完成。接下來則是測試階段了。

三.申請沙盒測試帳號(用來測試購買項目)

這個帳號,是利用蘋果的沙盒測試環境來模擬AppStore的購買流程,你確定不會想要用真實RMB去購買測試吧?
首先咱們回到iTunes Connect中,在這裏咱們選擇用戶和職能

而後在上面的第三個選項沙箱技術測試員中點擊加號,添加測試員。

在信息填寫頁面只簡單說兩句。

全部信息均可以隨意填寫,不用管是否真實。
App Store地區選擇,必定要選對,它對應的是你建立的App的地區, 你App是中國的話, 在這裏咱們依然選擇中國。
此帳號只能用來測試,不要在正式的appstore上使用

填寫完畢,點擊保存後,咱們則生成一個測試帳號,固然這個帳號是能夠隨時刪除和添加的。

四.核心代碼

以後終於到了咱們擼代碼的時候了,點開你的Xcode建立你的項目!

首先咱們須要在項目工程中加入「storekit.framework」,加入頭文件#import 
在.h文件中加入「SKPaymentTransactionObserver,SKProductsRequestDelegate」監聽機制
代碼很簡單,直接在.m文件在中填寫,添加了二次驗證,防止越獄手機等內購。以下,

.m文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
//
// ViewController.m
// 內購
//
// Created by Ely on 15/12/15.
// Copyright © 2015年 Ely. All rights reserved.
//

#import "ViewController.h"
#import <StoreKit/StoreKit.h>
#import "SVProgressHUD.h"

@interface ViewController ()<SKPaymentTransactionObserver,SKProductsRequestDelegate>
@property (nonatomic,strong) NSArray *profuctIdArr;
@property (nonatomic,copy) NSString *currentProId;

@end

@implementation ViewController

- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.

[self createPay];
}


- (void)createPay
{
[[SKPaymentQueue defaultQueue] addTransactionObserver:self];
self.profuctIdArr = @[@"123"];

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];
button.tag = 100;
[self.view addSubview:button];
}

- (void)btnClick:(UIButton *)button
{
NSString *product = self.profuctIdArr[button.tag-100];
_currentProId = product;
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

在這裏須要注意幾點,

  • 代碼中的self.profuctIdArr所填寫的是你的購買項目的的ID,我這裏是當時填寫的ID 123。
  • 在監聽購買結果後,必定要調用[[SKPaymentQueue defaultQueue] finishTransaction:tran];來容許你從支付隊列中移除交易。
  • 沙盒環境測試appStore內購流程的時候,請使用沒越獄的設備。
  • 請務必使用真機來測試,一切以真機爲準。
  • 項目的Bundle identifier須要與您申請AppID時填寫的bundleID一致,否則會沒法請求到商品信息。
  • 真機測試的時候,必定要退出原來的帳號,才能用沙盒測試帳號
  • 二次驗證,請注意區分宏, 測試用沙盒驗證

在這裏附上截圖:

點擊購買按鈕

選擇使用現有Apple ID,填寫測試帳號

確認是否購買

購買成功

最後師打印輸出日誌

到這裏,咱們的內購則所有完成了。
如還有不懂得請留言,或者 加羣67784110聯繫我。
本文所寫的Demo可在個人GITHUB下載,點此連接
內購時遇到的問題和解決辦法,我放在下一篇文章中,點此內購時遇到的問題和解決辦法

相關文章
相關標籤/搜索