iOS内购代码(苹果支付ApplePay)

iOS内购代码(苹果支付ApplePay),第1张

概述转载注明出处:https://www.jianshu.com/p/8c958e75f98f刚刚做了内购, 记录一下这里直接上代码, 至于写代码之前的一些设置工作参考以下文章:http://www.jianshu.com/p/690a7c68664ehttp://www.jianshu.com/p/86ac7d3b593a需要注意的是:只要工程配置了对应的证书, 就能请求商品信息, 不...

转载注明出处:https://www.jianshu.com/p/8c958e75f98f

刚刚做了内购,记录一下
这里直接上代码,至于写代码之前的一些设置工作参考以下文章:
http://www.jianshu.com/p/690a7c68664e
http://www.jianshu.com/p/86ac7d3b593a

需要注意的是:

只要工程配置了对应的证书,就能请求商品信息,不需要任何其他处理沙盒测试填写的邮箱不能是已经绑定appleID的邮箱,也不能是AppleID的救援邮箱,其他的无所谓,其实,哪怕你填写的邮箱不存在也没有关系
////  IAPManager.m//  SpeakEnglish////  Created by DanIEl on 16/6/8.//  copyright © 2016年 DanIEl. All rights reserved.//#import "IAPManager.h"#import <StoreKit/StoreKit.h>@interface IAPManager ()<SKPaymentTransactionObserver,SKProductsRequestDelegate>// 所有商品@property (nonatomic,strong)NSArray *products;@property (nonatomic,strong)SKProductsRequest *request;@endstatic IAPManager *manager = nil;@implementation IAPManager+ (instancetype)shaReiaPManager {    static dispatch_once_t oncetoken;    dispatch_once(&oncetoken,^{        manager = [self new];        [[SKPaymentQueue defaultQueue] addTransactionObserver:manager];    });    return manager;}- (voID)dealloc {    [[SKPaymentQueue defaultQueue] removeTransactionObserver:self];}// 请求可卖的商品- (voID)requestProducts{    if (![SKPaymentQueue canMakePayments]) {        // 您的手机没有打开程序内付费购买        return;    }        // 1.请求所有的商品ID    Nsstring *productfilePath = [[NSBundle mainBundle] pathForResource:@"iapdemo.pList" ofType:nil];    NSArray *products = [NSArray arrayWithContentsOffile:productfilePath];        // 2.获取所有的productID     NSArray *productIDs = [products valueForKeyPath:@"productID"];        // 3.获取productID的set(集合中)    NSSet *set = [NSSet setWithArray:productIDs];        // 4.向苹果发送请求,请求可卖商品    _request = [[SKProductsRequest alloc] initWithProductIDentifIErs:set];    _request.delegate = self;    [_request start];}/** *  当请求到可卖商品的结果会执行该方法 * *  @param response response中存储了可卖商品的结果 */- (voID)productsRequest:(SKProductsRequest *)request dIDReceiveResponse:(SKProductsResponse *)response{     for (SKProduct *product in response.products) {    // 用来保存价格    NSMutableDictionary *priceDic = @{}.mutablecopy;    // 货币单位    NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init];    [numberFormatter setFormatterBehavior:NSNumberFormatterBehavior10_4];    [numberFormatter setNumberStyle:NSNumberFormatterCurrencyStyle];    [numberFormatter setLocale:product.priceLocale];    // 带有货币单位的价格    Nsstring *formattedPrice = [numberFormatter stringFromNumber:product.price];        [priceDic setobject:formattedPrice forKey:product.productIDentifIEr];     NSLog(@"价格:%@",product.price);     NSLog(@"标题:%@",product.localizedTitle);     NSLog(@"秒速:%@",product.localizedDescription);     NSLog(@"productID:%@",product.productIDentifIEr);     }         // 保存价格列表    [[NSUserDefaults standardUserDefaults] setobject:priceDic forKey:@"priceDic"];    [[NSUserDefaults standardUserDefaults] synchronize];        // 1.存储所有的数据    self.products = response.products;    self.products = [self.products sortedArrayWithOptions:NSSortConcurrent usingComparator:^NSComparisonResult(SKProduct *obj1,SKProduct *obj2) {        return [obj1.price compare:obj2.price];    }];}#pragma mark - 购买商品- (voID)buyProduct:(SKProduct *)product{    // 1.创建票据    SKPayment *payment = [SKPayment paymentWithProduct:product];    WELog(@"productIDentifIEr----%@",payment.productIDentifIEr);        // 2.将票据加入到交易队列中    [[SKPaymentQueue defaultQueue] addPayment:payment];}#pragma mark - 实现观察者回调的方法/** *  当交易队列中的交易状态发生改变的时候会执行该方法 * *  @param transactions 数组中存放了所有的交易 */- (voID)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions{    /*     SKPaymentTransactionStatePurchasing,正在购买     SKPaymentTransactionStatePurchased,购买完成(销毁交易)     SKPaymentTransactionStateFailed,购买失败(销毁交易)     SKPaymentTransactionStateRestored,恢复购买(销毁交易)     SKPaymentTransactionStateDeferred 最终状态未确定     */    for (SKPaymentTransaction *transaction in transactions) {        switch (transaction.transactionState) {            case SKPaymentTransactionStatePurchasing:                WELog(@"用户正在购买");                break;                            case SKPaymentTransactionStatePurchased:                WELog(@"productIDentifIEr----->%@",transaction.payment.productIDentifIEr);                [self buySuccessWithPaymentQueue:queue Transaction:transaction];                break;                            case SKPaymentTransactionStateFailed:                NSLog(@"购买失败");                [queue finishTransaction:transaction];                break;                            case SKPaymentTransactionStateRestored:                NSLog(@"恢复购买");                //Todo:向服务器请求补货,服务器补货完成后,客户端再完成交易单子                //[queue finishTransaction:transaction];                break;                            case SKPaymentTransactionStateDeferred:                NSLog(@"最终状态未确定");                break;                            default:                break;        }    }}- (voID)buySuccessWithPaymentQueue:(SKPaymentQueue *)queue Transaction:(SKPaymentTransaction *)transaction {        AFhttpSessionManager *manager = [AFhttpSessionManager manager];    NSDictionary *params = @{@"user_ID":@"user_ID",// 获取商品                             @"goods":[self goodsWithProductIDentifIEr:transaction.payment.productIDentifIEr]};        [manager POST:@"url" parameters:params success:^(NSURLSessionDataTask *task,ID responSEObject) {                if ([responSEObject[@"code"] intValue] == 200) {                        // 防止丢单,必须在服务器确定后从交易队列删除交易            // 如果不从交易队列上删除交易,下次调用addTransactionObserver:,仍然会回调'updatedTransactions'方法,以此处理丢单                        WELog(@"购买成功");            [queue finishTransaction:transaction];        }            } failure:^(NSURLSessionDataTask *task,NSError *error) {            }];}// 商品列表 也可以使用从苹果请求的数据,具体细节自己视情况处理// goods1 是商品的ID- (Nsstring *)goodsWithProductIDentifIEr:(Nsstring *)productIDentifIEr {    NSDictionary *goodsDic = [[NSUserDefaults standardUserDefaults] objectForKey:@"priceDic"];    return goodsDic[productIDentifIEr];}// 恢复购买- (voID)restore{    [[SKPaymentQueue defaultQueue] restoreCompletedTransactions];}- (voID)paymentQueue:(SKPaymentQueue *)queue restoreCompletedTransactionsFailedWithError:(NSError *)error {    // 恢复失败    WELog(@"恢复失败");}// 取消请求商品信息- (voID)dealloc {    [_request cancel];}@end

补充:

对于丢单的交易,在执行初始化[[SKpaymentQueue defaultQueue] addTransactionObserver: self] 的时候,如果有未完成的交易,会直接回调updatedTransactions,并且进入case SKPaymentTransationStateRestored,此时把这些未完成的交易告知服务器进行补货,补货完成再通知客户端,客户端再执行completeTransaction关闭单子

总结:
内购有三个可能出现的问题

支付成功后,没来得及向服务器发送交易成功的数据就退出应用,导致丢单. 这个问题貌似不需要本地化数据也已经没问题了,除非再次回调updatedTransactions方法时已经拿不到票据了,这样才有必要本地存储票据.无法绑定交易和对应的用户. 因为applicationUsername的存在这已经不是问题了.只用别人的手机进行购买,导致丢单. 如果别人再也不打开这个应用甚至删掉了,目前看来,没有办法解决

参考资料:

苹果内购二次验证 PHP代码
http://my.oschina.net/qianglong/blog/503861

in-app Purchase Programming GuIDe
https://developer.apple.com/library/prerelease/content/documentation/NetworkingInternet/Conceptual/StoreKitGuide/Introduction.html#//apple_ref/doc/uid/TP40008267

iPhone In App Purchase购买完成时验证transactionReceipt
http://www.cnblogs.com/eagley/archive/2011/06/15/2081577.html

 

总结

以上是内存溢出为你收集整理的iOS内购代码(苹果支付ApplePay)全部内容,希望文章能够帮你解决iOS内购代码(苹果支付ApplePay)所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/999299.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-21
下一篇 2022-05-21

发表评论

登录后才能评论

评论列表(0条)

保存