iOS支付(含服务器验证)

直接上代码.....
.h文件:
#import 

@interface SDKApplePay : NSObject  {
    SKProductsRequest* _curProductRequest;
    NSMutableDictionary* _curActualProducts;  //实际可购买列表
    NSString* _curAppId;
    bool receiptValid;
    
#if __IPHONE_OS_VERSION_MAX_ALLOWED < __IPHONE_8_0
    UIAlertView *alertViewTest;
#else
    UIAlertController *alertController;
#endif
    
}

+ (SDKApplePay*) getInstance;

- (void) initSDK:(UIViewController *)viewController sdkName:(NSString *)sdkName;
- (void)requestProductsValidate:(NSDictionary*)productsDict;
- (void)requestProductsPay:(NSString*)productsDict;

@end


.mm文件:
#import "SDKApplePay.h"
#import "Util.h"
#import "JSCallObjectCBridge.h"

#define MyServerURL @"你的服务器网址"//服务器请求的地址
#define DebugModel @"0"    //@"sandbox" 沙盒测试  @"0" 正常购买

@implementation SDKApplePay

static NSString* const SDK_IAP_PREFIX_PRODUCT=@"com.xxxx.xxxx.";

static SDKApplePay* curInstance=nil;

+ (SDKApplePay*) getInstance
{
    if(nil==curInstance)
    {
        curInstance = [[SDKApplePay alloc] init];
    }
    return curInstance;
}

- (void)requestProductsValidate:(NSDictionary*)productsDict
{
    NSMutableSet* productsSet = [NSMutableSet set];
    for(NSString* key in productsDict)
    {
        [productsSet addObject:[NSString stringWithFormat:@"%@%@",SDK_IAP_PREFIX_PRODUCT,key]];
    }
    _curProductRequest=[[SKProductsRequest alloc] initWithProductIdentifiers:productsSet];
    _curProductRequest.delegate=self;
    [_curProductRequest start];
}

//购买时的调用方法
- (void)requestProductsPay:(NSString*)productsDict
{
    if(nil==productsDict){
        //参数为空,调用违法
        return;
    }
    if([SKPaymentQueue canMakePayments])
    {
        NSString* curProductIdentifier = nil;
        if(nil!=productsDict){
            curProductIdentifier = productsDict;
        }
        SKProduct* actualProduct = [_curActualProducts objectForKey:curProductIdentifier];
        SKPayment* payment = [SKPayment paymentWithProduct:actualProduct];
        [[SKPaymentQueue defaultQueue] addPayment:payment];
    }else
    {
        //TODO 通知用户无法进行购买
    }
}

//-----------------override---------------

- (void) initSDK:(UIViewController *)viewController sdkName:(NSString *)sdkName
{
    _curActualProducts=[[NSMutableDictionary alloc] init];
    NSMutableDictionary* mm = [[NSMutableDictionary alloc] init];
    [mm setObject:@"buy01" forKey:@"buy01"];
    [mm setObject:@"buy02" forKey:@"buy02"];
    [mm setObject:@"buy13" forKey:@"buy13"];
    [mm setObject:@"buy04" forKey:@"buy04"];
    
    [self requestProductsValidate:mm];
    
    [[SKPaymentQueue defaultQueue] addTransactionObserver:self];
}

//-----------------implements--------------
- (void) productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response
{
    NSArray* productList=response.products;
    long count = productList.count;
    [_curActualProducts removeAllObjects];
    for(int i=0;i-count<0;i++)
    {
        SKProduct* curProduct = [productList objectAtIndex:i];
        [_curActualProducts setObject:curProduct forKey:curProduct.productIdentifier];
    }
    [_curProductRequest release];
    
    //======!!!!!购买时的调用方法
    //[self requestProductsPay:nil];
}

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

- (void) paymentQueue:(SKPaymentQueue *)queue restoreCompletedTransactionsFailedWithError:(NSError *)error
{
    NSLog(@"restoreCompletedTransactionsFailedWithError");
    //[self processRestoreFailed:queue error:error];
}

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

//购买结果发的回调
- (void) paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions
{
    NSLog(@"==[开始处理用户交易操作]");
    for (SKPaymentTransaction *transaction in transactions)
    {
        NSLog(@"======[获得用户操作码]:%d",(int)transaction.transactionState);
        switch (transaction.transactionState)
        {
            case SKPaymentTransactionStatePurchasing:
                NSLog(@"SKPaymentTransactionStatePurchasing");
                break;
            case SKPaymentTransactionStatePurchased:
                //购买成功
                NSLog(@"SKPaymentTransactionStatePurchased:%@",transaction.payment.productIdentifier);
                //进行回调处理
                [self completeTransaction:transaction];
                break;
            case SKPaymentTransactionStateFailed:
                //购买失败
                NSLog(@"SKPaymentTransactionStateFailed");
                [self failedTransaction:transaction];
                break;
            case SKPaymentTransactionStateRestored:
                //已经购买过该商品
                NSLog(@"SKPaymentTransactionStateRestored");
                [self restoreTransaction:transaction];
                break;
            case SKPaymentTransactionStateDeferred:
                NSLog(@"SKPaymentTransactionStateDeferred");
                break;
            default:
                break;
        }
    }
    NSLog(@"==[结束处理用户交易操作!]");
}

- (void) paymentQueueRestoreCompletedTransactionsFinished:(SKPaymentQueue *)queue
{
    NSLog(@"removedTransactions");
}

//向服务器请求验证
- (void) verifyReceiptFromMyServer:(SKPaymentTransaction *)transaction
{
    //初始化为合法
    if (transaction.payment.productIdentifier !=nil) {
        //base64 encode the receipt data for sending
        if ([transaction.transactionReceipt base64Encoding] != nil) {
            //将数据http post请求发送到我的服务器
            NSURL* url = [NSURL URLWithString:MyServerURL];
            NSMutableURLRequest* theRequest = [NSMutableURLRequest requestWithURL:url];
            
            [theRequest setHTTPMethod:@"POST"];
            //修改通信方式
            NSString * productIdentifier = transaction.payment.productIdentifier;
            NSString *transactionReceiptString= nil;
            
            //系统IOS7.0以上获取支付验证凭证的方式应该改变,切验证返回的数据结构也不一样了。
//            if([[UIDevice currentDevice].systemVersion floatValue]>=7.0){
//                NSURLRequest*appstoreRequest = [NSURLRequest requestWithURL:[[NSBundle mainBundle]appStoreReceiptURL]];
//                NSError *error = nil;
//                NSData * receiptData = [NSURLConnection sendSynchronousRequest:appstoreRequest returningResponse:nil error:&error];
//                NSLog(@"+++apple_receipt:\n%@+++",receiptData);
//                //transactionReceiptString = [receiptData base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithLineFeed];
//                //transactionReceiptString = [receiptData base64EncodedStringWithOptions:0];
//                transactionReceiptString = [self base64Encode:receiptData];
//            }
//            else{
                NSData * receiptData = transaction.transactionReceipt;
                NSLog(@"+++apple_receipt:\n%@+++",receiptData);
                //transactionReceiptString = [receiptData base64EncodedString];
                transactionReceiptString = [self base64Encode:receiptData];
//            }
            NSLog(@"+++apple_receipt-base64:\n%@+++",transactionReceiptString);
            
            NSString *sendString = [NSString stringWithFormat:@"package_name=%@&product_id=%@&apple_receipt=\n%@&env=%@", @"com.tjyzy.dd2",productIdentifier,transactionReceiptString,DebugModel];
            NSLog(@"+++sendString:%@+++",sendString);
            [theRequest setHTTPBody:[sendString dataUsingEncoding:NSUTF8StringEncoding]];
            
            //发送同步请求  因为你将使用自己的服务器返回的数据来判断是否成功
            NSURLResponse* response = [[NSURLResponse alloc] init];
            NSError*       myerror =  [[NSError alloc] init];
            NSMutableData* receiveData = (NSMutableData *)[NSURLConnection sendSynchronousRequest:theRequest returningResponse:&response error:&myerror];
            
            //NSURLConnection* theConnection = [[NSURLConnection alloc] initWithRequest:theRequest delegate:self];
            
            //接收到服务器返回的数据
            NSString *receiptStatus = [[NSString alloc] initWithBytes: [receiveData mutableBytes] length:[receiveData length] encoding:NSUTF8StringEncoding];
            NSLog(@"\nreceiptStatus=%@",receiptStatus);
            NSString* str = @"\"errno\":0";
            
            if ([receiptStatus length]==0 || [receiptStatus isEqualToString:@""]) {
                receiptValid = false;
            }else{
                //转换成二进制数据
                NSData * data = [receiptStatus dataUsingEncoding:NSUTF8StringEncoding];
                //解析JSON文件 OC中自带的方法
                NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil];
                int receivCode = [[dict objectForKey:@"errno"] intValue];
                if(receivCode==0){
                    NSLog(@"++++服务器通信成功++++");
                    receiptValid = true;
                }else{
                    NSLog(@"++++服务器通信失败++++错误码为:%d",receivCode);
                    receiptValid = false;
                }
            }
            
//            [receiptStatus release];
//            [myerror release];
//            [response release];
            
        } else {
            NSLog(@"当向服务器发送验证数据时出错!!!");
            receiptValid = false;
        }
    }
    else
    {
        NSLog(@"无效的商品ID");
        receiptValid = false;
    }
}

//将NSData64位编码
- (NSString*) base64Encode:(NSData *)theData
{
    const uint8_t* input = (const uint8_t*)[theData bytes];
    NSInteger length = [theData length];
    
    static char table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
    
    NSMutableData* data = [NSMutableData dataWithLength:((length + 2) / 3) * 4];
    uint8_t* output = (uint8_t*)data.mutableBytes;
    
    NSInteger i;
    for (i=0; i < length; i += 3) {
        NSInteger value = 0;
        NSInteger j;
        for (j = i; j < (i + 3); j++) {
            value <<= 8;
            
            if (j < length) {
                value |= (0xFF & input[j]);
            }
        }
        
        NSInteger theIndex = (i / 3) * 4;
        output[theIndex + 0] =                    table[(value >> 18) & 0x3F];
        output[theIndex + 1] =                    table[(value >> 12) & 0x3F];
        output[theIndex + 2] = (i + 1) < length ? table[(value >> 6)  & 0x3F] : '=';
        output[theIndex + 3] = (i + 2) < length ? table[(value >> 0)  & 0x3F] : '=';
    }
    
    //return [[[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding] autorelease];
    return [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];
}

//购买成功
- (void) completeTransaction: (SKPaymentTransaction *)transaction

{
    receiptValid = false;
    //进行服务器验证
    [self verifyReceiptFromMyServer:transaction];//这个方法是内支付最重要的方法
    if (receiptValid) {
        //给物品
        [[JSCallObjectCBridge getInstance] applePaySuccess:transaction.payment.productIdentifier];
    } else {
        //[self failedTransaction:transaction];
    }
  
    [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
}
//购买恢复交易
- (void) restoreTransaction: (SKPaymentTransaction *)transaction

{
    NSLog(@" 交易恢复处理");
    //给物品
    [[JSCallObjectCBridge getInstance] applePaySuccess:transaction.payment.productIdentifier];
    [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
}
//购买失败
- (void) failedTransaction: (SKPaymentTransaction *)transaction{
    NSLog(@"失败");
    if (transaction.error.code != SKErrorPaymentCancelled)
    {
        //提示购买失败
        UIAlertView *alerView2 =  [[UIAlertView alloc] initWithTitle:@"Pay Result"
                                                             message:@"Payment failed, Please try again!"
                                                            delegate:nil cancelButtonTitle:NSLocalizedString(@"Close",nil) otherButtonTitles:nil];
        
        [alerView2 show];
        [alerView2 release];
    }
    [[SKPaymentQueue defaultQueue] finishTransaction: transaction];
}
-(void)dealloc
{
    [[SKPaymentQueue defaultQueue] removeTransactionObserver:self];//解除监听
    [super dealloc];
}
@end


PS:上面的代码部分,再查看某些文章时,发现“系统IOS7.0以上获取支付验证凭证的方式应该改变,切验证返回的数据结构也不一样了”,最后通过实际项目发现支付验证凭证采用原来的方式“transaction.transactionReceipt”即可。


使用方法:
1 在AppController.mm中进行初始化:
在函数“- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions”中
调用“[[SDKApplePay getInstance] initSDK:viewController sdkName:@"applepay"];“进行初始化;
2  在需要调用支付的部分调用支付代码:
[[SDKApplePay getInstance] requestProductsPay:appleProductId];  支付道具的id(appleProductId的值)例:com.xxxx.xxxx.buy01
这个id是你在苹果后台申请的id。

你可能感兴趣的:(cocos2d-x)