1. 程式人生 > 其它 >iOS開發·內購流程

iOS開發·內購流程

2019獨角獸企業重金招聘Python工程師標準>>> hot3.png

說明:
涉及到金額交易,蘋果稽核的一般嚴格許多。蘋果在涉及需要支付中間幣的購買必須走蘋果內購(例:點券、鑽石、K幣等等),若是涉及實物的交易,則可以走第三方(支付寶、微信等)支付購買。

iOS內購流程:

一、設定協議

1、登入蘋果開發者後臺,點選itunes Connect -> 協議、稅務和銀行業務

協議、稅務和銀行業務

2、點選Request Contracts(申請合同)下面的request,點選一直確定下去。

申請合同-1

Contact info:聯絡人資訊
Bank info:銀行資訊
Tax info:稅務資訊

申請合同-2

3、首先設定聯絡人資訊,點選Contact info下面的 Set up(設定),點選Add New Contract(增加先的聯絡方式)

申請合同-3

4、填寫詳情(填寫完成後點選save)

填寫詳情

5、在下面的所有專案中選擇剛剛填寫的資訊,選擇後點擊右下角的Done(完成),你可以建立聯絡人,在不同的職務選擇不同的聯絡人。

Senior Management:高管
Financial:財務
Technical:技術支援
Legal:法務
Marketing:市場推廣

填寫資訊

6、設定銀行資訊,點選Back info下面的Set up,彈出頁面

點選Add Bank Account(新增銀行賬號)

image

選擇china,後點擊next。

image

填寫了CNAPS Code後點擊Next

image

會彈出你的銀行卡開戶地的資訊,確認一下點選next

image

填寫銀行卡資訊,注意:戶主名只能寫拼音,比如:李三(Li San)。填完後點擊Next

image

彈出確定資訊頁面,在下面打鉤後點擊Save

image

點選了save後就可以在彈出的頁面中選擇剛剛填寫的卡了。選擇後點擊Save

image

7、設定稅務資訊,點選Tax info下面的Set up,此時聯絡人資訊已經變成可以編輯狀態,銀行資訊為瀏覽狀態。

image

彈出的介面中,稅務分為三種
U.S Tax Forms: 美國稅務

Australia Tax Forms:澳大利亞稅務
Canada Tax Forms: 加拿大稅務
這裡我選擇的美國稅務,就是第一個

image

彈出第一個選擇,點選submit(提交)後,彈出第二個選擇

image

彈出第二個選擇,選擇後點擊submit

image

彈出第三個頁面,填寫的資料後點擊提交,記得勾選頁面上的幾個複選框

image

在提交成功後,狀態就變成processing成功

image

到這裡設定的協議就已經設定完畢。

二、建立專案的內購

1、進入到APP資訊頁面,點選功能,在彈出的頁面點選App內購買專案後面的➕

image

2、在彈出的新對話方塊中選擇你需要哪一種服務,由於我的專案需要兌換成消耗的金幣,所以我選擇第一個。選擇後點擊建立。

image

3、開始填寫內購專案資訊。填完後點擊右上角的儲存(所有資訊必須填寫完整)。

image

4、點選儲存後,內購列表就會有剛剛建立的內購條目。

image

你app有幾個內購級別就需要依次建立幾個條目。

新增測試賬號,用來測試支付功能

1、點選圖中使用者和職能

image

2、點選沙盒測試員,然後點選左邊的➕

image

3、設定好資訊點選右上角儲存就可以,記住裡面的郵箱和密碼用於支付的時候登陸Apple id

image

三、程式碼整合

建立一個測試類:

#import "TestPayController.h"

// 1.首先匯入支付包
#import <StoreKit/StoreKit.h>

// 2.設定代理服務
@interface TestPayController ()<SKPaymentTransactionObserver,SKProductsRequestDelegate>

@end

@implementation TestPayController

- (void)viewDidLoad {
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor whiteColor];

    //3.建立測試按鈕
    UIButton *testBtn = [[UIButton alloc] initWithFrame:CGRectMake(100, 100, 100, 100)];
    testBtn.backgroundColor = [UIColor redColor];
    [testBtn addTarget:self action:@selector(clickTestBtnAction) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:testBtn];

    // 4.設定支付服務
    [[SKPaymentQueue defaultQueue] addTransactionObserver:self];

}

//點選測試按鈕
- (void)clickTestBtnAction
{

    // 5.點選按鈕的時候判斷app是否允許apple支付

    //如果app允許applepay
    if ([SKPaymentQueue canMakePayments]) {
        NSLog(@"yes");

        // 6.請求蘋果後臺商品
        [self getRequestAppleProduct];
    }
    else
    {
        NSLog(@"not");
    }
}

//請求蘋果商品
- (void)getRequestAppleProduct
{
    // 7.這裡的com.czchat.CZChat01就對應著蘋果後臺的商品ID,他們是通過這個ID進行聯絡的。
    NSArray *product = [[NSArray alloc] initWithObjects:@"com.czchat.CZChat01",nil];

    NSSet *nsset = [NSSet setWithArray:product];

    // 8.初始化請求
    SKProductsRequest *request = [[SKProductsRequest alloc] initWithProductIdentifiers:nsset];
    request.delegate = self;

    // 9.開始請求
    [request start];
}

// 10.接收到產品的返回資訊,然後用返回的商品資訊進行發起購買請求
- (void) productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response
{
    NSArray *product = response.products;

    //如果伺服器沒有產品
    if([product count] == 0){
        NSLog(@"nothing");
        return;
    }

    SKProduct *requestProduct = nil;
    for (SKProduct *pro in product) {

        NSLog(@"%@", [pro description]);
        NSLog(@"%@", [pro localizedTitle]);
        NSLog(@"%@", [pro localizedDescription]);
        NSLog(@"%@", [pro price]);
        NSLog(@"%@", [pro productIdentifier]);

        // 11.如果後臺消費條目的ID與我這裡需要請求的一樣(用於確保訂單的正確性)
        if([pro.productIdentifier isEqualToString:@"com.czchat.CZChat01"]){
            requestProduct = pro;
        }
    }

    // 12.傳送購買請求
    SKPayment *payment = [SKPayment paymentWithProduct:requestProduct];
    [[SKPaymentQueue defaultQueue] addPayment:payment];
}

//請求失敗
- (void)request:(SKRequest *)request didFailWithError:(NSError *)error{
    NSLog(@"error:%@", error);
}

//反饋請求的產品資訊結束後
- (void)requestDidFinish:(SKRequest *)request{
    NSLog(@"資訊反饋結束");
}

// 13.監聽購買結果
- (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(@"已經購買過商品");
                [[SKPaymentQueue defaultQueue] finishTransaction:tran];
                break;
            case SKPaymentTransactionStateFailed:
                NSLog(@"交易失敗");
                [[SKPaymentQueue defaultQueue] finishTransaction:tran];
                break;
            default:
                break;
        }
    }
}

// 14.交易結束,當交易結束後還要去appstore上驗證支付資訊是否都正確,只有所有都正確後,我們就可以給使用者方法我們的虛擬物品了。
- (void)completeTransaction:(SKPaymentTransaction *)transaction
{
    NSString * str=[[NSString alloc]initWithData:transaction.transactionReceipt encoding:NSUTF8StringEncoding];

    NSString *environment=[self environmentForReceipt:str];
    NSLog(@"----- 完成交易呼叫的方法completeTransaction 1--------%@",environment);

    // 驗證憑據,獲取到蘋果返回的交易憑據
    // appStoreReceiptURL iOS7.0增加的,購買交易完成後,會將憑據存放在該地址
    NSURL *receiptURL = [[NSBundle mainBundle] appStoreReceiptURL];
    // 從沙盒中獲取到購買憑據
    NSData *receiptData = [NSData dataWithContentsOfURL:receiptURL];
    /**
     20      BASE64 常用的編碼方案,通常用於資料傳輸,以及加密演算法的基礎演算法,傳輸過程中能夠保證資料傳輸的穩定性
     21      BASE64是可以編碼和解碼的
     22      */
    NSString *encodeStr = [receiptData base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithLineFeed];

    NSString *sendString = [NSString stringWithFormat:@"{\"receipt-data\" : \"%@\"}", encodeStr];
    NSLog(@"_____%@",sendString);
    NSURL *StoreURL=nil;
    if ([environment isEqualToString:@"environment=Sandbox"]) {

        StoreURL= [[NSURL alloc] initWithString: @"https://sandbox.itunes.apple.com/verifyReceipt"];
    }
    else{

        StoreURL= [[NSURL alloc] initWithString: @"https://buy.itunes.apple.com/verifyReceipt"];
    }
    //這個二進位制資料由伺服器進行驗證;zl
    NSData *postData = [NSData dataWithBytes:[sendString UTF8String] length:[sendString length]];

    NSLog(@"++++++%@",postData);
    NSMutableURLRequest *connectionRequest = [NSMutableURLRequest requestWithURL:StoreURL];

    [connectionRequest setHTTPMethod:@"POST"];
    [connectionRequest setTimeoutInterval:50.0];//120.0---50.0zl
    [connectionRequest setCachePolicy:NSURLRequestUseProtocolCachePolicy];
    [connectionRequest setHTTPBody:postData];

    //開始請求
    NSError *error=nil;
    NSData *responseData=[NSURLConnection sendSynchronousRequest:connectionRequest returningResponse:nil error:&error];
    if (error) {
        NSLog(@"驗證購買過程中發生錯誤,錯誤資訊:%@",error.localizedDescription);
        return;
    }
    NSDictionary *dic=[NSJSONSerialization JSONObjectWithData:responseData options:NSJSONReadingAllowFragments error:nil];
    NSLog(@"請求成功後的資料:%@",dic);
//這裡可以等待上面請求的資料完成後並且state = 0 驗證憑據成功來判斷後進入自己伺服器邏輯的判斷,也可以直接進行伺服器邏輯的判斷,驗證憑據也就是一個安全的問題。樓主這裡沒有用state = 0 來判斷。
    //  [[SKPaymentQueue defaultQueue] finishTransaction: transaction];

    NSString *product = transaction.payment.productIdentifier;

    NSLog(@"transaction.payment.productIdentifier++++%@",product);

    if ([product length] > 0)
    {
        NSArray *tt = [product componentsSeparatedByString:@"."];

        NSString *bookid = [tt lastObject];

        if([bookid length] > 0)
        {

            NSLog(@"列印bookid%@",bookid);
//這裡可以做操作吧使用者對應的虛擬物品通過自己伺服器進行下發操作,或者在這裡通過判斷得到使用者將會得到多少虛擬物品,在後面([self getApplePayDataToServerRequsetWith:transaction];的地方)上傳上面自己的伺服器。
        }
    }
//此方法為將這一次操作上傳給我本地伺服器,記得在上傳成功過後一定要記得銷燬本次操作。呼叫[[SKPaymentQueue defaultQueue] finishTransaction: transaction];
    [self getApplePayDataToServerRequsetWith:transaction];
}

//結束後一定要銷燬
- (void)dealloc
{
    [[SKPaymentQueue defaultQueue] removeTransactionObserver:self];
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
}

-(NSString * )environmentForReceipt:(NSString * )str
{
    str= [str stringByReplacingOccurrencesOfString:@"\r\n" withString:@""];

    str = [str stringByReplacingOccurrencesOfString:@"\n" withString:@""];

    str = [str stringByReplacingOccurrencesOfString:@"\t" withString:@""];

    str=[str stringByReplacingOccurrencesOfString:@" " withString:@""];

    str=[str stringByReplacingOccurrencesOfString:@"\"" withString:@""];

    NSArray * arr=[str componentsSeparatedByString:@";"];

    //儲存收據環境的變數
    NSString * environment=arr[2];
    return environment;
}

@end

四、注意事項

1、必須用真機測試;
2、測試的時候必須退出自己的apple ID,彈出頁面後登陸沙盒的測試apple id;
3、在需要修改已經上線的內購的時候需要重新建立新的內購條目,然後重新提交;
4、文章大部分內容來自iOS內購流程,感謝該作者的分享;

五、參考文章:

iOS內購流程-https://www.jianshu.com/p/f7bff61e0b31/

ps:

https://www.jianshu.com/p/31f2eaebfa4b

https://www.cnblogs.com/haohao-developer/p/5613998.html

https://cloud.tencent.com/developer/article/1423496

轉載於:https://my.oschina.net/jack088/blog/3055958