iOS游戏开发三:苹果内支付实现 In-app
2016-06-13 15:09
696 查看
iOS游戏开发三:苹果内支付实现 In-app
首先你必须熟悉内支付的流程,可以到网上搜搜看。
前几天因为需要做了个苹果的内支付,当中遇到了不少苦头,感觉网上的各种博客对内支付这一块都是点到即止,没有真真正正实现自己的需求。正所谓辛苦就有所得,通过东接西搬,终于内力小成,特与大家分享一下自己的经验。这里我假设你已经把商品的ID什么的都已经注册成功了,测试账号也有了。
下面直接贴代码了~~~~
[objc] view
plain copy
print?
//
// IAPHelperViewController.h
//
#import <UIKit/UIKit.h>
#import <StoreKit/StoreKit.h>
@interface IAPHelperViewController : UIViewController<SKProductsRequestDelegate,SKPaymentTransactionObserver>
{
NSString* kMyInAppIdentifier;
BOOL receiptValid;
UIActivityIndicatorView* spinner;
}
+ (IAPHelperViewController *) sharedIAPHelper;
- (void) requestProUpgradeProductData;
- (void) requestProductData;
- (void) buyGolds:(int)buyType;
- (BOOL) canInAppPayment;
- (void) paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions;
- (void) purchasedTransaction:(SKPaymentTransaction *)transaction;
- (void) completeTransaction:(SKPaymentTransaction *)transaction;
- (void) failedTransaction:(SKPaymentTransaction *)transaction;
- (void) paymentQueueRestoreCompletedTransactionsFinished: (SKPaymentTransaction *)transaction;
- (void) paymentQueue:(SKPaymentQueue *) paymentQueue restoreCompletedTransactionsFailedWithError:(NSError *)error;
- (void) restoreTransaction:(SKPaymentTransaction *)transaction;
- (void) recordTransaction:(SKPaymentTransaction *)product;
- (void) verifyReceiptFromMyServer:(SKPaymentTransaction *)transaction;
@end
[objc] view
plain copy
print?
//
// IAPHelperViewController.m
//
#import "IAPHelperViewController.h"
#include "cocos2d.h"
using namespace cocos2d;
const static int IAP1p99 = flag1;//主要是标记用户点击了那个商品
const static int IAP2p99 = flag2;
const static int IAP3p99 = flag3;
const static int IAP4p99 = flag4;
const static int IAP5p99 = flag5;
#define MyServerURL @"your server address , not apple"
#define ProductOne @"product 1 id"
#define ProductThree @"....... 2 .."
#define ProductFive @"....... 3 .."
#define ProductFifteen @"....... 4 .."
#define ProductFifty @"...... 5 .."
#define MyFrint NSLog(@"\n%s %d\n",__FUNCTION__, __LINE__)
@interface IAPHelperViewController ()
@end
@implementation IAPHelperViewController
//定义单例变量
static IAPHelperViewController* singleton = nil;
//单例模式
+ (IAPHelperViewController *) sharedIAPHelper
{
MyFrint;
if (singleton == nil) {
singleton = [[IAPHelperViewController alloc] initWithNibName:nil bundle:nil];
}
return singleton;
}
//初始化 这里应该根据自己的情况初始化 我用的是C++写的界面 OC不鸟~~~~~~
- (id) initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
MyFrint;
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
receiptValid = NO;
}
return self;
}
//加载视图
- (void) viewDidLoad
{
MyFrint;
[super viewDidLoad];
self.view.backgroundColor = [UIColor orangeColor];
}
//请求升级数据
- (void) requestProUpgradeProductData
{
MyFrint;
NSSet* productIdentifiers = [NSSet setWithObjects:ProductOne, ProductThree, ProductFive, ProductFifteen, ProductFifty, nil nil];
SKProductsRequest* request = [[SKProductsRequest alloc] initWithProductIdentifiers:productIdentifiers];
request.delegate = self;
[request start];
}
//点击商品按钮
- (void) buyGolds:(int)buyType
{
MyFrint;//根据点击标记 找到对应的商品IDs
switch (buyType) {
case IAP1p99: { kMyInAppIdentifier = ProductOne; break; }
case IAP2p99: { kMyInAppIdentifier = ProductThree; break; }
case IAP3p99: { kMyInAppIdentifier = ProductFive; break; }
case IAP4p99: { kMyInAppIdentifier = ProductFifteen; break; }
case IAP5p99: { kMyInAppIdentifier = ProductFifty; break; }
default: break;
}
[[SKPaymentQueue defaultQueue] addTransactionObserver:self];
if ([self canInAppPayment]) {
NSLog(@"允许应用内支付");
//首先向AppStore请求恢复交易
[[SKPaymentQueue defaultQueue] restoreCompletedTransactions];
} else {
NSLog(@"不允许应用内支付");
}
}
//判断是否可以应用内支付
- (BOOL) canInAppPayment
{
MyFrint;//你应该根据是否想让越狱的iOS设备允许内支付
if ([[NSFileManager defaultManager] fileExistsAtPath:@"/Applications/Cydia.app"]){
NSLog(@"Jailbroken detected!");
return NO;
}
if ([SKPaymentQueue canMakePayments]) {
return YES;
} else {
return NO;
}
}
//输入正确的帐号后进入 (如果是测试 必须必须使用你注册的沙河账号和密码)
- (void) paymentQueueRestoreCompletedTransactionsFinished:(SKPaymentTransaction *)transaction
{
MyFrint;
[self requestProductData];
}
//请求购买的商品信息
- (void) requestProductData
{
MyFrint;
NSSet * set = [NSSet setWithObjects:kMyInAppIdentifier, nil nil];//可以添加多个商品ID
SKProductsRequest* request = [[SKProductsRequest alloc] initWithProductIdentifiers:set];
request.delegate = self;
[request start];
}
#pragma mark SKProductsRequestDelegate 请求协议 ----------------------------------------------------------
//收到产品信息
- (void) productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response
{
// NSArray *myProduct = response.products;
// NSLog(@"产品付费数量: %d", [myProduct count]);
// NSLog(@"产品Product ID:%@",response.invalidProductIdentifiers);
// SKPayment *payment = nil;
// // populate UI
// for(SKProduct *product in myProduct)
// {
// NSLog(@"\n\nproduct info");
// NSLog(@"SKProduct 描述信息%@", [product description]);
// NSLog(@"产品标题 %@" , product.localizedTitle);
// NSLog(@"产品描述信息: %@" , product.localizedDescription);
// NSLog(@"价格: %@" , product.price);
// NSLog(@"Product id: %@\n\n" , product.productIdentifier);
// payment = [SKPayment paymentWithProduct:product];
// }
MyFrint;
SKPayment* payment = [SKPayment paymentWithProduct:[response.products lastObject]];
NSLog(@"\nPayment:\n productIdentifier=%@, \nrequestData=%@, \nquanlity=%d, \n",payment.productIdentifier,[payment.requestData description],payment.quantity);
[[SKPaymentQueue defaultQueue] addPayment:payment];
[request release];//请求已经生效
}
//请求错误信息
- (void) request:(SKRequest *)request didFailWithError:(NSError *)error
{
MyFrint;
UIAlertView *alerView = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Alert",NULL)
message:[error localizedDescription]
delegate:nil
cancelButtonTitle:NSLocalizedString(@"Close",nil)
otherButtonTitles:nil];
[alerView show];
[alerView release];
[request release];//请求失效
}
- (void) purchasedTransaction:(SKPaymentTransaction *)transaction
{
MyFrint;
}
- (void) requestDidFinish:(SKRequest *)request
{
MyFrint;
}
//然后当用户输入正确的appStore帐号密码后进入(再次说明 如果是测试 必须是你注册的测试账号 不能使用真实的AppleID 否则后果~~~~)
//方法在新交易被创建或更新时都会被调用
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions
{
MyFrint;
for ( SKPaymentTransaction* transaction in transactions )
{
switch (transaction.transactionState)
{
case SKPaymentTransactionStatePurchased:
{//交易完成
[self completeTransaction:transaction];
}
break;
case SKPaymentTransactionStateFailed:
{//交易失败
[self failedTransaction:transaction];
}
break;
case SKPaymentTransactionStateRestored:
{//已经购买过该商品
[self restoreTransaction:transaction];
}
case SKPaymentTransactionStatePurchasing:
{//商品添加进列表
NSLog(@"商品添加进列表==");
break;
}
default:
break;
}
}
}
//玩家等待 这里我想加个转动条 但没成功OC不鸟呀
- (void) activityIndicatorRun
{
spinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite];
spinner.color = [UIColor whiteColor];
spinner.frame = CGRectMake(100, 180.0f, 137.0f, 137.0f);
[spinner startAnimating];
}
//玩家结束等待
- (void) activityIndicatorStop
{
[spinner stopAnimating];
}
//observer在用户成功购买后提供相应的product
- (void)completeTransaction:(SKPaymentTransaction *)transaction
{
MyFrint;
[self activityIndicatorRun];
[self verifyReceiptFromMyServer:transaction];//这个方法是内支付最重要的方法
[self activityIndicatorStop];
if (receiptValid) {
[self recordTransaction:transaction];
//提示服务器刷新数据 ---
CCNotificationCenter::sharedNotificationCenter()->postNotification(kGNetworkNotificationName_Shop_BuyCredit_Successed, NULL);
} else {
[self failedTransaction:transaction];
}
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
}
//处理还原购买 结束交易
- (void) restoreTransaction: (SKPaymentTransaction *)transaction
{
MyFrint;
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
}
//处理失败购买 结束交易
- (void) failedTransaction: (SKPaymentTransaction *)transaction
{
MyFrint;
if (transaction.error.code != SKErrorPaymentCancelled) {
NSLog(@"购买失败");
}
[objc] view
plain copy
print?
<span style="white-space:pre"> </span>//根据项目的实际运行情况看 下面的完全多余.
[objc] view
plain copy
print?
<pre code_snippet_id="105137" snippet_file_name="blog_20131209_2_9929406" name="code" class="objc"> //else {
// NSLog(@"用户取消购买");
//}
[objc] view
plain copy
print?
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
}
//取消登陆帐号密码操作
- (void) paymentQueue:(SKPaymentQueue *) paymentQueue restoreCompletedTransactionsFailedWithError:(NSError *)error
{
MyFrint;
}
//用户成功购买
- (void) recordTransaction:(SKPaymentTransaction *)product
{
MyFrint;
UIAlertView* view = [[UIAlertView alloc] initWithTitle:@"购买结果" message:@"购买成功" delegate:nil cancelButtonTitle:@"确定" otherButtonTitles: nil nil];
[view show];
[view release];
}
//向服务器请求验证
- (void) verifyReceiptFromMyServer:(SKPaymentTransaction *)transaction
{
MyFrint;
//初始化为合法
if ([transaction.payment.productIdentifier isEqualToString:kMyInAppIdentifier]) {
//base64 encode the receipt data for sending
if ([transaction.transactionReceipt base64Encoding] != nil) {
//将数据http post请求发送到我的服务器
//data=base64(json(post))
//字典内容
NSDictionary* postDict = [[NSDictionary alloc] initWithObjectsAndKeys:@"ios",@"mode",
@"verify",@"method",
[NSDictionary dictionaryWithObjectsAndKeys:[self base64Encode:transaction.transactionReceipt],@"receipt",@"YES",@"test", nil nil],@"params",
@"1136",@"uid", nil nil];
//字典转化为json数据
NSError* error = nil;
NSData* jsonData = [NSJSONSerialization dataWithJSONObject:postDict options:NSJSONWritingPrettyPrinted error:&error];
if([jsonData length]>0 && error == nil){
}else if([jsonData length] == 0 && error == nil){
NSLog(@"No data returned after serialization.");
receiptValid = NO;
}else if(error != nil){
NSLog(@"An error happened = %@",error);
receiptValid = NO;
}
//json数据base64
NSString* base64 = [self base64Encode:jsonData];
if ([base64 length]==0 || [base64 isEqualToString:@""]) {
NSLog(@"Base64 error");
receiptValid = NO;
}
NSURL* url = [NSURL URLWithString:MyServerURL];
NSMutableURLRequest* theRequest = [NSMutableURLRequest requestWithURL:url];
[theRequest setHTTPMethod:@"POST"];
[theRequest setValue:[NSString stringWithFormat:@"%d", [jsonData length]] forHTTPHeaderField:@"Content-Length"];
[theRequest setHTTPBody:[[NSString stringWithFormat:@"data=%@", base64] 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 = @"\"status\":0";
if ([receiptStatus length]==0 || [receiptStatus isEqualToString:@""]) {
receiptValid = NO;
}
if ([receiptStatus rangeOfString:str].location != NSNotFound) {
NSLog(@"Yes Yes Yes!!!");
receiptValid = YES;
} else {
receiptValid = NO;
}
[receiptStatus release];
[myerror release];
[response release];
[postDict release];
} else {
NSLog(@"当向服务器发送验证数据时出错!!!");
receiptValid = NO;
}
}
else
{
NSLog(@"无效的商品ID");
receiptValid = NO;
}
}
//将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];
}
//收到内存警告释放资源
- (void) didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
//回收内存
-(void) dealloc
{
[[SKPaymentQueue defaultQueue] removeTransactionObserver:self];//解除监听
[spinner release]; spinner = nil;
[super dealloc];
}
@end
首先你必须熟悉内支付的流程,可以到网上搜搜看。
前几天因为需要做了个苹果的内支付,当中遇到了不少苦头,感觉网上的各种博客对内支付这一块都是点到即止,没有真真正正实现自己的需求。正所谓辛苦就有所得,通过东接西搬,终于内力小成,特与大家分享一下自己的经验。这里我假设你已经把商品的ID什么的都已经注册成功了,测试账号也有了。
下面直接贴代码了~~~~
[objc] view
plain copy
print?
//
// IAPHelperViewController.h
//
#import <UIKit/UIKit.h>
#import <StoreKit/StoreKit.h>
@interface IAPHelperViewController : UIViewController<SKProductsRequestDelegate,SKPaymentTransactionObserver>
{
NSString* kMyInAppIdentifier;
BOOL receiptValid;
UIActivityIndicatorView* spinner;
}
+ (IAPHelperViewController *) sharedIAPHelper;
- (void) requestProUpgradeProductData;
- (void) requestProductData;
- (void) buyGolds:(int)buyType;
- (BOOL) canInAppPayment;
- (void) paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions;
- (void) purchasedTransaction:(SKPaymentTransaction *)transaction;
- (void) completeTransaction:(SKPaymentTransaction *)transaction;
- (void) failedTransaction:(SKPaymentTransaction *)transaction;
- (void) paymentQueueRestoreCompletedTransactionsFinished: (SKPaymentTransaction *)transaction;
- (void) paymentQueue:(SKPaymentQueue *) paymentQueue restoreCompletedTransactionsFailedWithError:(NSError *)error;
- (void) restoreTransaction:(SKPaymentTransaction *)transaction;
- (void) recordTransaction:(SKPaymentTransaction *)product;
- (void) verifyReceiptFromMyServer:(SKPaymentTransaction *)transaction;
@end
[objc] view
plain copy
print?
//
// IAPHelperViewController.m
//
#import "IAPHelperViewController.h"
#include "cocos2d.h"
using namespace cocos2d;
const static int IAP1p99 = flag1;//主要是标记用户点击了那个商品
const static int IAP2p99 = flag2;
const static int IAP3p99 = flag3;
const static int IAP4p99 = flag4;
const static int IAP5p99 = flag5;
#define MyServerURL @"your server address , not apple"
#define ProductOne @"product 1 id"
#define ProductThree @"....... 2 .."
#define ProductFive @"....... 3 .."
#define ProductFifteen @"....... 4 .."
#define ProductFifty @"...... 5 .."
#define MyFrint NSLog(@"\n%s %d\n",__FUNCTION__, __LINE__)
@interface IAPHelperViewController ()
@end
@implementation IAPHelperViewController
//定义单例变量
static IAPHelperViewController* singleton = nil;
//单例模式
+ (IAPHelperViewController *) sharedIAPHelper
{
MyFrint;
if (singleton == nil) {
singleton = [[IAPHelperViewController alloc] initWithNibName:nil bundle:nil];
}
return singleton;
}
//初始化 这里应该根据自己的情况初始化 我用的是C++写的界面 OC不鸟~~~~~~
- (id) initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
MyFrint;
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
receiptValid = NO;
}
return self;
}
//加载视图
- (void) viewDidLoad
{
MyFrint;
[super viewDidLoad];
self.view.backgroundColor = [UIColor orangeColor];
}
//请求升级数据
- (void) requestProUpgradeProductData
{
MyFrint;
NSSet* productIdentifiers = [NSSet setWithObjects:ProductOne, ProductThree, ProductFive, ProductFifteen, ProductFifty, nil nil];
SKProductsRequest* request = [[SKProductsRequest alloc] initWithProductIdentifiers:productIdentifiers];
request.delegate = self;
[request start];
}
//点击商品按钮
- (void) buyGolds:(int)buyType
{
MyFrint;//根据点击标记 找到对应的商品IDs
switch (buyType) {
case IAP1p99: { kMyInAppIdentifier = ProductOne; break; }
case IAP2p99: { kMyInAppIdentifier = ProductThree; break; }
case IAP3p99: { kMyInAppIdentifier = ProductFive; break; }
case IAP4p99: { kMyInAppIdentifier = ProductFifteen; break; }
case IAP5p99: { kMyInAppIdentifier = ProductFifty; break; }
default: break;
}
[[SKPaymentQueue defaultQueue] addTransactionObserver:self];
if ([self canInAppPayment]) {
NSLog(@"允许应用内支付");
//首先向AppStore请求恢复交易
[[SKPaymentQueue defaultQueue] restoreCompletedTransactions];
} else {
NSLog(@"不允许应用内支付");
}
}
//判断是否可以应用内支付
- (BOOL) canInAppPayment
{
MyFrint;//你应该根据是否想让越狱的iOS设备允许内支付
if ([[NSFileManager defaultManager] fileExistsAtPath:@"/Applications/Cydia.app"]){
NSLog(@"Jailbroken detected!");
return NO;
}
if ([SKPaymentQueue canMakePayments]) {
return YES;
} else {
return NO;
}
}
//输入正确的帐号后进入 (如果是测试 必须必须使用你注册的沙河账号和密码)
- (void) paymentQueueRestoreCompletedTransactionsFinished:(SKPaymentTransaction *)transaction
{
MyFrint;
[self requestProductData];
}
//请求购买的商品信息
- (void) requestProductData
{
MyFrint;
NSSet * set = [NSSet setWithObjects:kMyInAppIdentifier, nil nil];//可以添加多个商品ID
SKProductsRequest* request = [[SKProductsRequest alloc] initWithProductIdentifiers:set];
request.delegate = self;
[request start];
}
#pragma mark SKProductsRequestDelegate 请求协议 ----------------------------------------------------------
//收到产品信息
- (void) productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response
{
// NSArray *myProduct = response.products;
// NSLog(@"产品付费数量: %d", [myProduct count]);
// NSLog(@"产品Product ID:%@",response.invalidProductIdentifiers);
// SKPayment *payment = nil;
// // populate UI
// for(SKProduct *product in myProduct)
// {
// NSLog(@"\n\nproduct info");
// NSLog(@"SKProduct 描述信息%@", [product description]);
// NSLog(@"产品标题 %@" , product.localizedTitle);
// NSLog(@"产品描述信息: %@" , product.localizedDescription);
// NSLog(@"价格: %@" , product.price);
// NSLog(@"Product id: %@\n\n" , product.productIdentifier);
// payment = [SKPayment paymentWithProduct:product];
// }
MyFrint;
SKPayment* payment = [SKPayment paymentWithProduct:[response.products lastObject]];
NSLog(@"\nPayment:\n productIdentifier=%@, \nrequestData=%@, \nquanlity=%d, \n",payment.productIdentifier,[payment.requestData description],payment.quantity);
[[SKPaymentQueue defaultQueue] addPayment:payment];
[request release];//请求已经生效
}
//请求错误信息
- (void) request:(SKRequest *)request didFailWithError:(NSError *)error
{
MyFrint;
UIAlertView *alerView = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Alert",NULL)
message:[error localizedDescription]
delegate:nil
cancelButtonTitle:NSLocalizedString(@"Close",nil)
otherButtonTitles:nil];
[alerView show];
[alerView release];
[request release];//请求失效
}
- (void) purchasedTransaction:(SKPaymentTransaction *)transaction
{
MyFrint;
}
- (void) requestDidFinish:(SKRequest *)request
{
MyFrint;
}
//然后当用户输入正确的appStore帐号密码后进入(再次说明 如果是测试 必须是你注册的测试账号 不能使用真实的AppleID 否则后果~~~~)
//方法在新交易被创建或更新时都会被调用
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions
{
MyFrint;
for ( SKPaymentTransaction* transaction in transactions )
{
switch (transaction.transactionState)
{
case SKPaymentTransactionStatePurchased:
{//交易完成
[self completeTransaction:transaction];
}
break;
case SKPaymentTransactionStateFailed:
{//交易失败
[self failedTransaction:transaction];
}
break;
case SKPaymentTransactionStateRestored:
{//已经购买过该商品
[self restoreTransaction:transaction];
}
case SKPaymentTransactionStatePurchasing:
{//商品添加进列表
NSLog(@"商品添加进列表==");
break;
}
default:
break;
}
}
}
//玩家等待 这里我想加个转动条 但没成功OC不鸟呀
- (void) activityIndicatorRun
{
spinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite];
spinner.color = [UIColor whiteColor];
spinner.frame = CGRectMake(100, 180.0f, 137.0f, 137.0f);
[spinner startAnimating];
}
//玩家结束等待
- (void) activityIndicatorStop
{
[spinner stopAnimating];
}
//observer在用户成功购买后提供相应的product
- (void)completeTransaction:(SKPaymentTransaction *)transaction
{
MyFrint;
[self activityIndicatorRun];
[self verifyReceiptFromMyServer:transaction];//这个方法是内支付最重要的方法
[self activityIndicatorStop];
if (receiptValid) {
[self recordTransaction:transaction];
//提示服务器刷新数据 ---
CCNotificationCenter::sharedNotificationCenter()->postNotification(kGNetworkNotificationName_Shop_BuyCredit_Successed, NULL);
} else {
[self failedTransaction:transaction];
}
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
}
//处理还原购买 结束交易
- (void) restoreTransaction: (SKPaymentTransaction *)transaction
{
MyFrint;
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
}
//处理失败购买 结束交易
- (void) failedTransaction: (SKPaymentTransaction *)transaction
{
MyFrint;
if (transaction.error.code != SKErrorPaymentCancelled) {
NSLog(@"购买失败");
}
[objc] view
plain copy
print?
<span style="white-space:pre"> </span>//根据项目的实际运行情况看 下面的完全多余.
[objc] view
plain copy
print?
<pre code_snippet_id="105137" snippet_file_name="blog_20131209_2_9929406" name="code" class="objc"> //else {
// NSLog(@"用户取消购买");
//}
[objc] view
plain copy
print?
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
}
//取消登陆帐号密码操作
- (void) paymentQueue:(SKPaymentQueue *) paymentQueue restoreCompletedTransactionsFailedWithError:(NSError *)error
{
MyFrint;
}
//用户成功购买
- (void) recordTransaction:(SKPaymentTransaction *)product
{
MyFrint;
UIAlertView* view = [[UIAlertView alloc] initWithTitle:@"购买结果" message:@"购买成功" delegate:nil cancelButtonTitle:@"确定" otherButtonTitles: nil nil];
[view show];
[view release];
}
//向服务器请求验证
- (void) verifyReceiptFromMyServer:(SKPaymentTransaction *)transaction
{
MyFrint;
//初始化为合法
if ([transaction.payment.productIdentifier isEqualToString:kMyInAppIdentifier]) {
//base64 encode the receipt data for sending
if ([transaction.transactionReceipt base64Encoding] != nil) {
//将数据http post请求发送到我的服务器
//data=base64(json(post))
//字典内容
NSDictionary* postDict = [[NSDictionary alloc] initWithObjectsAndKeys:@"ios",@"mode",
@"verify",@"method",
[NSDictionary dictionaryWithObjectsAndKeys:[self base64Encode:transaction.transactionReceipt],@"receipt",@"YES",@"test", nil nil],@"params",
@"1136",@"uid", nil nil];
//字典转化为json数据
NSError* error = nil;
NSData* jsonData = [NSJSONSerialization dataWithJSONObject:postDict options:NSJSONWritingPrettyPrinted error:&error];
if([jsonData length]>0 && error == nil){
}else if([jsonData length] == 0 && error == nil){
NSLog(@"No data returned after serialization.");
receiptValid = NO;
}else if(error != nil){
NSLog(@"An error happened = %@",error);
receiptValid = NO;
}
//json数据base64
NSString* base64 = [self base64Encode:jsonData];
if ([base64 length]==0 || [base64 isEqualToString:@""]) {
NSLog(@"Base64 error");
receiptValid = NO;
}
NSURL* url = [NSURL URLWithString:MyServerURL];
NSMutableURLRequest* theRequest = [NSMutableURLRequest requestWithURL:url];
[theRequest setHTTPMethod:@"POST"];
[theRequest setValue:[NSString stringWithFormat:@"%d", [jsonData length]] forHTTPHeaderField:@"Content-Length"];
[theRequest setHTTPBody:[[NSString stringWithFormat:@"data=%@", base64] 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 = @"\"status\":0";
if ([receiptStatus length]==0 || [receiptStatus isEqualToString:@""]) {
receiptValid = NO;
}
if ([receiptStatus rangeOfString:str].location != NSNotFound) {
NSLog(@"Yes Yes Yes!!!");
receiptValid = YES;
} else {
receiptValid = NO;
}
[receiptStatus release];
[myerror release];
[response release];
[postDict release];
} else {
NSLog(@"当向服务器发送验证数据时出错!!!");
receiptValid = NO;
}
}
else
{
NSLog(@"无效的商品ID");
receiptValid = NO;
}
}
//将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];
}
//收到内存警告释放资源
- (void) didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
//回收内存
-(void) dealloc
{
[[SKPaymentQueue defaultQueue] removeTransactionObserver:self];//解除监听
[spinner release]; spinner = nil;
[super dealloc];
}
@end
相关文章推荐
- Android样式的开发:Style篇
- 如何快速创建Android模拟器
- Android样式的开发:Property Animation篇
- iOS类中的属性设置背景色(统一)
- Android_异常_IllegalStateException(待完善)
- Android 在 LinearLayout 添加分割线 divider
- Android样式的开发:View Animation篇
- Android样式的开发:drawable汇总篇
- Android样式的开发:layer-list篇
- Security "Crypto" provider deprecated in Android N
- Android样式的开发:selector篇
- 精华阅读第 13 期 |常见的八种导致 APP 内存泄漏的问题
- Android 项目开发注意点
- 精华阅读第 13 期 |常见的八种导致 APP 内存泄漏的问题
- iOS开发经验:高德地图折线或者图形等覆盖物的适配显示
- android studio遇到bosshelper:transformClassesWithInstantRunForDebug
- iOS AppStore企业账号打包发布APP流程详解
- IOS Dev Intro - Object-C Call C C++
- Android 图片存储到指定路径和相册
- JdbcTemplate 版本4以上的queryforObject和queryforList的实现