蘋果內(nèi)購(訂購為主)

蘋果支付

一:綁定銀行卡visa卡 參考鏈接

參考2

二:創(chuàng)建內(nèi)購產(chǎn)品 :app里面的功能 參考鏈接

三:創(chuàng)建沙盒測試賬戶:Itunes里面用戶和職能。參考鏈接

四:購買代碼塊 參考鏈接

+(instancetype)share{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        applePay = [[AHApplePay alloc]init];
    });
    if (applePay.myProducts.count == 0) {
        [applePay getPurchaseGoodsList];
    }
    return applePay;
}

//獲取商品列表
-(void)getPurchaseGoodsList{
    if ([SKPaymentQueue canMakePayments]) {
        //此處內(nèi)購商品編碼是虛構(gòu)的 ?????
        NSString *productPath = [[NSBundle mainBundle] pathForResource:@"productIDS" ofType:@"plist"];
        NSArray *products = [NSArray arrayWithContentsOfFile:productPath];
        [self getProductInfo:products];
    }else{
        if (_cannotPurchaseBlock) {
            _cannotPurchaseBlock(nil,@"失敗,用戶禁止應(yīng)用內(nèi)付費購買");
        }
    }
}

//購買商品
-(void)purchaseGoods:(id)goods{
    
    [self purchaseGoodsWithApplePurchase:goods];
}

//蘋果支付
-(void)purchaseGoodsWithApplePurchase:(id)goods{
    NSString *identify = (NSString*)goods;
    SKProduct *paymentPay = nil;
    for (SKProduct *payment in self.myProducts) {
        if ([payment.productIdentifier isEqualToString:identify]) {
            paymentPay = payment;
        }
    }
    if (paymentPay == nil) {
        return;
    }
    //1.發(fā)起一個購買操作
    SKPayment *payment = [SKPayment paymentWithProduct:paymentPay];
    if (payment == nil) {
        return;
    }
    // 2.將票據(jù)加到到交易隊列中
    [[SKPaymentQueue defaultQueue] addPayment:payment];
    //3.觀察交易隊列中交易發(fā)生的改變
    [[SKPaymentQueue defaultQueue] addTransactionObserver:self];
}

//購買 根據(jù)在plist文件位置
-(void)applePay:(NSInteger)idx{
    NSString *productPath = [[NSBundle mainBundle] pathForResource:@"productIDS" ofType:@"plist"];
    NSArray *products = [NSArray arrayWithContentsOfFile:productPath];
    if (idx<products.count) {
        NSString *identify = products[idx];
        [self.myProducts enumerateObjectsUsingBlock:^(SKProduct *payment, NSUInteger idx, BOOL * _Nonnull stop) {
            if ([payment.productIdentifier isEqualToString:identify]) {
                //1.發(fā)起一個購買操作
                SKPayment *paymentPro = [SKPayment paymentWithProduct:payment];
                // 2.將票據(jù)加到到交易隊列中
                [[SKPaymentQueue defaultQueue] addPayment:paymentPro];
                //3.觀察交易隊列中交易發(fā)生的改變
                [[SKPaymentQueue defaultQueue] addTransactionObserver:self];
                
            }
            
        }];
        
    }
    
}

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

#pragma mark - SKProductsRequestDelegate

//查詢的回調(diào)函數(shù) -----獲取可銷售的商品,并且排序
-(void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response{
    
    //獲取到的所有內(nèi)購商品
    NSArray *myProducts = response.products;
    //判斷個數(shù)
    if (myProducts.count==0) {
        if (_failureBlock) {
            _failureBlock(nil,@"無法獲取產(chǎn)品信息,購買失敗。");
        }
        NSLog(@"無法獲取產(chǎn)品信息,購買失敗。");
        return;
    }else{
        self.myProducts = myProducts;
    }
    //刷新、配置UI ???
#warning 發(fā)起一個購買操作
    //        //1.發(fā)起一個購買操作
    //        SKPayment *payment = [SKPayment paymentWithProduct:myProducts[self.purchaseGoodsNumber]];
    //        // 2.將票據(jù)加到到交易隊列中
    //        [[SKPaymentQueue defaultQueue] addPayment:payment];
    //        //3.觀察交易隊列中交易發(fā)生的改變
    //        [[SKPaymentQueue defaultQueue] addTransactionObserver:self];
}

#pragma mark - SKPaymentTransactionObserver

//當(dāng)用戶購買的操作有結(jié)果時,就會觸發(fā)下面的回調(diào)函數(shù),相應(yīng)進行處理
-(void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray<SKPaymentTransaction *> *)transactions{
    
    for (SKPaymentTransaction *transaction in transactions) {
        
        switch (transaction.transactionState) {
            case SKPaymentTransactionStatePurchased:  //交易完成
                [self completeTransaction:transaction];
                break;
            case SKPaymentTransactionStateFailed:     //交易失敗
                [self failedTransaction:transaction];
                break;
            case SKPaymentTransactionStateRestored:  //已經(jīng)購買過該商品
                [self restoreTransaction:transaction];
                break;
            case SKPaymentTransactionStatePurchasing: //商品添加進列表
                LOG(@"商品添加進列表");
                break;
            default:
                break;
        }
    }
}

//交易完成后的操作
-(void)completeTransaction:(SKPaymentTransaction *)transaction{
    NSString * productIdentifier = transaction.payment.productIdentifier;
//    NSURL *url = [[NSBundle mainBundle] appStoreReceiptURL];
//    NSData *transactionReceiptData = [NSData dataWithContentsOfURL:url];
//    NSString *receipt = [transactionReceiptData base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength];
    
    NSData *data = transaction.transactionReceipt;
    NSString * receipt = [data base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength];

    [[NSUserDefaults standardUserDefaults]setObject:receipt forKey:@"receipt"];
    [[NSUserDefaults standardUserDefaults] synchronize];
    if ([productIdentifier length]>0 && !TestStringIsBlank(receipt)) {
        //向自己的服務(wù)器驗證購買憑證????
        AHPersonInfoModel *infoModel = [AHPersonInfoManager share].infoModel;
        NSDictionary *dic = @{@"uid":@(infoModel.uid),@"token":infoModel.token,@"orderid":receipt};
        [AHRequestTool applepay:dic succussBlock:^(AHBaseModel *baseModel) {
            LOG(@"%@",baseModel);
            
            if (self.successfulBlock) {
                self.successfulBlock(nil, nil);
                self.successfulBlock = nil;
            }
        } failureBlock:^(NSString *errorStr) {
            if (self.failureBlock) {
                self.failureBlock(nil, nil);
                self.failureBlock  = nil;
            }
        }];
        //創(chuàng)建描述請求的JSON對象
        NSError *error;
        NSDictionary * requestContents = @{@"receipt-data":receipt,@"password":@"7ad47dcb6de94b08aa3ac3b7dd0d55f8",@"exclude-old-transactions":@(YES)};
        NSData * requestData = [NSJSONSerialization dataWithJSONObject:requestContents
                                                               options:0 error:&error];
        if(!requestData){
            //錯誤處理
        }
        //創(chuàng)建帶有收據(jù)數(shù)據(jù)的POST請求。
        NSURL * storeURL = [NSURL URLWithString:@"https://sandbox.itunes.apple.com/verifyReceipt"];
        NSMutableURLRequest * storeRequest = [NSMutableURLRequest requestWithURL:storeURL];
        [storeRequest setHTTPMethod:@"POST"];
        [storeRequest setHTTPBody:requestData];
        
        //在后臺隊列上連接到iTunes Store。
        NSOperationQueue * queue = [[NSOperationQueue alloc] init];
        [NSURLConnection sendAsynchronousRequest:storeRequest queue:queue
                               completionHandler:^(NSURLResponse * response,NSData * data,NSError * connectionError){
                                   if(connectionError){
                                       //錯誤處理
                                   } else {
                                       NSError *error;
                                       NSDictionary * jsonResponse = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];
                                       if(jsonResponse){
                                           //驗證
                                           LOG(@"%@",jsonResponse);
                                       }
                                   }}];

    }
    //移除transaction購買操作
    [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
}

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

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

五:蘋果支付驗證代碼塊,建議后臺驗證。

NSString *recept =  [[NSUserDefaults standardUserDefaults]objectForKey:@"receipt"];
    if (!recept) {
        return;
    }
    //創(chuàng)建描述請求的JSON對象 只有訂閱型才有密碼設(shè)置。
    NSError *error;
    NSDictionary * requestContents = @{@"receipt-data":recept,@"password":@"7ad47dcb6de94b08aa3ac3b7dd0d55f8"};
    NSData * requestData = [NSJSONSerialization dataWithJSONObject:requestContents
                                                           options:0 error:&error];
    if(!requestData){
        //錯誤處理
    }
    //創(chuàng)建帶有收據(jù)數(shù)據(jù)的POST請求。
    NSURL * storeURL = [NSURL URLWithString:@"https://sandbox.itunes.apple.com/verifyReceipt"];
    NSMutableURLRequest * storeRequest = [NSMutableURLRequest requestWithURL:storeURL];
    [storeRequest setHTTPMethod:@"POST"];
    [storeRequest setHTTPBody:requestData];

    //在后臺隊列上連接到iTunes Store。
    NSOperationQueue * queue = [[NSOperationQueue alloc] init];
    [NSURLConnection sendAsynchronousRequest:storeRequest queue:queue
                           completionHandler:^(NSURLResponse * response,NSData * data,NSError * connectionError){
                               if(connectionError){
                                   //錯誤處理
                               } else {
                                   NSError *error;
                                   NSDictionary * jsonResponse = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];
                                   if(jsonResponse){
                                       //驗證
                                       LOG(@"%@",jsonResponse);
                                   }
                               }}];

內(nèi)購沙盒測試續(xù)訂周期時間不一樣,且一天測試次數(shù)大概6次,且自動續(xù)費一般失敗。

時間對應(yīng)關(guān)系

六 :上線注意事項(這里是以訂購為例)

購買協(xié)議連接或彈框一定要有
購買協(xié)議具體內(nèi)容

購買協(xié)議具體內(nèi)容:

一定要有:自動續(xù)費,可隨時取消。提前24續(xù)費,下個周期第一天可取消。app設(shè)置里面可取消訂購。協(xié)議里最好加上自己的公司。


NSDictionary *dic = @{NSFontAttributeName:[UIFont systemFontOfSize:13],NSForegroundColorAttributeName:[UIColor blackColor]};
    NSString *contentStr = @"* The cost of subscription for Super Powers is 2.99 USD for 7 days, 7.99 USD for 1 month, 19.99 USD for 3 months, and 49.99 USD for 1 year.\n\n* If you choose to purchase Super Powers, the payment will be charged to your iTunes account at confirmation of purchase.\n\n* Your subscription automatically renews unless auto-renew is turned off at least 24-hours before the end of the current period.\n\n* Account will be charged for renewal within 24-hours prior to the end of the current period, and the cost of the renewal would be the same as your first payment.\n\n* You can manage your auto-renewal and auto-renewal may be turned off by going to your Account Settings after purchase.\n\n* No cancellation of the current subscription is allowed during the active subscription period.\n\n* If you don't want to purchase Super Powers, you can simply continue using Dittor for free.\n\n* Any unused portion of a free trial period, if offered, will be forfeited when you purchase a subscription to that publication.\n\nhttp://godittor.com/terms.html\n\nhttp://godittor.com/privacy.html";
    NSMutableAttributedString *contentAttr = [[NSMutableAttributedString alloc]initWithString:contentStr attributes:dic];
    NSRange range = [contentStr rangeOfString:@"http://godittor.com/terms.html\n\nhttp://godittor.com/privacy.html"];
    NSString *lin1 = @"http://godittor.com/terms.html";
    NSString *lin2 = @"http://godittor.com/privacy.html";
    NSRange range1 = [contentStr rangeOfString:lin1];
    NSRange range2 = [contentStr rangeOfString:lin2];
    self.range1 = range1;
    self.range2 = range2;
    [contentAttr addAttributes:@{NSForegroundColorAttributeName:[UIColor blueColor]} range:range];
    [contentAttr addAttributes:@{NSLinkAttributeName:lin1}
               range:range1];
    [contentAttr addAttributes:@{NSLinkAttributeName:lin2}
                         range:range2];
    self.textView.attributedText = contentAttr;
    
    self.textView.delegate =self;
- (BOOL)textView:(UITextView *)textView shouldInteractWithURL:(NSURL *)URL inRange:(NSRange)characterRange
{
    if (characterRange.location == self.range1.location && characterRange.length == self.range1.length) {
        [self bt_pushTrermAction:nil];
    }else if(characterRange.location == self.range2.location && characterRange.length == self.range2.length){
        [self bt_privacyAction:nil];
    }
    return NO;
}

app上線app描述包含商品名字,價格,最好加購買協(xié)議。

app上線的時候要在app描述里面加入內(nèi)購信息

可參考愛奇藝,等有內(nèi)購功能app在appstore上的描述。

愛奇藝

七 :深坑記錄。

  • 第一次加內(nèi)購或者有新商品,發(fā)布成功后,服務(wù)器并沒有立刻同步,必須要等上一段時間(12小時左右)才能拉取到產(chǎn)品列表。
  • 點擊發(fā)布后等待時間較久,大概12小時才能在appstore上搜索到。(官方說24之內(nèi)可以看到)
  • 元數(shù)據(jù)需要,綁定銀行卡,設(shè)置報稅表,設(shè)置內(nèi)購項目(完整的需要截圖和描述),添加沙盒測試賬號(沙盒賬號不一定需要驗證,沙盒賬號iOS13在個人資料里有專門登陸的地方,iOS12在支付的時候會彈出登陸框登陸即可)。
  • 綁定銀行卡的時候需要設(shè)置報稅表,一般選美國就好,后面選擇NO,然后同意條款,輸入生日,簽名就好。如下圖。


    image.png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 參考借鑒了一下幾篇文章(在這里很感謝各位作者大大做出的總結(jié)和方案): http://blog.csdn.net/a...
    輝546閱讀 14,277評論 3 12
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,187評論 25 708
  • 前言 本教程第一步是通過兩個點畫一條直線到圖像中,例如 最后,通過畫直線的API,畫出一個頭部模型 準備工作 現(xiàn)在...
    看到了是吧閱讀 1,088評論 0 1
  • 秦攻宜陽,周君謂趙累曰:「子以為何如?」對曰:「宜陽必拔也?!咕唬骸敢岁柍欠桨死?,材士十萬,粟支數(shù)年,公仲之軍二...
    止裳閱讀 595評論 0 0
  • 最近人們對教養(yǎng)討論的越來越多,教養(yǎng)到底體現(xiàn)在那些方面呢? 1、不對別人的事評頭論足。別人做的好與壞都與...
    小調(diào)兒閱讀 831評論 0 1

友情鏈接更多精彩內(nèi)容