精华内容
下载资源
问答
  • iOS开发 内购流程

    千次阅读 2018-06-28 14:58:05
    三、添加项目内购测试帐号 第一步 第二步 四、废话不多说,上代码 第一步导入StoreKit.framework库 然后先看.h文件 #import enum {IAP0p20= 20 , IAP1p100, IAP4p600, IAP9p1000, IAP24p6000,} buyCoinsTag; /...

    一.向appStore提交资料

    第一步
    第二步


    第三步

    操作完第三步然后记得保存


    第四步
    第五步

    先点击Contact Info 的Set Up

    第六步
    第七步

    都填写完记得保存,然后回到上一个页面

    第八步
    第九步
    第十步
    第十一步
    第十二步

    进行十二步的时候可能有些银行通过苹果这个方法查不到,就需要借助百度了,一定要准确查询,否则会有问题。我这里推荐一个地址
    https://e.czbank.com/CORPORBANK/query_unionBank_index.jsp
    第十三步

    这一步需要注意的是,货币类型可能有歧义,看你是想收美元还是人民币了,都说美元合适。不过,我做的时候为了避免事情,还是选择了CNY,支持国产。还有一点,银行账号如果是对公的账号,需要填写公司的英文名称,如果没有的话,上拼音!然后点击 保存银行信息就算ok了,然后退回到最开始的页面


    第十四步
    第十五步
    第十六步
    第十七步
    第十八步
    第十九步

    这里要注意的是,虽然这个页面看起来要填写的信息很多,其实很多都没有什么卵用,都是对于美国那边什么法律需要配合的那些,一般咱们都不用,只需要把该勾选的地方勾选,然后提交就好了。

    第二十步
    第二十一步
    第二十二步

    二.创建内购项目

    第一步
    第二步

    根据自己app的需要选择类型,写的很详细,就不多说了

    第三步
    第四步
    第五步
    第六步

    三、添加项目内购测试帐号

    第一步
    第二步

    四、废话不多说,上代码

    第一步导入StoreKit.framework库
    然后先看.h文件

    #import <StoreKit/StoreKit.h>
    enum{IAP0p20=20,
    IAP1p100,
    IAP4p600,
    IAP9p1000,
    IAP24p6000,}
    buyCoinsTag;
    
    //代理@interface RechargeVC : UIViewController <SKPaymentTransactionObserver,SKProductsRequestDelegate >
    {
    int buyType;
    }
    
    - (void) requestProUpgradeProductData;
    
    -(void)RequestProductData;
    
    -(void)buy:(int)type;
    
    - (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions;
    
    -(void) PurchasedTransaction: (SKPaymentTransaction *)transaction;
    
    - (void) completeTransaction: (SKPaymentTransaction *)transaction;
    
    - (void) failedTransaction: (SKPaymentTransaction *)transaction;
    
    -(void) paymentQueueRestoreCompletedTransactionsFinished:(SKPaymentTransaction *)transaction;
    
    -(void) paymentQueue:(SKPaymentQueue *) paymentQueue restoreCompletedTransactionsFailedWithError:(NSError *)error;
    
    - (void) restoreTransaction: (SKPaymentTransaction *)transaction;-(void)provideContent:(NSString *)product;
    
    -(void)recordTransaction:(NSString *)product;
    
    @end
    

    然后看.m文件

    #import "RechargeVC.h"
    
    //在内购项目中创的商品单号
    #define ProductID_IAP0p20 @"Nada.JPYF01"//20
    #define ProductID_IAP1p100 @"Nada.JPYF02" //100
    #define ProductID_IAP4p600 @"Nada.JPYF03" //600
    #define ProductID_IAP9p1000 @"Nada.JPYF04" //1000
    #define ProductID_IAP24p6000 @"Nada.JPYF05" //6000
    
    @interface RechargeVC ()
    
    @end
    
    @implementation RechargeVC
    
    - (void)viewDidLoad { 
    
     [super viewDidLoad];
     [[SKPaymentQueue defaultQueue] addTransactionObserver:self];
     [self buy:IAP0p20];
    
    }
    
    -(void)buy:(int)type{ 
      buyType = type; 
      if ([SKPaymentQueue canMakePayments]) {
       [self RequestProductData]; NSLog(@"允许程序内付费购买");
      }else{ 
      NSLog(@"不允许程序内付费购买"); 
      UIAlertView *alerView = [[UIAlertView alloc] initWithTitle:@"提示" message:@"您的手机没有打开程序内付费购买" 
    delegate:nil cancelButtonTitle:NSLocalizedString(@"关闭",nil) otherButtonTitles:nil];
       [alerView show]; }
    }
    
    -(void)RequestProductData{
    
     NSLog(@"---------请求对应的产品信息------------"); 
    NSArray *product = nil; 
    switch (buyType) 
    {
       case IAP0p20: product=[[NSArray alloc] initWithObjects:ProductID_IAP0p20,nil];
       break;
    
       case IAP1p100: product=[[NSArray alloc] initWithObjects:ProductID_IAP1p100,nil];
       break; 
    
      case IAP4p600: product=[[NSArray alloc] initWithObjects:ProductID_IAP4p600,nil];
       break;
    
       case IAP9p1000: product=[[NSArray alloc] initWithObjects:ProductID_IAP9p1000,nil]; 
      break;
    
       case IAP24p6000: product=[[NSArray alloc] initWithObjects:ProductID_IAP24p6000,nil]; 
      break;
    
     default:
     break;
    } 
    
    NSSet *nsset = [NSSet setWithArray:product];
     SKProductsRequest *request=[[SKProductsRequest alloc] initWithProductIdentifiers: nsset];
     request.delegate=self; 
    
    [request start];}
    
    //<SKProductsRequestDelegate> 请求协议//收到的产品信息
    - (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response{
    
      NSLog(@"-----------收到产品反馈信息--------------"); 
      NSArray *myProduct = response.products;
      NSLog(@"产品Product ID:%@",response.invalidProductIdentifiers);  
      NSLog(@"产品付费数量: %d", (int)[myProduct count]); 
    
      // populate UI 
      for(SKProduct *product in myProduct){
      NSLog(@"product info"); 
      NSLog(@"SKProduct 描述信息%@", [product description]); 
      NSLog(@"产品标题 %@" , product.localizedTitle);
      NSLog(@"产品描述信息: %@" , product.localizedDescription); 
      NSLog(@"价格: %@" , product.price);
      NSLog(@"Product id: %@" , product.productIdentifier);
    
    }
    
     SKPayment *payment = nil; 
    switch (buyType) {
    
     case IAP0p20: payment = [SKPayment paymentWithProductIdentifier:ProductID_IAP0p20]; //支付25 break; case 
    IAP1p100: payment = [SKPayment paymentWithProductIdentifier:ProductID_IAP1p100]; //支付108 break; case 
    
    IAP4p600: payment = [SKPayment paymentWithProductIdentifier:ProductID_IAP4p600]; //支付618 break; case 
    
    IAP9p1000: payment = [SKPayment paymentWithProductIdentifier:ProductID_IAP9p1000]; //支付1048 break; 
    
    case IAP24p6000: payment = [SKPayment 
    paymentWithProductIdentifier:ProductID_IAP24p6000]; //支付5898 break; default: 
    break;
    } 
    NSLog(@"---------发送购买请求------------");
    
     [[SKPaymentQueue defaultQueue] addPayment:payment];
    }
    
    - (void)requestProUpgradeProductData{
    
     NSLog(@"------请求升级数据---------"); 
    
    NSSet *productIdentifiers = [NSSet setWithObject:@"com.productid"];
     SKProductsRequest* productsRequest = [[SKProductsRequest alloc] initWithProductIdentifiers:productIdentifiers]; 
    productsRequest.delegate = self; 
    [productsRequest start];}
    
    //弹出错误信息
    - (void)request:(SKRequest *)request didFailWithError:(NSError *)error{ 
    
        NSLog(@"-------弹出错误信息----------"); 
        UIAlertView *alerView = [[UIAlertView alloc]initWithTitle:NSLocalizedString(@"Alert",NULL) message:[error localizedDescription] delegate:nil cancelButtonTitle:NSLocalizedString(@"Close",nil) otherButtonTitles:nil]; 
    [alerView show];
    }
    
    -(void) requestDidFinish:(SKRequest *)request{
    
       NSLog(@"----------反馈信息结束--------------");
    
    }
    
    -(void) PurchasedTransaction: (SKPaymentTransaction *)transaction{ 
    
      NSLog(@"-----PurchasedTransaction----");
    
       NSArray *transactions =[[NSArray alloc] initWithObjects:transaction, nil]; 
      [ self paymentQueue:[SKPaymentQueue defaultQueue] updatedTransactions:transactions];
    
    }
    
    //<SKPaymentTransactionObserver>千万不要忘记绑定,代码如下:
    //----监听购买结果
    //[[SKPaymentQueue defaultQueue] addTransactionObserver:self];
    - (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions//交易结果{
    
     NSLog(@"-----paymentQueue--------"); 
    
      for (SKPaymentTransaction *transaction in transactions) { 
      switch (transaction.transactionState) { 
      case SKPaymentTransactionStatePurchased:{
    //交易完成 [self  completeTransaction:transaction]; 
    
      NSLog(@"-----交易完成 --------");
    
     UIAlertView *alerView = [[UIAlertView alloc] initWithTitle:@"" message:@"购买成功" delegate:nil cancelButtonTitle:NSLocalizedString(@"关闭",nil) otherButtonTitles:nil];
       [alerView show]; 
    } break;
     case SKPaymentTransactionStateFailed://交易失败 
    
    {
     [self failedTransaction:transaction]; 
      NSLog(@"-----交易失败 --------"); 
      UIAlertView *alerView2 = [[UIAlertView alloc] initWithTitle:@"提示" message:@"购买失败,请重新尝试购买" delegate:nil cancelButtonTitle:NSLocalizedString(@"关闭",nil) otherButtonTitles:nil]; 
      [alerView2 show]; 
    }break;
     
    case SKPaymentTransactionStateRestored://已经购买过该商品 [self restoreTransaction:transaction];
       NSLog(@"-----已经购买过该商品 --------");
       case SKPaymentTransactionStatePurchasing: 
    //商品添加进列表
     NSLog(@"-----商品添加进列表 --------");
     break
    ; default: 
    break;
           } 
        }
    }
    
    - (void) completeTransaction: (SKPaymentTransaction *)transaction{ 
      NSLog(@"-----completeTransaction--------"); 
      // 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];}
    } 
      // Remove the transaction from the payment queue. [[SKPaymentQueue   defaultQueue] finishTransaction: transaction];
    }
    
    //记录交易
    -(void)recordTransaction:(NSString *)product{
       NSLog(@"-----记录交易--------");
    
    }
    
    //处理下载内容
    -(void)provideContent:(NSString *)product{ 
      NSLog(@"-----下载--------");
    }
    
    - (void) failedTransaction: (SKPaymentTransaction *)transaction{ 
      NSLog(@"失败"); 
      if (transaction.error.code != SKErrorPaymentCancelled) { } 
      [[SKPaymentQueue defaultQueue] finishTransaction: transaction];
    }
    
    -(void) paymentQueueRestoreCompletedTransactionsFinished: (SKPaymentTransaction *)transaction{}- (void) restoreTransaction: (SKPaymentTransaction *)transaction{ 
      NSLog(@" 交易恢复处理");
    }
    
    -(void) paymentQueue:(SKPaymentQueue *) paymentQueue restoreCompletedTransactionsFailedWithError:(NSError *)error{ 
      NSLog(@"-------paymentQueue----");
    }
    
    #pragma mark connection delegate
    - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data{ 
      NSLog(@"%@", [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
    }
    
    - (void)connectionDidFinishLoading:(NSURLConnection *)connection{}- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response{ 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)dealloc{ 
      [[SKPaymentQueue defaultQueue] removeTransactionObserver:self];
      //解除监听
    
    }
    
    @end

    辅助开发的链接:https://www.cnblogs.com/TheYouth/p/6847014.html?utm_source=itdadao&utm_medium=referral


    作者:睡不着的叶
    链接:https://www.jianshu.com/p/d9d742e82188
    來源:简书
    简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。
    展开全文
  • iOS开发内购详细

    千次阅读 2017-07-26 10:48:35
    一、最近公司很多的项目用到了内购,抽空整理下内购的详细...一....iOS开发内购全套图文教程 ======================第一部分协议=============== 第一步.png 第二步.jpg 第三步.jpg 第四步.png 第五步.png

    一、最近公司很多的项目用到了内购,抽空整理下内购的详细内容吧。

    如对你有帮助,请不要吝惜打赏和喜欢,谢谢!

    一....iOS开发内购全套图文教程


    ======================第一部分协议===============


    第一步.png

    第二步.jpg

    第三步.jpg

    第四步.png

    第五步.png

    第六步.png

    第七步.jpg

    第八步.jpg

    第九步.jpg

    第十步.png

    CNAPS CODE 查询地址
    https://e.czbank.com/CORPORBANK/query_unionBank_index.jsp


    十一步.jpg

    十二步.jpg

    十三步.png

    十四步.png

    十五步.jpg

    十七步.jpg

    十八步.jpg

    十九步.png

    2016/11/18号更新


    十九步(1).png

    十九步(2).png

    没显示的都是可以不填的,主要是打钩 title 和最后面的Self


    二十步.png

    =============第二部分创建内购项目============


    1.png

    2.png

    3.png

    4.png

    5.png

    6.png

    7.png

    ===========第三部分贴加内购项目测试账号==========


    创建测试账号.png

    沙盒测试员.png

    账号信息.png

    =============第四部分主要实现代码==========

    首先导入StoreKit.framework

    .h文件

    #import <StoreKit/StoreKit.h>
    
    enum{
    IAP0p20=20,
    IAP1p100,
    IAP4p600,
    IAP9p1000,
    IAP24p6000,
    }buyCoinsTag;
    
    //代理
    @interface RechargeVC : UIViewController <SKPaymentTransactionObserver,SKProductsRequestDelegate >
    
    {
    int buyType;
    }
    
    - (void) requestProUpgradeProductData;
    
    -(void)RequestProductData;
    
    -(void)buy:(int)type;
    
    - (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions;
    
    -(void) PurchasedTransaction: (SKPaymentTransaction *)transaction;
    
    - (void) completeTransaction: (SKPaymentTransaction *)transaction;
    
    - (void) failedTransaction: (SKPaymentTransaction *)transaction;
    
    -(void) paymentQueueRestoreCompletedTransactionsFinished: (SKPaymentTransaction *)transaction;
    
    -(void) paymentQueue:(SKPaymentQueue *) paymentQueue restoreCompletedTransactionsFailedWithError:(NSError *)error;
    
    - (void) restoreTransaction: (SKPaymentTransaction *)transaction;
    
    -(void)provideContent:(NSString *)product;
    
    -(void)recordTransaction:(NSString *)product;
    
    @end

    .m文件

    #import "RechargeVC.h"
    
    //在内购项目中创的商品单号
    #define ProductID_IAP0p20 @"Nada.JPYF01"//20
    #define ProductID_IAP1p100 @"Nada.JPYF02" //100
    #define ProductID_IAP4p600 @"Nada.JPYF03" //600
    #define ProductID_IAP9p1000 @"Nada.JPYF04" //1000
    #define ProductID_IAP24p6000 @"Nada.JPYF05" //6000
    
    @interface RechargeVC ()
    
    @end
    
    @implementation RechargeVC
    
    - (void)viewDidLoad {
    
        [super viewDidLoad];
    
        [[SKPaymentQueue defaultQueue] addTransactionObserver:self];
        [self buy:IAP0p20];
    
    }
    
    -(void)buy:(int)type
    {
        buyType = type;
        if ([SKPaymentQueue canMakePayments]) {
        [self RequestProductData];
        NSLog(@"允许程序内付费购买");
    }
    else
    {
        NSLog(@"不允许程序内付费购买");
        UIAlertView *alerView =  [[UIAlertView alloc] initWithTitle:@"提示"
        message:@"您的手机没有打开程序内付费购买"
        delegate:nil cancelButtonTitle:NSLocalizedString(@"关闭",nil) otherButtonTitles:nil];
    
        [alerView show];
    
        }
    }
    
    -(void)RequestProductData
    {
        NSLog(@"---------请求对应的产品信息------------");
        NSArray *product = nil;
        switch (buyType) {
            case IAP0p20:
            product=[[NSArray alloc] initWithObjects:ProductID_IAP0p20,nil];
            break;
            case IAP1p100:
            product=[[NSArray alloc] initWithObjects:ProductID_IAP1p100,nil];
            break;
            case IAP4p600:
            product=[[NSArray alloc] initWithObjects:ProductID_IAP4p600,nil];
            break;
            case IAP9p1000:
            product=[[NSArray alloc] initWithObjects:ProductID_IAP9p1000,nil];
            break;
            case IAP24p6000:
            product=[[NSArray alloc] initWithObjects:ProductID_IAP24p6000,nil];
            break;
    
            default:
            break;
    }
        NSSet *nsset = [NSSet setWithArray:product];
        SKProductsRequest *request=[[SKProductsRequest alloc] initWithProductIdentifiers: nsset];
        request.delegate=self;
        [request start];
    
    }
    
    //<SKProductsRequestDelegate> 请求协议
    //收到的产品信息
    - (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response{
    
        NSLog(@"-----------收到产品反馈信息--------------");
        NSArray *myProduct = response.products;
        NSLog(@"产品Product ID:%@",response.invalidProductIdentifiers);
        NSLog(@"产品付费数量: %d", (int)[myProduct count]);
        // populate UI
        for(SKProduct *product in myProduct){
        NSLog(@"product info");
        NSLog(@"SKProduct 描述信息%@", [product description]);
        NSLog(@"产品标题 %@" , product.localizedTitle);
        NSLog(@"产品描述信息: %@" , product.localizedDescription);
        NSLog(@"价格: %@" , product.price);
        NSLog(@"Product id: %@" , product.productIdentifier);
    }
        SKPayment *payment = nil;
        switch (buyType) {
            case IAP0p20:
            payment  = [SKPayment paymentWithProductIdentifier:ProductID_IAP0p20];    //支付25
            break;
            case IAP1p100:
            payment  = [SKPayment paymentWithProductIdentifier:ProductID_IAP1p100];    //支付108
            break;
            case IAP4p600:
            payment  = [SKPayment paymentWithProductIdentifier:ProductID_IAP4p600];    //支付618
            break;
            case IAP9p1000:
            payment  = [SKPayment paymentWithProductIdentifier:ProductID_IAP9p1000];    //支付1048
            break;
            case IAP24p6000:
            payment  = [SKPayment paymentWithProductIdentifier:ProductID_IAP24p6000];    //支付5898
            break;
            default:
            break;
    }
        NSLog(@"---------发送购买请求------------");
        [[SKPaymentQueue defaultQueue] addPayment:payment];
    
    }
    - (void)requestProUpgradeProductData
    {
        NSLog(@"------请求升级数据---------");
        NSSet *productIdentifiers = [NSSet setWithObject:@"com.productid"];
        SKProductsRequest* productsRequest = [[SKProductsRequest alloc] initWithProductIdentifiers:productIdentifiers];
        productsRequest.delegate = self;
        [productsRequest start];
    
    }
    //弹出错误信息
    - (void)request:(SKRequest *)request didFailWithError:(NSError *)error{
        NSLog(@"-------弹出错误信息----------");
        UIAlertView *alerView =  [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Alert",NULL) message:[error localizedDescription]
        delegate:nil cancelButtonTitle:NSLocalizedString(@"Close",nil) otherButtonTitles:nil];
        [alerView show];
    
    }
    
    -(void) requestDidFinish:(SKRequest *)request
    {
        NSLog(@"----------反馈信息结束--------------");
    
    }
    
    -(void) PurchasedTransaction: (SKPaymentTransaction *)transaction{
        NSLog(@"-----PurchasedTransaction----");
        NSArray *transactions =[[NSArray alloc] initWithObjects:transaction, nil];
        [self paymentQueue:[SKPaymentQueue defaultQueue] updatedTransactions:transactions];
    }
    
    //<SKPaymentTransactionObserver> 千万不要忘记绑定,代码如下:
    //----监听购买结果
    //[[SKPaymentQueue defaultQueue] addTransactionObserver:self];
    
    - (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions//交易结果
    {
        NSLog(@"-----paymentQueue--------");
        for (SKPaymentTransaction *transaction in transactions)
        {
            switch (transaction.transactionState)
            {
                case SKPaymentTransactionStatePurchased:{//交易完成
                [self completeTransaction:transaction];
                NSLog(@"-----交易完成 --------");
    
                UIAlertView *alerView =  [[UIAlertView alloc] initWithTitle:@""
                message:@"购买成功"
                delegate:nil cancelButtonTitle:NSLocalizedString(@"关闭",nil) otherButtonTitles:nil];
    
                [alerView show];
    
            } break;
            case SKPaymentTransactionStateFailed://交易失败
                { [self failedTransaction:transaction];
                NSLog(@"-----交易失败 --------");
                UIAlertView *alerView2 =  [[UIAlertView alloc] initWithTitle:@"提示"
                message:@"购买失败,请重新尝试购买"
                delegate:nil cancelButtonTitle:NSLocalizedString(@"关闭",nil) otherButtonTitles:nil];
    
                [alerView2 show];
    
            }break;
            case SKPaymentTransactionStateRestored://已经购买过该商品
                [self restoreTransaction:transaction];
                NSLog(@"-----已经购买过该商品 --------");
                case SKPaymentTransactionStatePurchasing:      //商品添加进列表
                NSLog(@"-----商品添加进列表 --------");
                break;
                default:
                break;
            }
        }
    }
    - (void) completeTransaction: (SKPaymentTransaction *)transaction
    
    {
        NSLog(@"-----completeTransaction--------");
        // 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];
    }
    }
    
        // Remove the transaction from the payment queue.
    
        [[SKPaymentQueue defaultQueue] finishTransaction: transaction];
    
    }
    
    //记录交易
    -(void)recordTransaction:(NSString *)product{
        NSLog(@"-----记录交易--------");
    }
    
    //处理下载内容
    -(void)provideContent:(NSString *)product{
        NSLog(@"-----下载--------");
    }
    
    - (void) failedTransaction: (SKPaymentTransaction *)transaction{
        NSLog(@"失败");
        if (transaction.error.code != SKErrorPaymentCancelled)
        {
    
        }
        [[SKPaymentQueue defaultQueue] finishTransaction: transaction];
    
    }
    -(void) paymentQueueRestoreCompletedTransactionsFinished: (SKPaymentTransaction *)transaction{
    
    }
    
    - (void) restoreTransaction: (SKPaymentTransaction *)transaction
    {
        NSLog(@" 交易恢复处理");
    
    }
    
    -(void) paymentQueue:(SKPaymentQueue *) paymentQueue restoreCompletedTransactionsFailedWithError:(NSError *)error{
        NSLog(@"-------paymentQueue----");
    }
    
    #pragma mark connection delegate
    - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
    {
        NSLog(@"%@",  [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
    }
    - (void)connectionDidFinishLoading:(NSURLConnection *)connection{
    
    }
    
    - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response{
        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)dealloc
    {
        [[SKPaymentQueue defaultQueue] removeTransactionObserver:self];//解除监听
    
    }
    
    @end

    二......iOS开发内购详细版本说明

    1、先从内购的iTunesConnect里配置说起吧,我们先进入苹果的iTunesConnect链接https://itunesconnect.apple.com,然后进入入下界面。



    银行信息填写

    填写好银行卡信息和公司地址等信息以后,第一步算完成了。

    2、进入iTunesConnect选择我的APP模块,创建新的APP,绑定好你在苹果开发者中心创建的apple IDS还有bundle id,那么就创建成功了一个新的APP应用。如下图:



    创建APP

    3、进入新创建的APP应用,点击如图所示功能按钮:



    我的APP“功能”

    4、进入功能以后我们就可以创建我们想要的内购产品的ID了,一般都会存在如下几个选择项:



    选择类型

    5、我们公司的项目由于都是直播类型的课程购买,所以用的是消耗型的项目,选择好然后就进入创建界面里去创建产品了。



    需要填写的几项

    6、填写好这几项,一个新的内购产品就创建成功了,我们需要记录下每个产品的内购ID,也就是唯一ID,为以后购买产品做准备。

    7、我们需要在工程里配置好证书,测试证书是必须的因为我们内购需要连接到苹果的App Store的,需要正式的测试证书才能测试,同时把下图工程中的这一配置打开:



    这是很重要的一步

    二、讲完上面基本的配置以后,我们进入我们最重要的部分,那就是我们的代码部分。

    1、要使用苹果的内购功能,我们需要引入苹果的头件“#import<StoreKit/StoreKit.h>”,引入进来以后,我们就需要引入"SKProductsRequestDelegate,SKPaymentTransactionObserver"这两个代理,我们需要在内购的那个页面viewDidLoad方法里直接调用方法,如下图:



    开启内购检测

    然后接下来就是几个最重要的代理方法了,如果正常的内购能够走通,那么这几个代理方法就会很流畅的运行过去,并且返回你所购买的商品的信息。让我们一步步来分析:



    内购购买(1)



    内购购买(2)



    内购购买(3)



    内购购买(4)



    内购购买(5)



    内购购买(6)



    内购完成

    1.必须用真机测试。
    2.测试的时候必须退出自己的apple ID。弹出页面后登陆沙盒的测试apple id。

    #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(@"已经购买过商品");
    
                    break;
                case SKPaymentTransactionStateFailed:
                    NSLog(@"交易失败");
    
                    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


    2、进过我这一堆的代码组合,是否已经明白了内购的方式了呢,只要把我列举的这几个方法,统统的导入进你的工程,那么就基本上可以了。

    三、常见内购错误,自己做内购总结的几个常见错误。

    1、请求不到内购的产品信息。

    解决办法:(1)、先看看bundle id,和测试证书之类的东西配置的都对不对,然后看看产品的唯一ID和iTunesConnect里的能不能对应上。如果都没有问题,那么看下面的。

                      (2)、去看看iTunesConnect里的协议里面的公司的地址信息和银行卡信息是否填写正确,只要没有报错,报红就可以。基本上上面这几点弄好了也就能请求到商品了。

    2、手机提示无法连接到itunesStore

    解决办法:把手机的Apple ID先注销掉,然后购买的时候重新填写Apple ID。


    展开全文
  • 一个程序支付的view,之前是自己写的,但是每次写起来都很麻烦,抽时间集成了一个View,可以直接调用,使用方法,压缩包里面有,有兴趣的可以看一下
  • iOS开发内购零丢单问题

    千次阅读 2019-07-30 15:05:46
    苹果能够的零丢单操作文章的主要内容内购分析观察者代码构建着重所以下finishTransaction方法的处理 文章的主要内容 你好!这是我发表的第一段关于苹果技术的博客,如果有说的不对的地方请指教,今天要分享一下自己...

    文章的主要内容

    你好!这是我发表的第一段关于苹果技术的博客,如果有说的不对的地方请指教,今天要分享一下自己对于苹果内购的经验。苹果内购的前期准备工作基本相同,关于申请内购项目的时候要注意的是,内购项目和APP是同时审核的,所以先创建的内购得等新版本审核成功后才能正式购买。本片文章主要是关于内购代码级别的分析。

    内购分析

    关于内购这块,我们项目已经经过3个人修改,当时上线的时候没有啥问题,但是随着内购内容越来越多,就出现了问题,丢单问题随之出现,经过我查看了苹果的内购官方文档,要求所有的内购统一管理,苹果的官方解释,创建一个观察者,然后在软件启动的时候定义观察者;

     -(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
     [[SKPaymentQueue defaultQueue] addTransactionObserver:inPurchasingManage];
    }
    

    我定义的观察者是appdalagate里的一个属性,所以在其他界面使用时直接调用appdalagate.inPurchasingManage即可,注销该方法放在软件进程杀死状态下:

    -(void)applicationWillTerminate:(UIApplication *)application
    {   
     [[SKPaymentQueue defaultQueue] removeTransactionObserver:inPurchasingManage];
     }
    

    这样不管在哪个界面发起内购的话,都会走观察者里面的代码。

    观察者代码构建

    首先是根据内购产品的ID发起内购,因为这个ID,我是从后台拿过来的,前边不做赘述,

    #pragma mark - 内购
    -(void)requestProductData:(NSString *)type{
        NSArray *product = [[NSArray alloc] initWithObjects:type,nil]; 
        NSSet *nsset = [NSSet setWithArray:product];
        SKProductsRequest *request = [[SKProductsRequest alloc] initWithProductIdentifiers:nsset];
        request.delegate = self;
        [request start];
    }
    

    通过这段代码就能成功呼起苹果的内购支付,并且走了
    <SKProductsRequestDelegate,SKPaymentTransactionObserver>代理回调方法,这些苹果官方说明都有讲,虽然现在用的是swift语言,但是对于我们还依然用OC的人来说,不在话下:

    #pragma mark - 实现SKProductsRequest的代理方法
        -(void)productsRequest:(SKProductsRequest *)request            didReceiveResponse:(SKProductsResponse *)response
    {
          NSArray *product = response.products;
          if([product count] == 0){
          //如果这个参数没有,证明没有这个产品,也就不需要走下面的代码了
            return;
          } 
          SKProduct *p = nil;
          for (SKProduct *pro in product) {
            if([pro.productIdentifier isEqualToString:Singleton.currentProId]){
                p = pro;
            }
          }
          SKMutablePayment *payment = [SKMutablePayment paymentWithProduct:p];
          NSString *userOrderNo = [NSString stringWithFormat:@"%@#%@",userID,orderNo];
          payment.applicationUsername = userOrderNo;
          [[SKPaymentQueue defaultQueue] addPayment:payment];
    }
    

    如果订单存在的话,就已经呼起内购了,说道这里可能有些人会质疑我存储订单号的方法,因为好多博客不推荐用applicationUsername来存储重要的数据,因为觉得可能会丢失数据,但是没有明确的操作会导致这个属性丢失,因为这里如果存着订单号,就很有可能消失,这样就会出现丢单问题,其实这个问题我也思考了,先不说这个参数容不容易丢,即使丢了怕啥,再给它申请个订单号不就得了。这个是我们厉害的后台想出来的办法,具体的订单号问题往下看,再说说我存的userID,是为了区别用户存的,避免了钱充错人的问题,(这里说一下存在的问题,如果一个用户付完款之后退出的账号,这时又赶巧applicationUsername丢失,如果用户下一次登录的是另一个账号,有可能充错人,但是不会丢单),下面是我重点介绍的逻辑:

    #pragma mark - 实现SKPaymentQueue的回调方法
    /*
     队列中的交易发生改变时,就会调用该方法
     */
    - (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions
    {
        /*
         SKPaymentTransactionStatePurchasing,    正在购买
         SKPaymentTransactionStatePurchased,     已经购买(购买成功)
         SKPaymentTransactionStateFailed,        购买失败
         SKPaymentTransactionStateRestored,      恢复购买
         SKPaymentTransactionStateDeferred       未决定
         */
        for (SKPaymentTransaction *transation in transactions) {
            NSString *productIdentifier = transation.payment.productIdentifier;
            switch (transation.transactionState) {
                case SKPaymentTransactionStatePurchasing:
                break;
                    
                case SKPaymentTransactionStatePurchased:{
    
                    NSString *newOrderNo = transation.payment.applicationUsername;
                   //这个方法就是用户支付成功后回调方法,这样就可以拿着订单号和用户id去校验了了
                    break;
                    
                case SKPaymentTransactionStateFailed:{
          
                    // 用户取消或者支付失败取消订单
                    NSString *newOrderNo = transation.payment.applicationUsername;
                   
                    break;
                    
                case SKPaymentTransactionStateRestored:
                    //如果显示已经购买过该商品,则恢复该商品的购买性 <非消耗型商品>               
                     [self restoreCompletedTransactions:transation];             
                    break;                
                case SKPaymentTransactionStateDeferred:{
                    NSString *newOrderNo = transation.payment.applicationUsername;          
                    [queue finishTransaction:transation];
                    break;
                default:
                    break;
            }
        }
    }
    

    SKPaymentTransactionStatePurchased 这个方法就是用户支付成功后回调方法,applicationUsernam就是发起内购时,我们赋值的用户id和订单号的拼接,这里讲一下我们的出来,不管这个订单号有没有,我们都会拿着receiptData去校验,获取方法如下,这时只要receiptData存在,后台就会去查询用户之前是否发起过一个订单号,如果有直接二次校验,如果没有,那就给用户申请一个新的订单号,然后再进行校验。这样不管用户有没有订单号都无所谓。

        NSData *receiptData = [NSData dataWithContentsOfURL:[[NSBundle mainBundle] appStoreReceiptURL]];
    

    着重所以下finishTransaction方法的处理

     [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
    

    我只有在用户二次校验成功后才会调用该方法,如果不走这个方法,每次软件启动的时候,都会走上述的代理,所以如果你没有验证的话,用户卸载软件再安装以后还会走这代理,然后再去后天校验就行了,保证零丢单就是这么简单,不知道你们看懂没有?

    展开全文
  • iOS 内购开发流程(简洁版)

    千次阅读 2020-03-18 16:18:09
    内购开发流程 一、在开发者账号里面设置协议、税务和银行信息 二、在开发者账号里面创建内购的项目 三、代码集成 注意事项 必须用真机测试; 测试的时候必须退出自己的apple ID,弹出页面后登陆沙盒的测试apple id...
    内购开发流程

    一、在开发者账号里面设置协议、税务和银行信息
    二、在开发者账号里面创建内购的项目
    三、代码集成

    注意事项
    • 必须用真机测试;
    • 测试的时候必须退出自己的apple ID,弹出页面后登陆沙盒的测试apple id;
    • 在需要修改已经上线的内购的时候需要重新创建新的内购条目,然后重新提交;
    • 要区分apple pay 和 内购 的差别
    参考链接

    1、https://www.cnblogs.com/fengmin/p/5562769.html
    2、https://www.cnblogs.com/CH520/p/10796486.html
    3、https://www.jianshu.com/p/31f2eaebfa4b
    4、https://www.jianshu.com/p/f7bff61e0b31/

    展开全文
  • ios实现内购

    千次阅读 2019-06-11 18:00:43
    基础知识参考 :https://www.cnblogs.com/TheYouth/p/6847014.html?utm_source=itdadao&utm_medium=referral 代码参考,测试参考,... 思维导图 ... 1.获取内购列表(从App...
  • iOS开发内购详细版本说明

    千次阅读 2017-10-20 09:39:21
    一、最近公司很多的项目用到了内购,抽空整理下内购的详细内容吧。 1、先从内购的iTunesConnect里配置说起吧,我们先进入苹果的iTunesConnect链接https://itunesconnect.apple.com,然后进入入下界面。 银行信息...
  • iOS开发内购的完整流程

    千次阅读 2019-06-19 16:07:00
    之前自己在项目中做了内购,但忘了...iOS内购流程如下 通过产品ID获取产品信息列表 添加监听 把产品包装成SKPayment(支付)发送给苹果服务器 苹果服务器购买成功后会回调监听方法,根据苹果服务器返回信息...
  • ios 内购 恢复内购

    千次阅读 2019-08-28 15:33:57
    申请内购部分略。。。。。。。 代码部分 1 //准备工作 [[SKPaymentQueue defaultQueue] addTransactionObserver:self]; <SKPaymentTransactionObserver,SKProductsRequestDelegate> //遵循代理 打开支付开关 ...
  • 创建内购项目的时候,第一个项目由于没有提交截图,出现了元数据丢失问题,后来两个项目添加了截图还是出现元数据丢失问题
  • }else{ NSLog(@"失败,用户禁止应用付费购买."); } } return NO; } #pragma mark ------ SKProductsRequestDelegate -(void)productsRequest:(SKProductsRequest *)request didReceiveResponse:...
  • Swift iOS StoreKit 原生内购订阅代码封装,语言是Swift,内含demo,可以二次封装给其他开发工具使用.
  • iOS 内购详解-代码篇

    千次阅读 2020-07-04 16:29:34
    内购项目-代码篇一、分步骤说明1、获取商品列表2、苹果服务器返回的可购买商品3、下单购买商品4、购买队列状态变化,判断购买状态是否成功5、交易验证6、拿到的收据信息是,此App所有购买的记录7、恢复商品二、详细...
  • Objective-C iOS StoreKit 原生内购订阅代码封装,语言是Objective-C,内含demo,可以二次封装给其他开发工具使用. 支持Unity3D,cocos,xamarin...等开发工具进行二次封装使用.
  • iOS开发内购全套图文教程

    千次阅读 2015-10-29 14:53:31
    2015年最全的内购图文教程,首先是填各种资料,最后是代码,废话不多说,直接上图======================第一部分协议===============CNAPS CODE 查询地址 ...
  • 登录 https://appstoreconnect.apple.com/ 协议、税务和银行业务 协议 付费App 银行帐户 编辑 编辑当前账户 或者 替换为新账户
  • IOS苹果内购 PHP后端验证票据

    千次阅读 2019-02-03 01:52:40
    1.IOS端需要在iTunes Connect上面添加配置一些内购商品,并审核通过,每个内购商品有自己的唯一标识product_id。 2.PHP后端要有一套与之对应的内购商品、IOS应用唯一标识bundle_id和应用秘钥配置,以便用于验证。...
  • 最近给app增加内购移除广告功能,刚开始还比较顺利,把网上找到的内购代码,简单修改加入到app内,基本能用,测试完成后,提交审核。第一次提交,有点问题被拒,根据具体问题进行改正后,再提交,审核就通过了。接连...
  • 1、内购流程 1、在 AppStore 中创建相应的物品,创建内购沙盒测试账号2、客户端从后台获取相应的物品 ID (当然也可以再客户端写死,但后期扩展性就受限制了)3、依据相应的物品 ID 请求商品的相关信息4、依据...
  • 最近公司在做APP内购会员功能 遇到了很多问题 总结记录一下 首先一定要区分Apple pay 和IAP内购的区别 可以先去看一下官方文档地址 有每个步骤的详细解释本篇文章分为: 1、 内购支付流程; 2、开发集成步骤; 3、...
  • iOS内购项目审核被拒的坑

    千次阅读 2020-06-21 01:51:26
    这周照常更新版本,提交到App Store,没想到竟然被拒,拒绝理由是内购期间无限期加载,无法查看订阅内容。 一番查找发现: 苹果在审查的时候,环境是release,但账号是沙盒账号。而老项目中直接判断debug环境来设置...
  • iOS内购与定价

    千次阅读 2018-12-10 16:15:22
    一、内购信息 1.1 内购类型 月卡需要选择「非连续订阅」,其他充值选择「消费型项目」。若APP是首次提审,需先填写内购信息再提审,审核时无法修改。 1.2 参考名称 就是名字,如「999钻石」 1.3 产品ID 用户充值时...
  • 关于iOS订阅型内购开发

    千次阅读 2018-08-27 15:32:32
    由于公司项目里面有一个类似购买一个时期的产品,原本使用消耗式内购来做,但是被苹果审核拒绝了,苹果建议(要求)使用订阅式内购来做这个,于是就来研究一下 1.第一步添加内购产品 首先还是添加内购产品,...
  •  (2)内购产品id的配置 (开发人员配置)  如果是金币或其它消耗品的产品的话用消耗性型项目,参考名称(内购项目,比如金币100),产品id,定价信息,使用内购的快照,显示名称,描述。  (3)用户职能 测试员:...
  • iOS内购提示无效ID : .paymentInvalid

    千次阅读 2019-09-16 17:20:35
    1:您是否为应用程序ID启用了应用程序购买? 2:你有没有检查过你的产品清仓? 3:您是否已提交(并可选择拒绝)应用程序二进制文件? 4:您的项目的.plist捆绑ID是否与您的应用ID相匹配? 5:您是否为新的App...
  • iOS开发 内购流程 App中嵌入应用商店

    千次阅读 2016-09-18 11:21:52
    iOS开发 内购流程

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 18,903
精华内容 7,561
关键字:

ios开发内购

友情链接: 简单的软件代码.rar