IAP专题-包含基础知识和经常遇到的一些问题.In App Purchase 个人使用总结

编程入门 行业动态 更新时间:2024-10-10 14:26:54
  • 我要在app里添加IAP,必须要注册自己的产品标识符(product identifiers)。产品标识符是什么?

    产品标识符(Product Identifiers)是一串字符串,它用来识别你在应用内贩卖的每件商品。App Store用产品标识符来检索产品信息,标识符只能包含大小写字母(A-Z)、数字(0-9)、下划线(-)、以及圆点(.)。你可以任意排列这些元素,但我们建议你创建标识符时使用反向域名,比如 companyname.application.productid
    备注:产品标识符和Apple ID以及Bundle ID没有关系,它们看起来可能比较像Bundle ID,但是两者是不一样的。所以,在代码里你不能用Apple ID或者Bundle ID代替产品标识符。

  • 怎么创建产品标识符?

    IAP表单(TheIn-App Purchases form)是用来生成IAP产品的,它包含了产品ID的字段,这个字段必须要填到表里。这个字段可以为你的产品指定产品标识符。你可以按下面的步骤来创建产品标识符:
    1.登入iTunes Connect, 点击主页面上的Manage Your Applications模块。
    2.进入Manage Your Apps 页面,你可以看到你所有的应用列表。选择你想要创建IAP的产品的app,在下个页面中点击Manage In-App Purchases按键,然后在点击创建。
    3.选择IAP产品的类型。iTunes Connect会带你进入IAP表单,在这个表单里有“保存”按键。完整填写Product ID以及表单里的其他字段。
    注意事项:产品标识符一旦创建无法修改,此外,如果应用审核没有通过,这个产品标识符也无法再次使用。

  • 如何在app中如何使用产品标识符?

    首先创建SKProductsRequest,然后把产品标识符列表传至initWithProductIdentifiers 来读取产品信息。

  • 当在Sandbox 环境测试In-App Purchase 时,为什么我得到的是“Payment requests are restricted to products returned as valid via Store Kit's didReceiveResponse method”错误信息?

    执行In-App Purchase的app的用户界面必须有App Store允许的可供购买的产品。在你决定在用户界面展示用于购买的产品之前,你的app必须先向App Store发送一个产品请求。

  • StoreKit提供了两种支付支付请求的解决办法:

    [SKPayment paymentWithProductIdentifier:PRODUCT_ID] [SKPayment paymentWithProduct:YOUR_SKPRODUCT_OBJECT]苹果建议您使用 [SKPayment paymentWithProduct:YOUR_SKPRODUCT_OBJECT] 使用这个方法可以确保你一直处于有效的产品支付请求状态,同时也确保用户可以购买你的产品。所以,务必只展现App Store返回的产品信息。了解更多有关于app内产品展现信息,请查看In-App Purchase 编程指南的Feature Delivery 部分。

  • In-App Purchase有几种类型?

    In-App Purchase共有3中类型,Consumable:一次性购买,最简单的类型,不用保存历史记录。 Nonconsumable:每个产品,用户只买一次,此后就可以在自己的所有设备上看到该产品。 Subscriptions:订阅模式允许多次购买末一个产品,但是购买后,用户可以在自己的所有设备上看到该产品。

  • iOS 中使用 IAP 方式在程序内购买的内容在重装系统后还需要再次购买吗? 比如Camera+内的滤镜。

    不必。以 Camera+ 为例,Menu 里最下方的选项 Restore purchases 即可帮你解锁已经购买的滤镜。任何实现了 IAP 功能的 App 基本都会提供这一选项,或者在第二次购买时提示已购。
    消耗类(如游戏金币)需要购买。 功能类不需要购买,有些应用提供“Restore purchases”,没有的可以再次尝试购买,会提示已付费。

  • IAP 能做限时免费吗? 想做一个免费下载、部分内容免费,但是阅读更多内容需要付费解锁的阅读应用。这样可以把IAP的价格限时免费为0吗?

    你可以设置为0.99美元

  • 创建产品ID的时候,选择多少钱的时候选错了,程序还未提交,还能修改吗?

    可以的,在应用程序的信息中。

  • 升级iOS5 GM的过程中恢复备份出了问题,导致In-App Purchase也丢失了。有没有办法恢复? 在iPad上曾经进行过一些In-App Purchase,但是在升级iOS5 GM的过程中恢复备份出了问题,导致除了恢复升级前的所有应用程序之外,其余个人信息一概丢失。iTunes上可以查询到购买记录。具体来说,买的是Splashtop的把iPad作为第二显示器的软件,Xdisplay。

    In-App Purchase 分好几种,最常见的是 Non-Consumable,就是只需要用户购买一次的。如果是这种类型的,再购买一次同一个商品就能够恢复了,不会收取额外费用。如果 app 做得好的话,应该提供一个 Restore 功能,以专门恢复以前购买过的 Non-Consumable 的商品。

  • 在iTunes Connect中每个应用可以创建多少个IAP产品ID?

    请参阅iTunes Connect Developer Guide的注册IAP部分

  • 在iTunes Connect里找不到Manage In-App Purchase (管理IAP)按键怎么办?

    以下是可能导致“Manage In-App Purchase”按键无法使用的原因
    a.不是iTunes Connnect的管理员(Admin)或开发者(Technical)账号。
    b.没有同意最新的iOS或Mac开发者许可协议。
    c.最新的付费应用协议(Paid Applications contract)没有生效

  • 必须上传程序的二进制码才能测试IAP吗?

    没有这个必要。
    重要事项:除非你的应用已经做好了接受苹果审核的准备,否则请不要上传Development Binary至iTunes Connect。如果iTunes Connect里的二进制编码不完整,二进制编码被拒的可能性很大。一旦二进制编码通过审核,就可以测试In-App Purchase功能了。

  • 出现了“您的账号信息已变”错误怎么办?

    “您的账号信息已变”错误出现的原因是在测试IAP的时候你使用的是设备的测试账号。解决方法是退出账号,然后在iTunes Connect创建一个新的测试账号,使用新的测试账号来测试IAP。

  • 为什么我的产品标识符在invalidProductIdentifiers中被退返?

    有可能是以下原因:
    a.没有填完财政需求表(请参阅本文档的“合同、税务以及银行信息”部分)
    b.没有使用正确的App ID。
    c.没有使用正确的与App ID紧密关联的Provisioning Profile。
    d.代码中没有使用正确的产品标识符。更多产品标识符的信息请参阅技术问答,第1329条—IAP产品标识符。
    e.你没有清除iTunes Connect中促销的IAP产品。
    f.也许你已经修改了你的产品,但它没有在App Store的服务器中生效。
    g.苹果拒绝了你最新向iTunes Connect提交的二进制码。

  • 出现了“你已购买本商品,但商品没有被下载”错误怎么办?

    你的应用没有调用SKPaymentQueue 's finishTransaction。调用finishTransaction:允许你从支付队列中移除交易。

  • 出现“你已成功购买,点击‘确认’再次进行免费下载”错误怎么办?

    这个信息是个提醒,不是错误。这表明你试图购买一个你已经购买了的非消耗性产品。购买一个非消耗性的产品时不会被扣费。

  • 调用 payment queue的 restoreCompletedTransactions: 方法不能恢复app的任何产品。

    可能由于以下原因:
    你没有任何先前购买过的非消耗类产品。
    你试图恢复的订阅产品或者非消耗类产品是不可恢复的类型。
    restoreCompletedTransactions: 方法只能恢复非消耗类产品。
    注意: 在没有可恢复产品的情况下,Store Kit不会调用paymentQueue:updatedTransactions:方法。

  • 应该什么时候恢复In-App Purchase产品?

    在以下两种情况下你可以恢复自动更新的订阅产品和非消耗类产品:
    a.在客户其他设备上安装
    b.在删除了关联应用的其他设备上重新安装

  • 如何解决“这不是测试用的用户账号,请在Sandbox环境下创建一个新的账号”的问题?

    出现这个错误的原因是在确认购买信息时你使用的是iTunes用户账号。解决的办法是退出账号,然后使用你的IAP测试账号。

  • 回单(receipt )核实失败,并且出现字符串 (iOS)。

    可能有以下几个原因:
    a.在你的iOS app里,你没有使用64位编码对回单数据进行编码,
    b.没有有效的回单,你的回单大概使用了等号隔开键和值,用分号隔开了关键字。
    c.有效的回单使用冒号来隔开键和值,用逗号隔开关键字,
    下表是有效的回单样本
    receipt:{ "signature" : "...", "purchase-info" : "...", "pod" : "...", "signing-status" : "..."}

  • 我更新了使用In-App Purchase的iOS app,如何对它进行测试呢(iOS)?

    不管更新后的app是否正确执行地了In-App Purchase,如果你要测试的话就按照以下步骤:
    通过Ad Hoc Distribution方式安装原始app。
    通过Ad Hoc Distribution方式安装更新后的app来验证它是否完全覆盖了原始的app。
    试着从更新后的app中执行In-App Purchase。

  • 我应该使用哪个url核实回单(receipt)(iOS)?

    在sandbox环境测试app时使用 sandbox URL ,当应用处于审核状态时也可以使用这个URL:https://sandbox.itunes.apple/verifyReceipt 使用产品 URL 一旦你的app上架App Store,你就要用产品URL:http://buy.itunes.apple/verifyReceipt

  • 如何核实receipt(iOS)?

    第一次一般使用产品的URL核实收据。如果你收到一个21007状态代码,那么接下来要用sandbox URL。当app处于测试状态或者在sandbox环境下进行检测,或者上架App Store,你可以使用这种方法,从而避免在URL之间进行切换,
    注明:21007 状态码表明receipt是一个sandbox receipt。

 http://www.cocoachina/special/iap.html




程序具体步骤
1 添加Storekit.Framework,编写自己的storeObsever,用于处理交易,代码如下,其中completeTransaction和failedTransaction两个函数是自定义的用来处理交易成功与失败其它的就都是SKPaymentTransactionObserver这个代理要求的。

代码
 #import <Foundation/Foundation.h> 
#import <StoreKit/StoreKit.h> 
 #import <StoreKit/SKPaymentTransaction.h> 
@interface MyStoreObserver : NSObject < SKPaymentTransactionObserver > {
}
- (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; 
@end 

- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions函数用来更新transactions的状态
 - (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions { 
 for (SKPaymentTransaction* transaction in transactions)  {  
switch (transaction.transactionState)  {  
case SKPaymentTransactionStatePurchased:  
[self completeTransaction:transaction];  
break;  
case SKPaymentTransactionStateFailed: 
 [self failedTransaction:transaction];  
break;  
case SKPaymentTransactionStateRestored: 
 break;  
default:  
break;  
}  
2 在程序中添加storeObsever,最好在applicationDidFinishLaunching中添加
MyStoreObserver *tempObserver = [[MyStoreObserver alloc] init];  
self.observer = tempObserver;  
[tempObserver release];
[[SKPaymentQueue defaultQueue] addTransactionObserver:self.observer]; 

3 发送付费请求,在相应的类中实现SKProductsRequestDelegate,别忘记定义自己产品的identifier
//请求产品信息 
 #define kMyFeatureIdentifier yourProductIdentifiers  (你自己的产品identifiers)
SKProductsRequest *request= [[SKProductsRequest alloc] initWithProductIdentifiers: 
 [NSSet setWithObject: kMyFeatureIdentifier]]; 
 request.delegate = self; 
[request start];  
代理方法相关代码,如果请求成功的话就可以发送付费请求  
#pragma mark request delegate
 //!收到产品的消息 
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response{  
SKPayment *payment = [SKPayment paymentWithProductIdentifier:kMyFeatureIdentifier]; 
 [[SKPaymentQueue defaultQueue] addPayment:payment]; 
[request autorelease];
  }
- (void)request:(SKRequest *)request didFailWithError:(NSError *)error{  
UIAlertView *alerView =  [[UIAlertView alloc] initWithTitle:@"Alert" message:[error localizedDescription]  delegate:nil c
ancelButtonTitle:NSLocalizedString(@"Close",nil)  otherButtonTitles:nil];  [alerView show]; [alerView release]; 
}

4  接下来就是Apple自己的付费相关处理了,需要做是就是点击按钮来确定付费
5 交易完成后需要向Apple验证这次交易是否成功,要不然没成功就把产品给别人的话,那就亏了,在1中可以看到当交易成功时会调用自定义的completeTransaction函数,在该函数中我们需要验证transactionReceipt 关于验证SKPaymentTransaction的transactionReceipt transactionReceipt是只有当SKPaymentTransaction完成时,即transactionState 被设置为SKPaymentTransactionStatePurchased 或 SKPaymentTransactionStateRestored时才被创建,因此只有这两种状态下能去验证transactionReceipt

原始思路及具体步骤如下:  
a 从SKPaymentTranscation的实例中将transactionReceipt转化为NSString   
 NSString *temptransactionReceipt  = [[NSString alloc] initWithData:[mytransaction transactionReceipt] encoding:NSUTF8StringEncoding];

如果用NSLog的方法将其写出来显示如下,里边有很多的‘+’ { "signature" = 
"AZNZdoggtjbU/wMqZ4SSd3lgkxbWr+/zcV7Oez4io7f5oPMliKlQzWW4vj+FLsVyhjyyuPyTSugJ6m4Hrp+CjdAptGZg4iWExoyE6stltg0EfD8Ezggjg5q04ws74pMZ/0aRgjedua8dCMMqR7C8ZjojfOYU6LrFiK7qbUUiV+inMIIDUzCCAjugAwIBAgIIZRSRTdlYBLUwDQYJKoZIhvcNAQEFBQAwfzELMAkGA1UEBhMCVVMxEzARBgNVBAoMCkFwcGxlIEluYy4xJjAkBgNVBAsMHUFwcGxlIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MTMwMQYDVQQDDCpBcHBsZSBpVHVuZXMgU3RvcmUgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDkwNjE1MjIwNTU2WhcNMTQwNjE0MjIwNTU2WjBkMSMwIQYDVQQDDBpQdXJjaGFzZVJlY2VpcHRDZXJ0aWZpY2F0ZTEbMBkGA1UECwwSQXBwbGUgaVR1bmVzIFN0b3JlMRMwEQYDVQQKDApBcHBsZSBJbmMuMQswCQYDVQQGEwJVUzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAytGMXZy3gitJ2JMKFojSDynC/9yYezyn9HBX+u3/3VcpWE2XhcgGKYqNBA1+AewOzrKO774OsokTu4qymEx10ph8UTmsZewB0ESMHBEjF7FN6/HccsQUYC3WagrHnT12HG2Ih0OAm/ZhpWzj0HS4m813LpIyo00sewMvMNL2hkcCAwEAAaNyMHAwDAYDVR0TAQH/BAIwADAfBgNVHSMEGDAWgBQ2HejinYLSARi1MmsO10MLkVhDOjAOBgNVHQ8BAf8EBAMCB4AwHQYDVR0OBBYEFKmDg/IZSMU+ElcIFMzNo36ZXyT1MBAGCiqGSIb3Y2QGBQEEAgUAMA0GCSqGSIb3DQEBBQUAA4IBAQARpJs+O2Y3gL8gHdASkrfZHFpwINd1VcB5VF5LkVpnFz63zylA/3cGIDG91b/d5NIwZjkVt4Bgvd62o/mCbzCsWiNfSKTJVFK1D78BDQoSO2oHTuQuz1BR7xzNHxQZ90zUS6ZX9SC8N3g3A1jEtAyDhZNB+CRBBXLwZdnBUeBsT9QLpjvTnekZcGTnU08zfCjGF3eBJEu9eP6WgexK1xMSp72kEOmYbn6yTi3D4YrcYx4Q3n/57VBP2en8qXWeP5oHDsLTGzLRsWdoB3VxJLrF2ivL8JS8zqC0qyac452pN6xunRuzyyfpaqzQL12BzFEe44xna2byektSbtquA5LNAAAAAA=="; "purchase-info" = "ewoJIml0ZW0taWQiID0gIjMzMDU5OTg4MCI7Cgkib3JpZ2luYWwtdHJhbnNhY3Rpb24taWQiID0gIjEwMDAwMDAwMDAwOTEyNTgiOwoJInB1cmNoYXNlLWRhdGUiID0gIjIwMDktMTAtMTQgMDY6MDY6NTQgRXRjL0dNVCI7CgkicHJvZHVjdC1pZCIgPSAiY29tLnNlbnNreS5jbmFtZXNpZ3B1cmNoYXNlY29uc3VtYWJsZSI7CgkidHJhbnNhY3Rpb24taWQiID0gIjEwMDAwMDAwMDAwOTEyNTgiOwoJInF1YW50aXR5IiA9ICIxIjsKCSJvcmlnaW5hbC1wdXJjaGFzZS1kYXRlIiA9ICIyMDA5LTEwLTE0IDA2OjA2OjU0IEV0Yy9HTVQiOwoJImJpZCIgPSAiY29tLnNlbnNreS5jc2lnbmF0dXJlYXBwIjsKCSJidnJzIiA9ICIxLjAiOwp9"; "pod" = "100"; "signing-status" = "0";}    
b然后通过Post的方法将其提交给服务器,在这里只是将transactionReceipt传给服务器,验证由服务器完成。代码如下,    
 NSString *requestStirng =[NSString stringWithFormat: @"receipt_data=%@",temptransactioReceipt];  

requestStirng = [requestStirng stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; 

 NSData *postData = [NSData dataWithBytes:[requestStirng UTF8String] length:[requestStirng length]]; 
NSMutableURLRequest *connectionRequest = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:[kURL          stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]]; 
 [connectionRequest setHTTPMethod:@"POST"];  
[connectionRequest setTimeoutInterval:120.0]; 
 [connectionRequest setCachePolicy:NSURLRequestUseProtocolCachePolicy]; 
 [connectionRequest setHTTPBody:postData];  
出现的错误,服务器用传过去的receipt_data向Apple验证,通不过,但将用NSLog的方法在后台写出的temptransactionreceipt向Apple验证能通过  错误原因  对比发现通过URL传给服务器的字符串不能很好的完成urlEncode,在里边出现的+不能自动进行编码转化,因为在Objective-C 中不能将NSString 真正的实现URL encode , 
解决方法可参考下面的地址  
http://simonwoodside/weblog/2009/4/22/how_to_really_url_encode/ 
 但当我用上面地址给出的方法进行编码后仍不能解决该问题,原因不明 
 解决办法:
在将transactionReceipt转化成的NSString传给服务器之前先进行转化,将里边的+转换为%2B , 将步骤a中的代码改为 
 NSString *temptransactionReceipt  = [[NSString alloc] initWithData:[mytransaction transactionReceipt] encoding:NSUTF8StringEncoding]; 
 temptransactionReceipt =  [temptransactionReceipt stringByReplacingOccurrencesOfString:@"+" withString:@"%2B"];  


6 服务器端验证相关代码 其中XML为自定义的一个类,getHeader所做的工作就是把receipt数据Post给Apple然后得到返回的结果返回  
$url = "https://buy.itunes.apple/verifyReceipt";/ $receipt = json_encode(array("receipt-data" => base64_encode($receipt_data)));     
$response_json = $Xml->getHeader($url, $receipt);    
 $response = json_decode($response_json['content'], true);

getHeader的代码如下  public function getHeader($url, $data)         { 
                   $ch = curl_init(); 
                    $timeout = 300; // set to zero for no timeout  
                 curl_setopt($ch, CURLOPT_URL, $url); 
         //       curl_setopt($ch, CURLOPT_ENCODING, 'gzip'); 
                  curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 1); //post到https 
                  curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
                   curl_setopt($ch, CURLOPT_POST, true); 
                  curl_setopt($ch, CURLOPT_POSTFIELDS, $data);  
                 curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);  
                 curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);//跟随页面的跳转
         //       curl_setopt($ch, CURLOPT_HEADER, true); 
                  curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout); 
                   $handles = curl_exec($ch); 
                  $header = curl_getinfo($ch);
                   curl_close($ch); 
                  $header['content'] = $handles; 
                  return $header; 
        } 

http://www.cocoachina/bbs/read.php?tid-11357.html

更多推荐

IAP专题-包含基础知识和经常遇到的一些问题.In App Purchase 个人使用总结

本文发布于:2023-06-13 10:16:00,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1381354.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:基础知识   专题   IAP   App   Purchase

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!