集成苹果内购回调 购买成功有异步回调吗

真·iOS内购的完整流程 - 简书
真·iOS内购的完整流程
iOS的内购流程如下
通过产品ID获取产品信息列表
把产品包装成SKPayment(支付)发送给苹果服务器
苹果服务器购买成功后会回调监听方法,根据苹果服务器返回信息判断是否购买成功。
购买失败或已经购买过该商品则注销交易。如果购买成功,此时可以向自家服务器发送购买成功的消息,并通过后台向苹果服务器发送验证,然后注销交易。
一般而言,这就是iOS内购的基本过程,看似很简单,但是其实实际操作起来,还是比较麻烦的,因为要考虑到各种意外情况。
下面讲一讲iOS内购的具体过程
1.获取产品信息列表
if ([SKPaymentQueue canMakePayments]) {
NSSet *IDSet = [NSSet setWithArray:proID];
SKProductsRequest *productsRequest = [[SKProductsRequest alloc] initWithProductIdentifiers:IDSet];
productsRequest.delegate =
[productsRequest start];
NSLog(@"用户禁止付费");
上面代码中的proID就是装有你在开发者后台创建内购产品时输入的产品ID的NSArray。
delegate是指SKProductsRequestDelegate
首先判断用户是否禁止付费,如果没有禁止付费,就想苹果服务器请求产品信息。
请求的信息会在SKProductsRequestDelegate的方法中返回
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response
NSLog(@"%i", response.products.count);
NSArray *myProducts = response.
if (0 == myProducts.count) {
NSLog(@"无法获取产品信息列表");
self.products = [myProducts sortedArrayUsingComparator:^NSComparisonResult(id
_Nonnull obj1, id
_Nonnull obj2) {
SKProduct *pro1 = (SKProduct *)obj1;
SKProduct *pro2 = (SKProduct *)obj2;
return pro1.price.integerValue & pro2.price.integerValue ? NSOrderedAscending : NSOrderedD
for (SKProduct *pro in myProducts) {
NSLog(@"%@", [pro localizedTitle]);
NSLog(@"%@", [pro localizedDescription]);
NSLog(@"%@", [pro price]);
NSLog(@"%@", [pro.priceLocale objectForKey:NSLocaleCurrencySymbol]);
NSLog(@"%@", [pro.priceLocale objectForKey:NSLocaleCurrencyCode]);
NSLog(@"%@", [pro productIdentifier]);
拿到产品信息以后可以进行排序处理,因为请求的时候发送的产品ID是装在一个NSSet中的,所以返回的产品信息也是乱序的,这里需要注意一下。
2.内购监听
拿到产品信息以后要设置监听,因为当你点击购买和购买后苹果服务器会通过监听方法通知应用。
- (void)startObserver {
if (!self.isObserver) {
[[SKPaymentQueue defaultQueue] addTransactionObserver:self];
NSLog(@"开始监听 ------ 内购");
self.isObserver = YES;
- (void)stopObserver {
if (self.isObserver) {
[[SKPaymentQueue defaultQueue] removeTransactionObserver:self];
NSLog(@"移除监听 ------ 内购");
self.isObserver = NO;
监听方法和移除监听的方法一起送上,isObserver是一个判断是否已经监听的BOOL数据。
我的建议是将监听方法和移除监听的方法都在AppDelegate中执行。当App启动时(- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions)开始监听,当App被关闭时(- (void)applicationWillTerminate:(UIApplication *)application)移除监听。至于原因,后面会提到。
3.实现监听方法
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray&SKPaymentTransaction *& *)transactions
NSLog(@"调用了几次这个方法?");
SKPaymentTransaction *transaction = transactions.lastO
switch (transaction.transactionState) {
case SKPaymentTransactionStatePurchased: {
NSLog(@"购买完成,向自己的服务器验证 ---- %@", transaction.payment.applicationUsername);
NSData *data = [NSData dataWithContentsOfFile:[[[NSBundle mainBundle] appStoreReceiptURL] path]];
NSString *receipt = [data base64EncodedStringWithOptions:0];
[self buySuccessWithReceipt:receipt transaction:transaction];
case SKPaymentTransactionStateFailed: {
NSLog(@"交易失败");
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
case SKPaymentTransactionStateRestored: {
NSLog(@"已经购买过该商品");
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
case SKPaymentTransactionStatePurchasing: {
NSLog(@"商品添加进列表");
default: {
NSLog(@"这是什么情况啊?");
finishTransaction:就是注销方法,如果不注销会出现报错和苹果服务器不停的通知监听方法等等情况。总之,记住要注销交易。
有的同学可能会疑惑,transaction.payment.applicationUsername中的这个applicationUsername属性是干嘛的,先不要急,关于这个属性我们会在后面提到,现在先记住这个点就好。
NSData *data = [NSData dataWithContentsOfFile:[[[NSBundle mainBundle] appStoreReceiptURL] path]];
NSString *receipt = [data base64EncodedStringWithOptions:0];
[self buySuccessWithReceipt:receipt transaction:transaction];
关于这三句,要注意,receipt是刚才交易的清单,如果后台需要进行二次验证,需要用到这个数据。
至于最后一句,则是购买成功后向自家的服务器发送的请求。
发送内购请求
完成上面的代码后,就可以进行发送内购请求的部分啦
SKMutablePayment *payment = [SKMutablePayment paymentWithProduct:product];
payment.applicationUsername = [AppManager sharedInstance].userId.stringV
[[SKPaymentQueue defaultQueue] addPayment:payment];
内购请求很简单,就是用请求道的产品信息SKProduct创建一个“内购支付”SKPayment,然后添加进支付队列。
以上就是iOS内购的全部核心代码。接下来要讲的,就是一些内购中可能出现的坑和如何跳过这些坑。
细心的同学应该已经发现,在发送内购请求的代码部分,我们又一次见到了applicationUsername这个属性,并将用户的id赋值给了它,那么,这是用来干什么的呢?
答案是:在某些极端情况下,可能出现在发送内购请求的用户和内购成功后通知自家后台的用户可能不是同一个用户的情况(真是奇葩的用户。。。。但是没办法,用户就是上帝嘛。。。)这种情况下,为payment绑定一个appUsername就可以让这次payment有一个固定的发起者,这样当这次payment在苹果后台支付成功后,我们就可以通过监听的回调,将这个发起者的唯一标识符上传给自家后台,使得这次购买能找到一个合适的主人。就算用户在购买的过程中切换账号或者退出,也能够让这次充值验证成功。
既然说到了极端情况,那么我们不如更进一步,让情况更极端一点,那就是当购买请求发送后,直到向苹果后台购买成功的这段时间,如果程序崩溃了!或者程序被用户关闭了!怎么办?!
这种情况下,我们的App自然也就无法进行监听的回调,自然也就无法把购买成功的消息发送给自家后台,用户也就拿不到自己的充值啦。情况很糟糕,但是!不用担心,我们有办法解决。
还记得上边提到的注销交易的方法吗?没错就是:
[[SKPaymentQueue defaultQueue] finishTransaction:transaction]
当购买在苹果后台支付成功时,如果你的App没有调用这个方法,那么苹果就不会认为这次交易彻底成功,当你的App再次启动,并且设置了内购的监听时,监听方法- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray&SKPaymentTransaction *& *)transactions就会被调用,直到你调用了上面的方法,注销了这次交易,苹果才会认为这次交易彻底完成。
利用这个特性,我们可以将完成购买后注销方法放到我们向自家后台发送交易成功后调用。
讲到这里,关于内购的大坑我目前遇到的都已经解决啦,当然,你如果实际去操作,可能还会遇到各种各样的小坑,但是没关系,我相信你能够自己解决。。。所以,我就不说啦。
准备爬坑吧!少年!
从OC走向Swfit,拥抱变化
iOS应用如果涉及到支付功能,分为两类:第三方支付和苹果内购。那么什么情况下选择使用第三方支付,又在什么情况下选择苹果内购呢?让我们先来简单了解一下: Understanding What You Can Sell Using In-App PurchaseYou can ...
iOS内购流程: iOS内购
什么时候用到呢?
虚拟产品就需要用到iOS内购;购买的商品,是在本app中使用和消耗的,就一定要用内购,否则会被拒绝上线,例如:游戏币,在线书籍,app中使用的道具等。 重要的大概步骤: 内购步骤大步骤有4步: 1,填写协议,税务和银...
最近公司需要开发内购,特记录过程如下: 在写代码之前还要做在itunes里做几步操作: 先登录itunes(https://itunesconnect.apple.com)填写相关协议,税务和银行业务 首先,先填好公司地址 然后填写合同信息 要勾选同意才进行下一步 1、之后...
最强大的文案策略,内部资料,严禁外传!
你的广告是在为读者们创造机会,使他们得以从平时枯燥的生活中抽离出一会儿,可以变得高兴、感到震惊!怎样的文案才能让读者成为你的顾客,大少来为大家解答。
为了吸引大家的注意力,在网络上,报纸中,你的竞争对手是大量的有关死亡和税务的故事...
这段时间除了项目的开发,也一直在看内购、Apple Pay、微信支付和支付宝支付的相关官方文档。刚好把需要的文档都翻译了一遍,所以趁着双休日把这一阶段总结一遍,以便于进入下一个阶段的开发中。 第一阶段 内购相关 一定要意识到苹果的内购只能出售虚拟物件(如数字化内容、App功...
若在人生的舞台上演一场风花雪月,谁将扮演你的对手戏,直至落幕? 有些人问我:“你想找怎么样的另一半?”、“你会爱上什么样的人?”,每每听到这样的问话,我总会沉默一会,然后随便带过,实在不知道怎么回答,或许我自己都没有认真思考过个问题,有过喜欢,但如果说爱的话,也算不上,我是...
动画的本质- 定时器 改变元素的属性- 浏览器/GPU 的渲染过程####动画种类- JavaScript动画 - DOM动画 - Canvas动画- CSS3动画 - transition - animation- SVG动画
春寒。冷空气带来了降雨,更显得天气阴湿潮冷。 昨天忙了一天。 早上到新房子等美缝来试色,对方迟到了20分钟。不过给了些很专业的建议,因此很快选好了颜色。 到单位,一大堆事情等着我做,不得不提高效率。中午继续坚持一小时瑜伽。 到下午两点半终于完成今天必须做完的工作,直奔现代装...
开箱&晒单: 毕竟是限量版,和普通版本还是有区别,大法在普通版本的基础上增加了一个刀剑神域的外包装套子,不过感觉这种限定版稍微有点坑。 包装还是一如既往的大法风格,朋友订购的是红色限定版,略微骚气。 外包装还是很漂亮的,马上进入开箱环节。 开箱之前,特写一个SONY LOG...
赵奢,史称马服君,历史故事“纸上谈兵”的主角赵括的父亲。赵括被后世当作空谈误事的反面典型,但赵奢却是货真价实的名将大将,在名将如云的战国时期,我们就是把赵奢排进前十也不算过份。 事实上,赵奢原本也是普通人,干着普通的事。据史料记载,他在当将军之前,只是个在地方上负责征收田租...thinkphp之苹果AppStore内购付款的服务器端php验证 - ThinkPHP框架
thinkphp 整合系列之苹果 AppStore 内购付款的服务器端 php 验证如果要演一部霸道总裁的剧;
我想这主角必须非苹果莫属了;
苹果的霸道实在是出了名的;
这不;如果是非实物的交易;
现在你不给苹果交个过路费;
那都是立马被审核处死的节奏;
好了;以上仅为吐槽;
这里要讲的就是AppStore内购的服务器端验证;
在app中支付的过程那是由IOS程序猿完成的;
IOS会把支付凭证发给我们;
作为服务器端;
我等php需要做的就是对支付结果的验证;
写着是thinkphp整合系列;
其实脱离thinkphp别的框架也能很便利的使用;
因为我是给写成函数了的;
示例项目:
/Application/Common/Common/function.php/**
&*&验证AppStore内付
&*&@param&&string&$receipt_data&付款后凭证
&*&@return&array&&&&&&&&&&&&&&&&验证是否成功
function&validate_apple_pay($receipt_data){
&&&&&*&21000&App&Store不能读取你提供的JSON对象
&&&&&*&21002&receipt-data域的数据有问题
&&&&&*&21003&receipt无法通过验证
&&&&&*&21004&提供的shared&secret不匹配你账号中的shared&secret
&&&&&*&21005&receipt服务器当前不可用
&&&&&*&21006&receipt合法,但是订阅已过期。服务器接收到这个状态码时,receipt数据仍然会解码并一起发送
&&&&&*&21007&receipt是Sandbox&receipt,但却发送至生产系统的验证服务
&&&&&*&21008&receipt是生产receipt,但却发送至Sandbox环境的验证服务
&&&&function&acurl($receipt_data,&$sandbox=0){
&&&&&&&&//小票信息
&&&&&&&&$POSTFIELDS&=&array(&receipt-data&&=&&$receipt_data);
&&&&&&&&$POSTFIELDS&=&json_encode($POSTFIELDS);
&&&&&&&&//正式购买地址&沙盒购买地址
&&&&&&&&$url_buy&&&&&=&&https://buy.itunes.apple.com/verifyReceipt&;
&&&&&&&&$url_sandbox&=&&https://sandbox.itunes.apple.com/verifyReceipt&;
&&&&&&&&$url&=&$sandbox&?&$url_sandbox&:&$url_
&&&&&&&&//简单的curl
&&&&&&&&$ch&=&curl_init($url);
&&&&&&&&curl_setopt($ch,&CURLOPT_RETURNTRANSFER,&1);
&&&&&&&&curl_setopt($ch,&CURLOPT_POST,&1);
&&&&&&&&curl_setopt($ch,&CURLOPT_POSTFIELDS,&$POSTFIELDS);
&&&&&&&&$result&=&curl_exec($ch);
&&&&&&&&curl_close($ch);
&&&&&&&&return&$
&&&&//&验证参数
&&&&if&(strlen($receipt_data)&20){
&&&&&&&&$result=array(
&&&&&&&&&&&&'status'=&false,
&&&&&&&&&&&&'message'=&'非法参数'
&&&&&&&&&&&&);
&&&&&&&&return&$
&&&&//&请求验证
&&&&$html&=&acurl($receipt_data);
&&&&$data&=&json_decode($html,true);
&&&&//&如果是沙盒数据&则验证沙盒模式
&&&&if($data['status']=='2;){
&&&&&&&&//&请求验证
&&&&&&&&$html&=&acurl($receipt_data,&1);
&&&&&&&&$data&=&json_decode($html,true);
&&&&&&&&$data['sandbox']&=&'1';
&&&&if&(isset($_GET['debug']))&{
&&&&&&&&exit(json_encode($data));
&&&&//&判断是否购买成功
&&&&if(intval($data['status'])===0){
&&&&&&&&$result=array(
&&&&&&&&&&&&'status'=&true,
&&&&&&&&&&&&'message'=&'购买成功'
&&&&&&&&&&&&);
&&&&}else{
&&&&&&&&$result=array(
&&&&&&&&&&&&'status'=&false,
&&&&&&&&&&&&'message'=&'购买失败&status:'.$data['status']
&&&&&&&&&&&&);
&&&&return&$
}使用方法也非常简单;
就是把IOS发过来的支付凭证作为参数传入validate_apple_pay()函数即可;
但是既然挂上了thinkphp整合;
那就给个示例吧;
/Application/Api/Controller/AppstoreController.class.php&?php
namespace&Api\C
use&Common\Controller\HomeBaseC
&*&paypal支付
class&AppstoreController&extends&HomeBaseController{
&&&&//&支付回调
&&&&public&function&result(){
&&&&&&&&//苹果内购的验证收据
&&&&&&&&$receipt_data&=&I('post.apple_receipt');&
&&&&&&&&//&验证支付状态
&&&&&&&&$result=validate_apple_pay($receipt_data);
&&&&&&&&if($result['status']){
&&&&&&&&&&&&//&验证通过&此处可以是修改数据库订单状态等操作
&&&&&&&&&&&&
&&&&&&&&}else{
&&&&&&&&&&&&//&验证不通过
本文为白俊遥原创文章, 转载无需和我联系, 但请注明来自白俊遥博客
积分:4523
ThinkPHP 是一个免费开源的,快速、简单的面向对象的 轻量级PHP开发框架 ,创立于2006年初,遵循Apache2开源协议发布,是为了敏捷WEB应用开发和简化企业应用开发而诞生的。ThinkPHP从诞生以来一直秉承简洁实用的设计原则,在保持出色的性能和至简的代码的同时,也注重易用性。并且拥有众多的原创功能和特性,在社区团队的积极参与下,在易用性、扩展性和性能方面不断优化和改进,已经成长为国内最领先和最具影响力的WEB应用开发框架,众多的典型案例确保可以稳定用于商业以及门户级的开发。博主最新文章
博主热门文章
您举报文章:
举报原因:
原文地址:
原因补充:
(最多只允许输入30个字)博主最新文章
博主热门文章
您举报文章:
举报原因:
原文地址:
原因补充:
(最多只允许输入30个字)在实现 iOS 内充值购买(非内购)的时候,遇到了获取值和界面跳转的问题,在线等
19:31:20 +08:00 · 2511 次点击
在做充值购买功能的时候遇到了一点问题,希望大家帮忙看一下,谢啦首先是在app原生界面,填写完充值金额,点击提交,push出来一个webView显示第三方充值界面这时候,已经向数据库提交了一次post请求,接收到的response是webView跳转的网页地址上面的部分是已经完成的了,现在的问题是停留在了第二块,也就是下面这块在push出来的webView显示的wap界面里面,用户完成充值操作当用户充值成功,并且点击“返回商城”的按钮的时候,会同步给我们服务器(或者app)发一个回调我需要根据这个回调,push出来新的界面,用于显示用户购买产品的详情,这期间,涉及到一次捕获用户在wap上“返回商城”的操作还涉及到一次,接收用户返回的response数据的动作webViewDelegate中的方法,都是与webView界面加载相关的方法web的界面加载,可以关联到我上面所期望的动作响应吗?或者再简单点说,就是我想捕获这个用户在wap界面点击“返回商城”的response
3 回复 &| &直到
16:00:42 +08:00
& & 20:34:50 +08:00 via Android
可能通不过审核
& & 14:21:40 +08:00
@ 为什么呢,是苹果会因为非内购的应用内支付找麻烦么
& & 16:00:42 +08:00
如果没记错,苹果会reject 一切有非apple内购的购买渠道的app。
你可以一试。
& · & 937 人在线 & 最高记录 3541 & · &
创意工作者们的社区
World is powered by solitude
VERSION: 3.9.8.0 · 16ms · UTC 18:02 · PVG 02:02 · LAX 11:02 · JFK 14:02? Do have faith in what you're doing.}

我要回帖

更多关于 ios 内购回调 的文章

更多推荐

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

点击添加站长微信