iOS学习专题

IOS内购开发(Objc和Swift)及漏单处理

2020-06-10  本文已影响0人  Hahn_z

Demo

demo是使用FMDB保存到本地(也可以使用归档等方法保存)
支付测试必须要使用真机
注意:在调用支付的过程比较慢,需要加入动画提示,不然可能被拒。

内购申请

进入https://appstoreconnect.apple.com

1.png

这个是填写银行卡等信息的(这里我已经填写了)、具体就不展示了


2.png

添加上面的信息了、需要等待苹果审核(最晚一天、如果一天还没有通过。请检查个人信息)
进入我的App添加内购项目


3.png

这里我选择消耗型的项目作为Demo


4.png

进入用户和访问、添加沙盒测试员


5.png

沙盒测试


5.jpeg

内购流程

内购流程

根据上图可以知道苹果内购结果回调是APP告诉应用服务器的。不是苹果服务器直接告诉应用服务器。这样可能出现漏单的情况。

比如说
网络不好的说话、没有告诉应用服务器结果
还没有应用服务器结果、用户关闭了APP等等情况。

处理方法

1.当支付成功的时候、把订单数据保存到本地。重新进入App的时候请求支付回调
//实现第一部的时候可以处理大部分漏单情况、但是还是没有办法避免漏单(用户删除了APP没有本地数据的情况等)
2.在创建预订单的时候保存下单时间等数据、可以让客服查询

Objc

#import "ViewController.h"
#import "SqlManager.h"
#import "ApplePayModel.h"

#import <StoreKit/StoreKit.h>

@interface ViewController ()<SKPaymentTransactionObserver,SKProductsRequestDelegate>
@property (nonatomic, strong) SKProductsRequest * request;
@end

@implementation ViewController

- (void)dealloc {

    NSLog(@"释放充值");
    if (self.request)
    {
        [self.request cancel];
    }
    [[NSNotificationCenter defaultCenter] removeObserver:self];
    [[SKPaymentQueue defaultQueue] removeTransactionObserver:self];
    
}

- (void)viewDidLoad {
    [super viewDidLoad];
    
    
    NSArray *array = [[SqlManager sharedManager] getAllApplePayModel];
    NSLog(@"数据库里面的数据 = %@",array);
    if (array.count > 0) {
        for (ApplePayModel *model in array) {
            NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithCapacity:0];
            [dict setObject:model.payData forKey:@"receiptData"];
            /**
             * 内购校验的Api(你的应用的api)
             */
        }
    }
}

# pragma mark 购买
- (IBAction)buyBtn:(id)sender {
    
    [[SKPaymentQueue defaultQueue] addTransactionObserver:self];
    if([SKPaymentQueue canMakePayments]){
        // 你的itunesConnect的商品ID
        [self getProductInfowithprotectId:@""];
    }else{
        NSLog(@"不允许程序内付费");
    }
    

}


#pragma mark -- 苹果内购服务,下面的ProductId应该是事先在itunesConnect中添加好的,已存在的付费项目。否则查询会失败。
- (void)getProductInfowithprotectId:(NSString *)proId
{
    NSMutableArray *proArr = [NSMutableArray new];
    [proArr addObject:proId];
    NSSet * set = [NSSet setWithArray:proArr];
    
    self.request = [[SKProductsRequest alloc] initWithProductIdentifiers:set];
    self.request.delegate = self;
    [self.request start];
    
    NSLog(@"%@",set);
    NSLog(@"请求开始请等待...");
}




//收到产品返回信息
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response{
    
    NSLog(@"--------------收到产品反馈消息---------------------");
    
    NSArray *product = response.products;
    
    NSLog(@"productID:%@", response.invalidProductIdentifiers);
    if(product.count==0){
        NSLog(@"查找不到商品信息");
        return;
    }

    SKProduct *p = nil;
    for(SKProduct *pro in product) {
        NSLog(@"%@", [pro description]);
        NSLog(@"%@", [pro localizedTitle]);
        NSLog(@"%@", [pro localizedDescription]);
        NSLog(@"%@", [pro price]);
        NSLog(@"%@", [pro productIdentifier]);
        
        if([pro.productIdentifier isEqualToString: [pro productIdentifier]]){
            p = pro;
        }
    }
    SKPayment *payment = [SKPayment paymentWithProduct:p];
    NSLog(@"发送购买请求");
    [[SKPaymentQueue defaultQueue] addPayment:payment];
}

//请求失败
- (void)request:(SKRequest *)request didFailWithError:(NSError *)error{
    NSLog(@"支付失败");
}

- (void)requestDidFinish:(SKRequest *)request{
    NSLog(@"支付调用完成");
}

//监听购买结果
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transaction{
    for(SKPaymentTransaction *tran in transaction){

        switch(tran.transactionState) {
            case SKPaymentTransactionStatePurchased:{ // 购买成功,此时要提供给用户相应的内容

                [[SKPaymentQueue defaultQueue] finishTransaction:tran];
                
                NSLog(@"购买成功 = %@", tran);
                
                NSURL *receiptUrl = [[NSBundle mainBundle] appStoreReceiptURL];
                NSData *receiptData = [NSData dataWithContentsOfURL:receiptUrl];
                NSString *receiptString = [receiptData base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithLineFeed];
                
                // 保存订单信息到数据库
                ApplePayModel *model = [ApplePayModel new];
                // 这里把订单ID写死了
                model.orderId = @"12345";
                model.payData = receiptString;
                
                [[SqlManager sharedManager] saveApplePayModel:model];

                    
                /**
                 * 请求校验API 请求完成删除数据库对应数据
                 */
//              [[SqlManager sharedManager] removeMotionModel:model];

                
                
                
            }
                break;
            case SKPaymentTransactionStatePurchasing: // 购买中,此时可更新UI来展现购买的过程
                break;
            case SKPaymentTransactionStateRestored:{ //恢复已购产品,此时需要将已经购买的商品恢复给用户
                [[SKPaymentQueue defaultQueue] finishTransaction:tran];
                
            }
                break;
            case SKPaymentTransactionStateFailed:{ // 购买错误,此时要根据错误的代码给用户相应的提示
                [[SKPaymentQueue defaultQueue] finishTransaction:tran];
                NSLog(@"购买失败");
            }
                break;
            default:
                break;
        }
    }
}

@end

Swift

import UIKit
import StoreKit

class ViewController: UIViewController {

    var request:SKProductsRequest! = nil
    
    override func viewDidLoad() {
        super.viewDidLoad()

        
        let array = SqlManager.shared().getAllApplePayModel()
        if array.count > 0 {
            for model in array {
                let mo:ApplePayModel = model as! ApplePayModel
                print(mo.orderId as Any)
                /**
                 * 内购校验的Api(你的应用的api)
                 */
            }
        }
    }
    
    deinit {
        print("释放充值")
        if (self.request != nil) {
            self.request.cancel()
        }
        
        NotificationCenter.default.removeObserver(self)
        SKPaymentQueue.default().remove(self)
    }

    // MARK:-购买
    @IBAction func buyBtn(_ sender: Any) {
        SKPaymentQueue.default().add(self)
        if SKPaymentQueue.canMakePayments() {
            // 你的itunesConnect的商品ID
            self.getProductInfow(proId: "")
        }else{
            print("不允许程序内付费")
        }
    }
    
}

extension ViewController: SKProductsRequestDelegate, SKPaymentTransactionObserver{
    
    // 苹果内购服务,下面的ProductId应该是事先在itunesConnect中添加好的,已存在的付费项目。否则查询会失败。
    func getProductInfow(proId:String){
        let proArr = NSMutableArray()
        proArr.add(proId)
        let set = NSSet(array: proArr as! [Any])
        
        self.request = SKProductsRequest(productIdentifiers: set as! Set<String>)
        self.request.delegate = self
        self.request.start()
        
        print("set")
        print("请求开始请等待...")
    }
    
    // 收到产品返回信息
    func productsRequest(_ request: SKProductsRequest, didReceive response: SKProductsResponse) {
        print("--------------收到产品反馈消息---------------------")
        let product = response.products;
        print("productID:\(response.invalidProductIdentifiers)")
        if product.count == 0 {
            print("查找不到商品信息")
            return
        }
        
        var p = SKProduct()
        for pro in product {
            print(pro.description)
            print(pro.localizedTitle)
            print(pro.localizedDescription)
            print(pro.price)
            print(pro.productIdentifier)
            
            if pro.productIdentifier == pro.productIdentifier {
                p = pro
            }
            
            let payment = SKPayment(product: p)
            print("发送购买请求")
            SKPaymentQueue.default().add(payment)
        }
        
    }
    
    func request(_ request: SKRequest, didFailWithError error: Error) {
        print("请求失败")
    }
    
    func requestDidFinish(_ request: SKRequest) {
        print("支付调用完成")
    }
    
    func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
        for tran in transactions {
            switch tran.transactionState {
            case .purchased: // 购买成功,此时要提供给用户相应的内容
                SKPaymentQueue.default().finishTransaction(tran)
                
                let model = ApplePayModel()
                model.orderId = "1234"
                model.payData = "1234"
                SqlManager.shared().saveApplePayModel(model: model)
                
                
                /**
                 * 请求校验API 请求完成删除数据库对应数据
                 */
//                SqlManager.shared().removeMotionModel(model: model)
                
                break
                
            case .purchasing: // 购买中,此时可更新UI来展现购买的过程
                break
            
            case .restored: // 恢复已购产品,此时需要将已经购买的商品恢复给用户
                SKPaymentQueue.default().finishTransaction(tran)
                break
            
            case .failed: // 购买错误,此时要根据错误的代码给用户相应的提示
                SKPaymentQueue.default().finishTransaction(tran)
                print("购买失败")
                break
                
            default:
                break
            }
        }
    }
    

    
}

Demo

demo是使用FMDB保存到本地(也可以使用归档等方法保存)

上一篇下一篇

猜你喜欢

热点阅读