iOS App 内购 Demo

/*注意事项:

1.沙盒环境测试appStore内购流程的时候,请使用没越狱的设备。

2.请务必使用真机来测试,一切以真机为准。

3.项目的Bundle identifier需要与您申请AppID时填写的bundleID一致,不然会无法请求到商品信息。

4.如果是你自己的设备上已经绑定了自己的AppleID账号请先注销掉,否则你哭爹喊娘都不知道是怎么回事。

5.订单校验 苹果审核app时,仍然在沙盒环境下测试,所以需要先进行正式环境验证,如果发现是沙盒环境则转到沙盒验证。

识别沙盒环境订单方法:

1.根据字段 environment = sandbox。

2.根据验证接口返回的状态码,如果status=21007,则表示当前为沙盒环境。

苹果反馈的状态码:

21000App Store无法读取你提供的JSON数据

21002 订单数据不符合格式

21003 订单无法被验证

21004 你提供的共享密钥和账户的共享密钥不一致

21005 订单服务器当前不可用

21006 订单是有效的,但订阅服务已经过期。当收到这个信息时,解码后的收据信息也包含在返回内容中

21007 订单信息是测试用(sandbox),但却被发送到产品环境中验证

21008 订单信息是产品环境中使用,但却被发送到测试环境中验证

*/

开发内购功能,首先需要一个开发者账号,在 App store connect -> 我的App -> 功能 中申请 如图:

有四种类型,主要看项目的需求而决定(自动续期订阅这个最为麻烦,要签署协议,而已在App 启动是请求苹果服务器,是否存在自动续期订单)

这个图是新增一项内购产品

参考名称:介绍这个内购产品

产品ID(主要用到的):支付的时候用到

其他的都是在app store 中看到的介绍

首先引用 #import <StoreKit/StoreKit.h>

封装一个内购功能,这个在app 中可能多个地方用到

+ (instancetype)shareIAPManager;

//添加内购产品
- (void)addPurchWithProductID:(NSString *)product_id completeHandle:(IAPCompletionHandleBlock)handle;
复制代码

SKProductsRequestDelegate代理方法
交易结束后用到

- (void)completeTransaction:(SKPaymentTransaction *)transaction {

    NSString * productIdentifier = transaction.payment.productIdentifier;
    NSData *data = [productIdentifier dataUsingEncoding:NSUTF8StringEncoding];
    NSString *receipt = [data base64EncodedStringWithOptions:0];

    YMLog(@"%@",receipt);
    if ([productIdentifier length] > 0) {
        // 向自己的服务器验证购买凭证
        NSURL *receiptURL = [[NSBundle mainBundle] appStoreReceiptURL];
        if (![[NSFileManager defaultManager] fileExistsAtPath:[receiptURL path]]) {
            // 取 receipt 的时候要判空,如果文件不存在,就要从苹果服务器重新刷新下载 receipt 了
            // SKReceiptRefreshRequest 刷新的时候,需要用户输入 Apple ID,同时需要网络状态良好
            SKReceiptRefreshRequest *receiptRefreshRequest = [[SKReceiptRefreshRequest alloc] initWithReceiptProperties:nil];
            receiptRefreshRequest.delegate = self;
            [receiptRefreshRequest start];
            return;
        }
        NSData *data = [NSData dataWithContentsOfURL:receiptURL];
        /** 交易凭证*/
        NSString *receipt_data = [data base64EncodedStringWithOptions:0];
        /** 事务标识符(交易编号)  交易编号(必传:防止越狱下内购被破解,校验 in_app 参数)*/
        NSString *transaction_id = transaction.transactionIdentifier;
        NSString *goodID = transaction.payment.productIdentifier;

        //这里缓存receipt_data,transaction_id 因为后端做校验的时候需要用到这两个字段
        YMLog(@"%@",receipt_data);
        YMLog(@"%@",transaction_id);

        [self retquestApplePay:receipt_data transaction_id:transaction_id goodsID:goodID];
    }
    [self verifyPurchaseWithPaymentTransaction:transaction isTestServer:NO];
}
复制代码
  • (void)completeTransaction:(SKPaymentTransaction *)transaction ;

中 获取

NSString * productIdentifier = transaction.payment.productIdentifier;

NSData *data = [productIdentifier
dataUsingEncoding:NSUTF8StringEncoding];

NSString *receipt = [data base64EncodedStringWithOptions:0];

NSString *receipt_data = [data base64EncodedStringWithOptions:0];

/** 事务标识符(交易编号) 交易编号(必传:防止越狱下内购被破解,校验 in_app 参数)*/

NSString *transaction_id = transaction.transactionIdentifier;

NSString *goodID = transaction.payment.productIdentifier;

得到的 transaction_id receipt_data goodID需要上传到app 服务器校验(具体看后端的需求)

//private 提交订单数据到app 服务器校验

- (void)retquestApplePay:(NSString *)receipt_data transaction_id:(NSString *)transaction_id goodsID:(NSString *)goodsId;
复制代码

// 交易失败

- (void)failedTransaction:(SKPaymentTransaction *)transaction{
    if (transaction.error.code != SKErrorPaymentCancelled) {
        [self handleActionWithType:IAPPurchFailed data:nil];
    }else{
        [self handleActionWithType:IAPPurchCancel data:nil];
    }
    [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
}

#pragma mark -- 结束上次未完成的交易 防止串单
-(void)removeAllUncompleteTransactionBeforeStartNewTransaction{
    NSArray* transactions = [SKPaymentQueue defaultQueue].transactions;
    if (transactions.count > 0) {
        //检测是否有未完成的交易
        SKPaymentTransaction* transaction = [transactions firstObject];
        if (transaction.transactionState == SKPaymentTransactionStatePurchased) {
            [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
            return;
        }
    }
}复制代码

IAPDemo链接:Demo

我的掘金:https://juejin.im/post/5dca8b526fb9a04a8e3be109

原文地址:https://www.cnblogs.com/ljj-Andrew-519/p/11847045.html

时间: 2024-10-11 18:23:18

iOS App 内购 Demo的相关文章

iOS应用内购常见问题及注意事项

如果您在实现和测试iOS应用内购的时候遇到问题,可以逐一对照下面所列出的条目,并逐一进行检查.相信可以排除大部分的错误. 1.您是否在iOS Dev Center中打开了对应应用AppID的In-App Purchases功能?登陆iOS Dev Center的Certificates, Identifiers & Profiles下,在Identifiers中找到正在开发的App,In-App Purchase一项应当显示Enabled(如果使用Xcode5,可以直接在Xcode的Capabi

苹果开发——App内购以及验证store的收据(一)

原地址:http://zengwu3915.blog.163.com/blog/static/27834897201375105236580?suggestedreading 发了几天时间在网上折腾了几天,终于把App内购给弄好了.分享一下个人经验 一. 在iTunesConnect中创建内购的App,然后为这个App设置一些产品(付费道具等) 打开iTunesConnect网站https://itunesconnect.apple.com/WebObjects/iTunesConnect.wo

苹果开发——App内购以及验证store的收据(二)

原地址:http://zengwu3915.blog.163.com/blog/static/2783489720137605156966?suggestedreading 三. 客户端使用StoreKit完成内购 添加Storekit.Framework,编写自己的storeObsever,用于处理交易,代码如下,其中completeTransaction和failedTransaction两个函数是自定义的用来处理交易成功与失败其它的就都是SKPaymentTransactionObserv

app内购提示,您已购买此商品,但为下载

出现这样的问题,是支付没有finish造成的,一般在支付过程中断网了,下次再购买同一商品的时候就会出现这样的问题, 解决办法,在点击购买的时候判断支付队列中是否有为finish的商品,若有,则进行处理之后将其finish NSArray* transactions = [SKPaymentQueue defaultQueue].transactions; if (transactions.count > 0) { //检测是否有未完成的交易 SKPaymentTransaction* trans

iOS应用内购基本步骤及问题

公司最近让做一个iOS内购的demo,贴出大致的过程 首先准备一个99$的苹果开发者账号,299$不能使用应用内购 首先登录苹果开发者中心,创建app ID,开启应用内购的功能 https://developer.apple.com/account/ios/identifiers/bundle/bundleList.action 进入iTunes connect: https://itunesconnect.apple.com/WebObjects/iTunesConnect.woa 登录后,进

ios IAP 内购验证

参考我之前的笔记 苹果内购笔记,在客户端向苹果购买成功之后,我们需要进行二次验证. 二次验证 IOS在沙箱环境下购买成功之后,向苹果进行二次验证,确认用户是否购买成功. 当应用向Apple服务器请求购买,成功之后,Apple会返回以下四个数据给应用 四个验证数据 productIdentifier:cosmosbox.strikehero.gems60 state: Purchased receipt: ewoJInNpZ25hdHVyZSIgPSAiQXF1M3JiR1grbmJMeGVvZS

iOS 应用内购(iAP)

国内银行CNAPS CODE 查询 http://weekend.blog.163.com/blog/static/746895820127961346724/ 在iTunesConnect创建内购商品时,为什么只有Free Subscription一种类型? http://www.oschina.net/question/865151_115660 在iTunesConnect创建内购商品时,为什么只有Free Subscription一种类型? 阿里百川梦想创业大赛,500万创投寻找最赞的A

IOS,苹果内购和添加广告

内购——应用内购买 通过苹果应用程序商店有三种主要赚钱的方式: 直接收费(与国内大部分用户的消费习惯相悖) 广告(降低用户体验 应用程序名称带Lite可以添加广告) O2O -> Online推广 & Offline交易,闭环 不要砍功能,增加内容,而不是增加功能 内购:应用程序本身的增值产品,游戏装备,应用程序中增值功能同样可以内购 第三方支付:跟应用程序无关的 内购分成:三(苹果)七(开发商)开 提示: 要做好游戏 & 应用,一定要研究心理,要研究哲学 人人都是产品经理 内购的五

苹果内购demo

1.倒入:StoreKit.framework库 2.代码 1 #import <UIKit/UIKit.h> 2 3 //导入库 4 #import <StoreKit/StoreKit.h> 5 @interface ViewController : UIViewController<SKProductsRequestDelegate,SKPaymentTransactionObserver> 6 @property (strong, nonatomic) IBOu