1. 程式人生 > >蘋果內購買筆記

蘋果內購買筆記

如果 記得 nes finish iap leg 付費 quest arr

蘋果內購買包括4種類型:1.消耗性; 2.非消耗性;3.自動續訂訂閱;4.非續訂訂閱.

首先需要有一個itunesconnect上協議、稅務和銀行業務模塊中有銀行卡綁定同時遵守了各種蘋果協議的開發帳號;(具體如何申請填寫網上百度一堆)

然後代碼前記得添加協議

<SKPaymentTransactionObserver,SKProductsRequestDelegate,SKRequestDelegate>

//購買點擊
-(void)payBtnClick
{
    //購買
        if ([SKPaymentQueue canMakePayments]) {
            [self requestProductData:ProductId];

        } else {
            NSLog(@"用戶禁止應用內付費購買.");

        }
}
//恢復點擊
-(void)restoreClick
{
    [[SKPaymentQueue defaultQueue] restoreCompletedTransactions];
}

//請求商品
- (void)requestProductData:(NSString *)type{
    NSLog(@"----------請求對應的產品信息---------");
    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){
        NSLog(@"------沒有商品,商品個數為%ld--------",product.count);
        return;
    }

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

        if([pro.productIdentifier isEqualToString:ProductId]){
            p = pro;
        }
    }

    SKPayment *payment = [SKPayment paymentWithProduct:p];

    NSLog(@"發送購買請求");

    [[SKPaymentQueue defaultQueue] addPayment:payment];

}


- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions//交易結果
{

    NSLog(@"paymentQueue");
    for (SKPaymentTransaction *transaction in transactions)
    {

        switch (transaction.transactionState)
        {
            case SKPaymentTransactionStateRestored://已經購買過該商品,恢復商品
                [self restoreTransaction:transaction];
                NSLog(@"-----已經購買過該商品 恢復商品--------");
                //                [[XTool shareAppHandle]showWait:NO];
                break;
            case SKPaymentTransactionStatePurchased://交易完成
                [self completeTransaction:transaction];
                NSLog(@"-----交易完成 --------");
                break;
            case SKPaymentTransactionStateFailed://交易失敗
                [self failedTransaction:transaction];
                NSLog(@"-----交易失敗 --------");
                [[XTool shareAppHandle]showPaiXuWait:NO];
                break;
            case SKPaymentTransactionStatePurchasing:      //商品添加進列表
                NSLog(@"-----商品添加進列表 --------");
                break;
            case SKPaymentTransactionStateDeferred:
                break;
            default:
                break;
        }
    }

}

//完成恢復
- (void)paymentQueueRestoreCompletedTransactionsFinished:(SKPaymentQueue *)queue
{
    NSLog(@"paymentQueueRestoreCompletedTransactionsFinished");

    NSLog(@"%@",[queue description]);

    NSLog(@"-----完成恢復--------");

}


- (void) restoreTransaction: (SKPaymentTransaction *)transaction
{
    NSLog(@" 交易恢復處理");
    NSLog(@"-----恢復成功--------");
  
    NSData *iapData = transaction.transactionReceipt;


    // Your application should implement these two methods.
    NSString *product = transaction.payment.productIdentifier;
    if ([product length] > 0) {

        NSArray *tt = [product componentsSeparatedByString:@"."];
        NSString *bookid = [tt lastObject];
        if ([bookid length] > 0) {
            [self recordTransaction:bookid];
            [self provideContent:bookid];
        }
    }

    NSString *results = [[NSString alloc]initWithBytes:[iapData bytes] length:[iapData length] encoding:NSUTF8StringEncoding];

    {
        //    恢復交易信息發送給服務器代碼
    }
    [[SKPaymentQueue defaultQueue] finishTransaction: transaction];
}
        

//記錄交易
-(void)recordTransaction:(NSString *)product{
    NSLog(@"-----記錄交易--------");
}

//處理下載內容
-(void)provideContent:(NSString *)product{
    NSLog(@"-----下載--------");
}


-(void) PurchasedTransaction: (SKPaymentTransaction *)transaction{
    NSLog(@"-----PurchasedTransaction----");
    NSArray *transactions =[[NSArray alloc] initWithObjects:transaction, nil];
    [self paymentQueue:[SKPaymentQueue defaultQueue] updatedTransactions:transactions];
    [[SKPaymentQueue defaultQueue] finishTransaction: transaction];
}

- (void) completeTransaction: (SKPaymentTransaction *)transaction

{
    NSLog(@"-----購買成功--------");

    NSData *iapData = transaction.transactionReceipt;


    // Your application should implement these two methods.
    NSString *product = transaction.payment.productIdentifier;
    if ([product length] > 0) {

        NSArray *tt = [product componentsSeparatedByString:@"."];
        NSString *bookid = [tt lastObject];
        if ([bookid length] > 0) {
            [self recordTransaction:bookid];
            [self provideContent:bookid];
        }
    }

    NSString *results = [[NSString alloc]initWithBytes:[iapData bytes] length:[iapData length] encoding:NSUTF8StringEncoding];
    NSLog(@"%@",results);

    {
            //購買信息發送給服務器
    }
    [[SKPaymentQueue defaultQueue] finishTransaction: transaction];

}    


- (void) failedTransaction: (SKPaymentTransaction *)transaction{
 
    if (transaction.error.code != SKErrorPaymentCancelled)
    {
    }
    [[SKPaymentQueue defaultQueue] finishTransaction: transaction];


}



- (void)request:(SKRequest *)request didFailWithError:(NSError *)error{
    
    NSLog(@" 購買失敗");
}

-(void) paymentQueue:(SKPaymentQueue *) paymentQueue restoreCompletedTransactionsFailedWithError:(NSError *)error{
    NSLog(@"-------paymentQueue----");
}

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response{
    NSLog(@"%ld",(long)[(NSHTTPURLResponse *)response statusCode]);
    switch([(NSHTTPURLResponse *)response statusCode]) {
        case 200:
        case 206:
            break;
        case 304:
            break;
        case 400:
            break;
        case 404:
            break;
        case 416:
            break;
        case 403:
            break;
        case 401:
        case 500:
            break;
        default:
            break;
    }
}

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
    NSLog(@"test");
}


-(void) requestDidFinish:(SKRequest *)request
{
    NSLog(@"-----反饋信息結束-------");

}


- (BOOL)verify:(SKPaymentTransaction *)transaction
{
    return YES;
}

購買所需基本代碼如上;

1.消耗型

宏定義(或者從服務器都行,看需求)獲取個購買產品的ID(itunesconnect上申請的產品ID),將上面代碼中

ProductId替換成購買產品的ID

然後將返回信息發送給服務器進行處理

然後服務器端和蘋果進行購買驗證,確認購買成功後,返回給客戶端購買產品成功

客戶端顯示相應購買內容。

2.非消耗型

同消耗型,唯一區別是重復購買,蘋果會提示你不能重復購買。跟客戶端及服務器沒啥關系。

3.自動續訂訂閱

購買流程同消耗型,多了個恢復購買,同時在顯示時一定要有提醒用戶當前訂閱為自動續訂的文字說明,否則蘋果審核可能被拒

恢復流程時,用戶點擊恢復購買後,執行

restoreClick方法

進行恢復流程正常的話會執行(不正常,就需要檢查產品申請的內容;沙盒測試帳號問題;等等前面步驟是否有錯)

restoreTransaction方法

在獲取到用戶購買信息後客戶端傳給服務器,服務器端和蘋果進行數據驗證,驗證無誤後返回給客戶端相應用戶應該恢復的產品內容,客戶端進行展示。

4.非續訂訂閱

購買流程同消耗型;

恢復流程需要進入頁面後點擊恢復時執行

restoreClick方法

同時執行如下代碼進行用戶購買記錄數據獲取,不斷獲取直到獲取到或者用戶取消恢復為止。

    NSURLRequest *urlRequest = [NSURLRequest requestWithURL:[[NSBundle mainBundle] appStoreReceiptURL]];
    NSError *error = nil;
    NSData *iapData  = [NSURLConnection sendSynchronousRequest:urlRequest returningResponse:nil error:&error];
        NSString *transactionReceiptString = [iapData base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithLineFeed];

如果獲取到說明用戶已經輸入了AppleID,並進行了恢復操作;

此時將獲取到的用戶購買記錄及當前恢復產品ID發送給服務器,服務器和蘋果進行購買確認。如果已經購買此產品,則向客戶端返回恢復成功信息。客戶端展示相應需要恢復展示的內容。

蘋果內購買筆記