很久之前就想出一篇ios內付費的教程,但是一查網上的教程實在太多了,有的寫得真的蠻不錯的,就心想算了,于是就保存在草稿箱了。至于為什么寫完它呢!真是說來話長,最近公司有個項目經理跑來問我有關蘋果內付費相關的細節,跟他聊了半天,從項目對接蘋果官方支付接口聊到了如何查看app收益,最后終于使他有了一些眉目,但是悲催的是還要我繼續去跟他們項目的程序員講解(真是瘋了),所以我就決定給他們項目寫一個內購的文檔,所以我順便把這篇博客完成吧!
首先進入蘋果的itunesconnection(https://itunesconnect.apple.com)點擊左上角的加號新建一個app應用,點擊后該網站會彈出一個信息編輯框,大家只要將上面的信息填充完畢點擊save即可在蘋果的app平臺上擁有一個屬于自己的app。
在套裝id的上,需要提前為該app申請一個appid以及bundleid,只要是申請成功了就會在選擇列表中顯示出來。
這里順便多說一句這個itunesconnect是用來干嘛的,它是蘋果公司給個人或企業提供管理自己app的一個平臺。在這個平臺上開發者可以新建,刪除和管理自己的app應用,開發者可以根據需求對app應用進行上架與下架,編輯app信息,生成測試app所需的信息,例如賬號,邀請碼等,還有就是我們今天要講的內付費功能。當然啦,他的功能可不止我講的這些,我大致說一下這個平臺的作用,如果你經常跟它打交道的話就會慢慢熟悉了。
接下來,我就來為大家演示一下如何添加付費道具,首先打開itunesconnect,顯示如下頁面:
選擇紅圈所圈起來的選項,然后將里面的相關信息補充完畢,如果缺少這一步,內購功能是不會成功的。
假如你已經完成了上述相關銀行賬戶的設置,就點擊你的app,選擇上面標題欄中的"app 內購買項目"
隨后點擊左上角的 "create new"選項,如下圖所示,進入到下一個界面:
這個界面是讓你選擇消費道具的種類,現在改版的網站是有簡體中文翻譯的,所以不像以前打開一看都不知道選哪一個,甚至都不知道每個代表的什么意思(比如我第一次遇到的時候,在領導面前真是囧)。它的種類分為如下幾種:
一般對項目來說大多數都是選擇“消耗型項目”這個種類,比如游戲中購買金幣,寶石balabala~之類的,選中之后就會到這個界面中來:
在上圖所示的編輯框中輸入,商品名稱,產品id以及價格等級,在這邊說明一下:
1.商品名稱根據你的消費道具的實際意義來說明,比如“100顆寶石”,“100金幣”等。
2.產品id是比較重要的,由項目自定義,只要唯一即可,像我一般都是用app的bundleid加一個后綴來表示,這樣既跟項目關聯又具有唯一性。
3.價格等級的話“查看價格表”中有對應的說明,可以對照著表中每個國家的貨幣價格與等級來選擇。
我們繼續,在這個網頁的接下來部分如圖所示:
選擇添加語言選項,彈出一個編輯頁面:
點擊save保存,則會在界面上顯示成如下:
最后一步就是點擊“選取文件”提交一張蘋果它指定像素(640*920)的商品圖片,當他上傳完畢后點擊“save”按鈕,我們這第二部分就大工告成了。提交的商品最后會在內購的頁面上顯示為如圖:
這個圖是我在已經發布的app上面截取的,添加了3個商品,已經是通過的的狀態了(顯示綠色),當您剛提交的時候,因為通過蘋果的審查需要一段時間所以會顯示黃色的等待狀態,所以不必擔心是不是商品編輯錯了。如圖:
這部分,我主要給大家演示一下,如何申請測試賬號,利用蘋果的沙盒測試環境來模擬appstore的購買流程。
在itunesconnect中選擇“用戶和職能”選項~
隨后在左上角的選項中選擇沙盒測試者,點擊左上角的加號圖標增加一位測試者,如圖:
編輯好相應的內容,點擊保存,就創建了一個測試賬號,是不是很簡單啊!當然這個賬號如果你忘記了密碼可以重新生成一個,無關緊要。
順帶多句嘴,不要在正式的appstore上面用沙盒測試的賬號來登錄,千萬要牢記在心,此賬號只用于測試環境下~
接下來就是代碼部分啦~
1.首先在項目工程中加入“storekit.framework”,加入頭文件#import <storekit/storekit.h>
2.在.h文件中加入“skpaymenttransactionobserver,skproductsrequestdelegate”監聽機制
下面貼上內購的核心代碼,就幾個函數,我在這邊就不在做更多詳細的解釋了,各位看官可以運行跑一下就一目了然了。
.h文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
// // paymentviewcontroller.h // iappaytest // // created by silicon on 14-10-28. // copyright (c) 2014年 silicon. all rights reserved. // #import <uikit/uikit.h> #import <storekit/storekit.h> @interface paymentviewcontroller : uiviewcontroller<skpaymenttransactionobserver,skproductsrequestdelegate> @property (strong, nonatomic) iboutlet uitextfield *productid; @property (strong, nonatomic) iboutlet uibutton *purchase; - (ibaction)purchasefunc:(id)sender; @end |
.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
|
// // paymentviewcontroller.m // iappaytest // // created by silicon on 14-10-28. // copyright (c) 2014年 silicon. all rights reserved. // #import "paymentviewcontroller.h" @interface paymentviewcontroller () @end @implementation paymentviewcontroller - (id)initwithnibname:(nsstring *)nibnameornil bundle:(nsbundle *)nibbundleornil { self = [super initwithnibname:nibnameornil bundle:nibbundleornil]; if (self) { // custom initialization } return self; } - ( void )viewdidload { [super viewdidload]; // do any additional setup after loading the view from its nib. [[skpaymentqueue defaultqueue] addtransactionobserver:self]; self.productid.text = @ "com.games.ztyxs.product_point.1" ; } - ( void )didreceivememorywarning { [super didreceivememorywarning]; // dispose of any resources that can be recreated. } - (ibaction)purchasefunc:(id)sender { nsstring *product = self.productid.text; if ([skpaymentqueue canmakepayments]){ [self requestproductdata:product]; } else { nslog(@ "不允許程序內付費" ); } } //請求商品 - ( void )requestproductdata:(nsstring *)type{ nslog(@ "-------------請求對應的產品信息----------------" ); nsarray *product = [[nsarray alloc] initwithobjects:type, nil 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){ nslog(@ "--------------沒有商品------------------" ); return ; } nslog(@ "productid:%@" , response.invalidproductidentifiers); nslog(@ "產品付費數量:%d" ,[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:self.productid.text]){ p = pro; } } skpayment *payment = [skpayment paymentwithproduct:p]; nslog(@ "發送購買請求" ); [[skpaymentqueue defaultqueue] addpayment:payment]; } //請求失敗 - ( void )request:(skrequest *)request didfailwitherror:(nserror *)error{ nslog(@ "------------------錯誤-----------------:%@" , error); } - ( void )requestdidfinish:(skrequest *)request{ nslog(@ "------------反饋信息結束-----------------" ); } //監聽購買結果 - ( void )paymentqueue:(skpaymentqueue *)queue updatedtransactions:(nsarray *)transaction{ for (skpaymenttransaction *tran in transaction){ switch (tran.transactionstate) { case skpaymenttransactionstatepurchased: nslog(@ "交易完成" ); break ; case skpaymenttransactionstatepurchasing: nslog(@ "商品添加進列表" ); break ; case skpaymenttransactionstaterestored: nslog(@ "已經購買過商品" ); break ; case skpaymenttransactionstatefailed: nslog(@ "交易失敗" ); break ; default : break ; } } } //交易結束 - ( void )completetransaction:(skpaymenttransaction *)transaction{ nslog(@ "交易結束" ); [[skpaymentqueue defaultqueue] finishtransaction:transaction]; } - ( void )dealloc{ [[skpaymentqueue defaultqueue] removetransactionobserver:self]; [super dealloc]; } @end |
代碼就這么多,到這邊我們的ios內購教程就接近尾聲了,在測試的時候還有幾點因素要注意一下:
1.沙盒環境測試appstore內購流程的時候,請使用沒越獄的設備。
2.請務必使用真機來測試,一切以真機為準。
3.項目的bundle identifier需要與您申請appid時填寫的bundleid一致,不然會無法請求到商品信息。
講了這么多,附上幾張測試截屏給大家展示一下:
請求商品時的打印日志:
交易成功后:
手機截屏:
要求輸入appstore帳密,使用測試生成的即可:
確定購買:
交易完成:
當我們的交易完成后還要去appstore 上面去驗證票據信息是否正確,這樣我們才可以給玩家發放道具,apple官方文檔:
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
|
//交易結束 - ( void )completetransaction:(skpaymenttransaction *)transaction{ nslog(@ "交易結束" ); //交易驗證 nsurl *recepiturl = [[nsbundle mainbundle] appstorereceipturl]; nsdata *receipt = [nsdata datawithcontentsofurl:recepiturl]; if (!receipt){ } nserror *error; nsdictionary *requestcontents = @{ @ "receipt-data" : [receipt base64encodedstringwithoptions:0] }; nsdata *requestdata = [nsjsonserialization datawithjsonobject:requestcontents options:0 error:&error]; if (!requestdata) { /* ... handle error ... */ } //in the test environment, use https://sandbox.itunes.apple.com/verifyreceipt //in the real environment, use https://buy.itunes.apple.com/verifyreceipt // create a post request with the receipt data. nsurl *storeurl = [nsurl urlwithstring:@ "https://buy.itunes.apple.com/verifyreceipt" ]; nsmutableurlrequest *storerequest = [nsmutableurlrequest requestwithurl:storeurl]; [storerequest sethttpmethod:@ "post" ]; [storerequest sethttpbody:requestdata]; // make a connection to the itunes store on a background queue. nsoperationqueue *queue = [[nsoperationqueue alloc] init]; [nsurlconnection sendasynchronousrequest:storerequest queue:queue completionhandler:^(nsurlresponse *response, nsdata *data, nserror *connectionerror) { if (connectionerror) { /* ... handle error ... */ } else { nserror *error; nsdictionary *jsonresponse = [nsjsonserialization jsonobjectwithdata:data options:0 error:&error]; if (!jsonresponse) { /* ... handle error ...*/ } /* ... send a response back to the device ... */ //parse the response } }]; [[skpaymentqueue defaultqueue] finishtransaction:transaction]; } |
好了,所有的內購流程基本上講完了,原諒我在圖片上的涂抹,因為關系到產品的敏感詞匯所以希望大家能夠不介意。以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。
原文鏈接:http://blog.csdn.net/shenjie12345678/article/details/40978977