iOS 苹果内购详细步骤

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_22080737/article/details/79786500

一、设置协议等相关

1.点击协议、税务和银行业务。
这里写图片描述

2.点击 Request Contracts 下面的 Request,一直点击直到主协议界面。
这里写图片描述

主协议界面
这里写图片描述
Contact info :联系人信息
Bank info :银行信息
Tax info :税务信息

3.点击 Contact Info 下面的Set Up,设置联系人信息,然后点击 Add New Contract,添加新的联系信息。
这里写图片描述

4.填写完整并保存。
这里写图片描述

5.选择联系人,因为我是独立开发,所以填写的自己的,如果你是多人开发,你可以添加多个联系人。

Senior Management:高级管理人员
Financial :财务
Technical :技术支持
Legal :法务
Marketing :市场推广

添加完成之后,对应选择好就行。
这里写图片描述

6.点击 Bank Info 下的 Set Up,然后点击 Add Bank Account 添加银行账号。
这里写图片描述

点击 Select One,选择 China ,点击 next。
这里写图片描述

填写 CNAPS Code,点击 next。
这里写图片描述

CNAPS Code:中国现代化支付系统代码,又叫做联行号。可以从网上查询,也可以直接点击Look up CNAPS Code进行查询,再不济,也可以直接打电话咨询相应银行客服。

点击 next,核对一下,继续 next。

填写银行卡相关信息,点击 next。(持卡人姓名,如张三(Zhang San))
这里写图片描述

确认一下,点击 save 保存。
这里写图片描述

选择对应的银行卡,点击 save。
这里写图片描述

7.点击 Tax Info 下面的 Set Up,设置税务信息。

税务分三种:
U.S Tax Forms : 美国税务
Australia Tax Forms:澳大利亚税务
Canada Tax Forms : 加拿大税务

我们选择美国税务,点击 Done。
这里写图片描述

如果没有就选择 NO,点击 Submit。
这里写图片描述

如果没有就选择 NO。
这里写图片描述

填写完整,点击 Submit。
这里写图片描述

这里写图片描述

核对信息无误后提交,状态显示 Processing 表示成功。
这里写图片描述

二、创建项目的内购条目

1.进入 APP,点击功能。
这里写图片描述

根据情况选择,我选择的第一个。
这里写图片描述

填写内购项目信息,点击存储。
这里写图片描述

下面这些信息也要填完整,否则会提示元数据丢失(坑)。
这里写图片描述

注意:你 App 有几个内购级别就需要依次创建几个条目。
这里写图片描述

三、添加沙盒测试账号

1.点击用户和职能
这里写图片描述

2.点击沙盒技术测试员
这里写图片描述

3.点击 “+” 添加测试员,邮箱和密码用于支付的时候登陆 Apple ID。
这里写图片描述

四、代码集成

#import "ApplePayVC.h"
//导入
#import <StoreKit/StoreKit.h>

//遵循代理
@interface ApplePayVC ()
<
SKPaymentTransactionObserver,
SKProductsRequestDelegate
>

//支付按钮
@property (nonatomic, strong) UIButton *payBtn;

@end

@implementation ApplePayVC

- (void)viewDidLoad
{
    [super viewDidLoad];

    [self setupPayBtn];

    //设置支付服务
    [[SKPaymentQueue defaultQueue] addTransactionObserver:self];
}

#pragma mark - UI
- (void)setupPayBtn
{
    _payBtn = [UIButton buttonWithType:UIButtonTypeCustom];
    _payBtn.frame = CGRectMake(100, 100, 100, 100);
    _payBtn.backgroundColor = [UIColor redColor];
    [_payBtn setTitle:@"支付" forState:UIControlStateNormal];
    [_payBtn setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
    _payBtn.titleLabel.font = [UIFont systemFontOfSize:15.0];
    [_payBtn addTarget:self action:@selector(payBtnAction) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:_payBtn];
}

#pragma mark - BtnAction
- (void)payBtnAction
{
    //是否允许内购
    if ([SKPaymentQueue canMakePayments]) {
        NSLog(@"用户允许内购");

        //bundleid+xxx 就是你添加内购条目设置的产品ID
        NSArray *product = [[NSArray alloc] initWithObjects:@"bundleid+xxx",nil];
        NSSet *nsset = [NSSet setWithArray:product];

        //初始化请求
        SKProductsRequest *request = [[SKProductsRequest alloc] initWithProductIdentifiers:nsset];
        request.delegate = self;

        //开始请求
        [request start];

    }else{
        NSLog(@"用户不允许内购");
    }

}

#pragma mark - SKProductsRequestDelegate
//接收到产品的返回信息,然后用返回的商品信息进行发起购买请求
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response NS_AVAILABLE_IOS(3_0)
{
    NSArray *product = response.products;

    //如果服务器没有产品
    if([product count] == 0){
        NSLog(@"没有该商品");
        return;
    }

    SKProduct *requestProduct = nil;
    for (SKProduct *pro in product) {

        NSLog(@"%@", [pro description]);
        NSLog(@"%@", [pro localizedTitle]);
        NSLog(@"%@", [pro localizedDescription]);
        NSLog(@"%@", [pro price]);
        NSLog(@"%@", [pro productIdentifier]);

        //如果后台消费条目的ID与我这里需要请求的一样(用于确保订单的正确性)
        if([pro.productIdentifier isEqualToString:@"bundleid+xxx"]){
            requestProduct = pro;
        }
    }

    //发送购买请求
    SKMutablePayment *payment = [SKMutablePayment paymentWithProduct:requestProduct];
        payment.applicationUsername = userId;//可以是userId,也可以是订单id,跟你自己需要而定
    [[SKPaymentQueue defaultQueue] addPayment:payment];
}

#pragma mark - SKRequestDelegate
//请求失败
- (void)request:(SKRequest *)request didFailWithError:(NSError *)error
{
    NSLog(@"error:%@", error);
}

//请求结束
- (void)requestDidFinish:(SKRequest *)request
{
    NSLog(@"请求结束");
}

#pragma mark - SKPaymentTransactionObserver
//监听购买结果
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions
{
    for(SKPaymentTransaction *tran in transactions){
        switch (tran.transactionState) {
            case SKPaymentTransactionStatePurchased:
                NSLog(@"交易完成");
                [self completeTransaction:tran];

                break;
            case SKPaymentTransactionStatePurchasing:
                NSLog(@"商品添加进列表");

                break;
            case SKPaymentTransactionStateRestored:
                NSLog(@"已经购买过商品");
//                [[SKPaymentQueue defaultQueue] finishTransaction:tran]; 消耗型商品不用写

                break;
            case SKPaymentTransactionStateFailed:
                NSLog(@"交易失败");
                [[SKPaymentQueue defaultQueue] finishTransaction:tran];

                break;
            default:
                break;
        }
    }
}

//交易结束,当交易结束后还要去appstore上验证支付信息是否都正确,只有所有都正确后,我们就可以给用户方法我们的虚拟物品了。
- (void)completeTransaction:(SKPaymentTransaction *)transaction
{
    // 验证凭据,获取到苹果返回的交易凭据
    // appStoreReceiptURL iOS7.0增加的,购买交易完成后,会将凭据存放在该地址
    NSURL *receiptURL = [[NSBundle mainBundle] appStoreReceiptURL];
    // 从沙盒中获取到购买凭据
    NSData *receiptData = [NSData dataWithContentsOfURL:receiptURL];
    //发送POST请求,对购买凭据进行验证
    //测试验证地址:https://sandbox.itunes.apple.com/verifyReceipt
    //正式验证地址:https://buy.itunes.apple.com/verifyReceipt
    NSURL *url = [NSURL URLWithString:AppStore_URL];
    NSMutableURLRequest *urlRequest = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:15.0f];
    urlRequest.HTTPMethod = @"POST";
    NSString *encodeStr = [receiptData base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithLineFeed];
    _receipt = encodeStr;
    NSString *payload = [NSString stringWithFormat:@"{\"receipt-data\" : \"%@\"}", encodeStr];
    NSData *payloadData = [payload dataUsingEncoding:NSUTF8StringEncoding];
    urlRequest.HTTPBody = payloadData;

    NSData *result = [NSURLConnection sendSynchronousRequest:urlRequest returningResponse:nil error:nil];

    if (result == nil) {
        NSLog(@"验证失败");
        return;
    }

    NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:result options:NSJSONReadingAllowFragments error:nil];
    NSLog(@"请求成功后的数据:%@",dic);
    //这里可以通过判断 state == 0 验证凭据成功,然后进入自己服务器二次验证,,也可以直接进行服务器逻辑的判断。
    //本地服务器验证成功之后别忘了 [[SKPaymentQueue defaultQueue] finishTransaction: transaction];

    NSString *productId = transaction.payment.productIdentifier;
    NSString *applicationUsername = transaction.payment.applicationUsername;

    NSLog(@"applicationUsername++++%@",applicationUsername);
    NSLog(@"payment.productIdentifier++++%@",productId);

    if (dic != nil) {
        userId = applicationUsername;
        //服务器二次验证
        [self vertifyApplePayRequestWith:transaction];
    }
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}


注意:
1.内购必须用真机测试
2.测试时必须退出App Store自己的Apple ID,登录沙盒的测试Apple ID

猜你喜欢

转载自blog.csdn.net/qq_22080737/article/details/79786500