iOS- 给App添加内购& 验证购买iOS7新特性

IAP升级 代码分析 /* 如何理解如下代码? */ //跳转到应用程序段 //appxaddr:用户代码起始地址. void iap_load_app(u32 appxaddr) { if(((*(vu32*)appxaddr)&0x2FFE0000)==0x20000000) //检查栈顶地址是否合法. { jump2app=(iapfun)*(vu32*)(appxaddr+4); 阅读详情

1.内购——应用内购买                      

我所说的内购——也可以说是应用内购买

大家都知道通过苹果应用程序商店有三种主要赚钱的方式:
1.直接收费(与国内大部分用户的消费习惯相悖,如果要收费,直接收高的,别收6块钱)
2.广告(降低用户体验 应用程序名称带Lite可以添加广告)
3.内购
至于设计哪些卖钱?产品经理需要认真考虑和调研的。记录用户行为是可以帮助产品经理确认哪些收费!
所以要做好游戏,一定要研究心理,要研究哲学,哈哈。
 

2.内购的类别有哪几种呢?                    

在游戏中我们经常用到的主要由分两种:
 
非消耗品(Nonconsumable)买了就有,头衔,功能
指的是在游戏中一次性购买并拥有永久访问权的物品或服务。非消耗品物品可以被用户再次下载,并且能够在用户的所有设备上使用
消耗品(Consumable),买了就用,用了就没
专为支持可消耗的物品或服务设计的,消耗品购买不可被再次下载,根据其特点,消耗品不能在用户的设备之间跨设备使用,除非自定义服务在用户的账号之间共享这些信息
 
 

3.添加内购功能                             

3.1在iTunes Connect中给自己的应用添加消耗品定义                      


3.2在iTunes Connect中给自己的应用添加定义的商品              


3.3要使用内购,需要导入StoreKit框架                            

 定义好的商品

#define kIAPBomb @"airplay.10bombs"

#define kIAPBullet @"airplay.laserBullet"

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

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

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

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

@interface ITViewController () <SKProductsRequestDelegate, SKPaymentTransactionObserver>
{
    // 产品字典
    NSMutableDictionary *_productDict;
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    
    [self requestProducts];
    
    // 设置购买队列的监听器
    [[SKPaymentQueue defaultQueue] addTransactionObserver:self];
}

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

#pragma mark 询问苹果的服务器能够销售哪些商品
- (void)requestProducts
{
    // 能够销售的商品
    NSSet *set = [[NSSet alloc] initWithObjects:kIAPBomb, kIAPBullet, nil];
    
    // "异步"询问苹果能否销售
    SKProductsRequest *request = [[SKProductsRequest alloc] initWithProductIdentifiers:set];
    
    request.delegate = self;
    
    // 启动请求
    [request start];
}

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

- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response
{
    if (_productDict == nil) {
        _productDict = [NSMutableDictionary dictionaryWithCapacity:response.products.count];
    }
    
    for (SKProduct *product in response.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.用户决定购买商品                                      

#pragma mark - 用户决定购买商品
- (void)buyProduct:(SKProduct *)product
{
    // 要购买产品(店员给用户开了个小票)
    SKPayment *payment = [SKPayment paymentWithProduct:product];
    
//    // 设置购买队列的监听器
//    [[SKPaymentQueue defaultQueue] addTransactionObserver:self];
    
    // 去收银台排队,准备购买(异步网络)
    [[SKPaymentQueue defaultQueue] addPayment:payment];
}
- (IBAction)purchaseProducts
{
    [self buyProduct:_productDict[kIAPBullet]];
}

- (IBAction)purchaseBomb:(id)sender
{
    [self buyProduct:_productDict[kIAPBomb]];
}

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

#pragma mark - SKPaymentTransaction Observer
#pragma mark 购买队列状态变化
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions
{
    // 调试
    for (SKPaymentTransaction *transaction in transactions) {
        NSLog(@"队列状态变化 %@", transaction);
        // 如果小票状态是购买完成
        if (SKPaymentTransactionStatePurchased == transaction.transactionState) {
            NSLog(@"购买完成 %@", transaction.payment.productIdentifier);
            
            // 更新界面或者数据,把用户购买得商品交给用户
            // ...
            // 验证购买凭据
            [self verifyPruchase];
            
            // 将交易从交易队列中删除
            [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
        } else if (SKPaymentTransactionStateRestored == transaction.transactionState) {
            NSLog(@"恢复成功 %@", transaction.payment.productIdentifier);

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

            // 将交易从交易队列中删除
            [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
        }
    }
}

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

#pragma mark - 恢复商品
- (void)restorePurchase
{
    // 恢复已经完成的所有交易.(仅限永久有效商品)
    [[SKPaymentQueue defaultQueue] restoreCompletedTransactions];
}

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

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

#pragma mark 验证购买凭据
- (void)verifyPruchase
{
    // 验证凭据,获取到苹果返回的交易凭据
    // appStoreReceiptURL iOS7.0增加的,购买交易完成后,会将凭据存放在该地址
    NSURL *receiptURL = [[NSBundle mainBundle] appStoreReceiptURL];
    // 从沙盒中获取到购买凭据
    NSData *receiptData = [NSData dataWithContentsOfURL:receiptURL];
    
    // 发送网络POST请求,对购买凭据进行验证
    NSURL *url = [NSURL URLWithString:ITMS_SANDBOX_VERIFY_RECEIPT_URL];
    // 国内访问苹果服务器比较慢,timeoutInterval需要长一点
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:10.0f];
    
    request.HTTPMethod = @"POST";
    
    // 在网络中传输数据,大多情况下是传输的字符串而不是二进制数据
    // 传输的是BASE64编码的字符串
    /**
     BASE64 常用的编码方案,通常用于数据传输,以及加密算法的基础算法,传输过程中能够保证数据传输的稳定性
     BASE64是可以编码和解码的
     */
    NSString *encodeStr = [receiptData base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithLineFeed];
    
    NSString *payload = [NSString stringWithFormat:@"{\"receipt-data\" : \"%@\"}", encodeStr];
    NSData *payloadData = [payload dataUsingEncoding:NSUTF8StringEncoding];

    request.HTTPBody = payloadData;
    
    // 提交验证请求,并获得官方的验证JSON结果
    NSData *result = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];

    // 官方验证结果为空
    if (result == nil) {
        NSLog(@"验证失败");
    }
    
    NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:result options:NSJSONReadingAllowFragments error:nil];
    
    NSLog(@"%@", dict);
    
    if (dict != nil) {
        // 比对字典中以下信息基本上可以保证数据安全
        // bundle_id&application_version&product_id&transaction_id
        NSLog(@"验证成功");
    }
}

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

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

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

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

 

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


转自:http://www.cnblogs.com/qingche/p/3561424.html

Qt 6.7 LTS 新特性解析与实战:从环境搭建到部署发布 C++20 是现代 C++ 开发的重要标准,它引入了概念、范围库、协程等特性,旨在提升代码的表达力、安全性和性能。其原理在于通过更严格的类型约束和更高级的抽象,帮助开发者编写更清晰、更高效的代码。在跨平台 GUI 开发领域,Qt 框架将这些现代 C++ 特性与稳定的图形界面库相结合,技术价值体现在既能享受语言进化的红利,又能保障大型项目的可维护性与部署可靠性。应用场景广泛,从桌面应用到嵌入式系统,再到移动端开发,都需要这种平衡。本文聚焦于 Qt 6.7 LTS 这一长期支持版本,它全面支持 C++20,并增 阅读详情

相关推荐

OpenClaw接入Google DeepMind Flash 3.7:Agent配置、部署与排错全攻略

在AI Agent快速演进的背景下,如何让智能体真正具备执行多步任务的能力,取决于模型调度、工具调用与运行时环境的有效配合。OpenClaw作为一款面向个人与轻量团队的Agent运行时,负责连接模型、工具与工作区,是本地部署和云服务器环境中常见的自动化载体。理解其底层链路,需要先厘清Provider、模型标识、工具权限与记忆配置等核心概念。通过合理规划多模型调度,并结合Skill扩展与长期记忆,才能让Agent稳定完成从资料整理到项目管理等实际工作。同时,本地安装与云端上线的过程中,常会遇到审批文件兼容、模

weixin_34392435的博客 421

iOS 内付费(in-app purchase)--非消耗品的购买与恢复

iOS内付费的功能对于一个app来说是非常重要的,如果在这一环节出了一些致命的问题,那就很可能会影响app的推广和公司的利益了。我在很早之前写过一篇关于iOS内付费的文章(文章地址),在那篇博客中讲述了如何在苹果后台生成iOS内付费商品,以及在我们的app工程中如何去添加相应的内付费代码。但是,在后来的日子里面我发现网友在关于内购功能上遇到的问题比我想象的还要多,其中很大一部分都是一些很简单的问题,

shenjie12345678的专栏 3万+

Record3D 获取iphone RGBD 和 pose

最近准备复现Universal Manipulation Interface 遥操,在选择相机时,考虑到先快速验证下视觉模块,刚好手里有台 iphone 15 pro,这不巧了嘛,iphone自带LiDAR,有RGB图像、深度图、pose,刚好满足数据采集的需要。

boss-dog 490

iOS 苹果支付内购开发指南:创建 Apple 支付商品的完整流程

Apple 支付商品的创建流程看似繁琐,但只要掌握了步骤,其实并不复杂。从前期的准备工作,到在 App Store Connect 中配置商品,再到最后的测试,每一步都关系着内购功能是否顺利上线。建议在开发初期就尽早完成商品的创建与审核,避免在上线前因商品状态问题而耽误进度。如果你在商品创建过程中遇到什么问题,也欢迎留言交流!

weixin_39339407的博客 1万+

【IOS一气呵成】之IAP集成:内购和内购恢复 DEMO

博文地址:http://blog.youkuaiyun.com/vkenchen/article/details/24122345#t18 #import #import #import @class RMIAPHelper; @protocol RMIAPHelperDelegate //购买 -(void)requestProduct:(RMIAPHelper*)sender start:(SKProductsRequest*)request; -(void)requestProduct:(RMIAPHelper*)sender received:(SKProductsRequest*)request; -(void)paymentRequest:(RMIAPHelper*)sender start:(SKPayment*)payment; -(void)paymentRequest:(RMIAPHelper*)sender purchased:(SKPaymentTransaction*)transaction; -(void)paymentRequest:(RMIAPHelper*)sender restored:(SKPaymentTransaction*)transaction; -(void)paymentRequest:(RMIAPHelper*)sender failed:(SKPaymentTransaction*)transaction; //恢复 -(BOOL)restoredArray:(RMIAPHelper*)sender withArray:(NSArray*)productsIdArray; //其他 //不支持内购 -(void)iapNotSupported:(RMIAPHelper*)sender; @end @interface RMIAPHelper : NSObject +(RMIAPHelper*)sharedInstance; @property(nonatomic,assign) id delegate; -(void)setup; -(void)destroy; -(void)buy:(NSString*)productId; -(void)restore; @end

Multisim仿真入门:单相半波可控整流电路从搭建到波形分析(附避坑指南)

本文为电力电子技术初学者提供了一份详细的Multisim仿真指南,手把手教你从零搭建单相半波可控整流电路。通过对比纯电阻、阻感负载及加入续流二极管后的波形变化,直观理解晶闸管触发、电感续流等核心原理,并附有实用的参数设置与常见问题避坑指南,帮助你将抽象理论转化为可视化的工程实践。

weixin_29208077的博客 343

苹果IAP receipt验单较佳实践

前言 IAP支付的坑太多,这里写一些高级点的坑。 一、请求商品 下面是请求商品的代码: - (void)validateProductIdentifier:(NSArray *)productIdentifier { SKProductsRequest *productRequest = [[SKProductsRequest alloc] initWithProductIdentifiers:[NSSet setWithArray:productIdentifier]]; s

lzf的博客 4859

AI+医疗:多模态模型让肺结节诊断准确率突破95%+的实战方案

多模态融合是必由之路:单一影像模型难以突破95%准确率,必须整合临床、生物标志物等多维数据跨模态注意力机制是核心:简单拼接效果差,注意力机制能自动学习各模态权重,提升融合效果临床适配比技术先进更重要:模型输出必须符合医生诊断习惯,提供可解释的决策依据持续学习是长期成功的关键:医疗数据分布不断变化,模型必须具备自适应能力多学科协作是保障:放射科、胸外科、病理科、AI工程师共同参与模型设计与优化。

专注于Python爬虫开发,分享爬虫技巧、项目实战与反爬经验,使用Scrapy、BeautifulSoup等工具,解决数据抓取难题。 1022

【IOS】Firebase(Google、Facebook、Apple、Guest)登录,FCM,Apple In-App,Kakao

有的时候很多操作如果在cocos2dx的主线程中来调用,可能会极大地占用主线程的时间,从而使游戏的不流畅。比如在获取网络文件数据或者在数据比较大的游戏存档时,就需要使用多线程了。网上的一些教程上是使用pthread来创建新线程的,需要加入lib和头文件,但在cocos2dx 3.0中并未发现有pthread的支持文件,后来才发现在c++11中已经拥有了一个更好用的用于线程操作的类std::thread。

??? 5235

STM32嵌入式开发实战:如何用miniLZO压缩算法节省70%存储空间(附完整工程)

本文详细介绍了如何在STM32嵌入式开发中使用miniLZO无损压缩算法实现高达70%的存储空间节省。通过对比分析不同轻量级算法,重点讲解miniLZO的内存优化配置、分块压缩策略和完整工程实现,帮助开发者有效解决嵌入式系统中的存储瓶颈问题。

ss78901的博客 881

ECU-TEST笔记&使用技巧01

说明 1)所述均基于如下环境:ECU-TEST 8.0、Win10系统、NI Veristand 2018(HIL测试)。不排除因为版本及软件环境问题,所述方法不奏效或有更好的方法,欢迎交流,一起提高。 2)本博客以问答形式进行,所述问题均来自于实际测试(包括MIL、HIL测试)遇到的问题及需求,目的是提高测试效率和自动化测试序列的可维护性。 3)本博客尽量从测试方法及ECU-TEST原...

Eigrl的博客 1万+

thinkphp整合系列之苹果AppStore内购付款的服务器端php验证

这里要讲的就是AppStore内购的服务器端验证;在app中支付的过程那是由IOS程序猿完成的;IOS会把支付凭证发给我们;作为服务器端;我等php需要做的就是对支付结果的验证;thinkphp整合系列之苹果AppStore内购付款的服务器端php验证 演示地址做出来拉,大家可以参...

chouyulai0489的博客 350

过程挖掘(Process Mining)1——始于颜值

下周开始每周1-2篇的过程挖掘分享 过程挖掘是什么? 过程挖掘与过程管理的关系? 过程挖掘与数据挖掘的关系? 管理学还是计算机科学?

hyhy12580的博客 6236

2026年ios app历史版本下载方法

很多iphone用户在升级app后,可能想要用回之前的版本,但是app store没有提供历史版本安装的功能,所以造成了用户不能回退的情况,这篇文章提供了一种安装任意app历史版本的方法

高飞的专栏 8817

深度学习在地质勘探中的应用:使用Python构建卷积神经网络进行地震数据分析

在本文中,我们介绍了如何利用深度学习技术,特别是卷积神经网络(CNN),来处理和分析地震数据。我们使用了Python编程语言和TensorFlow框架构建了一个CNN模型,并使用地震数据进行了训练和评估。在本文中,我们将探讨如何利用深度学习技术,特别是卷积神经网络(CNN),来处理和分析地震数据。首先,我们需要获取地震数据集。通过本文的介绍,希望您能对深度学习在地质勘探领域的应用有更深入的了解,并能够应用这些技术来解决实际问题。在准备好地震数据和构建CNN模型后,我们需要将数据分为训练集和测试集。

斌擎科技 1471

YOLOv11改进策略【独家融合改进】| MobileNetV4+BiFPN,轻松实现降参涨点,适用专栏内所有的骨干替换

可扩展的高效物体检测BiFPN(加权双向特征金字塔网络)

Limiiiing的博客 2357

苹果支付服务器二次验证

IOS开发者肯定会用,此处提供一个苹果支付服务器二次验证的方法作为参考,希望对大家有用处

l602108654的博客 885

【图像超分】论文复现:新手入门必备!Pytorch实现SRGAN!手把手详细教程!代码注释详尽!可用于训练自己的数据集!实时验证模型性能!绘制PSNR曲线图!附训练好的各放大倍数的模型权重文件!

【图像超分】论文精读:SRResNet/SRGAN【图像超分】论文复现:万字长文!Pytorch实现SRResNet代码修改无报错!踩坑全记录!适合各种深度学习新手!帮助你少走弯路!附修改后的代码和PSNR最优的模型权重文件!请配合上述论文精读文章使用,效果更佳!与原论文描述不一样的实现部分,也即可以修改的部分数据集使用:论文中是ImageNet随机选35000张图像,本文是VOC2012数据集16700张图像。数据集预处理:裁剪大小不同,论文是96×96,本文是88×88。

主要更新底层视觉(去噪、超分等)相关的科研内容,形式为【论文精读】+【论文复现】 6852

苹果召开新品发布会 - iOS移动开发周报

新闻\\《苹果召开新品发布会》:北京时间10月17日凌晨1点,苹果在美国加州库比蒂诺总部Infinite Loop园区的Town Hall大会堂如期召开了主题为“久违了(It’s been way too long)”的新品发布会。这也是继苹果iPhone6、iPhone 6 Plus正式发布后,苹果在今年秋季举办的第二场大型发布会。在此次发布会上,苹果正式发布了iPad Air 2、iPad m...

cpongo5 213

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

电商App协议逆向实战:用AI解析黑盒API与AES加密逻辑

移动App后端接口已不再是标准RESTful API,而是一种‘客户端即协议’的强绑定契约。理解其原理需从HTTP语义、设备指纹、时间戳精度、AES-CBC-PKCS7加密等底层机制切入,技术价值在于绕过文档缺失与反爬封锁,实现稳定数据采集与系统集成。典型应用场景包括跨境选品、独立站对接及安全合规审计。本文聚焦COM.MFASHIONGALLERY.EMAG这类东南亚快时尚App的真实逆向案例,结合Python requests会话管理与DeepSeek模型驱动的协议语义聚类,系统拆解签名规则、429限流应

weixin_34221073的博客 307

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

深入解析VMware Unlocker 4.2.8:3步实现跨平台macOS虚拟化支持

在非苹果硬件上运行macOS虚拟机一直是开发者和技术爱好者的迫切需求,而VMware Unlocker 4.2.8正是解决这一技术挑战的完整解决方案。这款专业的开源虚拟化解锁工具通过创新的二进制补丁技术,让用户在Windows和Linux平台上能够无缝运行macOS虚拟机,为iOS应用开发、macOS软件测试提供了高效稳定的跨平台支持。 ## 技术挑战与需求分析 ### 虚拟化环境的技术壁垒

gitblog_00339的博客 747

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

上一篇: 两点之间走直线真的最近吗?
下一篇: 用C++面向对象的方式动态加载so
tspangle
博客等级 码龄19年 81粉丝 88原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值