ios内购退款2017发起支付 弹出一个等待窗口 如何实现

IOS内购支付服务器验证模式
时间: 11:58:56
&&&& 阅读:1452
&&&& 评论:
&&&& 收藏:0
标签:&&&&&&&&&&&&IOS 内购支付两种模式:
服务器模式
内置模式的流程:
app从app store 获取产品信息
用户选择需要购买的产品
app发送支付请求到app store
app store 处理支付请求,并返回transaction信息
app将购买的内容展示给用户
服务器模式的流程:
app从服务器获取产品标识列表
app从app store 获取产品信息
用户选择需要购买的产品
app 发送 支付请求到app store
app store 处理支付请求,返回transaction信息
app 将transaction receipt 发送到服务器
服务器收到收据后发送到app stroe验证收据的有效性
app store 返回收据的验证结果
根据app store 返回的结果决定用户是否购买成功
上述两种模式的不同之处主要在于:交易的收据验证,内建模式没有专门去验证交易收据,而服务器模式会使用独立的服务器去验证交易收据。内建模式简单快捷,但容易被破解。服务器模式流程相对复杂,但相对安全。
开发之初,苹果方就很负责的告知:我们的服务器不稳定。真正开发之后,发现苹果方果然是很负责的,不仅是不稳定,而且足够慢。app store server验证一个收据需要3-6s时间。
用户能否忍受3-6s的等待时间
如果app store server 宕机,如何确保成功付费的用户能够得到正常服务。
对于第一个问题,我们有理由相信用户完全无法忍受,所以采用异步验证的方式,服务器收到客户端的请求后,就将请求放到MCQ中去处理。
对于第二个问题,由于苹果人员很负责人的告知:我们的服务器不稳定,所以不排除收据验证超时的情况。对于验证超时的收据,保存到数据库中并标记为验证超时,定时任务每隔一定的时间去app store验证,确保能够获取收据的验证结果。
在开发过程中,需要测试应用是否能够正常的进行支付,但是又不能进行实际的支付,因此需要使用苹果提供的sandbox Store测试。Store Kit不能在iOS模拟器中使用,测试Store必须在真机上进行。
在sandbox中验证receipt:
https://sandbox./verifyReceipt
在生产环境中验证receipt:
https://buy./verifyReceipt
在实际开发过程中,服务器端通过issandbox字段标识客户端传递的收据是沙盒环境中的收据还是生产环境中的收据。在提交苹果审核前,沙盒测试均无问题。提交苹果审核后,被告知购买失败,审核未通过。通过查询日志发现,客户端发送的交易收据为沙盒收据,但是issandbox字段却标识为生产环境。
苹果审核app时,仍然在沙盒环境下测试。但是客户端同事在app提交苹果审核时,将issandbox字段写死,设置为生产环境。这样就导致沙盒收据发送到去验证。
那么如何自动的识别收据是否是sandbox receipt呢?
识别沙盒环境下收据的方法有两种:
1.根据收据字段 environment = sandbox。
2.根据收据验证接口返回的状态码,如果status=21007,则表示当前的收据为沙盒环境下收据, t进行验证。
苹果反馈的状态码;
21000App Store无法读取你提供的JSON数据
21002 收据数据不符合格式
21003 收据无法被验证
21004 你提供的共享密钥和账户的共享密钥不一致
21005 收据服务器当前不可用
21006 收据是有效的,但订阅服务已经过期。当收到这个信息时,解码后的收据信息也包含在返回内容中
21007 收据信息是测试用(sandbox),但却被发送到产品环境中验证
21008 收据信息是产品环境中使用,但却被发送到测试环境中验证
先生产验证后测试验证,可以避免来回切换接口的麻烦。测试验证只要用你自己申请的测试appid的时候才会用到,用户不会拥有测试appid,所以不会走到测试验证这一步。即使生产验证出错,应该也不回返回21007状态吗。测试验证通过的用户名,和充值金额最好用数据库记录下来,方便公司资金核对。
版权声明:本文为博主原创文章,未经博主允许不得转载。
标签:&&&&&&&&&&&&
&&国之画&&&& &&&&chrome插件
版权所有 京ICP备号-2
迷上了代码!当前位置: &>&&>& >
说说IOS内购那些事
1.支付类和协议
Store Kit框架下提供用来处理应用内购大致的类可以分为两部分:1.请求商品,2.购买商品。具体如下:
SKMutablePayment:该类为App Store定义了用户的付费请求功能,通过封装特定产品名称和购买数量,用来处理应用程序内购。
SKPayment:该类为App Store定义了用户的付费请求功能,通过封装特定产品名称和购买数量,用来处理应用程序内购。
SKPaymentQueue:该类为App Store交易支付提供了一个队列,用户可以通过它来校验支付。
SKPaymentTransaction:该类定义了支付队列对象。每当一个付款被添加到支付队列时就会创建一个该支付交易对象。当App Store已处理完支付交易时,该对象被回传到应用程序。完成的支付交易对象提供了收据,应用程序可以用它作为支付标识符,用来保存处理后支付的交易记录。
SKProduct:该类是作为SKProductsResponse的返回对象的一部分。每个产品对象提供有关您先前在iTunes Connect注册的产品信息。
SKProductsRequest:该类对象用于检索从App Store的产品列表本地化的信息。应用程序使用此请求提出局部价格等信息给用户,而无需维护该列表本身。
SKProductsResponse:该类对象是App Store在响应有关的产品的列表信息的请求时被返回。
SKReceiptRefreshRequest:该类允许应用程序刷新其收据。如果收据是无效或丢失,应用程序可以通过该类申请一个新的收据。在沙箱环境,您可以要求收据性质的任意组合进行测试与批量购买计划收益的状态转换。
SKRequest:该类是App Store的请求的抽象类。 SKRequest的子类代表不同类型的请求。
SKStoreProductViewController:该类对象提供了一个商店,允许用户从App Store购买其他媒体。
SKCloudServiceController:主要是针对Apple Music购买.
SKDownload:主要是针对Tunes购买.
Store Kit框架下提供以下协议用来处理请求事件
SKPaymentTransactionObserver:该协议为一个SKPaymentQueue对象的观察者提供方法。
SKProductsRequestDelegate:该协议声明由一个SKProductsRequest对象的委托实现的方法。委托收到该产品的信息请求是感兴趣的东西。
SKRequestDelegate:该协议声明了一个由SKRequest抽象类的任何子类实现的常用方法。
SKStoreProductViewControllerDelegate:当用户退出商店屏幕实现该协议的对象称为。通常情况下,这个协议是由您的应用程序最初显示的屏幕专卖店视图控制器实现的。
2.一般的内购流程
用户点击进入一个内购页面,页面刷新当前版本支持的内购商品列表,用户点击商品列表中的一个商品,弹出app strore帐号校验,完成校验后,弹出提示框询问用户是否购买,点击购买或是取消。
获取商品列表:这里获取商品列表,分两步,首先是从自己的服务器获取,其次是从app store获取。最终都是以app store获取为准。具体过程有以下几步:
每次进入商品列表界面都会直接去自己的服务器拉取。
拉取列表成功后,查询本地是否缓存了商品列表中的每一个商品id,
如果所有商品都已经缓存了,则直接返回商品列表,
如果校验发现有商品没有缓存(商品更新),此时,清空当前缓存,
并且直接去app store拉取商品列表,拉取成功后缓存再返回。
购买商品:点击某个商品进程购买,具体流程有以下几步:
检验当前是否支持内购(网络环境,权限等)
根据当前点击的商品,向自己的服务器去申请订单,如果申请订单成功
向app store发起支付请求,如果申请订单失败,直接返回提示信息
监听并等待app store返回支付交易信息。
如果交易完成,向自己的服务器更新订单状态,并结束完成app store交易。
如果交易失败,并结束完成app store交易。
如果交易取消,向自己的服务器取消订单,并结束完成app store交易。
2.3 状态处理
整个内购流程里面可分为两种类型的状态,一种是支付行为状态,就是从想苹果发起支付请求开始,中间包括支付校验的取消,确定两种行为状态,最后返回的支付交易完成和失败。一种是针对自己服务器的订单校验的状态,主要是开始校验,成功,失败,已校验,无法校验几种。
支付行为状态:该状态是通过监听app store回调来做区别处理。
交易完成:获取交易凭证,如果苹果返回了交易凭证,需要更具该交易凭证去和本地服务器做校验,校验成功,说明本次交易成功了,如果校验失败了,(验证找不到订单号)需要更具本次交易重新向服务器申请订单,并校验该订单凭证。
交易失败:如果是用户取消交易,直接向服务器取消本次订单。如果是交易失败,更新当前订单凭证到缓存中,用于下次校验。
已购买过:更新当前订单凭证到缓存中,标致成功。
交易加入队列:无处理。
本地订单校验凭证状态:该状态是根据支付行为状态用来对服务器的订单凭证进行管理。
校验成功:交易完成后,通过app store返回的凭证信息,去向服务器进行校验,校验成功后,更新当前订单凭证到缓存中,标致成功。
校验失败:尝试多次校验。
主要缓存:商品列表信息,支付凭证信息。
商品列表信息:每次进入内购界面时,根据从服务器拉取的商品信息与本地缓存做比较后,如果保持一直,则直接返回,如果存在差异,则还需要从app store拉取商品信息,再更新本地缓存后返回。
支付凭证信息:缓存每次交易支付凭证,用来与服务器订单进行校验。针对校验失败的凭证,会采取多次校验。每次进入商品购买时,需要对上次缓存的未成功的支付凭证进行再次校验。以确保服务器订单状态正确。
2.流程顺序
具体流程以伪代码
获取商品列表
- (void)fetchProducts:(xxxCompletBlo)complete {
if (![netWork isAvalabel]) {
if (complete)
complete(....);
[[ProductsOrderModel shareInstance] fetchProductsFromServer:xxxx complete:^(BOOL success, NSArry* products,.....) {
if (success) {
// 检验本地缓存
NSArry* cacheProducts = [[ProductOrderCache shareInstance] cacheProducte];
//缓存与服务器一直
if (complete)
complete(....);
//如果不一致,再去app store拉取
[ProductOrderCache shareInstance] cleanCacheProducte];
[[ProductsOrderModel shareInstance] fetchProductsFromApple:xxxx
complete:^(BOOL success, NSArry* products,.....) {
if (complete)
complete(....);
- (void)orderProduct:(NSString*)id complete:(xxxCompletBlo)complete {
//先去服务器获取订单
[[ProductsOrderModel shareInstance] fetchOrderFromServer:id
complete:^(BOOL success, ...) {
if (success) {
//发起苹果支付
SKPayment * payment = [SKPayment paymentWithProduct:product];
[[SKPaymentQueue defaultQueue] addPayment:payment];
//苹果支付回调
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions {
for (SKPaymentTransaction *transaction in transactions)
switch (transaction.transactionState)
case SKPaymentTransactionStatePurchased:
[self completeTransaction:transaction state:xxx_Succeed];
case SKPaymentTransactionStateFailed:
[self completeTransaction:transaction state:xxx_Failed];
case SKPaymentTransactionStateRestored:
[self completeTransaction:transaction state:xxx_Succeed];
case SKPaymentTransactionStatePurchasing:
- (void)completeTransaction:transaction state:(xxx_State)state {
switch(state) {
case xxx_Succeed:
//拿到苹果返回的凭证去务进行校验
[ProductsOrderModel shareInstance] verifyTransactionReceipt:xxx orderId:xxx complete:^(BOOL success, xxxx) {
if (success) {
// 更新缓存状态
[[ProductOrderCache shareInstance] updateOrderState:xxxid state:YES];
// 再次校验
case xxx_Failed:
// 更新缓存状态
[[ProductOrderCache shareInstance] updateOrderState:xxxid state:NO];
每次进行购买时,需要对本地缓存的上一次失败凭证进行再次校验。
商品列表信息,支付凭证信息需要做文件缓存。
延伸阅读:
(责任编辑:美朵)
每日重点推荐
夏医生是自己多年老同事的儿子,国外学成归来做事业,老同事担心儿子诊所刚开,门厅罗雀伤了自尊,便偷偷塞钱给李梅,求她装病去“捧场”。
一周热点文章
在线阅读专题iOS内购丢单处理及实现
iOS内购实现及测试Check List
在内购使用中存在的几种丢单的情况
1.客户端获取到交易回调后-(void) purchasedTransaction: (SKPaymentTransaction
*)transaction 后在交易成功的情况下,要拿到
transactionReceipt凭证,给后台验证的时候用户推出。(用户已经付钱但商家还没给商品)
& & 解决方法:在支付之前需要通过自己的服务器创建订单,在交易成功回调之后,立马将该订单和本次交易凭证存储到数据库中。在用户下次登录的时候,要首先验证该数据库中的交易凭证是否都经过后台验证过并成功给玩家商品。
<span style="font-size:18 color:#.这种情况是当交易回调有延时或者没有成功回调的时候,用户推出游戏。这个时候没有回调的transaction,无法将transactionReceipt和自己创建的订单绑定,也就是无法知道交易的用户。(感觉苹果这边有BUG,起码在交易对象中包含用户的数据)。这个时候,用户再下次登录的时候可以获取到transaction,但无法确定该交易的用户。
& &解决方法:在下次购买的时候,从购买队列中获取交易集合,对已经成功购买,但没下载的不需要重复购买,终止本地交易,将其存入已购买数据库中。
& 但还有一个问题,对于上次没有回调回来的交易,我们无法处理,以为虽然拿到了交易集合,但只凭借交易对象是无法知道用户信息的,也就无法充值。也就是说无法避免的丢单问题.................
找到解决办法了:ios7 苹果增加了一个属性applicationusername,SKMutablepayment的属性,所以用户在发起支付的时候可以指定用户的username及自己生成的订单,这样用户再下次得到回调的时候就知道,此交易是哪个订单发起的了进而完成交易。回调中获取username。
transaction.payment.applicationUsername(订单)将该属性连同transactionReceipt 传给后台做验证。完美解决问题 perfect&
如果您正在寻找一份手把手教你实现IAP的教程的话,这篇文章不是您的菜。关于IAP的实现和步骤,可以参考下面的教程:
Ray Wenderlich的
一篇图文并茂的
直接使用大神们封好的Store有关的库,比如
。推荐前两个,因为MKStoreKit有一些恼人的小bug。
一下是转载有兴趣可以看下:
免费+应用内购买的模式已经被证明了是最有效的盈利模式,所以实现内购功能可能是很多开发者必做的工作和必备的技能了。但是鉴于内购这块坑不算少,另外因为sandbox测试所需要特定的配置也很多,所以对于经验不太多的开发者来说很容易就遇到各种问题,并且测试时出错Apple给出的也只有“Can not connect iTunes Store”或者”Invalid Product IDs”之类毫无价值的错误提示,并没有详细的错误说明,因此调试起来往往没有方向。有老前辈在这里整理过一个相对完整的check list了,但是因为年代已经稍微久远,所以内容上和现在的情况已经有一些出入。趁着在最近两个项目里做内购这块遇到的新问题,顺便在此基础上总结整理了一份比较新的中文Check list,希望能帮到后来人。
如果您在实现和测试iOS应用内购的时候遇到问题,可以逐一对照下面所列出的条目,并逐一进行检查。相信可以排除大部分的错误。如果您遇到的问题不在这个列表范围内,欢迎在评论中指出,我会进行更新。
1.您是否在iOS Dev Center中打开了对应应用AppID的In-App Purchases功能?登陆iOS Dev Center的Certificates, Identifiers & Profiles下,在Identifiers中找到正在开发的App,In-App Purchase一项应当显示Enabled(如果使用Xcode5,可以直接在Xcode的Capabilities页面中打开In-App Purchases)。
2.您是否在iTunes Connect中注册了您的IAP项目,并将其设为Cleared for Sale?
3.您的plist中的Bundle identifier的内容是否和您的AppID一致?
4.您是否正确填写了Version(CFBundleVersion)和Build(CFBuildNumber)两个数字?两者缺一不可。
5.您用代码向Apple申请售卖物品列表时是否使用了完整的在iTC注册的Product ID?(使用在IAP管理中内购项目的Product ID一栏中的字符串)
6.您是否在打开IAP以后重新生成过包含IAP许可的provisioning profile?
7.您是否重新导入了新的包含IAP的provisioning profile?建议在Organizer中先删掉原来设备上的老的provisioning profile。
8.您是否在用包含IAP的provisioning profile在部署测试程序?在Xcode5中,建议使用General中的Team选项来自动管理。
9.您是否是在模拟器中测试IAP?虽然理论上说模拟器在某些情况下可以测试IAP,但是条件很多也不让人安心,因此您确实需要一台真机来做IAP测试。
10.您是在企业版发布中测试IAP么?因为企业版没有iTC进行内购项目管理,也无法发布AppStore应用,所以您在企业版的build中不能使用IAP。
11.您是否将设备上原来的app删除了,并重新进行了安装?记得在安装前做一下Clean和Clean Build Folder。
12.您是否在运行应用前将设备上实际的Apple ID登出了?建议在设置-&iTunes Store和App Stroe中将使用中的Apple ID登出,以未登录状态进入应用进行测试。
13.您是否使用的是Test User?如果你还没有创建Test User,你需要到iTC中创建。
14.您使用的测试账号是否是美国区账号?虽然不是一定需要,但是鉴于其他地区的测试账号经常抽风,加上美国区账号一直很稳定,因此强烈建议使用美国区账号。正常情况下IAP不需要进行信用卡绑定和其他信息填写,如果你遇到了这种情况,可以试试删除这个测试账号再新建一个其他地区的。
15.您是否有新建账户进行测试?可能的话,可以使用新建测试账户试试看,因为某些特定情况下测试账户会被Apple锁定。
16.您的应用是否是被拒状态(Rejected)或自己拒绝(Developer Rejected)了?被拒绝状态的应用的话对应还未通过的内购项目也会一起被拒,因此您需要重新将IAP项目设为Cleared for Sale。
17.您的应用是否处于等待开发者发布(Pending Developer Release)状态?等待发布状态的IAP是无法测试的。
18.您的内购项目是否是最近才新建的,或者进行了更改?内购项目需要一段时间才能反应到所有服务器上,这个过程一般是一两小时,也可能再长一些达到若干小时。
19.您在iTC中Contracts, Tax, and Banking Information项目中是否有还没有设置或者过期了的项目?不完整的财务信息无法进行内购测试。
20.您是在越狱设备上进行内购测试么?越狱设备不能用于正常内购,您需要重装或者寻找一台没有越狱的设备。
21.您是否能正常连接到Apple的服务器,你可以访问Apple开发者论坛关于IAP的板块,如果苹果服务器正down掉,那里应该有热烈的讨论。
如果您正在寻找一份手把手教你实现IAP的教程的话,这篇文章不是您的菜。关于IAP的实现和步骤,可以参考下面的教程:
Ray Wenderlich的
一篇图文并茂的
直接使用大神们封好的Store有关的库,比如
。推荐前两个,因为MKStoreKit有一些恼人的小bug。
原文:/applenews/devnews/75.html
请问下博主碰见过玩家已经扣款但是苹果返回skerrorunknown的情况呢,我这边玩家支付后会将每笔订单的code上传到服务器(每次玩家启动程序都会将改订单状态更新到服务器),但是有时候玩家反馈扣款了,我查询对应订单发现其状态一直是skerrorunknown,不知道怎么回事。
本分类共有文章7篇,更多信息详见
& 2012 - 2016 &
&All Rights Reserved. &
/*爱悠闲图+*/
var cpro_id = "u1888441";&>&&>&&>&&>&iOS 实现内购代码
iOS 实现内购代码
上传大小:85KB
实现iOS内购代码,获取计费信息,弹出购买得登录框
综合评分:4.1(8位用户评分)
所需积分:5
下载次数:45
审核通过送C币
创建者:nigelyq
创建者:nigelyq
课程推荐相关知识库
上传者其他资源上传者专辑
移动开发热门标签
VIP会员动态
您因违反CSDN下载频道规则而被锁定帐户,如有疑问,请联络:!
android服务器底层网络模块的设计方法
所需积分:0
剩余积分:720
您当前C币:0
可兑换下载积分:0
兑换下载分:
兑换失败,您当前C币不够,请先充值C币
消耗C币:0
你当前的下载分为234。
iOS 实现内购代码
会员到期时间:
剩余下载次数:
你还不是VIP会员
开通VIP会员权限,免积分下载
你下载资源过于频繁,请输入验证码
您因违反CSDN下载频道规则而被锁定帐户,如有疑问,请联络:!
若举报审核通过,可奖励20下载分
被举报人:
yingying081104
举报的资源分:
请选择类型
资源无法下载
资源无法使用
标题与实际内容不符
含有危害国家安全内容
含有反动色情等内容
含广告内容
版权问题,侵犯个人或公司的版权
*详细原因:热血传奇手机版ios内购失败解决方法_5577我机网
你的位置:
→ 热血传奇手机版ios内购失败解决方法
热血传奇手机版ios内购失败解决方法
热血传奇手机版ios内购可以获得大量的金币及钻石,在游戏中许多玩家对内购方法不是太了解,下面我机网小编来发分享下热血传奇手机版ios内购失败解决方法,希望大家喜欢。《热血传奇手机版》中有部分ios越狱过的玩家在内购游戏的时候会出现“支付失败,支付时出现错误,请稍后再试”的提示,那么要怎么办呢?下面给大家带来的就是热血传奇手机版ios内购失败办法。
大小:352M
语言: 中文
更新: 15-11-25
出现的问题:少部分越过狱的苹果iOS设备,在游戏内购买元宝时,可能会提示:支付失败,支付时出现错误,请稍后再试!解决的方案:请在内购插件中,关闭【热血传奇】在内购插件中的生效开关。以【IAPCrazy】为例,打开该内购插件:打开后点击【应用开关】的菜单 ,进入列表后找到 【热血传奇】游戏,将右侧的开关选择为【关闭状态】:然后退出插件,在进程中关闭【热血传奇】,并重新进入游戏,即可成功进行充值。如果还提示充值失败,可将内购插件删除,并重启设备后再次进入游戏。触乐此前针对内测版本进行过评测。移动端的《热血传奇》是一款ARPG手游,保留了端游《热血传奇》的经典职业设置、装备,加入了手游的F2P模式,并且针对移动端进行了操作优化。《热血传奇》手机版游戏截图目前在游戏的百度贴吧里,玩家主要关心游戏的职业平衡、内购设置,以及技能书和装备会被炒到怎样的价格,一些公会正在招兵买马。也有老玩家担心手游模式将会使“传奇”变味,新玩家则好奇地询问当年的老“传奇”究竟是怎样的游戏。关于这款游戏,我们之后会带来更详细的报道和讨论。以上就是我机网小编带来的热血传奇手机版ios内购失败解决方法,希望玩家朋友喜欢。
一年一度的双十一又要到了,除了购物节之外,还是万千单身汪的节
热血传奇手机版胜者为王版本即将正式上线,在胜者为王版本中新增
破解修改汉化
破解修改汉化
破解修改汉化
破解修改汉化
推荐手机游戏专区

我要回帖

更多关于 ios内购退款理由2017 的文章

 

随机推荐