内购

作者: 失心F | 来源:发表于2023-01-11 17:22 被阅读0次

#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

//typedef NS_ENUM(NSUInteger, APTYPE) {
//    AP_WECHAT,
//    AP_ALIPAY,
//};


//@protocol APDelegate <NSObject>
//-(void)APSuccess:(APTYPE)type;
//-(void)APFail:(APTYPE)type;
//@end


static NSString * const USERDEFAULT_KEY = @"transaction";

typedef enum : NSUInteger {
    VTPaymentTransactionStateNoPaymentPermission,//没有Payment权限
    VTPaymentTransactionStateAddPaymentFailed,//addPayment失败
    VTPaymentTransactionStatePurchasing,//正在购买
    VTPaymentTransactionStatePurchased,//购买完成(销毁交易)
    VTPaymentTransactionStateFailed,//购买失败(销毁交易)
    VTPaymentTransactionStateCancel,//用户取消
    VTPaymentTransactionStateRestored,//恢复购买(销毁交易)
    VTPaymentTransactionStateDeferred,//最终状态未确定
} VTPaymentTransactionState;

@class SKPaymentTransaction;

@protocol VTInAppPurchasingDelegate <NSObject>

@required
- (BOOL)isProductIdentifierAvailable:(NSString*)productIdentifier;
@optional
- (void)updatedTransactions:(VTPaymentTransactionState)state;
//购买成功
- (void)buySuccess;
//购买失败
- (void)buyFailed:(NSString*)errorInfo;

@end



@interface APManager : NSObject

+(instancetype) shared;

@property(nonatomic,weak) id<VTInAppPurchasingDelegate> delegate;
- (void)identifyCanMakePayments:(NSArray*)requestArray;
//-(void)handleOpenURL:(NSURL *)url;
//-(void)sendOrder:(APTYPE)type Order:(NSDictionary *)order;

@end

NS_ASSUME_NONNULL_END
#import "APManager.h"
#import <StoreKit/StoreKit.h>
//#import "WXApi.h"
//#import <AlipaySDK/AlipaySDK.h>

//#define WECHAT @"pay"
//#define WECHATSCHEME @""
//#define ALIPAY @"safepay"
//#define ALIPAYSCHEME @"alipay"
//#define WX_AppID @""


#define ITMS_VERIFY_RECEIPT_URL   @"https://sandbox.itunes.apple.com/verifyReceipt"
//@"https://buy.itunes.apple.com/verifyReceipt"

#define isServiceVerify 0

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

@implementation APManager


+(instancetype) shared{
    static APManager *_singleInstance;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _singleInstance = [[APManager alloc]init];
    });
    
    return _singleInstance;
}


-(instancetype)init{
    if (self = [super init]) {
        
         [[SKPaymentQueue defaultQueue] addTransactionObserver:self];
    //微信支付
//        [WXApi registerApp:WX_AppID];
    }
    return self;
}


- (void)identifyCanMakePayments:(NSArray*)requestArray{
    if (requestArray.count == 0) {
        if (self.delegate && [self.delegate respondsToSelector:@selector(updatedTransactions:)]) {
            [self.delegate updatedTransactions:VTPaymentTransactionStateAddPaymentFailed];
        }
        return;
    }
    
    if ([SKPaymentQueue canMakePayments]) {
        [self releaseRequest];
        self.request = [[SKProductsRequest alloc]initWithProductIdentifiers:[NSSet setWithArray:requestArray]];
        self.request.delegate = self;
        [self.request start];
    }else{
        if (self.delegate && [self.delegate respondsToSelector:@selector(updatedTransactions:)]) {
            [self.delegate updatedTransactions:VTPaymentTransactionStateNoPaymentPermission];
        }
    }
    
}




- (void)releaseRequest{
    if(_request) {
        [_request cancel];
        _request.delegate=nil;
        _request=nil;
    }
}

-(void)dealloc{
    [self releaseRequest];
    [[SKPaymentQueue defaultQueue] removeTransactionObserver:self];
}


#pragma mark ------------ SKProductsRequestDelegate

- (void)productsRequest:(SKProductsRequest*)request didReceiveResponse:(SKProductsResponse*)response{
    NSArray * myProducts = response.products;
    for(SKProduct*product in myProducts){
        NSLog(@"SKProduct 描述信息%@", [product description]);
        NSLog(@"产品标题 %@", product.localizedTitle);
        NSLog(@"产品描述信息: %@" , product.localizedDescription);
        NSLog(@"价格: %@", product.price);
        NSLog(@"Product id: %@" , product.productIdentifier);
        
        
        
        if (self.delegate && [self.delegate respondsToSelector:@selector(isProductIdentifierAvailable:)]) {
            if ([self.delegate isProductIdentifierAvailable:product.productIdentifier]) {
                SKPayment *payment = [SKPayment paymentWithProduct:product];
                [[SKPaymentQueue defaultQueue] addPayment:payment];
                return;
            }
        }
    }
    
    if (self.delegate && [self.delegate respondsToSelector:@selector(updatedTransactions:)]) {
        [self.delegate updatedTransactions:VTPaymentTransactionStateAddPaymentFailed];
    }
   
}

- (void)request:(SKRequest *)request didFailWithError:(NSError *)error{
    NSLog(@"-------弹出错误信息----------");
    
}

#pragma mark -------- SKPaymentTransactionObserver


-(void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray<SKPaymentTransaction *> *)transactions{
    
    for (SKPaymentTransaction *transaction in transactions) {
        VTPaymentTransactionState state;
        switch (transaction.transactionState) {
            case SKPaymentTransactionStatePurchasing:
                
                state = VTPaymentTransactionStatePurchasing;
                
                break;
            case SKPaymentTransactionStatePurchased:
                
                //防止漏单
//                [[NSUserDefaults standardUserDefaults] setObject:transaction forKey:USERDEFAULT_KEY];
//                [[NSUserDefaults standardUserDefaults] synchronize];
                
                state = VTPaymentTransactionStatePurchased;
                if (isServiceVerify) {
                    [self completeTransaction:transaction];
                }else{
                    [self verifyPurchase:transaction];
                }
                
                break;
            case SKPaymentTransactionStateFailed:
            {
                if (transaction.error.code!= SKErrorPaymentCancelled) {
                    state = VTPaymentTransactionStateFailed;
                }else{
                    state = VTPaymentTransactionStateCancel;
                }
                [self finshTransaction:transaction];
            }
                break;
            case SKPaymentTransactionStateRestored:
                state = VTPaymentTransactionStateRestored;
                [self finshTransaction:transaction];
                break;
            case SKPaymentTransactionStateDeferred:
                state = VTPaymentTransactionStateDeferred;
                break;
            default:
                break;
        }
        
        
        if (self.delegate && [self.delegate respondsToSelector:@selector(updatedTransactions:)]) {
            [self.delegate updatedTransactions:state];
        }
    }
}

// Sent when an error is encountered while adding transactions from the user's purchase history back to the queue.
- (void)paymentQueue:(SKPaymentQueue*)queue restoreCompletedTransactionsFailedWithError:(NSError*)error
{
    NSLog(@"restoreCompletedTransactionsFailedWithError");
}
// Sent when all transactions from the user's purchase history have successfully been added back to the queue.
- (void)paymentQueueRestoreCompletedTransactionsFinished:(SKPaymentQueue*)queue
{
    NSLog(@"paymentQueueRestoreCompletedTransactionsFinished");
}
// Sent when the download state has changed.
- (void)paymentQueue:(SKPaymentQueue*)queue updatedDownloads:(NSArray *)downloads
{
    NSLog(@"updatedDownloads");
}


- (void)paymentQueue:(SKPaymentQueue*)queue removedTransactions:(NSArray *)transactions
{
    NSLog(@"---removedTransactions");
}


#pragma mark ------ private methods

- (void)completeTransaction:(SKPaymentTransaction*)transaction{
    //服务器校验
    
}

- (void)verifyPurchase:(SKPaymentTransaction*)transaction{
    NSURL *receiptURL = [[NSBundle mainBundle] appStoreReceiptURL];
    NSData*receiptData = [NSData dataWithContentsOfURL:receiptURL];
    NSString *encodeStr = [receiptData base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithLineFeed];
    NSURL *url = [NSURL URLWithString:ITMS_VERIFY_RECEIPT_URL];
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:10.0f];
    
    NSString *payload = [NSString stringWithFormat:@"{\"receipt-data\" : \"%@\"}", encodeStr];
    NSData *payloadData = [payload dataUsingEncoding:NSUTF8StringEncoding];
    [request setHTTPBody:payloadData];
    [request setHTTPMethod:@"POST"];
    NSURLResponse*response = nil;
    // 此请求返回的是一个json结果  将数据反序列化为数据字典
    NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:nil];
    if(data ==nil) {
        return;
    }
    NSDictionary *jsonResponse = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:nil];
    if(jsonResponse !=nil) {
        if([[jsonResponse objectForKey:@"status"]intValue] ==0)
            {
                //通常需要校验:bid,product_id,purchase_date,status
                if (self.delegate && [self.delegate respondsToSelector:@selector(buySuccess)]) {
                    [self.delegate buySuccess];
                }
            }
        else
            {
                if (self.delegate && [self.delegate respondsToSelector:@selector(buyFailed:)]) {
                    [self.delegate buyFailed:@""];
                }
                //验证失败,检查你的机器是否越狱
            }
        
        [[NSUserDefaults standardUserDefaults] removeObjectForKey:USERDEFAULT_KEY];
        
    }else{
        if (self.delegate && [self.delegate respondsToSelector:@selector(buyFailed:)]) {
            [self.delegate buyFailed:@""];
        }
    }
    
    
    
    //结束交易
    [self finshTransaction:transaction];
    
}

- (void)finshTransaction:(SKPaymentTransaction*)transaction
{
    //结束交易
    [[SKPaymentQueue defaultQueue] finishTransaction: transaction];
}


//-(void)handleOpenURL:(NSURL *)url{
//    if ([url.host isEqualToString:WECHAT]) {
//        [WXApi handleOpenURL:url delegate:self];
//    }else if ([url.host isEqualToString:ALIPAY]){
//        // 支付跳转支付宝钱包进行支付,处理支付结果
//        [[AlipaySDK defaultService] processOrderWithPaymentResult:url standbyCallback:^(NSDictionary *resultDic) {
//            NSLog(@"result = %@",resultDic);
//        }];
//
////        // 授权跳转支付宝钱包进行支付,处理支付结果
////        [[AlipaySDK defaultService] processAuth_V2Result:url standbyCallback:^(NSDictionary *resultDic) {
////            NSLog(@"result = %@",resultDic);
////            // 解析 auth code
////            NSString *result = resultDic[@"result"];
////            NSString *authCode = nil;
////            if (result.length>0) {
////                NSArray *resultArr = [result componentsSeparatedByString:@"&"];
////                for (NSString *subResult in resultArr) {
////                    if (subResult.length > 10 && [subResult hasPrefix:@"auth_code="]) {
////                        authCode = [subResult substringFromIndex:10];
////                        break;
////                    }
////                }
////            }
////            NSLog(@"授权结果 authCode = %@", authCode?:@"");
////        }];
//    }
//}
//
//-(void)sendOrder:(APTYPE)type Order:(NSDictionary *)order{
//    switch (type) {
//        case AP_ALIPAY:
//        {
//            NSString *orderString = [order objectForKey:@"orderString"];
//            [[AlipaySDK defaultService] payOrder:orderString fromScheme:ALIPAYSCHEME callback:^(NSDictionary *resultDic) {
//                NSLog(@"reslut = %@",resultDic);
//            }];
//        }
//            break;
//        case AP_WECHAT:
//        {
//            PayReq *request = [[PayReq alloc] init];
//            request.openID = [order objectForKey:@"appid"];
//            request.partnerId = [order objectForKey:@"partnerid"];
//            request.prepayId= [order objectForKey:@"prepayid"];
//            request.package = [order objectForKey:@"package"];
//            request.nonceStr= [order objectForKey:@"noncestr"];
//            request.timeStamp = [[order objectForKey:@"timestamp"] intValue];
//            request.sign = [order objectForKey:@"sign"];
//            [WXApi sendReq:request];
//        }
//            break;
//        default:
//            break;
//    }
//}


//#pragma mark ----WXApiDelegate-----

//- (void)onResp:(BaseResp *)resp{
//    if ([resp isKindOfClass:[PayResp class]]) {
//        PayResp*response=(PayResp*)resp;  // 微信终端返回给第三方的关于支付结果的结构体
//        switch (response.errCode) {
//            case WXSuccess:
//            {// 支付成功,向后台发送消息
//                NSLog(@"支付成功");
//            }
//                break;
//            case WXErrCodeCommon:
//            { //签名错误、未注册APPID、项目设置APPID不正确、注册的APPID与设置的不匹配、其他异常等
//                NSLog(@"支付失败");
//            }
//                break;
//            case WXErrCodeUserCancel:
//            { //用户点击取消并返回
//                NSLog(@"取消支付");
//            }
//                break;
//            case WXErrCodeSentFail:
//            { //发送失败
//                NSLog(@"发送失败");
//            }
//                break;
//            case WXErrCodeUnsupport:
//            { //微信不支持
//                NSLog(@"微信不支持");
//            }
//                break;
//            case WXErrCodeAuthDeny:
//            { //授权失败
//                NSLog(@"授权失败");
//            }
//                break;
//            default:
//                break;
//        }
//    }
//}

@end

相关文章

  • 内购流程

    内购流程 1.构建内购的设置,需要设置内购商品,填写银行卡信息 进入苹果官方后台配置需要内购商品的信息(包括内购的...

  • 内购和广告

    内购和广告 1. 什么是内购? 2. 为什么做内购? 3. 内购的产品类型? 非消耗品(Nonconsumable...

  • 内购

    关于内购的资金流程:1.用户点击内购按钮, 付款成功给苹果公司, 成为我们的付费用户。2.当出现什么问题的时候,用...

  • 内购

    内购__应用内购买__storeKit AppleStore有三种主要赚钱的方式: - 直接 收费 - 广告 ...

  • 内购

    流程 程序向服务器请求, 获取一份产品列表 服务器返回包含产品标识符的服务列表 程序向 App Store 发送请...

  • 内购

    1. 无法获取内购项目 response.products.count一直为0 开发者帐号是否已经完善付费协议和税...

  • 内购

    关于内购的那些坑

  • 内购

    内购介绍 IAP 是一套商品交易系统,而非简单的支付系统,每一个购买项目都需要在开发者后台的Itunes Conn...

  • 内购

  • ios内购注意事项

    内购两种方式 ios内购及一些常用的破解手段 iap内购破解原理 苹果官方内购demo 内购的消耗性和非消耗性购买说明

网友评论

      本文标题:内购

      本文链接:https://www.haomeiwen.com/subject/bzzbcdtx.html