更新内购 (包括服务器双向验证)

最近在更新版本,发现好多用户来进行应用内的服务退款,理由频多,但是还不能确定用户是否支付成功,所以看了一下苹果内购的官方文档,发现有验证服务器的方法,于是就加上了。

具体内购怎么做在这里就不说了,网上有详细的讲解。

首先内购有几种类别呢,这个一定要搞清楚,否则会遇到很多问题。在游戏中我们经常用到的主要由分两种:

非消耗品 (Nonconsumable)买了就有,头衔,功能

指的是在游戏中一次性购买并拥有永久访问权的物品或服务。非消耗品物品可以被用户再次下载,并且能够在用户的所有设备上使用

消耗品 (Consumable),买了就用,用了就没

专为支持可消耗的物品或服务设计的,消耗品购买不可被再次下载,根据其特点,消耗品不能在用户的设备之间跨设备使用,除非自定义服务在用户的账号之间共享这些信息。

接下来我们就开始应用内购,需要导入StoreKit框架。定义好的商品

#define kIAPBomb @ "airplay.10bombs"

#define kIAPBullet @"airplay.laserBullet"

1. 实例化请求时,必须指定有效的identifiers集合,之所以如此处理,主要是为了确保提交的内购商品真的通过了苹果的审批,处于可用状态!

2. 要想获取到准确的可用产品集合,需要通过代理方法实现

- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response

3. 越狱用户无法测试内购,但是可以购买

1@interfaceITViewController() <SKProductsRequestDelegate,SKPaymentTransactionObserver>

2{

3// 产品字典

4NSMutableDictionary*_productDict;

5}

1-(void)viewDidLoad

2{

3[super viewDidLoad];

4

5[self requestProducts];

6

7// 设置购买队列的监听器

8[[SKPaymentQueue defaultQueue]addTransactionObserver:self];

9}

3.4.询问苹果的服务器能够销售哪些商品

#pragma mark 询问苹果的服务器能够销售哪些商品

- (void)requestProducts

{

// 能够销售的商品

NSSet*set=[[NSSetalloc] initWithObjects:kIAPBomb, kIAPBullet,nil];

// "异步"询问苹果能否销售

SKProductsRequest*request = [[SKProductsRequestalloc] initWithProductIdentifiers:set];

request.delegate=self;

// 启动请求

[request start];

}

3.5.获取询问结果,成功采取操作把商品加入可售商品字典里

- (void)productsRequest:(SKProductsRequest*)request didReceiveResponse:(SKProductsResponse*)response

{

if(_productDict ==nil) {

_productDict=[NSMutableDictionarydictionaryWithCapacity:response.products.count];

}

for(SKProduct*productinresponse.products) {

// 激活了对应的销售操作按钮,相当于商店的商品上架允许销售

NSLog(@"%@", product.productIdentifier);

if([product.productIdentifier isEqualToString:kIAPBullet]) {

_bulletButton.enabled=YES;

}

if([product.productIdentifier isEqualToString:kIAPBomb]) {

_bombButton.enabled=YES;

}

// 填充商品字典

[_productDict setObject:product forKey:product.productIdentifier];

}

}

3.6.用户决定购买商品

1#pragma mark - 用户决定购买商品

2- (void)buyProduct:(SKProduct*)product

3{

4// 要购买产品(店员给用户开了个小票)

5SKPayment*payment =[SKPaymentpaymentWithProduct:product];

6

7//// 设置购买队列的监听器

8//[[SKPaymentQueue defaultQueue] addTransactionObserver:self];

9

10// 去收银台排队,准备购买(异步网络)

11[[SKPaymentQueuedefaultQueue] addPayment:payment];

12}

1-(IBAction)purchaseProducts

2{

3[self buyProduct:_productDict[kIAPBullet]];

4}

5

6-(IBAction)purchaseBomb:(id)sender

7{

8[self buyProduct:_productDict[kIAPBomb]];

9}

3.7.判断购买状态是否成功

#pragma mark - SKPaymentTransaction Observer

#pragma mark 购买队列状态变化

- (void)paymentQueue:(SKPaymentQueue*)queue updatedTransactions:(NSArray*)transactions

{

// 调试

for(SKPaymentTransaction*transactionintransactions) {

NSLog(@"队列状态变化 %@", transaction);

// 如果小票状态是购买完成

if(SKPaymentTransactionStatePurchased==transaction.transactionState) {

NSLog(@"购买完成 %@", transaction.payment.productIdentifier);

// 更新界面或者数据,把用户购买得商品交给用户

// ...

// 验证购买凭据

[selfverifyPruchase];

// 将交易从交易队列中删除

[[SKPaymentQueuedefaultQueue] finishTransaction:transaction];

}elseif(SKPaymentTransactionStateRestored==transaction.transactionState) {

NSLog(@"恢复成功 %@", transaction.payment.productIdentifier);

// 更新界面或者数据,把用户购买得商品交给用户

// ...

// 将交易从交易队列中删除

[[SKPaymentQueuedefaultQueue] finishTransaction:transaction];

}

}

}

3.8.给用户提供恢复功能(因为在不同设备上永久性商品可能会出现需要恢复购买的情况)

#pragmamark-恢复商品

-(void)restorePurchase

{

// 恢复已经完成的所有交易.(仅限永久有效商品)

[[SKPaymentQueue defaultQueue]restoreCompletedTransactions];

}

3.9.验证购买(防止第三方插件漏洞)iOS7新特性

提示:虽然苹果在iOS7提升了购买凭据的安全性,但是处于金钱考虑,购买完成后,一定要做凭据的验证工作。

#pragma mark 验证购买凭据

- (void)verifyPruchase

{

// 验证凭据,获取到苹果返回的交易凭据

// appStoreReceiptURL iOS7.0增加的,购买交易完成后,会将凭据存放在该地址

NSURL*receiptURL =[[NSBundlemainBundle] appStoreReceiptURL];

// 从沙盒中获取到购买凭据

NSData*receiptData =[NSDatadataWithContentsOfURL:receiptURL];


// 发送网络POST请求,对购买凭据进行验证

NSURL*url =[NSURLURLWithString:ITMS_SANDBOX_VERIFY_RECEIPT_URL];

// 国内访问苹果服务器比较慢,timeoutInterval需要长一点

13NSMutableURLRequest*request = [NSMutableURLRequestrequestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicytimeoutInterval:10.0f];

request.HTTPMethod =@"POST";

// 在网络中传输数据,大多情况下是传输的字符串而不是二进制数据

/ 传输的是BASE64编码的字符串

/**

BASE64 常用的编码方案,通常用于数据传输,以及加密算法的基础算法,传输过程中能够保证数据传输的稳定性

BASE64是可以编码和解码的

*/

NSString*encodeStr =[receiptData base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithLineFeed];


NSString*payload = [NSStringstringWithFormat:@"{\"receipt-data\" : \"%@\"}", encodeStr];

NSData*payloadData =[payload dataUsingEncoding:NSUTF8StringEncoding];


request.HTTPBody =payloadData;


// 提交验证请求,并获得官方的验证JSON结果

NSData*result =[NSURLConnectionsendSynchronousRequest:request returningResponse:nilerror:nil];

// 官方验证结果为空

if(result ==nil) {

NSLog(@"验证失败");

}


NSDictionary*dict =[NSJSONSerializationJSONObjectWithData:result options:NSJSONReadingAllowFragmentserror:nil];


NSLog(@"%@", dict);


if(dict !=nil) {

// 比对字典中以下信息基本上可以保证数据安全

// bundle_id&application_version&product_id&transaction_id

NSLog(@"验证成功");

}

}

3.9.说说整个购买流程结构

1.苹果APP(商家) ——— 2.告诉苹果Store服务器要卖的商品 ——— 3.苹果审核完(告诉你是否可以卖)

4.用户(买商品) ———  5.苹果APP(商家) ———  6.开发票给(用户) ————

7.用户(拿着发票去苹果Store服务器付款) —— 8.付款成功(用户在APP里获得服务商品)

(注意:如果要模拟测试内购,需要用真机才可以测试)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,884评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,755评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,369评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,799评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,910评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,096评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,159评论 3 411
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,917评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,360评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,673评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,814评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,509评论 4 334
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,156评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,882评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,123评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,641评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,728评论 2 351

推荐阅读更多精彩内容

  • iOS应用如果涉及到支付功能,分为两类:第三方支付和苹果内购。那么什么情况下选择使用第三方支付,又在什么情况下选择...
    ZfRee阅读 38,846评论 36 66
  • 自己开发的视频直播项目,牵涉到充值金币,用到了苹果公司的内购,趴坑了两天,这里总结下实现苹果内购。 一. 创建测试...
    Leo丶Dicaprio阅读 3,365评论 8 7
  • iOS应用内付费(IAP)开发步骤 1.苹果iTunes Connect内购产品信息录入。 1)创建app内购买项...
    MillerWang阅读 10,995评论 0 7
  • 关于dom操作,我们分创建、增、删、改、查、属性操作、事件操作来大体介绍一下 创建 1.createElement...
    cb12hx阅读 2,180评论 1 2
  • 混沌.
    欧姆奶奶阅读 154评论 0 0