上一个项目用到了In App Purchase,发现现在大家对这个挺关注的,把上次写的总结贴出来给大家看一下,希望对大家有点帮助!
两种方案
一, 我的程序具体步骤
1 添加Storekit.Framework,编写自己的storeObsever,用于处理交易,代码如下,其中completeTransaction和failedTransaction两个函数是自定义的用来处理交易成功与失败其它的就都是SKPaymentTransactionObserver这个代理要求的。
代码
#import <Foundation/Foundation.h>
#import <StoreKit/StoreKit.h>
#import <StoreKit/SKPaymentTransaction.h>
@interface MyStoreObserver : NSObject < SKPaymentTransactionObserver > {
}
- (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;
@end
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions函数用来更新transactions的状态
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions {
for (SKPaymentTransaction* transaction in transactions) {
switch (transaction.transactionState) {case SKPaymentTransactionStatePurchased:
[self completeTransaction:transaction];break;case SKPaymentTransactionStateFailed:
[self failedTransaction:transaction];break;case SKPaymentTransactionStateRestored:
break;default:
break;}
2 在程序中添加storeObsever,最好在applicationDidFinishLaunching中添加}}
MyStoreObserver *tempObserver = [[MyStoreObserver alloc] init];
self.observer = tempObserver;
[tempObserver release];
[[SKPaymentQueue defaultQueue] addTransactionObserver:self.observer];
3 发送付费请求,在相应的类中实现SKProductsRequestDelegate,别忘记定义自己产品的identifier
//请求产品信息
#define kMyFeatureIdentifier yourProductIdentifiers (你自己的产品identifiers)
SKProductsRequest *request= [[SKProductsRequest alloc] initWithProductIdentifiers:
[NSSet setWithObject: kMyFeatureIdentifier]];
request.delegate = self;
[request start];
代理方法相关代码,如果请求成功的话就可以发送付费请求
#pragma mark request delegate
//!收到产品的消息
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response{
SKPayment *payment = [SKPayment paymentWithProductIdentifier:kMyFeatureIdentifier];[[SKPaymentQueue defaultQueue] addPayment:payment];[request autorelease];}
- (void)request:(SKRequest *)request didFailWithError:(NSError *)error{
UIAlertView *alerView = [[UIAlertView alloc] initWithTitle:@"Alert" message:[error localizedDescription] delegate:nil c
ancelButtonTitle:NSLocalizedString(@"Close",nil) otherButtonTitles:nil]; [alerView show]; [alerView release];
}
4 接下来就是Apple自己的付费相关处理了,需要做是就是点击按钮来确定付费
5 交易完成后需要向Apple验证这次交易是否成功,要不然没成功就把产品给别人的话,那就亏了,在1中可以看到当交易成功时会调用自定义的completeTransaction函数,在该函数中我们需要验证transactionReceipt 关于验证SKPaymentTransaction的transactionReceipt transactionReceipt是只有当SKPaymentTransaction完成时,即transactionState 被设置为SKPaymentTransactionStatePurchased 或 SKPaymentTransactionStateRestored时才被创建,因此只有这两种状态下能去验证transactionReceipt
原始思路及具体步骤如下:
a 从SKPaymentTranscation的实例中将transactionReceipt转化为NSString
NSString *temptransactionReceipt = [[NSString alloc] initWithData:[mytransaction transactionReceipt] encoding:NSUTF8StringEncoding];
如果用NSLog的方法将其写出来显示如下,里边有很多的‘+’ { "signature" =
"AZNZdoggtjbU/wMqZ4SSd3lgkxbWr+/zcV7Oez4io7f5oPMliKlQzWW4vj+FLsVyhjyyuPyTSugJ6m4Hrp+CjdAptGZg4iWExoyE6stltg0EfD8Ezggjg5q04ws74pMZ/0aRgjedua8dCMMqR7C8ZjojfOYU6LrFiK7qbUUiV+inMIIDUzCCAjugAwIBAgIIZRSRTdlYBLUwDQYJKoZIhvcNAQEFBQAwfzELMAkGA1UEBhMCVVMxEzARBgNVBAoMCkFwcGxlIEluYy4xJjAkBgNVBAsMHUFwcGxlIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MTMwMQYDVQQDDCpBcHBsZSBpVHVuZXMgU3RvcmUgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDkwNjE1MjIwNTU2WhcNMTQwNjE0MjIwNTU2WjBkMSMwIQYDVQQDDBpQdXJjaGFzZVJlY2VpcHRDZXJ0aWZpY2F0ZTEbMBkGA1UECwwSQXBwbGUgaVR1bmVzIFN0b3JlMRMwEQYDVQQKDApBcHBsZSBJbmMuMQswCQYDVQQGEwJVUzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAytGMXZy3gitJ2JMKFojSDynC/9yYezyn9HBX+u3/3VcpWE2XhcgGKYqNBA1+AewOzrKO774OsokTu4qymEx10ph8UTmsZewB0ESMHBEjF7FN6/HccsQUYC3WagrHnT12HG2Ih0OAm/ZhpWzj0HS4m813LpIyo00sewMvMNL2hkcCAwEAAaNyMHAwDAYDVR0TAQH/BAIwADAfBgNVHSMEGDAWgBQ2HejinYLSARi1MmsO10MLkVhDOjAOBgNVHQ8BAf8EBAMCB4AwHQYDVR0OBBYEFKmDg/IZSMU+ElcIFMzNo36ZXyT1MBAGCiqGSIb3Y2QGBQEEAgUAMA0GCSqGSIb3DQEBBQUAA4IBAQARpJs+O2Y3gL8gHdASkrfZHFpwINd1VcB5VF5LkVpnFz63zylA/3cGIDG91b/d5NIwZjkVt4Bgvd62o/mCbzCsWiNfSKTJVFK1D78BDQoSO2oHTuQuz1BR7xzNHxQZ90zUS6ZX9SC8N3g3A1jEtAyDhZNB+CRBBXLwZdnBUeBsT9QLpjvTnekZcGTnU08zfCjGF3eBJEu9eP6WgexK1xMSp72kEOmYbn6yTi3D4YrcYx4Q3n/57VBP2en8qXWeP5oHDsLTGzLRsWdoB3VxJLrF2ivL8JS8zqC0qyac452pN6xunRuzyyfpaqzQL12BzFEe44xna2byektSbtquA5LNAAAAAA=="; "purchase-info" = "ewoJIml0ZW0taWQiID0gIjMzMDU5OTg4MCI7Cgkib3JpZ2luYWwtdHJhbnNhY3Rpb24taWQiID0gIjEwMDAwMDAwMDAwOTEyNTgiOwoJInB1cmNoYXNlLWRhdGUiID0gIjIwMDktMTAtMTQgMDY6MDY6NTQgRXRjL0dNVCI7CgkicHJvZHVjdC1pZCIgPSAiY29tLnNlbnNreS5jbmFtZXNpZ3B1cmNoYXNlY29uc3VtYWJsZSI7CgkidHJhbnNhY3Rpb24taWQiID0gIjEwMDAwMDAwMDAwOTEyNTgiOwoJInF1YW50aXR5IiA9ICIxIjsKCSJvcmlnaW5hbC1wdXJjaGFzZS1kYXRlIiA9ICIyMDA5LTEwLTE0IDA2OjA2OjU0IEV0Yy9HTVQiOwoJImJpZCIgPSAiY29tLnNlbnNreS5jc2lnbmF0dXJlYXBwIjsKCSJidnJzIiA9ICIxLjAiOwp9"; "pod" = "100"; "signing-status" = "0";}
b然后通过Post的方法将其提交给服务器,在这里只是将transactionReceipt传给服务器,验证由服务器完成。代码如下,
NSString *requestStirng =[NSString stringWithFormat: @"receipt_data=%@",temptransactioReceipt];
requestStirng = [requestStirng stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSData *postData = [NSData dataWithBytes:[requestStirng UTF8String] length:[requestStirng length]];NSMutableURLRequest *connectionRequest = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:[kURL stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]];
[connectionRequest setHTTPMethod:@"POST"];[connectionRequest setTimeoutInterval:120.0];[connectionRequest setCachePolicy:NSURLRequestUseProtocolCachePolicy];[connectionRequest setHTTPBody:postData];出现的错误,服务器用传过去的receipt_data向Apple验证,通不过,但将用NSLog的方法在后台写出的temptransactionreceipt向Apple验证能通过 错误原因 对比发现通过URL传给服务器的字符串不能很好的完成urlEncode,在里边出现的+不能自动进行编码转化,因为在Objective-C 中不能将NSString 真正的实现URL encode ,
解决方法可参考下面的地址
http://simonwoodside.com/weblog/2009/4/22/how_to_really_url_encode/
但当我用上面地址给出的方法进行编码后仍不能解决该问题,原因不明
解决办法:
在将transactionReceipt转化成的NSString传给服务器之前先进行转化,将里边的+转换为%2B , 将步骤a中的代码改为
NSString *temptransactionReceipt = [[NSString alloc] initWithData:[mytransaction transactionReceipt] encoding:NSUTF8StringEncoding];
temptransactionReceipt = [temptransactionReceipt stringByReplacingOccurrencesOfString:@"+" withString:@"%2B"];
6 服务器端验证相关代码 其中XML为自定义的一个类,getHeader所做的工作就是把receipt数据Post给Apple然后得到返回的结果返回
$url = "https://buy.itunes.apple.com/verifyReceipt";/ $receipt = json_encode(array("receipt-data" => base64_encode($receipt_data)));
$response_json = $Xml->getHeader($url, $receipt);
$response = json_decode($response_json['content'], true);
getHeader的代码如下 public function getHeader($url, $data) {
$ch = curl_init();
$timeout = 300; // set to zero for no timeout
curl_setopt($ch, CURLOPT_URL, $url);
// curl_setopt($ch, CURLOPT_ENCODING, 'gzip');
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 1); //post到https
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);//跟随页面的跳转
// curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
$handles = curl_exec($ch);
$header = curl_getinfo($ch);
curl_close($ch);
$header['content'] = $handles;
return $header;
}
二 。项目源码
//
// IAPSecond.h
// SpritePetText026Test
//
// Created by luonan on 13-12-28.
//
//
#import "cocos2d.h"
USING_NS_CC;
#import <StoreKit/StoreKit.h>
@interface APPPay : NSObject<SKProductsRequestDelegate,SKPaymentTransactionObserver>
{
@public
int buyType;
}
+ (APPPay *) sharedHelper;
//+(CCScene *) scene;
- (void) requestProUpgradeProductData;
-(void)RequestProductData;
-(bool)CanMakePay;
-(void)buy:(int)type;
-(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)provideContent:(NSString *)product;
-(void)recordTransaction:(NSString *)product;
-(BOOL)putStringToItunes:(NSData*)iapData;
@end
//
// IAPSecond.m
// SpritePetText026Test
//
// Created by luonan on 13-12-28.
//
//
//
#import "IAPSecond.h"
#include "../../MainView.h"
#include "../../ResManager.h"
#include "../../constants/StringConstant.h"
#include "../../socket/message/NetWaitManager.h"
#if defined(NXPetforTw)
#include "../../channel/appstore/IAPSecond.h"
#else//除了Tw其他都接入TD
#include "TDCCAccount.h"
#include "TalkingDataGA.h"
#endif
enum{
gpmjewel45=0,
gpmjewel450,
gpmjewel750,
gpmjewel1450,
gpmjewel2550,
gpmjewel3600,
gpmjewel5400,
}buyCoinsTag;
#if defined (SpritePetText026Test)
//#define ProductID_gpmjewel1450 @"gpm_jewel_1450"//900
//#define ProductID_gpmjewel2550 @"gpm_jewel_2550" //1500
//#define ProductID_gpmjewel3600 @"gpm_jewel_3600" //2100
//#define ProductID_gpmjewel450 @"gpm_jewel_450" //$300
//#define ProductID_gpmjewel45 @"gpm_jewel_45" //$30
//#define ProductID_gpmjewel5400 @"gpm_jewel_5400" //3000
//#define ProductID_gpmjewel1750 @"gpm_jewel_750"//450
#define ProductID_gpmjewel1450 @"gpmjewel1450"//900
#define ProductID_gpmjewel2550 @"gpmjewel2550" //1500
#define ProductID_gpmjewel3600 @"gpmjewel3600" //2100
#define ProductID_gpmjewel450 @"gpmjewel450" //$300
#define ProductID_gpmjewel45 @"gpmjewel45" //$30
#define ProductID_gpmjewel5400 @"gpmjewel5400" //3000
#define ProductID_gpmjewel1750 @"gpmjewel750"//450
#else
#define ProductID_gpmjewel1450 @"gpmjewel1450"//900
#define ProductID_gpmjewel2550 @"gpmjewel2550" //1500
#define ProductID_gpmjewel3600 @"gpmjewel3600" //2100
#define ProductID_gpmjewel450 @"gpmjewel450" //$300
#define ProductID_gpmjewel45 @"gpmjewel45" //$30
#define ProductID_gpmjewel5400 @"gpmjewel5400" //3000
#define ProductID_gpmjewel1750 @"gpmjewel750"//450
#endif
USING_NS_CC;
static APPPay * _sharedHelper;
@implementation APPPay
+ (APPPay *) sharedHelper {
if (_sharedHelper != nil) {
// [[SKPaymentQueue defaultQueue] addTransactionObserver:self];
return _sharedHelper;
}
_sharedHelper = [APPPay alloc];
return _sharedHelper;
}
//+(CCScene *) scene
//{
// CCScene *scene = [CCScene node];
// HelloWorldLayer *layer = [HelloWorldLayer node];
// [scene addChild: layer];
// return scene;
//}
-(id)init
{
return self;
}
-(void)buy:(int)type
{
buyType = type;
if ([SKPaymentQueue canMakePayments]) {
//[[SKPaymentQueue defaultQueue] restoreCompletedTransactions];
[self RequestProductData];
CCLOG("允许程序内付费购买");
}
else
{
CCLOG("不允许程序内付费购买");
string buyerror = "buyerror";
// MainView::showToast(buyerror);
UIAlertView *alerView = [[UIAlertView alloc] initWithTitle:@"Alert"
message:@"You can‘t purchase in app store(没允许应用程序内购买)"
delegate:nilcancelButtonTitle:NSLocalizedString(@"Close(关闭)",nil) otherButtonTitles:nil];
[alerView show];
[alerView release];
}
}
-(bool)CanMakePay
{
return [SKPaymentQueue canMakePayments];
}
-(void)RequestProductData
{
CCLOG("---------请求对应的产品信息------------");
NSArray *product = nil;
switch (buyType) {
case gpmjewel750:
product=[[NSArray alloc] initWithObjects:ProductID_gpmjewel1750,nil];
break;
case gpmjewel5400:
product=[[NSArray alloc] initWithObjects:ProductID_gpmjewel5400,nil];
break;
case gpmjewel45:
product=[[NSArray alloc] initWithObjects:ProductID_gpmjewel45,nil];
break;
case gpmjewel450:
product=[[NSArray alloc] initWithObjects:ProductID_gpmjewel450,nil];
break;
case gpmjewel3600:
product=[[NSArray alloc] initWithObjects:ProductID_gpmjewel3600,nil];
break;
case gpmjewel2550:
product=[[NSArray alloc] initWithObjects:ProductID_gpmjewel2550,nil];
break;
case gpmjewel1450:
product=[[NSArray alloc] initWithObjects:ProductID_gpmjewel1450,nil];
break;
default:
break;
}
NSSet *nsset = [NSSet setWithArray:product];
SKProductsRequest *request=[[SKProductsRequest alloc] initWithProductIdentifiers: nsset];
request.delegate=self;
[request start];
[product release];
}
//<SKProductsRequestDelegate> 请求协议
//收到的产品信息
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response{
NSLog(@"-----------收到产品反馈信息--------------");
NSArray *myProduct = response.products;
NSLog(@"产品Product ID:%@",response.invalidProductIdentifiers);
NSLog(@"产品付费数量: %d", [myProduct count]);
// populate UI
for(SKProduct *product in myProduct){
NSLog(@"product info");
NSLog(@"SKProduct 描述信息%@", [product description]);
NSLog(@"产品标题 %@" , product.localizedTitle);
NSLog(@"产品描述信息: %@" , product.localizedDescription);
NSLog(@"价格: %@" , product.price);
NSLog(@"Product id: %@" , product.productIdentifier);
}
// [TDGAVirtualCurrency onChargeRequst:"@sss" iapId:"@aaa" currencyAmount:1000 currencyType:"@dddd" virtualCurrencyAmount:100 paymentType:"@qqqq" ];
SKPayment *payment = nil;
switch (buyType) {
case gpmjewel1450:
payment = [SKPayment paymentWithProductIdentifier:ProductID_gpmjewel1450]; //支付$0.99
break;
case gpmjewel2550:
payment = [SKPayment paymentWithProductIdentifier:ProductID_gpmjewel2550]; //支付$1.99
break;
case gpmjewel3600:
payment = [SKPayment paymentWithProductIdentifier:ProductID_gpmjewel3600]; //支付$9.99
break;
case gpmjewel45:
payment = [SKPayment paymentWithProductIdentifier:ProductID_gpmjewel45]; //支付$19.99
break;
case gpmjewel450:
payment = [SKPayment paymentWithProductIdentifier:ProductID_gpmjewel450]; //支付$19.99
break;
case gpmjewel5400:
payment = [SKPayment paymentWithProductIdentifier:ProductID_gpmjewel5400]; //支付$29.99
break;
case gpmjewel750:
payment = [SKPayment paymentWithProductIdentifier:ProductID_gpmjewel1750]; //支付$29.99
break;
default:
break;
}
CCLOG("---------发送购买请求------------");
[[SKPaymentQueue defaultQueue] addPayment:payment];
[request autorelease];
}
- (void)requestProUpgradeProductData
{
CCLOG("------请求升级数据---------");
NSSet *productIdentifiers = [NSSet setWithObject:ProductID_gpmjewel1450];
SKProductsRequest* productsRequest = [[SKProductsRequest alloc] initWithProductIdentifiers:productIdentifiers];
productsRequest.delegate = self;
[productsRequest start];
}
//弹出错误信息
- (void)request:(SKRequest *)request didFailWithError:(NSError *)error{
CCLOG("-------弹出错误信息----------");
NetWaitManager::getInstance()->endNormalWaitting();
UIAlertView *alerView = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Alert",NULL) message:[error localizedDescription]
delegate:nilcancelButtonTitle:NSLocalizedString(@"Close",nil) otherButtonTitles:nil];
[alerView show];
[alerView release];
}
-(void) requestDidFinish:(SKRequest *)request
{
NSLog(@"----------反馈信息结束--------------");
}
-(void) PurchasedTransaction: (SKPaymentTransaction *)transaction{
CCLOG("-----PurchasedTransaction----");
NSArray *transactions =[[NSArray alloc] initWithObjects:transaction, nil];
[self paymentQueue:[SKPaymentQueue defaultQueue] updatedTransactions:transactions];
[transactions release];
}
//<SKPaymentTransactionObserver> 千万不要忘记绑定,代码如下:
//----监听购买结果
//[[SKPaymentQueue defaultQueue] addTransactionObserver:self];
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions//交易结果
{
NetWaitManager::getInstance()->endNormalWaitting();
CCLOG("-----paymentQueue--------");
for (SKPaymentTransaction *transaction in transactions)
{
switch (transaction.transactionState)
{
// NSData* d = transaction.transactionReceipt;
case SKPaymentTransactionStatePurchased://交易完成
{
[self completeTransaction:transaction];
CCLOG("-----交易完成 --------");
CCLOG("不允许程序内付费购买");
if([self putStringToItunes:transaction.transactionReceipt]){
//这里给用户添加金币,装备
}
// string chargeOk =ResManager::getInstance()->getString(StringConstant::chargeOk);
// MainView::showToast(chargeOk);
UIAlertView *alerView = [[UIAlertView alloc] initWithTitle:@"Alert"
message:@"購買成功啦"
delegate:nilcancelButtonTitle:NSLocalizedString(@"Close(關閉)",nil) otherButtonTitles:nil];
[alerView show];
CCLOG("order haved call on ");
[alerView release];
}
break;
case SKPaymentTransactionStateFailed://交易失败
{
[self failedTransaction:transaction];
CCLOG("-----交易失败 --------");
string chargeError = ResManager::getInstance()->getString(StringConstant::chargeError);
MainView::showToast(chargeError);
// UIAlertView *alerView2 = [[UIAlertView alloc] initWithTitle:@"Alert"
// message:@"購買失敗,請重新嘗試購買~"
// delegate:nil cancelButtonTitle:NSLocalizedString(@"Close(關閉)",nil) otherButtonTitles:nil];
//
// [alerView2 show];
// [alerView2 release];
}
break;
case SKPaymentTransactionStateRestored://已经购买过该商品
{
[self restoreTransaction:transaction];
CCLOG("-----已经购买过该商品 --------");
MainView::showToast("buyed ");
}
case SKPaymentTransactionStatePurchasing: //商品添加进列表
CCLOG("-----商品添加进列表 --------");
break;
default:
break;
}
}
}
- (void) completeTransaction: (SKPaymentTransaction *)transaction
{
CCLOG("-----completeTransaction--------");
// Your application should implement these two methods.
NSString *product = transaction.payment.productIdentifier;
if ([product length] > 0) {
NSArray *tt = [product componentsSeparatedByString:@"."];
NSString *bookid = [tt lastObject];
if ([bookid length] > 0) {
[self recordTransaction:bookid];
[self provideContent:bookid];
}
}
// Remove the transaction from the payment queue.
[[SKPaymentQueue defaultQueue] finishTransaction: transaction];
}
//记录交易
-(void)recordTransaction:(NSString *)product{
CCLOG("-----记录交易--------");
}
//处理下载内容
-(void)provideContent:(NSString *)product{
CCLOG("-----下载--------");
}
- (void) failedTransaction: (SKPaymentTransaction *)transaction{
NSLog(@"失败");
if (transaction.error.code != SKErrorPaymentCancelled)
{
}
[[SKPaymentQueue defaultQueue] finishTransaction: transaction];
}
-(void) paymentQueueRestoreCompletedTransactionsFinished: (SKPaymentTransaction *)transaction{
}
- (void) restoreTransaction: (SKPaymentTransaction *)transaction
{
NSLog(@" 交易恢复处理");
}
-(void) paymentQueue:(SKPaymentQueue *) paymentQueue restoreCompletedTransactionsFailedWithError:(NSError *)error{
CCLOG("-------paymentQueue----");
}
#pragma mark connection delegate
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
NSLog(@"%@", [[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] autorelease]);
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection{
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response{
switch([(NSHTTPURLResponse *)response statusCode]) {
case 200:
case 206:
break;
case 304:
break;
case 400:
break;
case 404:
break;
case 416:
break;
case 403:
break;
case 401:
case 500:
break;
default:
break;
}
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
NSLog(@"test");
}
-(void)dealloc
{
[[SKPaymentQueue defaultQueue] removeTransactionObserver:self];//解除监听
[super dealloc];
}
-(BOOL)putStringToItunes:(NSData*)iapData{//用户购成功的transactionReceipt
NSString* adStr= [[NSString alloc] initWithData:iapData encoding://NSASCIIStringEncoding
NSUTF8StringEncoding];
NSLog(@"adStr: %@",adStr);
// NSString*encodingStr = [iapData base64EncodedString];
//
// NSLog(@"encodingStr: %@",encodingStr);
const char* destDir = [adStr UTF8String];
//CCUserDefault::sharedUserDefault()->setStringForKey("charge", destDir);
NetDataSend::getInstance()->sendIOSCharge(destDir);
return true;
/**
NSString *URL=@"https://sandbox.itunes.apple.com/verifyReceipt";
//https://buy.itunes.apple.com/verifyReceipt 测试
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];// autorelease];
[request setURL:[NSURL URLWithString:URL]];
[request setHTTPMethod:@"POST"];
//设置contentType
[request addValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
//设置Content-Length
[request setValue:[NSString stringWithFormat:@"%d", [encodingStr length]] forHTTPHeaderField:@"Content-Length"];
NSDictionary* body = [NSDictionary dictionaryWithObjectsAndKeys:encodingStr, @"receipt-data", nil];
SBJsonWriter *writer = [SBJsonWriter new];
[request setHTTPBody:[[writer stringWithObject:body] dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES]];
NSHTTPURLResponse *urlResponse=nil;
NSError *errorr=nil;
NSData *receivedData = [NSURLConnection sendSynchronousRequest:request
returningResponse:&urlResponse
error:&errorr];
//解析
NSString *results=[[NSString alloc]initWithBytes:[receivedData bytes] length:[receivedData length] encoding:NSUTF8StringEncoding];
NSLog(@"yhh; %@",results);
NSDictionary*dic = [results JSONValue];
if([[dic objectForKey:@"status"] intValue]==0){//注意,status=@"0" 是验证收据成功
return true;
}
return false;**/
}
@end
参考
http://www.cocoachina.com/bbs/read.php?tid-11357.html
//
// IAPSecond.h
// SpritePetText026Test
//
// Created by luonan on 13-12-28.
//
//
#import "cocos2d.h"
USING_NS_CC;
#import <StoreKit/StoreKit.h>
@interface APPPay : NSObject<SKProductsRequestDelegate,SKPaymentTransactionObserver>
{
@public
int buyType;
}
+ (APPPay *) sharedHelper;
//+(CCScene *) scene;
- (void) requestProUpgradeProductData;
-(void)RequestProductData;
-(bool)CanMakePay;
-(void)buy:(int)type;
-(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)provideContent:(NSString *)product;
-(void)recordTransaction:(NSString *)product;
-(BOOL)putStringToItunes:(NSData*)iapData;
@end
//
// IAPSecond.m
// SpritePetText026Test
//
// Created by luonan on 13-12-28.
//
//
//
#import "IAPSecond.h"
#include "../../MainView.h"
#include "../../ResManager.h"
#include "../../constants/StringConstant.h"
#include "../../socket/message/NetWaitManager.h"
#if defined(NXPetforTw)
#include "../../channel/appstore/IAPSecond.h"
#else//除了Tw其他都接入TD
#include "TDCCAccount.h"
#include "TalkingDataGA.h"
#endif
enum{
gpmjewel45=0,
gpmjewel450,
gpmjewel750,
gpmjewel1450,
gpmjewel2550,
gpmjewel3600,
gpmjewel5400,
}buyCoinsTag;
#if defined (SpritePetText026Test)
//#define ProductID_gpmjewel1450 @"gpm_jewel_1450"//900
//#define ProductID_gpmjewel2550 @"gpm_jewel_2550" //1500
//#define ProductID_gpmjewel3600 @"gpm_jewel_3600" //2100
//#define ProductID_gpmjewel450 @"gpm_jewel_450" //$300
//#define ProductID_gpmjewel45 @"gpm_jewel_45" //$30
//#define ProductID_gpmjewel5400 @"gpm_jewel_5400" //3000
//#define ProductID_gpmjewel1750 @"gpm_jewel_750"//450
#define ProductID_gpmjewel1450 @"gpmjewel1450"//900
#define ProductID_gpmjewel2550 @"gpmjewel2550" //1500
#define ProductID_gpmjewel3600 @"gpmjewel3600" //2100
#define ProductID_gpmjewel450 @"gpmjewel450" //$300
#define ProductID_gpmjewel45 @"gpmjewel45" //$30
#define ProductID_gpmjewel5400 @"gpmjewel5400" //3000
#define ProductID_gpmjewel1750 @"gpmjewel750"//450
#else
#define ProductID_gpmjewel1450 @"gpmjewel1450"//900
#define ProductID_gpmjewel2550 @"gpmjewel2550" //1500
#define ProductID_gpmjewel3600 @"gpmjewel3600" //2100
#define ProductID_gpmjewel450 @"gpmjewel450" //$300
#define ProductID_gpmjewel45 @"gpmjewel45" //$30
#define ProductID_gpmjewel5400 @"gpmjewel5400" //3000
#define ProductID_gpmjewel1750 @"gpmjewel750"//450
#endif
USING_NS_CC;
static APPPay * _sharedHelper;
@implementation APPPay
+ (APPPay *) sharedHelper {
if (_sharedHelper != nil) {
// [[SKPaymentQueue defaultQueue] addTransactionObserver:self];
return _sharedHelper;
}
_sharedHelper = [APPPay alloc];
return _sharedHelper;
}
//+(CCScene *) scene
//{
// CCScene *scene = [CCScene node];
// HelloWorldLayer *layer = [HelloWorldLayer node];
// [scene addChild: layer];
// return scene;
//}
-(id)init
{
return self;
}
-(void)buy:(int)type
{
buyType = type;
if ([SKPaymentQueue canMakePayments]) {
//[[SKPaymentQueue defaultQueue] restoreCompletedTransactions];
[self RequestProductData];
CCLOG("允许程序内付费购买");
}
else
{
CCLOG("不允许程序内付费购买");
string buyerror = "buyerror";
// MainView::showToast(buyerror);
UIAlertView *alerView = [[UIAlertView alloc] initWithTitle:@"Alert"
message:@"You can‘t purchase in app store(没允许应用程序内购买)"
delegate:nilcancelButtonTitle:NSLocalizedString(@"Close(关闭)",nil) otherButtonTitles:nil];
[alerView show];
[alerView release];
}
}
-(bool)CanMakePay
{
return [SKPaymentQueue canMakePayments];
}
-(void)RequestProductData
{
CCLOG("---------请求对应的产品信息------------");
NSArray *product = nil;
switch (buyType) {
case gpmjewel750:
product=[[NSArray alloc] initWithObjects:ProductID_gpmjewel1750,nil];
break;
case gpmjewel5400:
product=[[NSArray alloc] initWithObjects:ProductID_gpmjewel5400,nil];
break;
case gpmjewel45:
product=[[NSArray alloc] initWithObjects:ProductID_gpmjewel45,nil];
break;
case gpmjewel450:
product=[[NSArray alloc] initWithObjects:ProductID_gpmjewel450,nil];
break;
case gpmjewel3600:
product=[[NSArray alloc] initWithObjects:ProductID_gpmjewel3600,nil];
break;
case gpmjewel2550:
product=[[NSArray alloc] initWithObjects:ProductID_gpmjewel2550,nil];
break;
case gpmjewel1450:
product=[[NSArray alloc] initWithObjects:ProductID_gpmjewel1450,nil];
break;
default:
break;
}
NSSet *nsset = [NSSet setWithArray:product];
SKProductsRequest *request=[[SKProductsRequest alloc] initWithProductIdentifiers: nsset];
request.delegate=self;
[request start];
[product release];
}
//<SKProductsRequestDelegate> 请求协议
//收到的产品信息
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response{
NSLog(@"-----------收到产品反馈信息--------------");
NSArray *myProduct = response.products;
NSLog(@"产品Product ID:%@",response.invalidProductIdentifiers);
NSLog(@"产品付费数量: %d", [myProduct count]);
// populate UI
for(SKProduct *product in myProduct){
NSLog(@"product info");
NSLog(@"SKProduct 描述信息%@", [product description]);
NSLog(@"产品标题 %@" , product.localizedTitle);
NSLog(@"产品描述信息: %@" , product.localizedDescription);
NSLog(@"价格: %@" , product.price);
NSLog(@"Product id: %@" , product.productIdentifier);
}
// [TDGAVirtualCurrency onChargeRequst:"@sss" iapId:"@aaa" currencyAmount:1000 currencyType:"@dddd" virtualCurrencyAmount:100 paymentType:"@qqqq" ];
SKPayment *payment = nil;
switch (buyType) {
case gpmjewel1450:
payment = [SKPayment paymentWithProductIdentifier:ProductID_gpmjewel1450]; //支付$0.99
break;
case gpmjewel2550:
payment = [SKPayment paymentWithProductIdentifier:ProductID_gpmjewel2550]; //支付$1.99
break;
case gpmjewel3600:
payment = [SKPayment paymentWithProductIdentifier:ProductID_gpmjewel3600]; //支付$9.99
break;
case gpmjewel45:
payment = [SKPayment paymentWithProductIdentifier:ProductID_gpmjewel45]; //支付$19.99
break;
case gpmjewel450:
payment = [SKPayment paymentWithProductIdentifier:ProductID_gpmjewel450]; //支付$19.99
break;
case gpmjewel5400:
payment = [SKPayment paymentWithProductIdentifier:ProductID_gpmjewel5400]; //支付$29.99
break;
case gpmjewel750:
payment = [SKPayment paymentWithProductIdentifier:ProductID_gpmjewel1750]; //支付$29.99
break;
default:
break;
}
CCLOG("---------发送购买请求------------");
[[SKPaymentQueue defaultQueue] addPayment:payment];
[request autorelease];
}
- (void)requestProUpgradeProductData
{
CCLOG("------请求升级数据---------");
NSSet *productIdentifiers = [NSSet setWithObject:ProductID_gpmjewel1450];
SKProductsRequest* productsRequest = [[SKProductsRequest alloc] initWithProductIdentifiers:productIdentifiers];
productsRequest.delegate = self;
[productsRequest start];
}
//弹出错误信息
- (void)request:(SKRequest *)request didFailWithError:(NSError *)error{
CCLOG("-------弹出错误信息----------");
NetWaitManager::getInstance()->endNormalWaitting();
UIAlertView *alerView = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Alert",NULL) message:[error localizedDescription]
delegate:nilcancelButtonTitle:NSLocalizedString(@"Close",nil) otherButtonTitles:nil];
[alerView show];
[alerView release];
}
-(void) requestDidFinish:(SKRequest *)request
{
NSLog(@"----------反馈信息结束--------------");
}
-(void) PurchasedTransaction: (SKPaymentTransaction *)transaction{
CCLOG("-----PurchasedTransaction----");
NSArray *transactions =[[NSArray alloc] initWithObjects:transaction, nil];
[self paymentQueue:[SKPaymentQueue defaultQueue] updatedTransactions:transactions];
[transactions release];
}
//<SKPaymentTransactionObserver> 千万不要忘记绑定,代码如下:
//----监听购买结果
//[[SKPaymentQueue defaultQueue] addTransactionObserver:self];
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions//交易结果
{
NetWaitManager::getInstance()->endNormalWaitting();
CCLOG("-----paymentQueue--------");
for (SKPaymentTransaction *transaction in transactions)
{
switch (transaction.transactionState)
{
// NSData* d = transaction.transactionReceipt;
case SKPaymentTransactionStatePurchased://交易完成
{
[self completeTransaction:transaction];
CCLOG("-----交易完成 --------");
CCLOG("不允许程序内付费购买");
if([self putStringToItunes:transaction.transactionReceipt]){
//这里给用户添加金币,装备
}
// string chargeOk =ResManager::getInstance()->getString(StringConstant::chargeOk);
// MainView::showToast(chargeOk);
UIAlertView *alerView = [[UIAlertView alloc] initWithTitle:@"Alert"
message:@"購買成功啦"
delegate:nilcancelButtonTitle:NSLocalizedString(@"Close(關閉)",nil) otherButtonTitles:nil];
[alerView show];
CCLOG("order haved call on ");
[alerView release];
}
break;
case SKPaymentTransactionStateFailed://交易失败
{
[self failedTransaction:transaction];
CCLOG("-----交易失败 --------");
string chargeError = ResManager::getInstance()->getString(StringConstant::chargeError);
MainView::showToast(chargeError);
// UIAlertView *alerView2 = [[UIAlertView alloc] initWithTitle:@"Alert"
// message:@"購買失敗,請重新嘗試購買~"
// delegate:nil cancelButtonTitle:NSLocalizedString(@"Close(關閉)",nil) otherButtonTitles:nil];
//
// [alerView2 show];
// [alerView2 release];
}
break;
case SKPaymentTransactionStateRestored://已经购买过该商品
{
[self restoreTransaction:transaction];
CCLOG("-----已经购买过该商品 --------");
MainView::showToast("buyed ");
}
case SKPaymentTransactionStatePurchasing: //商品添加进列表
CCLOG("-----商品添加进列表 --------");
break;
default:
break;
}
}
}
- (void) completeTransaction: (SKPaymentTransaction *)transaction
{
CCLOG("-----completeTransaction--------");
// Your application should implement these two methods.
NSString *product = transaction.payment.productIdentifier;
if ([product length] > 0) {
NSArray *tt = [product componentsSeparatedByString:@"."];
NSString *bookid = [tt lastObject];
if ([bookid length] > 0) {
[self recordTransaction:bookid];
[self provideContent:bookid];
}
}
// Remove the transaction from the payment queue.
[[SKPaymentQueue defaultQueue] finishTransaction: transaction];
}
//记录交易
-(void)recordTransaction:(NSString *)product{
CCLOG("-----记录交易--------");
}
//处理下载内容
-(void)provideContent:(NSString *)product{
CCLOG("-----下载--------");
}
- (void) failedTransaction: (SKPaymentTransaction *)transaction{
NSLog(@"失败");
if (transaction.error.code != SKErrorPaymentCancelled)
{
}
[[SKPaymentQueue defaultQueue] finishTransaction: transaction];
}
-(void) paymentQueueRestoreCompletedTransactionsFinished: (SKPaymentTransaction *)transaction{
}
- (void) restoreTransaction: (SKPaymentTransaction *)transaction
{
NSLog(@" 交易恢复处理");
}
-(void) paymentQueue:(SKPaymentQueue *) paymentQueue restoreCompletedTransactionsFailedWithError:(NSError *)error{
CCLOG("-------paymentQueue----");
}
#pragma mark connection delegate
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
NSLog(@"%@", [[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] autorelease]);
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection{
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response{
switch([(NSHTTPURLResponse *)response statusCode]) {
case 200:
case 206:
break;
case 304:
break;
case 400:
break;
case 404:
break;
case 416:
break;
case 403:
break;
case 401:
case 500:
break;
default:
break;
}
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
NSLog(@"test");
}
-(void)dealloc
{
[[SKPaymentQueue defaultQueue] removeTransactionObserver:self];//解除监听
[super dealloc];
}
-(BOOL)putStringToItunes:(NSData*)iapData{//用户购成功的transactionReceipt
NSString* adStr= [[NSString alloc] initWithData:iapData encoding://NSASCIIStringEncoding
NSUTF8StringEncoding];
NSLog(@"adStr: %@",adStr);
// NSString*encodingStr = [iapData base64EncodedString];
//
// NSLog(@"encodingStr: %@",encodingStr);
const char* destDir = [adStr UTF8String];
//CCUserDefault::sharedUserDefault()->setStringForKey("charge", destDir);
NetDataSend::getInstance()->sendIOSCharge(destDir);
return true;
/**
NSString *URL=@"https://sandbox.itunes.apple.com/verifyReceipt";
//https://buy.itunes.apple.com/verifyReceipt 测试
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];// autorelease];
[request setURL:[NSURL URLWithString:URL]];
[request setHTTPMethod:@"POST"];
//设置contentType
[request addValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
//设置Content-Length
[request setValue:[NSString stringWithFormat:@"%d", [encodingStr length]] forHTTPHeaderField:@"Content-Length"];
NSDictionary* body = [NSDictionary dictionaryWithObjectsAndKeys:encodingStr, @"receipt-data", nil];
SBJsonWriter *writer = [SBJsonWriter new];
[request setHTTPBody:[[writer stringWithObject:body] dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES]];
NSHTTPURLResponse *urlResponse=nil;
NSError *errorr=nil;
NSData *receivedData = [NSURLConnection sendSynchronousRequest:request
returningResponse:&urlResponse
error:&errorr];
//解析
NSString *results=[[NSString alloc]initWithBytes:[receivedData bytes] length:[receivedData length] encoding:NSUTF8StringEncoding];
NSLog(@"yhh; %@",results);
NSDictionary*dic = [results JSONValue];
if([[dic objectForKey:@"status"] intValue]==0){//注意,status=@"0" 是验证收据成功
return true;
}
return false;**/
}
@end