支付篇——内购(IAP)详解
2018-10-31 本文已影响15人
iOS祎
流程
1.注册app,填写协议、税务和银行业务
注册app,需要唯一设置Bundle identifier,然后详细填写协议、税务和银行业务,此个步骤这里就不在写了
2.内购商品的添加
我的App—>准提交的项目—>功能—>App内购买项目:添加内购商品信息
3.添加沙盒测试账号
iTunes Connect —>用户和职能 —>沙盒测试技术员:添加沙盒测试账号
4.代码实现过程
写了一个购买的单例
@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 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];
}