#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權(quán)限
VTPaymentTransactionStateAddPaymentFailed,//addPayment失敗
VTPaymentTransactionStatePurchasing,//正在購買
VTPaymentTransactionStatePurchased,//購買完成(銷毀交易)
VTPaymentTransactionStateFailed,//購買失敗(銷毀交易)
VTPaymentTransactionStateCancel,//用戶取消
VTPaymentTransactionStateRestored,//恢復(fù)購買(銷毀交易)
VTPaymentTransactionStateDeferred,//最終狀態(tài)未確定
} 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(@"產(chǎn)品標題 %@", product.localizedTitle);
NSLog(@"產(chǎn)品描述信息: %@" , 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{
//服務(wù)器校驗
}
- (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結(jié)果 將數(shù)據(jù)反序列化為數(shù)據(jù)字典
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:@""];
}
}
//結(jié)束交易
[self finshTransaction:transaction];
}
- (void)finshTransaction:(SKPaymentTransaction*)transaction
{
//結(jié)束交易
[[SKPaymentQueue defaultQueue] finishTransaction: transaction];
}
//-(void)handleOpenURL:(NSURL *)url{
// if ([url.host isEqualToString:WECHAT]) {
// [WXApi handleOpenURL:url delegate:self];
// }else if ([url.host isEqualToString:ALIPAY]){
// // 支付跳轉(zhuǎn)支付寶錢包進行支付赛糟,處理支付結(jié)果
// [[AlipaySDK defaultService] processOrderWithPaymentResult:url standbyCallback:^(NSDictionary *resultDic) {
// NSLog(@"result = %@",resultDic);
// }];
//
//// // 授權(quán)跳轉(zhuǎn)支付寶錢包進行支付疚沐,處理支付結(jié)果
//// [[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(@"授權(quán)結(jié)果 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; // 微信終端返回給第三方的關(guān)于支付結(jié)果的結(jié)構(gòu)體
// switch (response.errCode) {
// case WXSuccess:
// {// 支付成功魄宏,向后臺發(fā)送消息
// NSLog(@"支付成功");
// }
// break;
// case WXErrCodeCommon:
// { //簽名錯誤、未注冊APPID台盯、項目設(shè)置APPID不正確罢绽、注冊的APPID與設(shè)置的不匹配、其他異常等
// NSLog(@"支付失敗");
// }
// break;
// case WXErrCodeUserCancel:
// { //用戶點擊取消并返回
// NSLog(@"取消支付");
// }
// break;
// case WXErrCodeSentFail:
// { //發(fā)送失敗
// NSLog(@"發(fā)送失敗");
// }
// break;
// case WXErrCodeUnsupport:
// { //微信不支持
// NSLog(@"微信不支持");
// }
// break;
// case WXErrCodeAuthDeny:
// { //授權(quán)失敗
// NSLog(@"授權(quán)失敗");
// }
// break;
// default:
// break;
// }
// }
//}
@end