码迷,mamicode.com
首页 > 移动开发 > 详细

iOS应用内支付

时间:2015-08-03 22:23:05      阅读:339      评论:0      收藏:0      [点我收藏+]

标签:

IOS 内支付有两种模式:

 1) 内置模式

2) 服务器模式

内置模式的流程可以简单的总结为以下几步:

 1) app从app store 获取产品信息

2) 用户选择需要购买的产品

 3) app发送支付请求到app store

4) app store 处理支付请求,并返回transaction信息

5) app将购买的内容展示给用户

 服务器模式的主要流程如下所示:

1) app从服务器获取产品标识列表

2) app从app store 获取产品信息

3) 用户选择需要购买的产品

4) app 发送 支付请求到app store

5) app store 处理支付请求,返回transaction信息

6) app 将transaction receipt 发送到服务器

7) 服务器收到收据后发送到app stroe验证收据的有效性

8) app store 返回收据的验证结果 

9) 根据app store 返回的结果决定用户是否购买成功

 

二.示例代码

//使用应用支付,客户端部分操作

#import "ViewController.h"

#import <StoreKit/StoreKit.h>

 @interface ViewController ()<SKProductsRequestDelegate, SKPaymentTransactionObserver>

@end

 @implementation ViewController

- (void)viewDidLoad {

    [super viewDidLoad];

    [self payment];

    //7.在viewDidLoad中,将购买页面设置成购买的Observer  遵循SKPaymentTransactionObserver协议

    [[SKPaymentQueue defaultQueue] addTransactionObserver:self];

}

 

-(void)dealloc

{

    [[SKPaymentQueue defaultQueue] removeTransactionObserver:self];

}

 

-(void)payment

{

    //1.导入Store.framework,引入头文件#import <StoreKit/StoreKit.h>

    //2.获得付费的Product ID 列表,本地或者服务器。

    //3.制作界面,展示付费项目。从自己服务器或者从App Store查询获得,但是从App Store需要2到3秒,建议从自己服务器

    //4.用户点击一个IPA(iOS应用内付费)项目,查询用户是否允许应用内付费

    if([SKPaymentQueue canMakePayments]){

        //5.通过Product ID 向App Store查询,获得SKPayment实例。然后通过SKPaymentQueue的addPayment方法发起一个购买操作.

        [self getProductInfo];

    }else{

        NSLog(@"用户禁止应用内付费");

    }

    

}

 

//5.示例代码

-(void)getProductInfo

{

    NSSet *set = [NSSet setWithArray:@[@"ProductId"]];

    SKProductsRequest *request = [[SKProductsRequest alloc]initWithProductIdentifiers:set];

    request.delegate = self;//遵循代理SKProductsRequestDelegate

    [request start];

}

 

//6.查询的回调函数

#pragma mark -SKProductsRequestDelegate的回调函数

-(void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response

{

    NSArray *myProduct = response.products;

    if (myProduct && myProduct.count > 0) {

        SKPayment *payment = [SKPayment paymentWithProduct:myProduct[0]];

        [[SKPaymentQueue defaultQueue] addPayment:payment];

    }else{

        NSLog(@"无法获得产品信息,购买失败");

    }

}

 

//8.用户操作有结果时,就会触发下面的回调函数

#pragma mark -SKPaymentTransactionObserver的回调函数

-(void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions

{

    for (SKPaymentTransaction *transaction in transactions) {

        switch (transaction.transactionState)

        {

            case SKPaymentTransactionStatePurchased://交易完成

            {

                [self completeTransaction:transaction];

                break;

            }

            case SKPaymentTransactionStateFailed://交易失败

            {

                [self failedTransaction:transaction];

                break;

            }

            case SKPaymentTransactionStateRestored://已经购买过该商品

            {

                [self restoredTransaction:transaction];

                break;

            }

            case SKPaymentTransactionStatePurchasing://商品已经添加进列表

            {

                break;

            }

//                case SKPaymentTransactionStateDeferred://iOS8新增

            default:

                break;

        }

    }

}

#pragma mark -transactionState的对应操作

-(void)completeTransaction:(SKPaymentTransaction *)transaction

{

    NSString *productIdentifier = transaction.payment.productIdentifier;

    NSString *receipt = [transaction.transactionReceipt base64Encoding];

    if ([productIdentifier length] > 0) {

         //服务端操作

        //向自己的服务器验证购买凭证

        //8.服务器验证凭证(可选项)。如果购买成功,我们需要将凭证发送到服务器上进行验证。考虑网络异常,存入沙盒进行恢复重试。

        //8.1 接收iOS端发送过来的购买凭证transactionReceipt iOS7废弃,

#warning transactionReceipt iOS7废弃

        //8.2 判断凭证是否已经存在,是否验证过,然后存储该凭证

        //8.3 将该凭证发送到苹果的服务器验证,并将验证结果返回给客户端

        //8.4 如果需要,修改用户相应的会员权限

    }

    //从SKPaymentQueue移除交易

    [[SKPaymentQueue defaultQueue] finishTransaction:transaction];

}

-(void)failedTransaction:(SKPaymentTransaction *)transaction

{

    if (transaction.error.code != SKErrorPaymentCancelled) {

        NSLog(@"购买失败");

    }else{

        NSLog(@"用户取消");

    }

    //从SKPaymentQueue移除交易

    [[SKPaymentQueue defaultQueue] finishTransaction:transaction];

}

-(void)restoredTransaction:(SKPaymentTransaction *)transaction

{

    //对于已经购买的商品,处理恢复购买的逻辑

    [[SKPaymentQueue defaultQueue]finishTransaction:transaction];

   

}

三.解决iOS7以后废弃transactionReceipt的办法

if (floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_6_1) {

     // iOS 6.1 or earlier.

    // Use SKPaymentTransaction‘s transactionReceipt.

} else {

    // iOS 7 or later.

    NSURL *receiptFileURL = nil;

    NSBundle *bundle = [NSBundle mainBundle];

    if ([bundle respondsToSelector:@selector(appStoreReceiptURL)]) {

        // Get the transaction receipt file path location in the app bundle.

        receiptFileURL = [bundle appStoreReceiptURL];

        // Read in the contents of the transaction file.

    } else {

        // Fall back to deprecated transaction receipt,

        // which is still available in iOS 7.

        // Use SKPaymentTransaction‘s transactionReceipt.

    }

}

四.注意事项

在开发过程中,需要测试应用是否能够正常的进行支付,但是又不能进行实际的支付,因此需要使用苹果提供的sandbox Store测试。Store Kit不能在iOS模拟器中使用,测试Store必须在真机上进行。苹果审核app时,仍然在沙盒环境下测试。在app提交苹果审核时,不能将issandbox字段写死。

 

iOS应用内支付

标签:

原文地址:http://www.cnblogs.com/booksky/p/4700426.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!