美文网首页
ios 内购

ios 内购

作者: 洒一地阳光_217d | 来源:发表于2019-03-04 22:35 被阅读0次

首先要引入#import <StoreKit/StoreKit.h>
本文介绍的是有服务器的情况下,已经从服务器获取到了productId

#import <StoreKit/StoreKit.h>
#import "IapManager.h"

@implementation IapManager {
    NSMutableDictionary *products;
}

static IapManager *_instance;

+ (IapManager *)instance {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _instance = [[IapManager alloc] init];
    });
    
    return _instance;
}

- (id) init {
    self = [super init];

    products = [[NSMutableDictionary alloc] init];
    return self;
}

/**
* productId: 已经从服务器获取到了productId
* outTradeNo: 服务器自己构建的校验订单
*/
+ (void)iapPay:(NSString *)productId
    outTradeNo:(NSString *)outTradeNo {
    [[IapManager instance] iapPay:productId
                       outTradeNo:outTradeNo];
}

/**
 * 执行实际的支付逻辑
 */
- (void)iapPay:(NSString *)productId
    outTradeNo:(NSString *)outTradeNo {
    
    if (productId == nil || outTradeNo == nil) {
        NSLog(@"iap pay fail, invalid parameter.");
        // 此处应该通知客户端
        return;
    }
    
    if (![SKPaymentQueue canMakePayments]) {
        NSLog(@"iap pay fail, can not make payments.");
        NSLog(@"失败,用户禁止应用内付费购买.");
        // 此处应该通知客户端
        return;
    }
    
    SKProduct *product = nil;
    @synchronized (self) {
        product = products[productId];
    }
    
    if (product == nil) {
        NSLog(@"iap pay fail, no product info.");
        // 此处应该通知客户端
        return;
    }
    
    NSLog(@"iap start payment -> {productId:%@, outTradeNo:%@}",
          productId,
          outTradeNo);
    
    SKMutablePayment *payment = [SKMutablePayment paymentWithProduct:product];
    payment.quantity = 1;
    payment.applicationUsername = outTradeNo;
    [[SKPaymentQueue defaultQueue] addPayment:payment];
     NSLog(@"iap inprogress.");
}

/**
 * 监听Iap交易的状态
 */
- (void)paymentQueue:(SKPaymentQueue *)queue
 updatedTransactions:(NSArray *)transactions {
    NSLog(@"监听Iap交易的状态");
   
    for (SKPaymentTransaction *trans in transactions) {
        NSLog(@"%d",trans.error.code);

        switch (trans.transactionState) {
            case SKPaymentTransactionStatePurchased:
                     NSLog(@"交易ok");
                [self transactionSuccess:trans];
                break;
                
            case SKPaymentTransactionStatePurchasing:
                 NSLog(@"交易中");
                //[self transactionAbort:trans];
                // 正在支付中这个状态,会在刚刚发起支付,弹出用户名密码对话框的时候调用一次。
                break;
                
            case SKPaymentTransactionStateFailed:
                [self transactionFail:trans];
                break;
                
            case SKPaymentTransactionStateDeferred:
                     NSLog(@"交易deferred");
                // 这个状态应该是在出现家长监护的时候出现。
                break;
                
            case SKPaymentTransactionStateRestored:
                // 不存在不同设备间恢复的问题,因此直接结束当前的订单。
                [self transactionFinish:trans];
                break;
                
            default:
                // 不知名情况的订单,也直接结束掉。
                [self transactionFinish:trans];
                break;
        }
    }
}

/**
 * 交易成功。
 */
- (void)transactionSuccess:(SKPaymentTransaction *)trans {
    NSLog(@"交易成功");
    if (trans == nil) {
        return;
    }
    
    NSURL *receiptUrl = [[NSBundle mainBundle] appStoreReceiptURL];
    NSData *receipt = [NSData dataWithContentsOfURL:receiptUrl];
    NSString *receiptDataString = [receipt base64EncodedStringWithOptions:0];
    
    NSString *outTradeNo = trans.payment.applicationUsername;
    NSString *productId = trans.payment.productIdentifier;
 
    NSLog(@"注意transactionIdentifier %@",trans.transactionIdentifier);
    NSLog(@"iap pay success. productId:%@, outTradeNo:%@, receipt:%@",
          productId,
          outTradeNo,
          receiptDataString);
 
   // 此处应该通知客户端
    [[SKPaymentQueue defaultQueue] finishTransaction:trans];
}

/**
 * 交易失败
 */
- (void)transactionFail:(SKPaymentTransaction *)trans {
    NSLog(@"交易失败");
    if (trans == nil) {
        return;
    }
    
    NSString *outTradeNo = trans.payment.applicationUsername;
    NSString *productId = trans.payment.productIdentifier;
    
    NSLog(@"iap pay fail. productId:%@, outTradeNo:%@",
          productId,
          outTradeNo);

    // 此处应该通知客户端
    [[SKPaymentQueue defaultQueue] finishTransaction:trans];
}

/**
 * 交易完成
 */
- (void)transactionFinish:(SKPaymentTransaction *)trans {
    NSLog(@"交易结束");
    if (trans == nil) {
        return;
    }
    
    NSString *outTradeNo = trans.payment.applicationUsername;
    NSString *productId = trans.payment.productIdentifier;
    
    NSLog(@"iap pay finish. productId:%@, outTradeNo:%@",
          productId,
          outTradeNo);
   
    [[SKPaymentQueue defaultQueue] finishTransaction:trans];
}

相关文章

  • iOS 苹果内购流程

    本文参考: iOS开发之内购完全笔记 iOS开发内购全套图文教程 iOS应用程序内购/内付费(一) 代码...

  • iOS内购流程文档-Lion

    iOS内购流程: iOS内购 什么时候用到呢? 虚拟产品就需要用到iOS内购;购买的商品,是在本app中...

  • iOS-内购

    前言:关于iOS内购,参考两篇博文 iOS-iOS内购流程(手把手图文教程)iOS内购你看我就够了(埋坑篇) 我自...

  • iOS内购一条龙------项目代码 (4)

    步骤一 iOS内购一条龙------账户信息填写(1)步骤二 iOS内购一条龙------配置内购产品ID (2)...

  • iOS内购一条龙------内购测试账号 (3)

    步骤一 iOS内购一条龙------账户信息填写(1)步骤二 iOS内购一条龙------配置内购产品ID (2)...

  • iOS 内购 IAP

    1. iOS内购IAP(一) —— 基础配置篇(一)2. iOS内购IAP(二) —— 工程实践(一)3. iOS...

  • 应用内购(In-App Purchase)常见问题解答

    应用内购(In-App Purchase)常见问题解答iOS的应用内购买 iAP 坑 iOS内购你看我就够了(一)...

  • iOS内购从放弃到上架

    iOS内购方面的坑

  • ios内购IAP相关内容

    ios内购IAP相关内容 iOS IAP应用内购详细步骤和问题总结指南 - 简书https://www.jians...

  • 2019-05-20

    iOS内购编程指南 - 简书 iOS内购 服务端票据验证及漏单引发的思考. - WidgetBox - 博客园 一...

网友评论

      本文标题:ios 内购

      本文链接:https://www.haomeiwen.com/subject/ufgwuqtx.html