ios 内购需要向netty服务端发送数据什么数据

iOS内购买IAP问题和服务器交互 - 简书
iOS内购买IAP问题和服务器交互
warning 此处不讲解IA如何P配置了,网上挺全面的而且还写的都不错的。但是前提是你有沙盒测试账号和itunesconnect设置过了内购买所需虚拟物品和银行协议的一堆配置
此处只讲解两点
我碰见的问题
和服务器的交互问题(此处以PHP为例子,本人PHP刚入门也是copy来的,根据自己的需求做出小小改变)
配置消耗型物品重复购买却显示此项目免费恢复
需要在``` objectivec?linenums
(void)paymentQueue:(SKPaymentQueue )queue updatedTransactions:(NSArray&SKPaymentTransaction & *)transactions```
的每个状态后面都需要添加
[[SKPaymentQueue defaultQueue] finishTransaction:tran];
先解释一下OC代码和PHP代码
第一步拾掇拾掇需要的东西
import &StoreKit/StoreKit.h&
&SKPaymentTransactionObserver, SKProductsRequestDelegate& 两个协议方法你也得实现吧
第二步注册观察者,并且判断该用户能否使用内购买
[[SKPaymentQueue defaultQueue] addTransactionObserver:self];
if([SKPaymentQueue canMakePayments]){
weakSelf.currentProId
= productID;
[weakSelf requestProductData:productID];
UIAlertView *alerView
= [[UIAlertView alloc] initWithTitle:@"提示"
message:@"您的手机没有打开程序内付费购买"
delegate:self cancelButtonTitle:NSLocalizedString(@"关闭",nil) otherButtonTitles:NSLocalizedString(@"提示",nil), nil];
[alerView show];
第三步查询 =& 你传一个你在itunesconnect 中App中定义的内购买Product_ID
itunesconntent.png
NSArray *product = [[NSArray alloc] initWithObjects:type, nil];
NSSet *nsset = [NSSet setWithArray:product];
// 请求动作
SKProductsRequest *request = [[SKProductsRequest alloc] initWithProductIdentifiers:nsset];
request.delegate =
[request start];
第四步 收到你在itunesconnect 中定义的Product_ID的详细数据,顺便把购买请求发送了()``` objectivec?linenums
(void)productsRequest:(SKProductsRequest )request didReceiveResponse:(SKProductsResponse )response {
NSLog(@"--------------收到产品反馈消息---------------------");
NSArray *product
= response.
if([product count] == 0){
//[SVProgressHUD dismiss];
NSLog(@"--------------没有商品------------------");
NSLog(@"productID:%@", response.invalidProductIdentifiers);
NSLog(@"产品付费数量:%lu",(unsigned long)[product count]);
SKProduct p
for (SKProduct pro in product) {
NSLog(@"%@", [pro description]);
NSLog(@"%@", [pro localizedTitle]);
NSLog(@"%@", [pro localizedDescription]);
NSLog(@"%@", [pro price]);
NSLog(@"%@", [pro productIdentifier]);
if([pro.productIdentifier isEqualToString:_currentProId]){
SKPayment *payment
= [SKPayment paymentWithProduct:p];
NSLog(@"发送购买请求");
[[SKPaymentQueue defaultQueue] addPayment:payment];}
& 第五步收到信息给你返回数据了
``` objectivec?linenums
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray&SKPaymentTransaction *& *)transactions {
for(SKPaymentTransaction *tran in transactions){
switch (tran.transactionState) {
case SKPaymentTransactionStatePurchased:{
NSLog(@"交易完成");
//方法在下面
[self completeTransaction:tran];
case SKPaymentTransactionStatePurchasing:
NSLog(@"商品添加进列表");
case SKPaymentTransactionStateRestored:{
NSLog(@"已经购买过商品");
[[SKPaymentQueue defaultQueue] finishTransaction:tran];
case SKPaymentTransactionStateFailed:{
NSLog(@"交易失败");
[[SKPaymentQueue defaultQueue] finishTransaction:tran];
[SVProgressHUD showErrorWithStatus:@"购买失败"];
startConntentService =
此处是最后的方法还有我和服务器交互的地方,但是此处我也不懂为什么这个方法会调用两次如果您明白,请在下面留言告诉我谢谢,所以我此处加了一个全局的判断,来约束它和服务器交互的次数。!!!看好我发送数据请求的方法其实就是AFNetworing的封装,都会用对吧。。。网址看好,别光顾着复制哦``` objectivec?linenums
(void)completeTransaction:(SKPaymentTransaction *)transaction {
NSLog(@"交易结束");
[SVProgressHUD dismiss];
NSURL *receiptURL
= [[NSBundle mainBundle] appStoreReceiptURL];
NSData *receipt
= [NSData dataWithContentsOfURL:receiptURL];
if (!receipt) { /* No local receipt -- handle the error. */ }
//因为此处可能会多次调用原因不明所以加判断只调用一次
else if (receipt && startConntentService) {
服务器要做的事情:
接收ios端发过来的购买凭证。
判断凭证是否已经存在或验证过,然后存储该凭证。
将该凭证发送到苹果的服务器验证,并将验证结果返回给客户端。
如果需要,修改用户相应的会员权限
startConntentService =
//字典中第二个参数是为了debug准备的,正常你不用写
NSDictionary *requestContents = @{
@"receipt-data": [receipt base64EncodedStringWithOptions:0],
@"XDEBUG_SESSION_START":@"12477"
[HTTPClient postWithURLString:@"你的后台网址" parameters:requestContents success:^(id returnValue) {
} failure:^(id failureValue) {
//这个千万别忘了 ,要不你就会犯第一条问题(配置消耗型物品重复购买却显示此项目免费恢复)
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
### 下面是PHP代码,我用的是ThinkPHP框架(会php都会框架,像我只会框架暂时还不会php.咳咳...)
& 只有两个方法
& 1 外部调用的方法,此处我的逻辑都系在了Controller中,是为了大家方便,我建议还是写在Model中(MVC哦,其实感觉都一样哈哈)
``` php?linenums
public function iosIAPPay() {
$status = array('status'=&-1);
//获取 App 发送过来的数据,设置时候是沙盒状态
= $_POST['receipt-data'];
$isSandbox =
//开始执行验证
$info = $this-&getReceiptData($receipt, $isSandbox);
// 通过product_id 来判断是下载哪个资源
switch($info['product_id']){
case '你的Product_ID':
$status['status'] = 1;
Header("Location:xxxx.zip");
//捕获异常
catch(\Exception $e)
$this-&ajaxReturn($status);
//服务器二次验证代码
function getReceiptData($receipt, $isSandbox = false)
if ($isSandbox) {
$endpoint = 'https://sandbox./verifyReceipt';
$endpoint = 'https://buy./verifyReceipt';
$postData = json_encode(array("receipt-data" =& $receipt));;
$ch = curl_init($endpoint);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
curl_setopt ($ch, CURLOPT_SSL_VERIFYPEER, 0);
//这两行一定要加,不加会报SSL 错误
curl_setopt ($ch, CURLOPT_SSL_VERIFYHOST, 0);
$response = curl_exec($ch);
= curl_errno($ch);
= curl_error($ch);
curl_close($ch);
//判断时候出错,抛出异常
if ($errno != 0) {
throw new \Exception($errmsg, $errno);
$data = json_decode($response);
//此处是看到先人们的指导,又看到apple的官方说法改的。否则会审核不过貌似是审核也会走沙盒测试者,
//此处先判断一次返回的status是否=21007 这数据是从测试环境,但它发送到生产环境中进行验证。它发送到测试环境来代替。
if ($data-&status == 21007) {
$this-&getReceiptData($receipt,true);
//判断返回的数据是否是对象
if (!is_object($data)) {
throw new \Exception('Invalid response data');
//判断购买时候成功
if (!isset($data-&status) || $data-&status != 0) {
throw new \Exception('Invalid receipt');
//返回产品的信息
$in_app = $data-&receipt-&in_app[0];//返回产品的信息
'quantity' =& $in_app-&quantity,
'product_id' =& $in_app-&product_id,
'transaction_id' =& $in_app-&transaction_id,
'purchase_date' =& $in_app-&purchase_date,
'app_item_id' =& $data-&receipt-&app_item_id,)
我一直都困在和后台交互的时候苹果返回的数据中status=21002,哭死。。。因为status=0才是购买成功.
OC中将苹果所需的凭证其实就是NSData *receipt
= [NSData dataWithContentsOfURL:receiptURL];
base64EncodedStringWithOptions一次在PHP在将这个数据json_encode(array("receipt-data" =& $receipt));一次在传给苹果服务器,自己写百度谷歌一起来真心好难。一遍一遍的改OC和PHP代码,还好公司太小两个都是我在做,我有大把时间和不用麻烦别人。iOS In-App Purchase 内购之 问题总结 - CSDN博客
iOS In-App Purchase 内购之 问题总结
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 的编译环境确定相关的参数
个人没有找到相关的方法可以打完包后动态的检测购买物品的账号性质,希望知道的朋友分享一下,感谢 ^_^
5、iOS7 客户端验证的订单状态
苹果在iOS7提升了购买凭据的安全性,可以直接单独在客户端完成订单正确性的验证,但是处于金钱考虑,购买完成后,建议还是要做凭据的后台验证工作。
6、内购验证凭据返回结果状态码说明
苹果反馈的状态码:
更为详细的信息请参考
7、如何恢复购买
注:此部分内容后期再详细添加 ^_^
相关代码:
XYPayManager.h
XYPayManager.m
原文地址:http://blog.csdn.net/jiisd/article/details/
本文已收录于以下专栏:
相关文章推荐
之前一个项目做的代码全部不见了,过了一段时间后想拿来用,发现早己不了,不得己,摸了半天才弄成功了,汗,不是做IOS开发的,见笑。
1、   在IOS前端拿到的收据(Receipt)格式是:
iOS内购(iap)
本文会给大家详细介绍iOS内购,这是本人16年5月底的开发过程,希望对看完此篇文章的人有所帮助。
本文基于XcodeVersion 7.3 (7D175)版本,手机是iPhone 6,9.3系统。 ...
iOS开发之内购完全笔记
解决无限提示 --(您已购买此 App 内购买项目。此项目将免费恢复。)的问题
梳理内购逻辑
记录个人集成过程中遇到的问题点与大家分享
上次介绍了苹果内购的交易流程,接下来讲讲获取票据信息和防止漏单。为什么要获取票据信息?
IAP,无法连接到iTunes store ,RMStore,SKErrorUnknown,Error Domain=com.alamofire.error.serialization.respons...
1.苹果iTunes Connect内购产品信息录入。
1)创建app内购买项目(Create New),选择类型:
1.消耗型项目
对于消耗型 App 内购买项目,用户每次下载时都必须进...
很久之前就想出一篇IOS内付费的教程,但是一查网上的教程实在太多了,有的写得真的蛮不错的......进入苹果的ItunesConnection(https://itunesconnect.apple....
IOS7开始:AppStore增加了验证内购(In App Purchasement)的方法, 以确保此次支付是有效地.
下面是苹果提供的验证地址:
开发测试用:
https://sandbox.it...
Users restore transactions to maintain access to content they’ve already purchased. For example, whe...
他的最新文章
讲师:宋宝华
讲师:何宇健
您举报文章:
举报原因:
原文地址:
原因补充:
(最多只允许输入30个字)27被浏览4395分享邀请回答213 条评论分享收藏感谢收起

我要回帖

更多关于 苹果内购 服务端 的文章

 

随机推荐