iOS: 實現蘋果的內購


一、介紹:

在個人開發的app上架到AppStore后,蘋果官方允許我們將自己的app在appstore上進行付費使用,也就是所謂的內購。其中,支付方式規定的必須是蘋果的支付方式:應用內支付。

 

二、流程:

1、后台設置

(1)配置Developer.apple.com,為應用建立一個不帶通配符的App ID

(2)用該應用的App ID生成和安裝相應的Provisioning Profile文件

 

2、配置iTunes Connect

(1)用該App ID創建一個新的應用;

(2)在該應用中,創建應用內付費項目,選擇付費類型,通常可選的是可重復消費的(Consumenable)和永久有效的(Non-Consumenable)兩種,然后設置好價格、Product ID、購買介紹和截圖,這里的Product ID是必須記住的,后面開發的時候要用到;

(3)添加一個用於在sandbox付費的測試用戶,注意蘋果對測試用戶的密碼要求和正是賬號一樣,至少8位,並且包包含數字和大小寫字母;

(4)填寫相關的稅務。銀行和聯系人

 

3、iOS端開發

(1)在工程中引入storeKit.framework和#import <storeKit/storeKit.h>;

(2)獲取所有的付費Product ID列表。這個可以用常量存儲到本地,也可以由自己的服務器返回;

(3)制作一個界面(如tableView),顯示所有的應用內付費項目。這些應用內付費項目的價格和介紹信息可以是自己的服務器返回。但如果是不帶服務器的單機游戲應用或者工具類應用,則可以通過向App Store查詢所得;

(4)當用戶點擊一個IAP項目,我們需要先查詢用戶是否允許應用內付費,如果不允許則不進行接下來的步驟;

(5)先通過該IAP的ProductID向AppStore查詢,獲取SKPayment實例,然后通過SKPaymentQueue的addPayment方法發起一個購買的操作;

(6)在ViewdidLoad方法中,將購買頁面設置成購買額observe;

(7)當用戶購買的操作有結果時,就會觸發調用回調函數,相應的進行處理;

(8)服務器驗證憑證(可選項)。如果購買成功,我們需要將憑證發送到服務器上進行驗證。考慮到網路異常情況,iOS端的發送憑證操作應該可以持久化,如果程序退出、崩潰或者網絡異常,可以恢復重試。

 

4、服務端開發

(1)接收iOS端發過來的購買憑證;

(2)判斷憑證是否已經存在,是否驗證過,然后進行存儲;

(3)將該憑證發送到蘋果的服務器驗證,並將結果返回給客戶端;

(4)如果需要,修改用戶相應的會員權限。

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

蘋果AppStore線上的購買憑證驗證地址:https://buy.itunes.apple.com/verifyreceipt

測試的驗證地址:https://sandbox.itunes.apple.com/verifyreceipt

 

三、iOS基本代碼如下:

//  ViewController.m
//
//  Created by 夏遠全 on 16/11/20.
//  Copyright © 2016年 廣州市東德網絡科技有限公司. All rights reserved.
//

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

@interface ViewController ()<SKProductsRequestDelegate,SKPaymentTransactionObserver>

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    //監聽購買結果
    [[SKPaymentQueue defaultQueue] addTransactionObserver:self];
}

-(void)dealloc{
    
    //移除購買監聽
    [[SKPaymentQueue defaultQueue] removeTransactionObserver:self];
}


//用戶點擊一個IAP項目時,首先查詢用戶是否允許應用內付費(tableViewCell點擊時,傳遞內購商品ProductId,ProductID可以提前存儲到本地,用到時直接獲取即可)
-(void)validateIsCanBought{
    
    if ([SKPaymentQueue canMakePayments]) {
        [self getProductInfo:@[@"ProductIds"]];
    }else{
        NSLog(@"失敗,用戶禁止應用內付費購買");
    }
}

//通過該IAP的Product ID向App Store查詢,獲取SKPayment實例,接着通過SKPaymentQueue的addPayment方法發起一個購買的操作
//下面的ProductId應該是事先在itunesConnect中添加好的,已存在的付費項目,否則會查詢失敗
-(void)getProductInfo:(NSArray *)productIds{
    
    NSSet *set = [NSSet setWithArray:productIds];
    SKProductsRequest *request = [[SKProductsRequest alloc] initWithProductIdentifiers:set];
    request.delegate = self;
    [request start];
}

#pragma mark - SKProductsRequestDelegate
//查詢的回調函數
-(void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response{
    
    //獲取到的所有內購商品
    NSArray *myProducts = response.products;
    
    //判斷個數
    if (myProducts.count==0) {
        NSLog(@"無法獲取產品信息,購買失敗。");
        return;
    }
    
    //發起一個購買操作
    SKPayment *payment = [SKPayment paymentWithProduct:myProducts[0]];
    [[SKPaymentQueue defaultQueue] addPayment:payment];
}

#pragma mark - SKPaymentTransactionObserver
//當用戶購買的操作有結果時,就會觸發下面的回調函數,相應進行處理
-(void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray<SKPaymentTransaction *> *)transactions{
    
    for (SKPaymentTransaction *transaction in transactions) {
        
        switch (transaction.transactionState) {
            case SKPaymentTransactionStatePurchased:  //交易完成
                NSLog(@"transactionIdentifier = %@",transaction.transactionIdentifier);
                [self completeTransaction:transaction];
                break;
            case SKPaymentTransactionStateFailed:     //交易失敗
                [self failedTransaction:transaction];
                break;
            case SKPaymentTransactionStateRestored:  //已經購買過該商品
                [self restoreTransaction:transaction];
                break;
            case SKPaymentTransactionStatePurchasing: //商品添加進列表
                NSLog(@"商品添加進列表");
                break;
            default:
                break;
        }
    }
}

//交易完成后的操作
-(void)completeTransaction:(SKPaymentTransaction *)transaction{
    
    NSString *productIdentifier = transaction.payment.productIdentifier;
    NSData *transactionReceiptData = [NSData dataWithContentsOfURL:[[NSBundle mainBundle] appStoreReceiptURL]];
    NSString *receipt = [transactionReceiptData base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength];
    
    if ([productIdentifier length]>0) {
        //向自己的服務器驗證購買憑證
        NSLog(@"%@",receipt);
    }
    
    //移除transaction購買操作
    [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
}

//交易失敗后的操作
-(void)failedTransaction:(SKPaymentTransaction *)transaction{
    
    if (transaction.error.code != SKErrorPaymentCancelled) {
        NSLog(@"購買失敗");
    }else{
        NSLog(@"用戶取消交易");
    }
    //移除transaction購買操作
    [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
}

//已經購買過該商品
-(void)restoreTransaction:(SKPaymentTransaction *)transaction{
 
    //對於已購買商品,處理恢復購買的邏輯
    //移除transaction購買操作
    [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
}

@end

 

三、個人參考demo

https://github.com/xiayuanquan/AppleStoreKitDemo.git

效果圖:

 

打印日志:

2017-02-28 18:21:08.009166 StoreKit[18455:370113] [MC] Reading from private effective user settings.
2017-02-28 18:21:08.012 StoreKit[18455:370113] ---------請求對應的產品信息------------
2017-02-28 18:21:08.015 StoreKit[18455:370113] 允許程序內付費購買
2017-02-28 18:21:09.193 StoreKit[18455:370113] -----------收到產品反饋信息--------------
2017-02-28 18:21:09.193 StoreKit[18455:370113] 產品Product ID:(
)
2017-02-28 18:21:09.194 StoreKit[18455:370113] 產品付費數量: 1
2017-02-28 18:21:09.194 StoreKit[18455:370113] product info
2017-02-28 18:21:09.194 StoreKit[18455:370113] SKProduct 描述信息<SKProduct: 0x600000004950>
2017-02-28 18:21:09.194 StoreKit[18455:370113] 產品標題 1元=10金幣
2017-02-28 18:21:09.195 StoreKit[18455:370113] 產品描述信息: 通過虛擬金幣充值,獲取會員資格
2017-02-28 18:21:09.195 StoreKit[18455:370113] 價格: 0.99
2017-02-28 18:21:09.195 StoreKit[18455:370113] Product id: www.biaojiepay.com.StoreKit01
2017-02-28 18:21:09.195 StoreKit[18455:370113] ---------發送購買請求------------
2017-02-28 18:21:09.196 StoreKit[18455:370113] -----paymentQueue--------
2017-02-28 18:21:09.196 StoreKit[18455:370113] -----商品添加進列表 --------
2017-02-28 18:21:09.196 StoreKit[18455:370113] ----------反饋信息結束--------------
2017-02-28 18:21:10.125470 StoreKit[18455:370288] subsystem: com.apple.BackBoardServices.fence, category: Observer, enable_level: 1, persist_level: 0, default_ttl: 0, info_ttl: 0, debug_ttl: 0, generate_symptoms: 0, enable_oversize: 0, privacy_setting: 0, enable_private_data: 0
2017-02-28 18:21:10.127183 StoreKit[18455:370113] subsystem: com.apple.BackBoardServices.fence, category: Workspace, enable_level: 1, persist_level: 0, default_ttl: 0, info_ttl: 0, debug_ttl: 0, generate_symptoms: 0, enable_oversize: 0, privacy_setting: 0, enable_private_data: 0
2017-02-28 18:21:10.127707 StoreKit[18455:370113] subsystem: com.apple.BackBoardServices.fence, category: Trace, enable_level: 1, persist_level: 0, default_ttl: 0, info_ttl: 0, debug_ttl: 0, generate_symptoms: 0, enable_oversize: 0, privacy_setting: 0, enable_private_data: 0
2017-02-28 18:21:12.044 StoreKit[18455:370113] -----paymentQueue--------
2017-02-28 18:21:12.045 StoreKit[18455:370113] 失敗
2017-02-28 18:21:12.048 StoreKit[18455:370113] -----交易失敗 --------

 


免責聲明!

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



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