iOS支付(含服务器验证)
2016-12-19 10:32
811 查看
直接上代码.....
.h文件:
.mm文件:
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。
.h文件:
#import <StoreKit/StoreKit.h> @interface SDKApplePay : NSObject <SKProductsRequestDelegate,SKPaymentTransactionObserver>{ 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<SKProduct*>* 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<SKPaymentTransaction *> *)transactions { NSLog(@"removedTransactions"); } - (void) paymentQueue:(SKPaymentQueue *)queue restoreCompletedTransactionsFailedWithError:(NSError *)error { NSLog(@"restoreCompletedTransactionsFailedWithError"); //[self processRestoreFailed:queue error:error]; } - (void) paymentQueue:(SKPaymentQueue *)queue updatedDownloads:(NSArray<SKDownload *> *)downloads { NSLog(@"updatedDownloads"); } //购买结果发的回调 - (void) paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray<SKPaymentTransaction *> *)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 returningResp 4000 onse:&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。
相关文章推荐
- IOS内购支付服务器验证模式
- IOS内购支付服务器验证模式
- ios支付,带本地服务器验证
- IOS内购支付服务器验证模式
- iOS IAP 服务器二次验证突然断网了怎么办
- ios 应用内支付(In-App Purchase,沙盒测试,后台验证)
- Unity内IAP支付二次验证/服务器验证————最白话,手把手教你做系列。
- ios开发之验证你的服务器ATS是否PASS
- iap支付服务器验证python版本
- unity3d ios支付验证
- ios 内购 服务器二次验证元宝处理
- ios 应用内支付(In-App Purchase,沙盒测试,后台验证)iap
- iOS游戏IAP数据服务器验证
- ##iOS中的微信支付 支付验证签名失败
- iOS的in-app purchase C#服务器二次验证实现
- 【读书笔记】iOS-验证应用内支付的凭证注意事项
- iOS- 微信支付 (服务器调起支付 )以及回调不成功的原因 不看后悔
- 微信支付:服务器(Java)统一下单获取prepay_id成功,前端公众号里调用jsapi提示支付验证签名失败
- iOS HTTPS安全请求 验证服务器返回的证书
- IOS内购支付server验证模式