美文网首页iOS收藏小知识点iOS进阶高级
iOS 内购的最新讲解(审核上线的坑)

iOS 内购的最新讲解(审核上线的坑)

作者: IIronMan | 来源:发表于2017-12-02 00:56 被阅读2271次

一.总说内购的内容

  • 1.协议、税务和银行业务 信息填写
  • 2.内购商品的添加
  • 3.添加沙盒测试账号
  • 4.内购代码的具体实现
  • 5.内购的注意事项
  • 6.掉单的处理(这个是一个蛋疼的事情)

二.协议、税务和银行业务 信息填写

  • 2.1、协议、税务和银行业务 信息填写 的入口


    协议、税务和银行业务 信息填写 的入口
  • 2.2、选择申请合同类型

    • 进入协议、税务和银行业务页面后,会有3种合同类型,如果你之前没有主动申请过去合同,那么一般你现在激活的合同只有iOS Free Application一种。

    • 页面内容分为两块:

      Request Contracts(申请合同)
      Contracts In Effect(已生效合同)。

    • 合同类型分为3种:

      iOS Free Application(免费应用合同)
      iOS Paid Application(付费应用合同)
      iAd App NetNetwork(广告合同)
      这里我们主要主要讲一下付费应用合同的申请流程。


      付费应用合同的申请流程
  • 2.3、申请iOS Paid Application合同(协议、税务和银行业务3个都要填写)

    协议、税务和银行业务
  • 2.4、Contact Info(填写联系方式)


    填写联系方式

    如果你没有添加过联系人,你需要通过Add New Contact按钮来添加一个新的联系人。然后指定联系人的职务,
    职务如下:

    Senior Management:高管
    Financial:财务
    Technical:技术支持
    Legal:法务
    Marketing:市场推广
    如果你是独立开发者,可以全部填你自己一个人。

  • 2.5、填写银行信息


    填写银行信息

    选择你的银行账户,如果你没有,点击旁边的Add Bank Account添加一个账户。下面是添加一个账户的流程。

    • 2.5.1、选择银行所在的国家


      选择银行所在的国家
    • 2.5.2、填写银行标识CNAPS Code
      如果你不知道CNAPS Code是多少,可以百度搜CNAPS Code来查询,查询时会根据3个关键信息来查询,如下:

      Bank Name:银行的英文名称(不能是拼音)
      City:银行所在的城市英文名称(中国的城市用拼音)
      Postal Code:邮编
      然后在下面就会出来备选的银行,选择正确的银行后,点击next,进入下一步。

      百度搜CNAPS Code来查询
      银行信息的填写
    • 2.5.3、确认银行信息


      确认银行信息
    • 2.5.4、填写银行账号信息
      Bank Account Number:银行账号
      Confirm Bank Account Number:再次输入银行账号
      Account Holder Name:持卡人姓名,中文名用拼写,名在前,姓在后
      Bank Account Currency:货币类型,一般国内的开发者选择CNY

      填写银行账号信息
    • 2.5.5、确认所有信息


      确认所有信息
  • 2.6.填写税务信息(这个内容比较多)

    • 2.6.1.税务信息这一块了解不是很多,不过因为是国内开发者,可以不用太费心,税务信息分3种:
      U.S Tax Forms: 美国税务
      Australia Tax Forms:澳大利亚税务
      Canada Tax Forms: 加拿大税务

      税务信息
    • 2.6.2.一堆条约
        我选择的是U.S Tax Forms,选择后会问你两个问题,

      • 第1个问题如下:询问你是否是美国居民,有没有美国伙伴关系或者美国公司,如果没有直接选择No。


        询问你是否是美国居民,有没有美国伙伴关系或者美国公司,如果没有直接选择No
      • 接下来第二个问题如下:询问你有没有在美国的商业性活动,没有也直接选No


        接下来第二个问题如下:询问你有没有在美国的商业性活动,没有也直接选No
    • 2.6.3.然后填写你的税务信息,包括以下几点:
      Individual or Organization Name:个人或者组织名称
      Country of incorporation: 所在国家
      Type of Beneficial Owner:受益方式,独立开发者选个人
      Permanent Residence:居住地址
      Mailing address:邮寄地址
      Name of Person Making this Declaration:声明人
      Title:头衔

      填写你的税务信息
    • 2.6.4.打钩


      打钩
    • 2.6.5.澳大利亚的不要管了


      澳大利亚的不要管了
    • 2.6.6.加拿大的也不用管了


      加拿大的也不用管了
  • 2.7.填写完成


    填写完成
  • 2.8.待审核
    你填写完所有资料后,合同状态就会变成Processing, 大概24小时内就会有结果。

三.内购商品的添加

  • 3.1.创建内购商品
创建内购商品
  • 3.2.选择内购类型

    • 3.2.1.消耗型商品:类似游戏中的钻石,还有现在某些APP中的货币,比如斗鱼里的鱼丸、映客里的映票。会被消耗的,要选择消耗型商品
      注意:大多数的消耗型商品都是需要登录的,因为需要在数据库存余额。
      需要注意的是:在登录之前,你最好不要让用户看到商品,有可能会因为这个原因被拒(大家都说看运气)
    • 3.2.2.非消耗型商品:无法被消耗的商品,比如上文提到的视频课程,一次购买,就应该永久可以观看
      注意:当你使用非消耗型商品时,你需要添加一个恢复购买的按钮
      这个常见于各种游戏中,其实知道这个规定以后还是挺好理解的,非消耗型商品是不可被消耗的,一次购买终身使用的,非消耗型的商品是跟appleId绑定的,就是你平时下载APP让你输入账号密码的内个。
      你需要一个恢复购买的按钮,来让用户恢复他购买的内容
    • 3.2.3.订阅类型商品:如果你的公司是外包公司,有订阅类型商品的APP一定要用客户的账号提交审核,因为当APP中有过订阅类型商品,注意是有过,创建过再删除也算,这个APP无法被转移账号
      注意:使用或曾经使用过订阅型商品的APP无法转移
      选择内购类型
      具体内购类型
      选择语言
      FA40E42F-400E-4A85-949A-ED90C9B6B475.png
  • 3.3.创建好的产品


    创建好的产品
  • 3.4.在上线的时候记得添加内购的商品


    添加内购商品
    选择内购产品之后的状态

四.添加沙盒测试账号

  • 4.1.添加沙盒测试的入口


    添加沙盒测试的入口
  • 4.2.添加沙盒测试账号


    添加沙盒测试账号
  • 4.3.具体的测试账号信息填写


    具体的测试账号信息填写

五.内购代码的具体实现(这才是大家所期望看到的)

  • 5.1.我创建了一个购买金币的内购控制器ApplePayCIOViewController
    在此,我仅仅向大家贴出.m的详细代码

  • 5.2.内购的流程详细讲解

    • 5.2.1. 用户先拿到购买产品的单子,
    • 5.2.2.拿着单子去苹果那里交钱,交完钱让苹果在单子上盖个章
    • 5.2.3.拿着盖了章的单子传给自己的服务器来验证是否真的支付成功
    • 5.2.4.根据服务器返回的信息做具体的处理


      内购的流程详细讲解
  • 5.3.上代码

    • 5.3.1..先导入StoreKit.framework库;

    • 5.3.2.创建ApplePayCIOViewController,遵守协议<SKPaymentTransactionObserver,SKProductsRequestDelegate>

    • 5.3.3.ApplePayCIOViewController.m代码

      #import "ApplePayCIOViewController.h"
      #import <StoreKit/StoreKit.h>
      // 产品的ID
      #define ProductID1 @"CIOCourses1"
      @interface ApplePayCIOViewController ()<SKProductsRequestDelegate,SKPaymentTransactionObserver>
      {
          NSString *selectProductID;
      }
      @end
      @implementation ApplePayCIOViewController
      -(void)viewWillAppear:(BOOL)animated{
         [super viewWillAppear:animated];
         // 添加观察者
         [[SKPaymentQueue defaultQueue] addTransactionObserver:self];   
      }
      -(void)viewWillDisappear:(BOOL)animated{
         [super viewWillDisappear:animated];
         // 移除观察者
        [[SKPaymentQueue defaultQueue] removeTransactionObserver:self];
      }
      
      - (void)viewDidLoad {
        [super viewDidLoad];
         self.title = @"内购";
      
         self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc]initWithTitle:@"测试" style:UIBarButtonItemStylePlain target:self action:@selector(test)];
      
          // 恢复购买的按钮
          UIButton * revert = [[UIButton alloc]initWithFrame:CGRectMake(20, 100, 100, 80)];
          [revert setBackgroundColor:JKRandomColor];
          [revert addTarget:self action:@selector(replyToBuy) forControlEvents:UIControlEventTouchUpInside];
          [self.view addSubview: revert];
          self.view.backgroundColor =[UIColor redColor];
      }
      
      #pragma mark 恢复购买(主要是针对非消耗产品)
      -(void)replyToBuy{
      
         [[SKPaymentQueue defaultQueue] restoreCompletedTransactions];
      }
      #pragma mark 测试内购
      -(void)test{
      
        if([SKPaymentQueue canMakePayments]){
      
          // productID就是你在创建购买项目时所填写的产品ID
          selectProductID = [NSString stringWithFormat:@"%@",ProductID1];
          [self requestProductID:selectProductID];
      
         }else{
                    
         // NSLog(@"不允许程序内付费");
         UIAlertView *alertError = [[UIAlertView alloc] initWithTitle:@"温馨提示"
                                                                                                                          message:@"请先开启应用内付费购买功能。"
                                                                                                          delegate:nil
                                                                                                                    cancelButtonTitle:@"确定"
                                                                                                              otherButtonTitles: nil];
         [alertError show];
         }
      }
      #pragma mark 1.请求所有的商品ID
      -(void)requestProductID:(NSString *)productID{
      
         // 1.拿到所有可卖商品的ID数组
         NSArray *productIDArray = [[NSArray alloc]initWithObjects:productID, nil];
         NSSet *sets = [[NSSet alloc]initWithArray:productIDArray];
      
         // 2.向苹果发送请求,请求所有可买的商品
         // 2.1.创建请求对象
         SKProductsRequest *sKProductsRequest = [[SKProductsRequest alloc]initWithProductIdentifiers:sets];
         // 2.2.设置代理(在代理方法里面获取所有的可卖的商品)
         sKProductsRequest.delegate = self;
         // 2.3.开始请求
         [sKProductsRequest start];
      
      }
      #pragma mark 2.苹果那边的内购监听
      -(void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response{
      
         NSLog(@"可卖商品的数量=%ld",response.products.count);
      
         NSArray *product = response.products;
         if([product count] == 0){
      
           NSLog(@"没有商品");
           return;
         }
      
       for (SKProduct *sKProduct in product) {
      
            NSLog(@"pro info");
            NSLog(@"SKProduct 描述信息:%@", sKProduct.description);
            NSLog(@"localizedTitle 产品标题:%@", sKProduct.localizedTitle);
            NSLog(@"localizedDescription 产品描述信息:%@",sKProduct.localizedDescription);
            NSLog(@"price 价格:%@",sKProduct.price);
            NSLog(@"productIdentifier Product id:%@",sKProduct.productIdentifier);
      
           if([sKProduct.productIdentifier isEqualToString: selectProductID]){
        
              [self buyProduct:sKProduct];
        
              break;
        
           }else{
        
            //NSLog(@"不不不相同");
           }
        }
      
      }
      
      #pragma mark 内购的代码调用
      -(void)buyProduct:(SKProduct *)product{
      
         // 1.创建票据
        SKPayment *skpayment = [SKPayment paymentWithProduct:product];
      
        // 2.将票据加入到交易队列
        [[SKPaymentQueue defaultQueue] addPayment:skpayment];
      
        // 3.添加观察者,监听用户是否付钱成功(不在此处添加观察者)
        //[[SKPaymentQueue defaultQueue] addTransactionObserver:self];
      
      }
      
      #pragma mark 4.实现观察者监听付钱的代理方法,只要交易发生变化就会走下面的方法
      -(void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray<SKPaymentTransaction *> *)transactions{
      
        /*
          SKPaymentTransactionStatePurchasing,    正在购买
          SKPaymentTransactionStatePurchased,     已经购买
          SKPaymentTransactionStateFailed,        购买失败
          SKPaymentTransactionStateRestored,      回复购买中
          SKPaymentTransactionStateDeferred       交易还在队列里面,但最终状态还没有决定
        */
      
        for (SKPaymentTransaction *transaction in transactions) {
           switch (transaction.transactionState) {
                 case SKPaymentTransactionStatePurchasing:{
            
                      NSLog(@"正在购买");
                 }break;
                 case SKPaymentTransactionStatePurchased:{
            
                    NSLog(@"购买成功");
                    // 购买后告诉交易队列,把这个成功的交易移除掉
                    [queue finishTransaction:transaction];
                    [self buyAppleStoreProductSucceedWithPaymentTransactionp:transaction];
                 }break;
                 case SKPaymentTransactionStateFailed:{
            
                     NSLog(@"购买失败");
                     // 购买失败也要把这个交易移除掉
                     [queue finishTransaction:transaction];
                 }break;
                 case SKPaymentTransactionStateRestored:{
                     NSLog(@"回复购买中,也叫做已经购买");
                     // 回复购买中也要把这个交易移除掉
                     [queue finishTransaction:transaction];
                 }break;
        case SKPaymentTransactionStateDeferred:{
            
                    NSLog(@"交易还在队列里面,但最终状态还没有决定");
                 }break;
                 default:
                 break;
               }
          }
       }
      
      // 苹果内购支付成功
      - (void)buyAppleStoreProductSucceedWithPaymentTransactionp:(SKPaymentTransaction *)paymentTransactionp {
      
        NSString * productIdentifier = paymentTransactionp.payment.productIdentifier;
        // NSLog(@"productIdentifier Product id:%@", productIdentifier);
        NSString *transactionReceiptString= nil;
      
        //系统IOS7.0以上获取支付验证凭证的方式应该改变,切验证返回的数据结构也不一样了。
         NSString *version = [UIDevice currentDevice].systemVersion;
         if([version intValue] >= 7.0){
             // 验证凭据,获取到苹果返回的交易凭据
             // appStoreReceiptURL iOS7.0增加的,购买交易完成后,会将凭据存放在该地址
             NSURLRequest * appstoreRequest = [NSURLRequest requestWithURL:[[NSBundle mainBundle]appStoreReceiptURL]];
             NSError *error = nil;
             NSData * receiptData = [NSURLConnection sendSynchronousRequest:appstoreRequest returningResponse:nil error:&error];
             transactionReceiptString = [receiptData base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithLineFeed];
         }else{
      
            NSData * receiptData = paymentTransactionp.transactionReceipt;
              //  transactionReceiptString = [receiptData base64EncodedString];
            transactionReceiptString = [receiptData base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithLineFeed];
          }
         // 去验证是否真正的支付成功了
         [self checkAppStorePayResultWithBase64String:transactionReceiptString];
      
      }
      
      - (void)checkAppStorePayResultWithBase64String:(NSString *)base64String {
      
         /* 生成订单参数,注意沙盒测试账号与线上正式苹果账号的验证途径不一样,要给后台标明 */
        /*
         注意:
         自己测试的时候使用的是沙盒购买(测试环境)
         App Store审核的时候也使用的是沙盒购买(测试环境)
         上线以后就不是用的沙盒购买了(正式环境)
         所以此时应该先验证正式环境,在验证测试环境
      
        正式环境验证成功,说明是线上用户在使用
        正式环境验证不成功返回21007,说明是自己测试或者审核人员在测试
         */
         /*
           苹果AppStore线上的购买凭证地址是: https://buy.itunes.apple.com/verifyReceipt
           测试地址是:https://sandbox.itunes.apple.com/verifyReceipt
          */
         //    NSNumber *sandbox;
         NSString *sandbox;
         #if (defined(APPSTORE_ASK_TO_BUY_IN_SANDBOX) && defined(DEBUG))
        //sandbox = @(0);
        sandbox = @"0";
        #else
        //sandbox = @(1);
        sandbox = @"1";
        #endif
      
        NSMutableDictionary *prgam = [[NSMutableDictionary alloc] init];;
        [prgam setValue:sandbox forKey:@"sandbox"];
        [prgam setValue:base64String forKey:@"reciept"];
      
        /*
           请求后台接口,服务器处验证是否支付成功,依据返回结果做相应逻辑处理
           0 代表沙盒  1代表 正式的内购
           最后最验证后的
         */
          /*
            内购验证凭据返回结果状态码说明
            21000 App Store无法读取你提供的JSON数据  
            21002 收据数据不符合格式  
            21003 收据无法被验证  
            21004 你提供的共享密钥和账户的共享密钥不一致  
            21005 收据服务器当前不可用  
            21006 收据是有效的,但订阅服务已经过期。当收到这个信息时,解码后的收据信息也包含在返回内容中  
            21007 收据信息是测试用(sandbox),但却被发送到产品环境中验证  
            21008 收据信息是产品环境中使用,但却被发送到测试环境中验证
            */
      
         NSLog(@"字典==%@",prgam);
      
      }
      
      #pragma mark 客户端验证购买凭据
      - (void)verifyTransactionResult
      {
         // 验证凭据,获取到苹果返回的交易凭据
         // appStoreReceiptURL iOS7.0增加的,购买交易完成后,会将凭据存放在该地址
         NSURL *receiptURL = [[NSBundle mainBundle] appStoreReceiptURL];
         // 从沙盒中获取到购买凭据
         NSData *receipt = [NSData dataWithContentsOfURL:receiptURL];
         // 传输的是BASE64编码的字符串
         /**
            BASE64 常用的编码方案,通常用于数据传输,以及加密算法的基础算法,传输过程中能够保证数据传输的稳定性
            BASE64是可以编码和解码的
          */
         NSDictionary *requestContents = @{
                                  @"receipt-data": [receipt base64EncodedStringWithOptions:0]
                                  };
         NSError *error;
         // 转换为 JSON 格式
         NSData *requestData = [NSJSONSerialization dataWithJSONObject:requestContents
                                                      options:0
                                                        error:&error];
         // 不存在
         if (!requestData) { /* ... Handle error ... */ }
      
         // 发送网络POST请求,对购买凭据进行验证
         NSString *verifyUrlString;
         #if (defined(APPSTORE_ASK_TO_BUY_IN_SANDBOX) && defined(DEBUG))
         verifyUrlString = @"https://sandbox.itunes.apple.com/verifyReceipt";
         #else
          verifyUrlString = @"https://buy.itunes.apple.com/verifyReceipt";
         #endif
         // 国内访问苹果服务器比较慢,timeoutInterval 需要长一点
         NSMutableURLRequest *storeRequest = [NSMutableURLRequest requestWithURL:[[NSURL alloc] initWithString:verifyUrlString] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:10.0f];
      
         [storeRequest setHTTPMethod:@"POST"];
         [storeRequest setHTTPBody:requestData];
      
         // 在后台对列中提交验证请求,并获得官方的验证JSON结果
         NSOperationQueue *queue = [[NSOperationQueue alloc] init];
         [NSURLConnection sendAsynchronousRequest:storeRequest queue:queue
                       completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
                           if (connectionError) {
                               NSLog(@"链接失败");
                           } else {
                               NSError *error;
                               NSDictionary *jsonResponse = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];
                               if (!jsonResponse) {
                                   NSLog(@"验证失败");
                               }
                               
                               // 比对 jsonResponse 中以下信息基本上可以保证数据安全
                               /*
                                bundle_id
                                application_version
                                product_id
                                transaction_id
                                */
                               
                               NSLog(@"验证成功");
                           }
                       }];
      
      }
      @end
      

六.内购的注意事项

  • 6.1.一般发生于首次提交app或添加新商品,当你的app通过审核以后,你发现在生产环境下获取不到商品,这是因为app虽然过审核了,但是内购商品还没有正式添加到苹果的服务器里,耐心等待一段时间就可以啦~

  • 6.2. 代码中的_currentProId所填写的是你的购买项目的的ID,这个和第二步创建的内购的productID要一致;本例中是 123。

  • 6.3. 在监听购买结果后,一定要调用[[SKPaymentQueue defaultQueue] finishTransaction:tran];来允许你从支付队列中移除交易。

  • 6.4. 沙盒环境测试appStore内购流程的时候,请使用没越狱的设备。

  • 6.5. 请务必使用真机来测试,一切以真机为准。

  • 6.6. 项目的Bundle identifier需要与您申请AppID时填写的bundleID一致,不然会无法请求到商品信息。

  • 6.7. 真机测试的时候,一定要退出原来的账号,才能用沙盒测试账号

  • 6.8. 二次验证,请注意区分宏, 测试用沙盒验证,App Store审核的时候也使用的是沙盒购买,所以验证购买凭证的时候需要判断返回Status Code决定是否去沙盒进行二次验证,为了线上用户的使用,验证的顺序肯定是先验证正式环境,此时若返回值为21007,就需要去沙盒二次验证,因为此购买的是在沙盒进行的。

  • 6.9.您的应用是否处于等待开发者发布(Pending Developer Release)状态?等待发布状态的IAP是无法测试的。

  • 6.10.您的内购项目是否是最近才新建的,或者进行了更改?内购项目需要一段时间才能反应到所有服务器上,这个过程一般是一两小时,也可能再长一些达到若干小时。

  • 6.11.您在iTC中Contracts, Tax, and Banking Information项目中是否有还没有设置或者过期了的项目?不完整的财务信息无法进行内购测试。

  • 6.12.您是在越狱设备上进行内购测试么?越狱设备不能用于正常内购,您需要重装或者寻找一台没有越狱的设备。

  • 6.13.您的应用是否是被拒状态(Rejected)或自己拒绝(Developer Rejected)了?被拒绝状态的应用的话对应还未通过的内购项目也会一起被拒,因此您需要重新将IAP项目设为Cleared for Sale。

  • 6.14.您使用的测试账号是否是美国区账号?虽然不是一定需要,但是鉴于其他地区的测试账号经常抽风,加上美国区账号一直很稳定,因此强烈建议使用美国区账号。正常情况下IAP不需要进行信用卡绑定和其他信息填写,如果你遇到了这种情况,可以试试删除这个测试账号再新建一个其他地区的。

  • 6.15.您是否将设备上原来的app删除了,并重新进行了安装?记得在安装前做一下Clean和Clean Build Folder。

  • 6.16.您的plist中的Bundle identifier的内容是否和您的AppID一致?

七.内购审核的注意事项

  • 7.1.项目里面的内购一定要勾选


    • 7.2.协议一定要通过(下载的状态)


      协议一定要通过
    • 7.3.证书的配置文件里面要支持内购


      证书的配置文件里面要支持内购
    • 7.4.项目第一次使用内购,内购的产品一定要跟着版本一起提交,如果提交被拒,内购产品要删掉重新建

      项目第一次使用内购

八.最后,聊一聊内购上线与苹果的沟通

  • 8.1、在2018年2月初,内购准备充分,测试环境测试以及TestFlight开发环境测试,购买流程都是OK的。信心满满的提交给了苹果,第二天,果断被拒,说让加游客购买😅,按照要求加了游客购买,设置了用户设备的唯一标识符IDFV+KeyChain来做游客购买,
    游客购买
  • 8.2、当游客购买做完,开开心心的去提交,第二天回家过年,没想到到家后技术总监告诉我又被苹果拒绝,说点击游客购买不了,邮件说ipv6的问题(第2,3,4,5次说是在ipv6 下点击游客内购购买始终没有反应!),因为苹果审核测试人员并非技术人员,他们只能从现象给出理由,所以经常会归为ipv6问题,但不一定是ipv6问题,有时候网络不好,或许他们测试的iPad出问题了。于是我在Mac上搭建ipv6测试App,包括翻墙什么的,录视频,都说明在ipv6下没问题,购买流程很顺畅。然后给苹果回复,请求重新审核。
  • 8.3、请求重新审核的结果是还是点击购买没反应(也可以解释为苹果那审核测试商品一直是无效的),后面开始怀疑审核人员的网络不好或者是测试的地区没换。于是请求了技术的支持以及客服代表的电话协助,技术测试说内购没问题了,原因是是审核人员的设备的问题(大爷的审核人员,白痴啊)。于是再次请求审核人员审核。
  • 8.4、请求审核还是被拒😅,原因是定位和相册请求的描述不正确,修改完之后,打包,提交,第二天早晨起来一看,通过了😆。到公司后测试线上的内购,所有的流程都是OK的。
  • 8.5、当天下午又重新上了一版,第二天起来审核通过了,但是问题来了又提交的五个内购商品无法购买,原因是appstore还没反应过来(商品在2~24小时是生效时间)。
  • 8.6、说个题外话,在app被拒后,如果自己的app没问题,就直接上诉苹果审查委员会,不要再提新包,等着申诉的回复。申诉成功后,苹果审核人员会自己把应用的包重新从二进制被拒->正在审核,等待再次被审核的结果就好。

End: 路过的给个喜欢!谢谢

相关文章

  • iOS 内购的最新讲解(审核上线的坑)

    一.总说内购的内容 1.协议、税务和银行业务 信息填写 2.内购商品的添加 3.添加沙盒测试账号 4.内购代码的具...

  • iOS开发-内购丢单处理方式

    之前写了一篇关于内购的博客iOS开发-2017苹果内购最新教程,上线审核很顺利,但是上线后很多问题暴露出来.用户购...

  • iOS 内购最新讲解

    一.总说内购的内容 协议、税务和银行业务 信息填写 内购商品的添加 添加沙盒测试账号 内购代码的具体实现 内购的注...

  • iOS 内购最新讲解

    一.总说内购的内容 协议、税务和银行业务 信息填写 内购商品的添加 添加沙盒测试账号 内购代码的具体实现 内购的注...

  • iOS 开发——审核篇

    项目上线有一段时间了,最近一直在弄马甲号,说说最近的坑。 审核失败的原因: 内购问题:明确内购购买的虚拟物品作用。...

  • iOS内购从放弃到上架

    iOS内购方面的坑

  • iOS-内购

    前言:关于iOS内购,参考两篇博文 iOS-iOS内购流程(手把手图文教程)iOS内购你看我就够了(埋坑篇) 我自...

  • applePay

    # iOS应用内支付(内购)的个人开发过程及坑!

  • iOS 内购 : 审核上线了, 内购商品找不到

    记录一个奇葩的问题 : 说明 :1.前面提示支付失败的是点击最后一档位(350)2.后面弹出可以支付的是点击倒数第...

  • 应用内购(In-App Purchase)常见问题解答

    应用内购(In-App Purchase)常见问题解答iOS的应用内购买 iAP 坑 iOS内购你看我就够了(一)...

网友评论

  • 终点_2fb6:价格不能自定义,你说的群号,加不进去
    IIronMan:QQ群号是:584599353
    IIronMan:@终点_2fb6 价格是苹果设置的固定价格,但是你要是想随意定义的话,你可以设置中间货币,加不进去可以加我私人微信:wangc2318151015
  • 49097947abe4:楼主你好,第一次新建内购项目要和app一起提交审核吗?
    我新建内购项目后显示准备提交,提交以供审核的按钮不能点击。
    内购项目审核通过后才能测试内购吗?
    我现在测试的时候提示 “无法获取数据,请配置后台信息”。
    我是做U3D开发的,对ios不熟悉。
    IIronMan:@391 首先回答您的第1个问题:第一次新建内购项目“必须”要和app一起提交审核;第2个问题:新建内购项目后不要点击提交,等测试完和app版本一起提交,在提交app的那里有添加内购的的选项;第三个问题:建完内购有可能苹果那边没更新完内购的项目,一般在24小时内会更新内购信息,稍后再测试。注意:内购之前的协议,银行信息等要填写完整,等协议通过,一般过一天就通过了。如果还有其他的问题联系我:wangc2318151015或者加群
  • 亲爱的苗苗:描述一直通不过,表示要崩溃
    IIronMan:@亲爱的苗苗 发给我看看你的描述,加我微信 wangc2318151015
  • Elvis丶仰望星空:内购项目和APP提交审核的时候,内购验证地址是写沙盒地址还是正式地址,有一次苹果那边打电话说他们审核的时候使用正式地址测试,而且内购项目没有审核通过的时候,是不是正式的账号请求不到数据,只有在沙箱测试的时候才能获取,内购项目审核和APP审核是一个部门吗
    Elvis丶仰望星空:@IIronMan 那内购项目没有审核通过的时候,APP请求不到内购项目,然后APP就被拒了,还是说我做错了,哪有问题
    IIronMan:@Elvis丶仰望星空 你自己在测试的时候用测试的地址,上线审核的时候写正式的地址,苹果他们自有办法测试
    IIronMan:@Elvis丶仰望星空 写正式的,苹果他们会测的
  • miliPolo:我想问下,如果用户取消订阅了之后,代码中怎么来判断啊
  • 在没老之前:你好,我想请问一下。我现在是在ViewController里面添加了个webView,充值的界面是web做的,我拦截到点击,就调起内购。的确调起了,但是-(void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response这个代理方法不调用。我设置了代理,也添加了监听,请问为啥?
    IIronMan:@在没老之前 商品创建了吗??
    在没老之前:@IIronMan 楼主,你好。我们这个APP功能本身就不多。这个内购肯定是要的,关键是我按照你的方法一步步的写好了。就是不调用代理方法,好气啊。。。有啥可能导致这种情况发生:sob:
    IIronMan:@在没老之前 你既然做了网页,就做后台开关好了,苹果审核后再点击就走跳转你的网页好了,不会再调内购,自然方法-(void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response也就用不到了
  • BohrIsLay:请问你们内购从拿到需求开始,到上线花了多久?
    IIronMan:@BohrIsLay 一两个月,刚开始经验少,在苹果那里审核的时间长了点,有经验了之后也就一两个星期吧
  • 0x00chen:楼主在吗?问一个问题,内购时候用测试账号弹出来的都是输入账号密码。但是我在别人APP上用内购的时候就死touchID验证,是上线以后自动会使用touchID支付还是使用touchID支付需要其他的设置呢?
    IIronMan:@0x00chen 更多的问题可以进我们的iOS开发交流QQ群:584599353
    IIronMan:@0x00chen 上线以后touchID
  • 剪刀_石头_布:我想问一下。内购的钱什么时候公司才能收到。是有时间限制还是得有最低数额限制。这个限制是多少呢
    IIronMan:@剪刀_石头_布 恩恩
    剪刀_石头_布:@IIronMan 差不多要三个月才会有。谢谢
    IIronMan:@剪刀_石头_布 当月交易的款项,苹果系统里在第二个月15日后,会出具账单,再等待1个月后银行通知结汇,提交结汇资料后,再1个月款项才会到企业银行账户
  • a637237315f9:感谢分享
    IIronMan:共同进步
  • 捏捏你的脸:非常详细。
    IIronMan:@捏捏你的脸 共享,有问题多进群交流 584599353 :smile:
  • 汤姆的杰瑞:-验证结果 {
    environment = Sandbox;
    receipt = {
    "adam_id" = 0;
    "app_item_id" = 0;
    "application_version" = 3;
    "download_id" = 0;
    "in_app" = (
    {
    "is_trial_period" = false;
    "original_purchase_date" = "2017-12-21 06:43:09 Etc/GMT";
    "original_purchase_date_ms" = 1513838589000;
    "original_purchase_date_pst" = "2017-12-20 22:43:09 America/Los_Angeles";
    "original_transaction_id" = 1000000361559240;
    "product_id" = "com.maomaocat.www600";
    "purchase_date" = "2017-12-21 06:43:09 Etc/GMT";
    "purchase_date_ms" = 1513838589000;
    "purchase_date_pst" = "2017-12-20 22:43:09 America/Los_Angeles";
    quantity = 1;
    "transaction_id" = 1000000361559240;
    }
    );
    "original_application_version" = "1.0";
    "original_purchase_date" = "2013-08-01 07:00:00 Etc/GMT";
    "original_purchase_date_ms" = 1375340400000;
    "original_purchase_date_pst" = "2013-08-01 00:00:00 America/Los_Angeles";
    "receipt_creation_date" = "2017-12-21 06:43:09 Etc/GMT";
    "receipt_creation_date_ms" = 1513838589000;
    "receipt_creation_date_pst" = "2017-12-20 22:43:09 America/Los_Angeles";
    "receipt_type" = ProductionSandbox;
    "request_date" = "2017-12-21 06:43:23 Etc/GMT";
    "request_date_ms" = 1513838603605;
    "request_date_pst" = "2017-12-20 22:43:23 America/Los_Angeles";
    "version_external_identifier" = 0;
    };
    status = 0;
    }

    大佬你好,我想请问下 这个是购买成功后苹果返回我的结果
    我做的虚拟货币所以不清楚选择哪个
    1:消耗性项目&非消耗性项目 我选择的是消耗性项目 不知道是不是对的
    2:假设6元=600钻石 我购买6元钻石成功后,我从哪里获取这个值呢
    IIronMan:支付成功后从沙盒取出凭证 去后台验证或者前台验证,上面代码都有写 ,base64
  • 汤姆的杰瑞:很详细~点赞 能否请教几个问题了
    IIronMan:@汤姆的杰瑞 qq群 584599353
    汤姆的杰瑞:@IIronMan 加不了
    IIronMan:@汤姆的杰瑞 可以,群里方便 584599353
  • 棍武中原:楼主,添加的沙箱测试账号在哪用呢?
    没有看到啊?
    IIronMan:@棍武中原 不是,在创建商品ID的时候设置价格,如果有更多的问题加群 584599353
    棍武中原:@IIronMan 你好,我想问下,是不是沙箱测试内购价格默认就是6块钱的?
    我没找到在哪里创建价格。
    IIronMan:@棍武中原 在购买弹框那么用啊
  • 谦言忘语:深度好文,点个赞。对了,内购的时候我从来没有给过苹果沙盒账号,我觉得苹果本身应该会有一个内购使用的超级沙盒账号。或者说他会知道我们的沙盒账号,所以我们可以不给他。【iOS】苹果IAP(内购)中沙盒账号使用注意事项 http://www.jianshu.com/p/1ef61a785508
    IIronMan:@谦言忘语 您说的有道理,最好还是给苹果一下沙盒的测试账号,以便于更快的审核
  • scscsc::+1:
    IIronMan:@如缩影ccc遂心_ 一起进步,有好的文章欢迎您投稿

本文标题:iOS 内购的最新讲解(审核上线的坑)

本文链接:https://www.haomeiwen.com/subject/wqapbxtx.html