iOS開發支付篇——內購(IAP)詳解


 

1
<em>內購所需要的資料整理總結,史上最完整的,哈哈哈哈哈哈</em>

思維導圖

重點總結:

1
2
3
4
5
6
7
8
9
10
11
12
13
1.獲取內購列表(從App內讀取或從自己服務器讀取)
2.App Store請求可用的內購列表
3.向用戶展示內購列表
4.用戶選擇了內購列表,再發個購買請求,收到購買完成的回調(購買完成后會把錢打給申請內購的銀行卡內)
5.購買流程結束后, 向服務器發起驗證憑證以及支付結果的請求
6.自己的服務器將支付結果信息返回給前端並發放虛擬產品
7.服務端的工作比較簡單,分4步:
  7.1.接收ios端發過來的購買憑證。
  7.2.判斷憑證是否已經存在或驗證過,然后存儲該憑證。
  7.3.將該憑證發送到蘋果的服務器驗證,並將驗證結果返回給客戶端。
    7.4.如果需要,修改用戶相應的會員權限。
    7.5.考慮到網絡異常情況,服務器的驗證應該是一個可恢復的隊列,如果網絡失敗了,應該進行重試。
簡單來說就是將該購買憑證用Base64編碼,然后POST給蘋果的驗證服務器,蘋果將驗證結果以JSON形式返回。

一、使用注意事項及遇到的坑

  1.使用注意

1
2
3
4
5
6
7
8
1. 代碼中的_currentProId所填寫的是你的購買項目的的ID,這個和第二步創建的內購的productID要一致,產品id與_currentProId一致。
2. 在監聽購買結果后,一定要調用[[SKPaymentQueue defaultQueue] finishTransaction:tran];來允許你從支付隊列中移除交易。
3. 真機測試的時候,一定要退出原來的賬號(app store 登錄的賬號退出),才能用沙盒測試賬號。
4. 請務必使用真機來測試,一切以真機為准。
5. 項目的Bundle identifier需要與您申請AppID時填寫的bundleID一致,不然會無法請求到商品信息。
6. 沙盒環境測試appStore內購流程的時候,請使用沒越獄的設備。
7. 二次驗證,請注意區分宏, 測試用沙盒驗證,App Store審核的時候也使用的是沙盒購買,所以驗證購買憑證的時候需要判斷返回Status Code決定是否去沙盒進行二次驗證,為了線上用戶的使用,驗證的順序肯定是先驗證正式環境,此時若返回值為21007,就需要去沙盒二次驗證,因為此購買的是在沙盒進行的。
8.貨幣類型(Bank Account Currency) :填CNY(如果你的app在中國使用的話)。

  2.獲取不到商品信息

1
2
3
4
5
6
1.確定配置環節正確。
2.確定是真機測試且手機沒有越獄。
3.確定內購商品添加到了需要內購功能的App中。
4.確定當前運行的App的Bundle ID和后台配置的App的Bundle ID是一致的。
5.可以嘗試先刪除舊App,再重新編譯生成新的,避免新App未覆蓋錯誤。
6.這里要提一點,沙盒的測試賬號和你請求商品信息沒有關系。請求商品信息的流程是,你在后台配置好了內購商品,並且將其添加到了需要集成內購功能的App中,然后你請求商品。請求到商品后的流程是這樣的,蘋果系統會自動彈出登錄框讓你登錄賬號。然后根據提示操作進行購買,這里的賬號就是你配置的沙盒測試賬號。

二、為什么要使用內購?(why)和內購是什么?(what)

1
2
3
4
  1.如果你購買的商品,是在本app中使用和消耗的,就一定要用內購,否則會被拒絕上線,例如:游戲幣,在線書籍
app中使用的道具等。本例中,就是直播中你用來打賞用的金幣,那東西可就屬於消耗型的。
  2.如果是直接購買商城之類的快遞包郵的那些東東,那就直接調用支付寶,微信啦,之類的三方支付就好了,淘寶,京東都玩過哈!
比較坑的一點就是,內購的話,還要和蘋果3/7分成,那就可以說,充值相同的錢,相對來說,iOS是比安卓虧的!

三、怎樣使用內購?(how)

1
2
3
4
5
6
7
8
9
10
  1.使用內購需要哪些資料<br>     1張visa銀行卡,appid,1張銀行卡與蘋果三七分打錢用
    (1)協議、稅務和銀行業務
       聯系人信息:(appid賬號人)姓名,郵箱,電話號碼,地址(城市、具體街道分行寫)
       visa銀行卡信息:開戶行,開戶行所在地址,開戶行的郵政編碼,開戶行持有人卡號,開戶行持有人姓名
       稅務信息:1.會問你是不是美國居民選擇NO.  2. 有沒有在美國從事商業性活動,選擇NO. 之后填寫個人或組織名稱,所在國家,受益方式(獨立開發者選擇個人),居住地址,郵寄地址,聲明人,頭銜
        (2)內購產品id的配置 (開發人員配置)
            如果是金幣或其它消耗品的產品的話用消耗性型項目,參考名稱(內購項目,比如金幣100),產品id,定價信息,使用內購的快照,顯示名稱,描述。
    (3)用戶職能
      測試員:添加水箱測試員及沙箱賬號,水箱測試賬號不能是正常使用的appid賬號,直接使用一個沒有注冊過的郵箱賬號即可。
姓名,測試賬號密碼,appstore地區(必須填對)。

四、操作流程圖解與代碼

  1.創建app后填寫用戶信息

1
2
3
4
5
6
7
8
9
10
11
功能簡介 :
     1.我的App主要用於管理自己的App應用,例如編輯資料,上架,下架等。
     2.銷售和趨勢主要是來查看App在各個平台的下載量,收入等方面數據,里面有曲線圖等圖文結合的方式給我們參考。
     3.付款和財務報告顯示的是你的收入以及付款等相關信息。
     4.iAd主要是跟廣告有關,開發者可以登錄到Workbench,通過iAd對應用的廣告進行控制。
     5.用戶和職能用於生成相應賬號,例如蘋果沙盒測試賬號。
     6.協議,稅務和銀行業務則是你銀行相關賬戶的信息設置。
流程
  1.注冊app,填寫協議、稅務和銀行業務
    注冊app,需要設置Bundle identifier,此個步驟這里就不在寫了
   填寫協議、稅務和銀行業務

  

1
2
3
4
5
6
7
8
<strong>選擇申請合同類型</strong>
頁面內容:
Request Contracts(申請合同)
Contracts In Effect(已生效合同)。
合同類型:
iOS Free Application(免費應用合同)
iOS Paid Application(付費應用合同)
iAd App NetNetwork(廣告合同)

  1.申請iOS Paid Application合同

 2. 設置協議稅務、銀行卡信息

1
2
當我們點擊申請iOS Paid Application合同后,該合同的狀態會變成如下的樣子,我們可以看到其中Status為Contact, Bank, Pending Tax,
意思是聯系方式、銀行和稅務信息沒有填寫。

 

 2.1設置聯系人信息

1
2
3
4
5
6
7
如果你沒有添加過聯系人,你需要通過Add New Contact按鈕來添加一個新的聯系人。然后指定聯系人的職務,職務如下:
Senior Management:高管
Financial:財務
Technical:技術支持
Legal:法務
Marketing:市場推廣
如果你是獨立開發者,可以全部填你自己一個人。

  新增聯系人

  通過新增或之前增加的聯系人設置高管等信息

  

待完成后點擊Done,返回后狀態會變成Edit狀態

 2.2設置銀行卡信息(可以通過銀行名稱和地址直接上網查詢CNAPS Code號,不要問我上那查)

 

  

確認銀行卡信息

 

 2.3設置稅務信息(1.是美國稅務,只需要這個就行,后面的澳大利亞和日本的和我們沒的關系)

1
選擇U.S Tax Forms,選擇后會問你兩個問題,第一個問題如下:詢問你是否是美國居民,有沒有美國伙伴關系或者美國公司,如果沒有直接選擇No。

1
接下來第二個問題如下:詢問你有沒有在美國的商業性活動,沒有也直接選No。

然后填寫稅務信息

1
2
3
4
5
6
7
8
9
10
然后填寫你的稅務信息,包括以下幾點:
 
Individual or Organization Name:個人或者組織名稱
Country of incorporation: 所在國家
Type of Beneficial Owner:受益方式,獨立開發者選個人
Permanent Residence:居住地址
Mailing address:郵寄地址
Name of Person Making  this  Declaration:聲明人
Title:頭銜
當你填寫完所有資料后,合同狀態就會變成Processing,筆者凌晨1點左右提交,下午就通過了。

  具體填寫見下圖(以下是確認稅務信息圖)

  填寫完成后效果

 3.配置內購產品ID

1
2
完成以上操作,並且蘋果審核完畢之后,就可以配置內購產品了。
登錄 iTunesConnect -->我的App 模塊找到需要內購的App,最后找到頁面如下:

  

1
2
3
4
5
填寫沙箱測試員和添加內購產品注意事項
1、郵箱必須是沒有注冊或者說關聯過appstore的郵箱。
2、密碼必須有一個是大寫字母有一個是小寫字母(蘋果規定的,理解)。
3、內購屏幕截圖規格必須是312*290,且最低分辨率是72ppi。
4、內購的價格是蘋果規定的不能自定義(坑啊)。

4.增加內購測試賬號

     4.1 內購測試之前准備

1
2
3
4
5
6
7
8
9
10
11
12
13
14
1、什么是內購測試賬號(what)及為什么使用內購測試賬號(why)?
     iOS應用里面用到了蘋果應用內付費(IAP)功能,在項目上線前一定要進行功能測試。測試肯定是需要的,何況這個跟money有關。。。開發完成了之后,如何進行測試呢?難道我測試個內購功能要自己掏錢?就算是也是公司掏錢,但是蘋果要吃掉3成的啊,想想如果是99刀的商品,點下購買的時候心里都有點發慌。。。
蘋果當然沒這么坑了,測試內購,蘋果提供了沙盒賬號(也叫沙箱賬號)的方式。這個沙箱賬號其實是虛擬的AppleID,在開發者賬號后台的iTune Connect上配置了之后就能使用沙盒賬號測試內購,有了沙盒賬號,就能體驗一把土豪的感覺了,游戲鑽石什么的隨便充,反正不用我的錢。
     注意:你可以把沙盒賬號看做是一個虛擬的AppleID,這個AppleID只有進行內購測試的功能。重要,重要,重要,這個虛擬的賬號只能在自己的測試號中使用,如果在其它地方如appstore使用的話會提示賬號無效之類的話。   
 
2、如何使用內購測試賬號(how)?
     2.1作用內購賬號的前提
1)內購的商品ID,價格等相關信息已經錄入到開發者后台了(不然那你買什么)
2)開發者后台已經創建好沙盒測試賬號了(下面我們會將如何創建)
3)你要有一部真機(iPhone或iPad都行,別用模擬器就好。而且不能是越獄機)
4)bundleID別搞錯了,開發者賬號、證書、bundleID要一致
5)如果你是第一次在這個開發者賬號上集成內購功能,
請先將iTune Connect上的稅務協議都填寫好,否則內購時會發現商品ID無效。
  重要,如果不添加稅務協議會報錯,找不到商品。

  選擇用戶和職能就是在協議、稅務和銀行業務左側

   4.2內購測試開始

1
2
3
4
5
6
7
8
1.在iPhone上安裝測試包(必須是打包簽名證書或者develop簽名證書打的包,不能是從App Store上下載的)
2.退出iPhone的App Store賬號(因為我們需要使用沙盒賬號登錄)。
操作方法一:打開App Store應用首頁滑到最下方--選中AppleID--注銷
操作方法二:設置--iTunes Store與App Store--選中AppleID--注銷
3.不能用沙盒測試帳號來登錄appstore官網或去其它已上線平台去支付詳見圖4.21
4.運行下面代碼的demo,傳入你創建的產品id(就是在app iTunes Connect ->我的app ->功能 ->app內購買項目添加的商品),點擊充值跳轉開始購買詳見圖4.22
5.再次購買時需要輸入測試沙盒賬號密碼(在用戶和職能->沙箱技術測試員創建的測試賬號)詳見圖4.23
6.購買成功反饋詳見圖4.24

  4.21 圖

  4.22 圖

  4.23 圖

  4.24 圖

 

5.代碼及業務邏輯

   業務邏輯

  1. 獲取內購列表(從App內讀取或從自己服務器讀取)
  2. App Store請求可用的內購列表
  3. 向用戶展示內購列表
  4. 用戶選擇了內購列表,再發個購買請求,收到購買完成的回調(購買完成后會把錢打給申請內購的銀行卡內)
  5. 購買流程結束后, 向服務器發起驗證憑證以及支付結果的請求
  6. 自己的服務器將支付結果信息返回給前端並發放虛擬產品
  7. 服務端的工作比較簡單,分4步:

    1. 接收ios端發過來的購買憑證。
    2. 判斷憑證是否已經存在或驗證過,然后存儲該憑證。
    3. 將該憑證發送到蘋果的服務器驗證,並將驗證結果返回給客戶端。
    4. 如果需要,修改用戶相應的會員權限。

    考慮到網絡異常情況,服務器的驗證應該是一個可恢復的隊列,如果網絡失敗了,應該進行重試。

    簡單來說就是將該購買憑證用Base64編碼,然后POST給蘋果的驗證服務器,蘋果將驗證結果以JSON形式返回。

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
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
 代碼如下 :
/*注意事項:
1.沙盒環境測試appStore內購流程的時候,請使用沒越獄的設備。
2.請務必使用真機來測試,一切以真機為准。
3.項目的Bundle identifier需要與您申請AppID時填寫的bundleID一致,不然會無法請求到商品信息。
4.如果是你自己的設備上已經綁定了自己的AppleID賬號請先注銷掉,否則你哭爹喊娘都不知道是怎么回事。
5.訂單校驗 蘋果審核app時,仍然在沙盒環境下測試,所以需要先進行正式環境驗證,如果發現是沙盒環境則轉到沙盒驗證。
識別沙盒環境訂單方法:
  1.根據字段 environment = sandbox。
  2.根據驗證接口返回的狀態碼,如果status=21007,則表示當前為沙盒環境。
  蘋果反饋的狀態碼:
  21000App Store無法讀取你提供的JSON數據
  21002 訂單數據不符合格式
  21003 訂單無法被驗證
  21004 你提供的共享密鑰和賬戶的共享密鑰不一致
  21005 訂單服務器當前不可用
  21006 訂單是有效的,但訂閱服務已經過期。當收到這個信息時,解碼后的收據信息也包含在返回內容中
  21007 訂單信息是測試用(sandbox),但卻被發送到產品環境中驗證
  21008 訂單信息是產品環境中使用,但卻被發送到測試環境中驗證
  */
 
#import <Foundation/Foundation.h>
 
typedef  enum  {
     SIAPPurchSuccess = 0,        // 購買成功
     SIAPPurchFailed = 1,         // 購買失敗
     SIAPPurchCancle = 2,         // 取消購買
     SIAPPurchVerFailed = 3,      // 訂單校驗失敗
     SIAPPurchVerSuccess = 4,     // 訂單校驗成功
     SIAPPurchNotArrow = 5,       // 不允許內購
}SIAPPurchType;
 
typedef  void  (^IAPCompletionHandle)(SIAPPurchType type,NSData *data);
 
 
@ interface  STRIAPManager : NSObject
+ (instancetype)shareSIAPManager;
//開始內購
- ( void )startPurchWithID:(NSString *)purchID completeHandle:(IAPCompletionHandle)handle;
@end
.m
#import "STRIAPManager.h"
#import <StoreKit/StoreKit.h>
@ interface  STRIAPManager()<SKPaymentTransactionObserver,SKProductsRequestDelegate>{
    NSString           *_purchID;
    IAPCompletionHandle _handle;
}
@end
@implementation STRIAPManager
 
#pragma mark - ♻️life cycle
+ (instancetype)shareSIAPManager{
     
     static  STRIAPManager *IAPManager = nil;
     static  dispatch_once_t onceToken;
     dispatch_once(&onceToken,^{
         IAPManager = [[STRIAPManager alloc] init];
     });
     return  IAPManager;
}
- (instancetype)init{
     self = [super init];
     if  (self) {
         // 購買監聽寫在程序入口,程序掛起時移除監聽,這樣如果有未完成的訂單將會自動執行並回調 paymentQueue:updatedTransactions:方法
         [[SKPaymentQueue defaultQueue] addTransactionObserver:self];
     }
     return  self;
}
 
- ( void )dealloc{
     [[SKPaymentQueue defaultQueue] removeTransactionObserver:self];
}
 
 
#pragma mark - 🚪public
- ( void )startPurchWithID:(NSString *)purchID completeHandle:(IAPCompletionHandle)handle{
     if  (purchID) {
         if  ([SKPaymentQueue canMakePayments]) {
             // 開始購買服務
             _purchID = purchID;
             _handle = handle;
             NSSet *nsset = [NSSet setWithArray:@[purchID]];
             SKProductsRequest *request = [[SKProductsRequest alloc] initWithProductIdentifiers:nsset];
             request. delegate  = self;
             [request start];
         } else {
             [self handleActionWithType:SIAPPurchNotArrow data:nil];
         }
     }
}
#pragma mark - 🔒private
- ( void )handleActionWithType:(SIAPPurchType)type data:(NSData *)data{
#if DEBUG
     switch  (type) {
         case  SIAPPurchSuccess:
             NSLog( @"購買成功" );
             break ;
         case  SIAPPurchFailed:
             NSLog( @"購買失敗" );
             break ;
         case  SIAPPurchCancle:
             NSLog( @"用戶取消購買" );
             break ;
         case  SIAPPurchVerFailed:
             NSLog( @"訂單校驗失敗" );
             break ;
         case  SIAPPurchVerSuccess:
             NSLog( @"訂單校驗成功" );
             break ;
         case  SIAPPurchNotArrow:
             NSLog( @"不允許程序內付費" );
             break ;
         default :
             break ;
     }
#endif
     if (_handle){
         _handle(type,data);
     }
}
#pragma mark - 🍐delegate
// 交易結束
- ( void )completeTransaction:(SKPaymentTransaction *)transaction{
   // Your application should implement these two methods.
     NSString * productIdentifier = transaction.payment.productIdentifier;
     NSString * receipt = [transaction.transactionReceipt base64EncodedString];
     if  ([productIdentifier length] > 0) {
         // 向自己的服務器驗證購買憑證
     }
 
     [self verifyPurchaseWithPaymentTransaction:transaction isTestServer:NO];
}
 
// 交易失敗
- ( void )failedTransaction:(SKPaymentTransaction *)transaction{
     if  (transaction.error.code != SKErrorPaymentCancelled) {
         [self handleActionWithType:SIAPPurchFailed data:nil];
     } else {
         [self handleActionWithType:SIAPPurchCancle data:nil];
     }
     
     [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
}
 
- ( void )verifyPurchaseWithPaymentTransaction:(SKPaymentTransaction *)transaction isTestServer:(BOOL)flag{
     //交易驗證
     NSURL *recepitURL = [[NSBundle mainBundle] appStoreReceiptURL];
     NSData *receipt = [NSData dataWithContentsOfURL:recepitURL];
     
     if (!receipt){
         // 交易憑證為空驗證失敗
         [self handleActionWithType:SIAPPurchVerFailed data:nil];
         return ;
     }
     // 購買成功將交易憑證發送給服務端進行再次校驗
     [self handleActionWithType:SIAPPurchSuccess data:receipt];
     
     NSError *error;
     NSDictionary *requestContents = @{
                                       @"receipt-data" : [receipt base64EncodedStringWithOptions:0]
                                       };
     NSData *requestData = [NSJSONSerialization dataWithJSONObject:requestContents
                                                           options:0
                                                             error:&error];
     
     if  (!requestData) {  // 交易憑證為空驗證失敗
         [self handleActionWithType:SIAPPurchVerFailed data:nil];
         return ;
     }
     
     //In the test environment, use https://sandbox.itunes.apple.com/verifyReceipt
     //In the real environment, use https://buy.itunes.apple.com/verifyReceipt
     
     NSString *serverString =  @"https://buy.itunes.apple.com/verifyReceipt" ;
     if  (flag) {
         serverString =  @"https://sandbox.itunes.apple.com/verifyReceipt" ;
     }
     NSURL *storeURL = [NSURL URLWithString:serverString];
     NSMutableURLRequest *storeRequest = [NSMutableURLRequest requestWithURL:storeURL];
     [storeRequest setHTTPMethod: @"POST" ];
     [storeRequest setHTTPBody:requestData];
     
     NSOperationQueue *queue = [[NSOperationQueue alloc] init];
     [NSURLConnection sendAsynchronousRequest:storeRequest queue:queue
                            completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
                                if  (connectionError) {
                                    // 無法連接服務器,購買校驗失敗
                                    [self handleActionWithType:SIAPPurchVerFailed data:nil];
                                else  {
                                    NSError *error;
                                    NSDictionary *jsonResponse = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];
                                    if  (!jsonResponse) {
                                        // 蘋果服務器校驗數據返回為空校驗失敗
                                        [self handleActionWithType:SIAPPurchVerFailed data:nil];
                                    }
                                    
                                    // 先驗證正式服務器,如果正式服務器返回21007再去蘋果測試服務器驗證,沙盒測試環境蘋果用的是測試服務器
                                    NSString *status = [NSString stringWithFormat: @"%@" ,jsonResponse[ @"status" ]];
                                    if  (status && [status isEqualToString: @"21007" ]) {
                                        [self verifyPurchaseWithPaymentTransaction:transaction isTestServer:YES];
                                    } else  if (status && [status isEqualToString: @"0" ]){
                                        [self handleActionWithType:SIAPPurchVerSuccess data:nil];
                                    }
#if DEBUG
                                    NSLog( @"----驗證結果 %@" ,jsonResponse);
#endif
                                }
                            }];
     
     
     // 驗證成功與否都注銷交易,否則會出現虛假憑證信息一直驗證不通過,每次進程序都得輸入蘋果賬號
     [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
}
 
#pragma mark - SKProductsRequestDelegate
- ( void )productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response{
     NSArray *product = response.products;
     if ([product count] <= 0){
#if DEBUG
         NSLog( @"--------------沒有商品------------------" );
#endif
         return ;
     }
     
     SKProduct *p = nil;
     for (SKProduct *pro  in  product){
         if ([pro.productIdentifier isEqualToString:_purchID]){
             p = pro;
             break ;
         }
     }
     
#if DEBUG
     NSLog( @"productID:%@" , response.invalidProductIdentifiers);
     NSLog( @"產品付費數量:%lu" ,(unsigned  long )[product count]);
     NSLog( @"%@" ,[p description]);
     NSLog( @"%@" ,[p localizedTitle]);
     NSLog( @"%@" ,[p localizedDescription]);
     NSLog( @"%@" ,[p price]);
     NSLog( @"%@" ,[p productIdentifier]);
     NSLog( @"發送購買請求" );
#endif
     
     SKPayment *payment = [SKPayment paymentWithProduct:p];
     [[SKPaymentQueue defaultQueue] addPayment:payment];
}
 
//請求失敗
- ( void )request:(SKRequest *)request didFailWithError:(NSError *)error{
#if DEBUG
     NSLog( @"------------------錯誤-----------------:%@" , error);
#endif
}
 
- ( void )requestDidFinish:(SKRequest *)request{
#if DEBUG
     NSLog( @"------------反饋信息結束-----------------" );
#endif
}
 
#pragma mark - SKPaymentTransactionObserver
- ( void )paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray<SKPaymentTransaction *> *)transactions{
     for  (SKPaymentTransaction *tran  in  transactions) {
         switch  (tran.transactionState) {
             case  SKPaymentTransactionStatePurchased:
                 [self completeTransaction:tran];
                 break ;
             case  SKPaymentTransactionStatePurchasing:
#if DEBUG
                 NSLog( @"商品添加進列表" );
#endif
                 break ;
             case  SKPaymentTransactionStateRestored:
#if DEBUG
                 NSLog( @"已經購買過商品" );
#endif
                 // 消耗型不支持恢復購買
                 [[SKPaymentQueue defaultQueue] finishTransaction:tran];
                 break ;
             case  SKPaymentTransactionStateFailed:
                 [self failedTransaction:tran];
                 break ;
             default :
                 break ;
         }
     }
}
@end
在控制器中調用,導入頭文件
調用方法
- ( void )purchaseAction{
     
     if  (!_IAPManager) {
         _IAPManager = [STRIAPManager shareSIAPManager];
     }
     // iTunesConnect 蘋果后台配置的產品ID
     [_IAPManager startPurchWithID: @"com.bb.helper_advisory"  completeHandle:^(SIAPPurchType type,NSData *data) {
//請求事務回調類型,返回的數據
         
     }];
}
經典文章參考: 1.  http: //yimouleng.com/2015/12/17/ios-AppStore/  內購流程
        2.   http: //www.jianshu.com/p/b199a4672608   完成交易后和服務器交互
              3.   http: //www.jianshu.com/p/1ef61a785508 沙盒賬號測試
將來的自己,會感謝現在不放棄的自己!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM