iOS开发实现苹果内购无法完成购买的恢复购买遇到了问题

请教大神 ---- ios内购失败,订单核对问题
[问题点数:20分,结帖人noaso]
请教大神 ---- ios内购失败,订单核对问题
[问题点数:20分,结帖人noaso]
不显示删除回复
显示所有回复
显示星级回复
显示得分回复
只显示楼主
匿名用户不能发表回复!|
每天回帖即可获得10分可用分!小技巧:
你还可以输入10000个字符
(Ctrl+Enter)
请遵守CSDN,不得违反国家法律法规。
转载文章请注明出自“CSDN(www.csdn.net)”。如是商业用途请联系原作者。问题:苹果公司现任CEO是谁?2字正确答案:库克
Pages: 1/2
主题 : 非消耗品的内购如何实现恢复购买?如何判断已经购买过了非消耗品
级别: 骑士
可可豆: 1680 CB
威望: 1679 点
在线时间: 276(时)
发自: Web Page
来源于&&分类
非消耗品的内购如何实现恢复购买?如何判断已经购买过了非消耗品&&&
购买的代码如下//发送购买请求[[SKPaymentQueue defaultQueue] addPayment:payment];- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions{    for (SKPaymentTransaction * transaction in transactions) {        switch (transaction.transactionState)        {            case SKPaymentTransactionStatePurchasing:                            case SKPaymentTransactionStatePurchased:               [self completeTransaction:transaction];                            case SKPaymentTransactionStateFailed:                [self failedTransaction:transaction];                            case SKPaymentTransactionStateRestored:                [self restoreTransaction:transaction];            default:                        }    }}- (void)completeTransaction:(SKPaymentTransaction *)transaction {     //交易成功}- (void)restoreTransaction:(SKPaymentTransaction *)transaction {    //恢复交易}- (void)failedTransaction:(SKPaymentTransaction *)transaction {    //交易失败}我有一个商品是非消耗品的,我购买过了,然后删掉游戏重新build,再次购买该商品,提示请确认您的软件内购买,你想以12远购买。。。。。嘛?然后我点击购买,提示您已经购买了此项目,可免费再次下载。整个过程都没有进restoreTransaction这个方法里面,而是进completeTransaction这个方法里面。。请问谁知道原因啊?如果做恢复购买功能?[ 此帖被鸭鸭宝贝在 16:47重新编辑 ]
级别: 骑士
可可豆: 1680 CB
威望: 1679 点
在线时间: 276(时)
发自: Web Page
解决方法很简单,增加一个Restore按钮,并调用[[SKPaymentQueue defaultQueue] restoreCompletedTransactions],接下来的流程是1,弹出对话框输入帐号信息2,如果点击“取消”,调用方法-(void)paymentQueue:(SKPaymentQueue *)queue restoreCompletedTransactionsFailedWithError:(NSError *)error如果点击“确定”,开始请求数据3,返回数据后,回调-(void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions4,判断交易队列中交易的状态,在状态为“SKPaymentTransactionStateRestored”的switch分支下调用恢复处理方法5,恢复完成后回调-(void)completeTransaction:(SKPaymentTransaction *)transaction
级别: 骑士
可可豆: 1680 CB
威望: 1679 点
在线时间: 276(时)
发自: Web Page
另一个问题:有什么办法可以判断我已经购买过了这个非消耗品???比如:我在设备1上下载了游戏并购买了这个非消耗品。然后我在设备2上用同样的帐号下载了这个游戏。那如何在设备2上,判断这个非消耗品已经购买过了,这样我就可以把购买过的非消耗品buy按钮换成restore按钮呢?
级别: 禁止发言
可可豆: -46 CB
威望: -46 点
在线时间: 0(时)
发自: Web Page
用户被禁言,该主题自动屏蔽!
级别: 骑士
可可豆: 1680 CB
威望: 1679 点
在线时间: 276(时)
发自: Web Page
回 3楼(vkrvh) 的帖子
g呵呵 不用回了,我大概了解整个过程了 。谢谢了
级别: 新手上路
可可豆: 35 CB
威望: 35 点
在线时间: 43(时)
发自: Web Page
还是不明白。能分享一下吗 ?恢复交易是不是实际上走了一遍标准的购买流程,发起后系统调用和第一次买一样的回调。但是不扣钱。最后会调用一下 restoreTransaction ?多谢回答。
级别: 新手上路
可可豆: 35 CB
威望: 35 点
在线时间: 43(时)
发自: Web Page
没人回答吗,自顶一下
级别: 新手上路
可可豆: 13 CB
威望: 13 点
在线时间: 4(时)
发自: Web Page
回 4楼(鸭鸭宝贝) 的帖子
能说一下咋解决的购买和恢复购买的流程么。。谢谢
级别: 精灵王
UID: 42990
发帖: 1566
可可豆: 12999 CB
威望: 12936 点
在线时间: 1758(时)
发自: Web Page
回 4楼(鸭鸭宝贝) 的帖子
求方式?如何知道这个商品需要restore.
级别: 新手上路
可可豆: 28 CB
威望: 31 点
在线时间: 172(时)
发自: Web Page
回 4楼(鸭鸭宝贝) 的帖子
如何在另一个设备判断这个非消耗品已经购买过了,或者获知哪些商品已经被购买呢?请教楼主。。
Pages: 1/2
关注本帖(如果有新回复会站内信通知您)
苹果公司现任CEO是谁?2字 正确答案:库克
发帖、回帖都会得到可观的积分奖励。
按"Ctrl+Enter"直接提交
关注CocoaChina
关注微信 每日推荐
扫一扫 浏览移动版应用内购(In-App Purchase)常见问题解答
招聘信息:
本文档为您解答应用内购相关的常见问题。配置(Configuration)1.我必须上传一个二进制文件来测试应用内购么?不,测试应用内购(In-App Purchase,以下简称IAP)不需要上传二进制文件。注:在应用程序准备好接受审核批准之前,不要将开发中的二进制文件上传到iTunes Connect。如果二进制文件出现在iTunes Connect中,但功能不完整,那么App Review将审查二进制文件,很有可能会拒绝该文件。在iTunes Connect中,如果App Review拒绝了最新的二进制文件,测试IAP将会失败。一个变通方案是上传没有IAP功能的二进制文件通过App Review。一旦二进制文件通过审核,就可以测试IAP功能。2.我如何启用通配符App ID来支持IAP?参考如下步骤:在Xcode或者iTunes Connect中识别确认app当前的Bundle ID。更多信息请查看。参考中的步骤1-6和8-10,更新通配符App ID以支持IAP。3.支持自动订阅商品的最低版本是什么?iOS系统:iOS 4.2&OS系统:OS X 10.94.何时使用SKPaymentQueue的restoreCompletedTransactions方法?在如下两种情况下,你只能使用来恢复自动订阅或者非消耗性商品:1.在消费者拥有的其他设备上安装它们。2.在相关应用程序被删除的设备上重新安装它们。5.在iTunes Connect中,可以为每个应用程序创建多少个IAP商品ID?阅读可以找到答案。错误信息(Error Messages)1.您的账户信息已经更改(Your account info has changed)由于你在设备上登陆App Store时使用的是测试账户,所以你会收到一条“您的账户信息已经更改”的消息。一旦使用这个账户登陆商品购买环境,沙盒(Sandbox)就会检测到你的用户账户不可用。要解决这个问题,需要在设备的设置应用程序中退出当前账号,在iTunes Connect中创建一个新的测试账户,当Store Kit提示确认从你的应用内购买时,使用这个账户。2.不能连接到iTunes Store(Cannot connect to iTunes Store)&“Cannot connect to iTunes Store”的问题或许是由以下的一个或多个原因引起:沙盒不可达。你的应用程序没有bundle version()。更多信息请查看你的应用程序是在模拟器上运行,不支持应用内购买。你尝试购买的商品不在出售之列。更多信息请查看3.该Apple ID尚未在iTunes Store中使用(This Apple ID has not yet been used in this iTunes Store)收到该条消息意味着你使用测试账号登陆了iTunes Store。要解决这个问题,你需要在设备中的设置应用程序中退出当前账号,在iTunes Connect中创建一个新的测试账户,当Store Kit提示确认从你的应用程序内购买时,使用这个账户。4.你已经购买该商品,点击确定再次免费下载该商品(You've already purchased this. Tap OK to download it again for free)该条消息并不是一个通知而非错误提示。它的意思是你正在购买一个已经购买过的非消耗性商品。你无需为已经购买过的非消耗性商品付费。5.你已购买该应用内购买商品,但尚未下载(You've already purchased this In-App Purchase but it hasn't been downloaded)收到该条消息是因为你在应用程序中没有调用SKPaymentQueue的finishTransaction:method方法。调用finishTransaction:方法可以从购买队列中删除一个事务。6.该账户不是测试账户,请在沙盒环境中创建一个新账户(This is not a test user account. Please create a new account in the Sandbox environment)当Store Kit提示确认购买时,你使用iTunes账户登录,会收到这个信息。要解决这个问题,需要在设备中的设置应用程序中退出App Store,当Store Kit提示确认从你的应用程序内购买时,使用沙盒测试用户账户。本土化(Localization)在iTunes Connect中我的应用内购已本土化为多种语言。但是,localizedDescription和localizedTitle属性总是返回英文信息,即便测试设备的语言不是英文。localizedDescription和localizedTitle返回的本土化信息语言是基于当前iTunes Store的语言而不是当前设备所设置的语言。比如,在iTunes Connect中你的应用内购针对德语进行了本地化,但你使用英文测试账户登录,那么localizedDescription和localizedTitle都将返回英文信息。如果需要返回德语信息,在你的测试设备上使用德语测试账号登陆。Receipt1.我应该使用哪个URL来验证Receipt?(What url should I use to verify my receipt?)在沙盒中测试应用程序以及应用程序处于审核状态时,使用沙盒URL:https://sandbox./verifyReceipt&当应用程序通过审核上架App Store时,使用商品URL:https://buy./verifyReceipt&注:确保将应用程序用于验证的receipt发送至App Store。一定要先使用商品URL核实你的receipt;如果收到一个21007状态码,那接下来要使用沙盒URl验证。按照这个步骤,当app处于测试状态或在sandbox环境下进行审核,或者上架App Store,可让你避免在URL之间切换。21007状态码表示该receipt是一个sandbox receipt,但已被发送至商品服务进行验证。0状态码表示已正确验证receipt。2.当前receipt&无效或者与当前用户ID不匹配(Current receipt invalid or mismatched ds person id)收到这条消息是因为你的应用程序中缺少OS X App Store receipt。更多关于如何从应用程序中获取receipt的消息请查看:3.Receipt验证失败,状态为(Verifying my receipt fails with a status of)可能原因:在iOS app中,你没有使用base64编码对回单数据进行编码。发布到App Store的对象不是JSON格式。Listing 1是自动订阅的正确JSON对象:Listing 1 &验证自动订阅的有效receipt示例:{
&&&&"receipt-data"&:&"...",
&&&&&&&&"password"&:&"..."
}4.应用审核不能查看已购买成功的目录如果应用程序在购买成功后通过App Store验证receipt,请检查你的应用程序是否使用了正确的App Store URL来验证receipt。更多信息请查看&5.在购买成功后,我的应用程序使用paymentQueue:updatedTransactions:验证receipt。但是,返回的receipt中包含了一个空in_app数组而不是预期的产品。空in_app数组表示Store Kit没有为当前用户记录任何交易。或许是没有更新应用程序receipt,若果是这样,应用程序可以通知用户尚未出现receipt,是否要进行刷新。如果用户同意,应用程序会使用类来更新receipt。此时,如果Store Kit已经记录用户购买信息,那应用程序receipt将会显示在in_app数组中。更多关于如何更新receipt的信息请查看:订阅(Subscriptions)1.使用Xcode 6不能将托管内容上传至iTunes Connect这是目前存在的一个bug。为了解决这个问题,请使用Application Loader上传包含托管内同的包。步骤如下:在Xcode Archives Organizer中,选择包含托管内容的文档。单击Export在弹出的对话框中,选择Export as an Installer Package.单击Next开始生成你的包,然后选择Export保存你的包(一个文件扩展名为.pkg的文件)。使用Application Loader上传这个包,更多信息请查看:下图演示为托管内容生成一个包,图中的数字对应上述步骤。&2.如何从自动更新订阅服务更改为IAP商品?参考如下步骤:在iTunes&Connect中关掉Clear for Sale标志,从而移除当前自动更新订阅的商品/服务,然后将其从代码中移除。此时将会禁止商品/服务的自动更新,并会给用户发一封邮件。记住,你必须为用户提供已付费的商品/服务,直到订阅终止。此外,之前自动更新订阅的商品/服务都是可恢复的。例如,如果你的用户在4月1号购买了一个月的订阅,但是这个订阅将在4月19日下线,那你也必须提供已购买的内容直到5月1日。创建一个新的IAP商品类型,然后更新二进制文件来使用它。更多信息请查看:注:需要该步骤是因为一旦应用内购类型被创建,则不能再更改。3.通过App Store中验证应用程序receipt,然后分析是否需要向你的用户提供相关功能。更多信息请查看:3.如何知道用户是否将其联系信息分享给我?使用receipt中的Subscription Expiration Date (expires_date)字段来检测用户是否将自己的信息共享给你。假设你决定为购买一个月订阅服务并愿意分享个人信息的顾客提供7天免费试用,Store Kit将为你提供一个receipt,这个receipt的expires_date存储了7天再加1个月的长度。在首次购买后,你的订阅服务将于1月零7天后到期,此后的每个月都将为其开启自动更新。4.即使在前台运行,我的应用程序也未收到任何自动更新提醒如果你的应用程序有一个稳定的交易观察者,那么在打开或者从后台恢复时,它都将接收到所有自动更新提醒。更多信息请查看:疑难解答(Troubleshooting)1.为什么我的产品标识符在invalidProductIdentifiers数组中被退返?或许由于以下一个或多个原因:1.没有使用Explicit App ID。2.在iTunes Connect中,苹果拒绝了你最新向iTunes Connect提交的二进制码。3.你没有清除iTunes Connect中在售的IAP产品。4.没有使用与正确的App ID相关联的Provisioning Profile注册你的应用程序。5.可能修改了商品,但是这些修改没有在所有App Store的服务器中生效。6.未能完成所有财政需求表。更多信息请查看:7.你的商品由苹果托管上,内容尚未上传至iTunes Connect上。更多关于上传托管内容的信息请查看:注:商品内容上传到iTunes Connect上之前,你的商品标识符将是无效的。如果内容还没准备好,那么可在iTunes Connect中禁用Hosting Content with Apple功能便可以解决这个问题。一旦内容准备好可以上传了,就可重新启用该功能。8.在iTunes Connect中指定的商品标示符与应用程序中SKProductsRequest对象所使用的标示符不匹配。更多关于商品标示符的信息请查看:。2.调用payment queue的restoreCompletedTransactions 方法不能恢复app中的任何商品可能由以下一个或多个原因引起:1.你的商品有尚未完成的交易。如果付费队列中有未完成的交易,则恢复进程不返回商品。更多关于结束交易的信息请查看:。2.你没有任何先前购买过的非消耗类、自动更新订阅以及免费订阅的商品。3.你试图恢复的非更新订阅或消耗类商品是不可恢复的类型。restoreCompletedTransactions方法只能恢复非消耗类商品、自动更新订阅以及免费订阅的商品。注:在无可恢复产品的情况下,Store Kit不会调用paymentQueue:updatedTransactions:方法。4.应用程序的编译版本号(CFBundleVersion) 没有按照开发指南创建版本号。CFBundleVersion是一个由点号隔开的三个无符号整数组成的字符串。更多信息请查看:。参考:
微信扫一扫
订阅每日移动开发及APP推广热点资讯公众号:CocoaChina
您还没有登录!请或
点击量16272点击量10875点击量8664点击量8017点击量7488点击量7063点击量6588点击量6497点击量5716
&2016 Chukong Technologies,Inc.
京公网安备895700人阅读
iOS开发(30)
1、内购流程
1、在 AppStore 中创建相应的物品,创建内购沙盒测试账号2、客户端从后台获取相应的物品 ID (当然也可以再客户端写死,但后期扩展性就受限制了)3、依据相应的物品 ID 请求商品的相关信息4、依据商品信息创建订单请求交易5、依据返回的订单状态处理交易结果6、请求后台再次验证订单状态7、依据后台返回结果处理相关逻辑
2、创建内购物品以及沙盒测试账号
已经有朋友写出了完善的教程,请参考如下链接,一步一步来就可以
3、客户端编写相关代码
再这里我把和支付相关的逻辑都抽取到了一个单例中,在最后贴上个人梳理的相关代码大家一起学习
4、做内购过程中遇到的坑
1、内购沙盒测试账号在支付成功后,再次购买相同 ID 的物品,会提示如下内容的弹窗。
您已购买此 App 内购买项目。此项目将免费恢复。
解决方法:在使用
[[SKPaymentQueue defaultQueue] addPayment:payment];
将支付信息添加进苹果的支付队列后,苹果会自动完成后续的购买请求,在用户购买成功或者点击取消购买的选项后回调
&- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)
方法返回响应的结果信息,在该方法内除了得到响应的支付信息编写自身的业务的代码外还要记得调用
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
方法通知苹果的支付队列该交易已经完成,否者就会已发起相同 ID 的商品购买就会有此项目将免费恢复的提示。
2、每次启动一个新的内购支付流程,刚发起的时候系统就会调用- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)这个方法,结果扰乱一部分的支付业务逻辑
在 SKPaymentQueue 被启动并且添加了 addObserver之后,如果其判断到有未完成的交易,会主动调用paymentQueue updatedTransactions 这个方法来继续完成相关的交易流程,所以如果在上面那种情况下得到结果后不去调用 finish 接口,下次重新开启支付流程就会检查未完成的支付并调用该接口。
解决方法:
1.在得到支付结果后及时调用 finish 方法
2.添加一个是否是新发起的支付流程的条件,在条件符合的情况下才触发应用的相关逻辑的代码
(PS:在拿到苹果的支付结果凭据的时候最好在客户端做一份持久化的数据备份,等待后台验证完成后再清除掉,避免出现验证中间出现问题导致用户支付成功但后台相关的增值处理没有完成导致用户金钱损失的问题)
3、如何区分购买物品的是 沙盒测试账号 还是 真实账号&
后台再验证支付凭据的时候要区分是沙盒测试账号购买的还是用户真实账号购买的,所以在传凭据的时候还需要告诉后台当前购买的账号性质。
解决方法:通过在配置文件中定义相关的宏定义并结合 Debug 与 Release 的编译环境确定相关的参数
// 苹果内购是否为沙盒测试账号,打开就代表为沙盒测试账号,注意上线时注释掉
#define APPSTORE_ASK_TO_BUY_IN_SANDBOX 1
// 生成订单参数,注意沙盒测试账号与线上正式苹果账号的验证途径不一样,要给后台标明
NSNumber *
#if (defined(APPSTORE_ASK_TO_BUY_IN_SANDBOX) && defined(DEBUG))
sandbox = @(0);
sandbox = @(1);
个人没有找到相关的方法可以打完包后动态的检测购买物品的账号性质,希望知道的朋友分享一下,感谢 ^_^
5、iOS7 客户端验证的订单状态
苹果在iOS7提升了购买凭据的安全性,可以直接单独在客户端完成订单正确性的验证,但是处于金钱考虑,购买完成后,建议还是要做凭据的后台验证工作。
#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]
// 转换为 JSON 格式
NSData *requestData = [NSJSONSerialization dataWithJSONObject:requestContents
error:&error];
if (!requestData) { /* ... Handle error ... */ }
// 发送网络POST请求,对购买凭据进行验证
NSString *verifyUrlS
#if (defined(APPSTORE_ASK_TO_BUY_IN_SANDBOX) && defined(DEBUG))
verifyUrlString = @&https://sandbox./verifyReceipt&;
verifyUrlString = @&https://buy./verifyReceipt&;
// 国内访问苹果服务器比较慢,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(@&链接失败&);
NSDictionary *jsonResponse = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];
if (!jsonResponse) {
NSLog(@&验证失败&);
// 比对 jsonResponse 中以下信息基本上可以保证数据安全
application_version
product_id
transaction_id
NSLog(@&验证成功&);
6、内购验证凭据返回结果状态码说明
苹果反馈的状态码:
21000 App Store无法读取你提供的JSON数据
21002 收据数据不符合格式
21003 收据无法被验证
21004 你提供的共享密钥和账户的共享密钥不一致
21005 收据服务器当前不可用
21006 收据是有效的,但订阅服务已经过期。当收到这个信息时,解码后的收据信息也包含在返回内容中
21007 收据信息是测试用(sandbox),但却被发送到产品环境中验证
21008 收据信息是产品环境中使用,但却被发送到测试环境中验证
更为详细的信息请参考
7、如何恢复购买
注:此部分内容后期再详细添加 ^_^
相关代码:
XYPayManager.h
XYPayManager.h
Created by 郑亚恒 on 15/11/2.
Copyright © 2015年 郑亚恒. All rights reserved.
#import &Foundation/Foundation.h&
// 苹果内购是否为沙盒测试账号,打开就代表为沙盒测试账号,注意上线时注释掉!!
#define APPSTORE_ASK_TO_BUY_IN_SANDBOX 1
typedef void(^payCompleteBlock)(NSDictionary *resultDic, BOOL isSuccess);
@interface XYPayManager : NSObject
+ (instancetype)sharedPayM
/// 苹果内购
- (void)requestAppleStoreProductDataWithString:(NSString *)productIdentifier payComplete:(payCompleteBlock)payCompletionB
/// 验证苹果支付订单凭证
- (void)checkAppStorePayResultWithBase64String:(NSString *)base64S
XYPayManager.m
XYPayManager.m
Created by 郑亚恒 on 15/11/2.
Copyright © 2015年 郑亚恒. All rights reserved.
#import &XYPayManager.h&
#import &StoreKit/StoreKit.h&
@interface XYPayManager() &SKPaymentTransactionObserver, SKProductsRequestDelegate&
// 苹果内购
@property (nonatomic, copy) NSString *appleProductI
@property (nonatomic, copy) payCompleteBlock payC
@implementation XYPayManager
+ (instancetype)sharedPayManager {
static XYPayManager *payM
static dispatch_once_t once = 0;
dispatch_once(&once, ^{
payManager = [[XYPayManager alloc] init];
// 注册苹果内购
[[SKPaymentQueue defaultQueue] addTransactionObserver:payManager];
return payM
- (void)dealloc {
[[SKPaymentQueue defaultQueue] removeTransactionObserver:self];
#pragma mark - 苹果支付充值
//请求商品
- (void)requestAppleStoreProductDataWithString:(NSString *)productIdentifier payComplete:(payCompleteBlock)payCompletionBlock {
if(![SKPaymentQueue canMakePayments]) {
NSLog(@&不允许程序内付费&);
[APPCONTEXT.hudHelper showHudOnWindow:@&不允许程序内付费& image:nil acitivity:NO autoHideTime:DEFAULTTIME];
NSLog(@&-------------请求对应的产品信息----------------&);
self.startBuyAppleProduct = YES;
self.payComplete = payCompletionB
self.appleProductIdentifier = productI
NSLog(@&生成产品信息&);
NSArray *product = [[NSArray alloc] initWithObjects:productIdentifier, nil];
NSSet *nsset = [NSSet setWithArray:product];
SKProductsRequest *request = [[SKProductsRequest alloc] initWithProductIdentifiers:nsset];
request.delegate =
[request start];
//收到产品返回信息
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response{
NSLog(@&--------------收到产品反馈消息---------------------&);
NSArray *productArray = response.
if([productArray count] == 0){
NSLog(@&--------------没有商品------------------&);
NSLog(@&productID:%@&, response.invalidProductIdentifiers);
NSLog(@&产品付费数量:%lu&,(unsigned long)[productArray count]);
SKProduct *product =
for (SKProduct *pro in productArray) {
NSLog(@&%@&, [pro description]);
NSLog(@&%@&, [pro localizedTitle]);
NSLog(@&%@&, [pro localizedDescription]);
NSLog(@&%@&, [pro price]);
NSLog(@&%@&, [pro productIdentifier]);
if([pro.productIdentifier isEqualToString:self.appleProductIdentifier]){
SKPayment *payment = [SKPayment paymentWithProduct:product];
NSLog(@&发送购买请求&);
[[SKPaymentQueue defaultQueue] addPayment:payment];
//请求失败
- (void)request:(SKRequest *)request didFailWithError:(NSError *)error{
NSLog(@&------------------错误-----------------:%@&, error);
- (void)requestDidFinish:(SKRequest *)request{
NSLog(@&------------反馈信息结束-----------------&);
//监听购买结果
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transaction {
for(SKPaymentTransaction *paymentTransactionp in transaction){
switch (paymentTransactionp.transactionState) {
case SKPaymentTransactionStatePurchased:
NSLog(@&交易完成-restoreCompletedTransactions&);
/* your code */
[self buyAppleStoreProductSucceedWithPaymentTransactionp:paymentTransactionp];
[self completeTransaction:paymentTransactionp];
case SKPaymentTransactionStatePurchasing:
NSLog(@&商品添加进列表&);
case SKPaymentTransactionStateRestored:
NSLog(@&已经购买过商品&);
case SKPaymentTransactionStateFailed:
NSLog(@&交易失败&);
/* your code */
[self completeTransaction:paymentTransactionp];
// 苹果内购支付成功
- (void)buyAppleStoreProductSucceedWithPaymentTransactionp:(SKPaymentTransaction *)paymentTransactionp {
/* 获取相应的凭据,并做 base64 编码处理 */
NSString *base64Str = [paymentTransactionp.transactionReceipt base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithLineFeed];
NSLog(@&苹果内购凭据号\n\n\n\n\n\n%@\n\n\n\n\n\n&,base64Str);
[self checkAppStorePayResultWithBase64String:base64Str];
- (void)checkAppStorePayResultWithBase64String:(NSString *)base64String {
/* 生成订单参数,注意沙盒测试账号与线上正式苹果账号的验证途径不一样,要给后台标明 */
NSNumber *
#if (defined(APPSTORE_ASK_TO_BUY_IN_SANDBOX) && defined(DEBUG))
sandbox = @(0);
sandbox = @(1);
NSMutableDictionary *prgam = [[NSMutableDictionary alloc] init];;
[prgam setValue:sandbox forKey:@&sandbox&];
[prgam setValue:base64String forKey:@&reciept&];
请求后台接口,服务器处验证是否支付成功,依据返回结果做相应逻辑处理
//交易结束
- (void)completeTransaction:(SKPaymentTransaction *)transaction{
NSLog(@&交易结束&);
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:18964次
排名:千里之外
原创:35篇
(2)(1)(3)(1)(1)(1)(3)(4)(6)(4)(3)(1)(5)(2)}

我要回帖

更多关于 内购 恢复购买 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信