iOS开发支付篇——内购(IAP)详解

iOS开发支付篇——内购(IAP)详解

苹果客户端购买虚拟商品是需要走内购

先看gif图
在这里插入图片描述
具体步骤:

  • 协议、税务和银行业务 信息填写
  • 内购商品的添加
  • 添加沙盒测试账号
  • 内购代码的具体实现
  • 内购的注意事项
    流程
    1.注册app,填写协议、税务和银行业务
    注册app,需要唯一设置Bundle identifier,然后详细填写协议、税务和银行业务,此个步骤这里就不在写了(【官方地址】(https://developer.apple.com/library/archive/technotes/tn2259/_index.html#//apple_ref/doc/uid/DTS40009578))。
    2.内购商品的添加
    我的App—>准提交的项目—>功能—>App内购买项目:添加内购商品信息
    3.添加沙盒测试账号
    iTunes Connect —>用户和职能 —>沙盒测试技术员:添加沙盒测试账号
    4.代码实现过程
    写了一个购买的单例
//
//  VistaInAppPurchaseManager.h
//  vista.homework
//
//  Created by htkj on 2018/9/17.
//  Copyright © 2018年 vista. All rights reserved.
#import <Foundation/Foundation.h>
#import <StoreKit/StoreKit.h>
@protocol VistaInAppPurchaseManagerDelegate <NSObject>
//接收到商品信息
-(void)receiveProductInfo:(SKProduct *)product;
//购买成功反馈
-(void)successfulPurchaseOfId:(NSString *)productID andReceipt:(NSData *)transactionReceipt;
//购买失败反馈
-(void)failedPurchaseWithError:(NSString *)errorDescripiton;
@end

@interface VistaInAppPurchaseManager : NSObject
@property (nonatomic, weak)id<VistaInAppPurchaseManagerDelegate> delegate;
//单例
+(instancetype)sharedInstance;
/*
 *  请求商品信息,productID 商品ID
*/
-(void)requestProductWithID:(NSString *)productID;
/*
 * 购买商品
 */
-(BOOL)purchaseProudct:(SKProduct *)skProduct;
@end
//
//  VistaInAppPurchaseManager.m
//  vista.homework
//
//  Created by htkj on 2018/9/17.
//  Copyright © 2018年 vista. All rights reserved.
//

#import "VistaInAppPurchaseManager.h"

@interface VistaInAppPurchaseManager ()<SKProductsRequestDelegate, SKPaymentTransactionObserver>


@end

@implementation VistaInAppPurchaseManager
{
    SKProduct *myProduct;
    
}


static VistaInAppPurchaseManager *manager = nil;

+(instancetype)sharedInstance{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        if (manager == nil) {
            manager = [[VistaInAppPurchaseManager alloc]init];
        }
        
    });
    return manager;
}

#pragma mark ------  public Methods
-(void)requestProductWithID:(NSString *)productID{
    if (productID.length > 0) {
        SKProductsRequest *productRequest = [[SKProductsRequest alloc]initWithProductIdentifiers:[NSSet setWithObject:productID]];
        productRequest.delegate = self;
        [productRequest start];
        
    }else{
        
        NSLog(@"productID为空");
    }
    
    
}

-(BOOL)purchaseProudct:(SKProduct *)skProduct{
   
    if (skProduct != nil) {
        if ([SKPaymentQueue canMakePayments]) {
            SKPayment *payment = [SKPayment paymentWithProduct:skProduct];
            [[SKPaymentQueue defaultQueue] addTransactionObserver:self];
            [[SKPaymentQueue defaultQueue] addPayment:payment];
            return YES;
        }else{
            NSLog(@"失败,用户禁止应用内付费购买.");
        }
    }
    return NO;
}

#pragma mark ------  SKProductsRequestDelegate

-(void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response{
    NSArray *productArr = response.products;
    if (productArr.count > 0) {
        myProduct = [productArr objectAtIndex:0];
        [_delegate receiveProductInfo:myProduct];
    }else{
        NSLog(@"无法购买商品信息,购买失败");
        [_delegate receiveProductInfo:myProduct];
    }
}

#pragma mark ------  SKPaymentTransactionObserver

-(void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray<SKPaymentTransaction *> *)transactions{
    for (SKPaymentTransaction *transaction in transactions) {
        switch (transaction.transactionState) {
            case SKPaymentTransactionStatePurchasing://商品添加进列表
                NSLog(@"商品:%@被添加进购买列表",myProduct.localizedTitle);
                break;
            case SKPaymentTransactionStatePurchased://交易成功
                [self completeTransaction:transaction];
                break;
            case SKPaymentTransactionStateFailed://交易失败
                [self failedTransaction:transaction];
                NSLog(@"交易失败");
                //发送通知
                [[NSNotificationCenter defaultCenter] postNotificationName:@"failNotification" object:self userInfo:nil];
                break;
            case SKPaymentTransactionStateRestored://已购买过该商品
                break;
                
                case SKPaymentTransactionStateDeferred://交易延迟
            default:
                break;
        }
    }
}


#pragma mark ---- private Methods

-(void)completeTransaction:(SKPaymentTransaction *)transaction{
    NSURL *receiptUrl = [[NSBundle mainBundle] appStoreReceiptURL];
    NSData *receiptData = [NSData dataWithContentsOfURL:receiptUrl];
    [_delegate successfulPurchaseOfId:transaction.payment.productIdentifier andReceipt:receiptData];
//   [[NSUserDefaults standardUserDefaults] setObject:receiptData forKey:@"receiptData"];
//    [[NSUserDefaults standardUserDefaults] synchronize];
    [[SKPaymentQueue defaultQueue]finishTransaction:transaction];
}

- (void)failedTransaction:(SKPaymentTransaction *)transaction{
    if (transaction.error.code != SKErrorPaymentCancelled && transaction.error.code != SKErrorUnknown) {
        [_delegate failedPurchaseWithError:transaction.error.localizedDescription];
    }
    [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
}

-(void)dealloc{
    [[SKPaymentQueue defaultQueue] removeTransactionObserver:self];
}

@end

导入单例
#import “VistaInAppPurchaseManager.h”
设置代理
VistaInAppPurchaseManagerDelegate
点击充值按钮事件

-(void)commitBtnClick{
    [self createhui];
    [MBProgressHUD showLoadToView:self.view title:@"支付中,请勿关闭App"];
    NSString *productID = nil;
    switch (purchaseType) {
        case 0:
            productID = @"Vista_coin_1";
            break;
        case 1:
            productID = @"Vista_coin_6";
            break;
        case 2:
            productID = @"Vista_coin_18";
            break;
        case 3:
            productID = @"Vista_coin_30";
            break;
        case 4:
            productID = @"Vista_coin_68";
            break;
        case 5:
            productID = @"Vista_coin_108";
            break;
        case 6:
            productID = @"Vista_coin_208";
            break;
        case 7:
            productID = @"Vista_coin_388";
            break;
        case 8:
            productID = @"Vista_coin_698";
            break;
        default:
            break;
    }
    if (productID == nil) {
        Hidden
        return;
    }
    [self.payManager requestProductWithID:productID];
}

代理方法

#pragma mark -----   VistaInAppPurchaseManagerDelegate
//购买商品回调
-(void)receiveProductInfo:(SKProduct *)product{
    Hidden
    if (product != nil) {
        if (![self.payManager purchaseProudct:product]) {
            UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"失败" message:@"您禁止了应用内购买权限,请到设置中开启" delegate:self cancelButtonTitle:@"关闭" otherButtonTitles:nil, nil];
            [alert show];
        }
        NSLog(@"SKProduct 描述信息%@", [product description]);
        NSLog(@"产品标题 %@" , product.localizedTitle);
        NSLog(@"产品描述信息: %@" , product.localizedDescription);
        NSLog(@"价格: %@" , product.price);
        NSLog(@"Product id: %@" , product.productIdentifier);
    }else{
        UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@"失败" message:@"无法连接App store!" delegate:self cancelButtonTitle:@"关闭" otherButtonTitles:nil, nil];
        [alert show];
    }
     [self hidden];
}
#pragma mark-VistaInAppPurchaseManagerDelegate
//成功回调
//附加:官方文档:向苹果校验支付结果https://developer.apple.com/library/content/releasenotes/General/ValidateAppStoreReceipt/Chapters/ValidateRemotely.html
-(void)successfulPurchaseOfId:(NSString *)productID andReceipt:(NSData *)transactionReceipt{
    NSString *transactionReceiptString = [transactionReceipt base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithLineFeed];
    NSDictionary *dict = @{@"receipt-data":transactionReceiptString};
    NSString *str=[self conData11:dict];
    //上传支付凭证到后台
        NSDictionary *json = @{@"receipt":str};
        NSDictionary *Json=@{@"code":@"5077",@"payload":[HHCommon convertToJsonData:json],@"token":personalToken};
        [HTTPRequestManager postNetworkRequestWithUrlString:Com parameters:Json succeed:^(id data) {
            if ([data[@"code"] integerValue]==0&&[data[@"payload"][@"status"] integerValue]==0) {
                 [PHAlertView showTitle:@"充值成功!" message:@"" surnBtnTitle:@"确定" result:nil];
                [self loadmoney];
                [[NSUserDefaults standardUserDefaults] removeObjectForKey:@"receiptData"];
            }else{
                NSLog(@"%@",data[@"message"]);
            }
        } fail:^(NSError *error) {
    
        }];
}
//失败回调
- (void)failedPurchaseWithError:(NSString *)errorDescripiton {
    NSLog(@"购买失败");
    UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@"失败" message:errorDescripiton delegate:self cancelButtonTitle:@"关闭" otherButtonTitles:nil, nil];
    [alert show];
    
}

  • 8
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值