Cocos2d-Lua 接IOS支付记录

来源:互联网 发布:effect java 中文 编辑:程序博客网 时间:2024/05/16 17:19

网上可以找到Cocos2d-X或者Cocos2d-Js接IOS支付的参考,但是没有Lua的,所以就暂且提供一个我的版本。
没有折腾Lua和C++之间的交互,暂且用着Cocos2d框架提供的LuaObjcBridge,非常简单。一些类名取自IAP Js版本作者。

第一个文件:IAPDelegates.h

#import <Foundation/Foundation.h>#import <StoreKit/StoreKit.h>@class AppController;@interface iAPProductsRequestDelegate : NSObject<SKProductsRequestDelegate>@property (nonatomic, assign) AppController *iosiap;@end@interface iAPTransactionObserver : NSObject<SKPaymentTransactionObserver>@property (nonatomic, assign) AppController *iosiap;@end

第二个文件:IAPDelegates.m

#import <Foundation/Foundation.h>#import "IAPDelegates.h"#import "AppController.h"@implementation iAPProductsRequestDelegate- (void)productsRequest:(SKProductsRequest *)request     didReceiveResponse:(SKProductsResponse *)response{    if (_iosiap.skProducts) {        [(NSArray *)(_iosiap.skProducts) release];    }    _iosiap.skProducts = [response.products retain];}- (void)requestDidFinish:(SKRequest *)request{    [request.delegate release];    [request release];}- (void)request:(SKRequest *)request didFailWithError:(NSError *)error{    NSLog(@"%@", error);}@end@implementation iAPTransactionObserver- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions{    for (SKPaymentTransaction *transaction in transactions) {        if(transaction.transactionState == SKPaymentTransactionStatePurchased){            [_iosiap onPaymentEvent:transaction.payment.productIdentifier andQuantity:transaction.payment.quantity];        }        if (transaction.transactionState != SKPaymentTransactionStatePurchasing) {            [[SKPaymentQueue defaultQueue] finishTransaction: transaction];        }    }}- (void)paymentQueue:(SKPaymentQueue *)queue removedTransactions:(NSArray *)transactions{}@end

主文件,也就是Cocos2d提供的AppController.h 和 AppController.mm:

@class RootViewController;@interface AppController : NSObject <UIApplicationDelegate>{    UIWindow *window;    RootViewController *viewController;}//skProducts would be called outside the class@property (nonatomic, assign) NSArray *skProducts;- (void) onPaymentEvent:(NSString *)productId andQuantity:(NSInteger)count;@end
#import <UIKit/UIKit.h>#import "cocos2d.h"#import "platform/ios/CCLuaObjcBridge.h"#import "AppController.h"#import "AppDelegate.h"#import "RootViewController.h"#import "platform/ios/CCEAGLView-ios.h"#import "IAPDelegates.h"@implementation AppController{    iAPTransactionObserver* skTransactionObserver;    int nLuaFunctionMemoryWarningCallback;    int nLuaFunctionPaySuccessCallback;    NSMutableDictionary* dictOfPayInfo;    BOOL bTriggerAd;}#pragma mark -#pragma mark Application lifecycle// cocos2d application instancestatic AppDelegate s_sharedApplication;static AppController* s_sharedAppController;+ (void)InitIAp:(NSDictionary *) dict{    [s_sharedAppController applicationInitiAP:dict];}+ (void)Charge:(NSDictionary *) dict{    [s_sharedAppController applicationPayRequest:dict];}+ (void)ListenMemoryWarning:(NSDictionary *) dict{    s_sharedAppController->nLuaFunctionMemoryWarningCallback = [[dict objectForKey:@"callback"] intValue];}- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{    cocos2d::Application *app = cocos2d::Application::getInstance();    app->initGLContextAttrs();    cocos2d::GLViewImpl::convertAttrs();    // Override point for customization after application launch.    // Add the view controller's view to the window and display.    window = [[UIWindow alloc] initWithFrame: [[UIScreen mainScreen] bounds]];    CCEAGLView *eaglView = [CCEAGLView viewWithFrame: [window bounds]                                     pixelFormat: (NSString*)cocos2d::GLViewImpl::_pixelFormat                                     depthFormat: cocos2d::GLViewImpl::_depthFormat                              preserveBackbuffer: NO                                      sharegroup: nil                                   multiSampling: NO                                 numberOfSamples: 0 ];    [eaglView setMultipleTouchEnabled:YES];    // Use RootViewController manage CCEAGLView    viewController = [[RootViewController alloc] initWithNibName:nil bundle:nil];    viewController.wantsFullScreenLayout = YES;    viewController.view = eaglView;    // Set RootViewController to window    if ( [[UIDevice currentDevice].systemVersion floatValue] < 6.0)    {        // warning: addSubView doesn't work on iOS6        [window addSubview: viewController.view];    }    else    {        // use this method on ios6        [window setRootViewController:viewController];    }    [window makeKeyAndVisible];    [[UIApplication sharedApplication] setStatusBarHidden: YES];    // IMPORTANT: Setting the GLView should be done after creating the RootViewController    cocos2d::GLView *glview = cocos2d::GLViewImpl::createWithEAGLView(eaglView);    cocos2d::Director::getInstance()->setOpenGLView(glview);    s_sharedAppController = self;    app->run();    return YES;}//初始化IAP- (void)applicationInitiAP:(NSDictionary *) dict{    // Initialize iAp Observer    skTransactionObserver = [[iAPTransactionObserver alloc] init];    ((iAPTransactionObserver *)skTransactionObserver).iosiap = self;    [[SKPaymentQueue defaultQueue] addTransactionObserver:(iAPTransactionObserver *)skTransactionObserver];    int productId = 1;    NSMutableSet *set = [NSMutableSet setWithCapacity:4];//MagicNumber, but doesn't matter.    NSString *productName = nil;    while ((productName = [dict objectForKey:[NSString stringWithFormat:@"productid_%d", productId]]) != nil) {        productId++;        [set addObject:productName];    }    SKProductsRequest *productsRequest = [[SKProductsRequest alloc] initWithProductIdentifiers:set];    iAPProductsRequestDelegate *delegate = [[iAPProductsRequestDelegate alloc] init];    delegate.iosiap = self;    productsRequest.delegate = delegate;    [productsRequest start];}//调用IAP支付, dict中含有{"productId":"xxx", "quantity":1, "callback":xx}- (void)applicationPayRequest:(NSDictionary *) dict{    NSString *productId = [dict objectForKey:@"productId"];    for(int i = 0; i < [self.skProducts count]; i++){        SKProduct *skProduct = [self.skProducts objectAtIndex:i];        if([skProduct.productIdentifier isEqualToString:productId]){            SKMutablePayment *payment = [SKMutablePayment paymentWithProduct:skProduct];            payment.quantity = [[dict objectForKey:@"quantity"] intValue];            [[SKPaymentQueue defaultQueue] addPayment:payment];            self->nLuaFunctionPaySuccessCallback = [[dict objectForKey:@"callback"] intValue];            break;        }    }}- (void)applicationWillResignActive:(UIApplication *)application {    /*     Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.     Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.     */    cocos2d::Director::getInstance()->pause();}- (void)applicationDidBecomeActive:(UIApplication *)application {    /*     Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.     */    cocos2d::Director::getInstance()->resume();}- (void)applicationDidEnterBackground:(UIApplication *)application {    /*     Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.     If your application supports background execution, called instead of applicationWillTerminate: when the user quits.     */    cocos2d::Application::getInstance()->applicationDidEnterBackground();}- (void)applicationWillEnterForeground:(UIApplication *)application {    /*     Called as part of  transition from the background to the inactive state: here you can undo many of the changes made on entering the background.     */    cocos2d::Application::getInstance()->applicationWillEnterForeground();}- (void)applicationWillTerminate:(UIApplication *)application {    /*     Called when the application is about to terminate.     See also applicationDidEnterBackground:.     */}//支付成功的回调- (void) onPaymentEvent:(NSString *)productId andQuantity:(NSInteger)count{    cocos2d::LuaObjcBridge::pushLuaFunctionById(self->nLuaFunctionPaySuccessCallback);    cocos2d::LuaObjcBridge::getStack()->pushLuaValue(cocos2d::LuaValue::stringValue([productId UTF8String]));    cocos2d::LuaObjcBridge::getStack()->executeFunction(1);    cocos2d::LuaObjcBridge::releaseLuaFunctionById(self->nLuaFunctionPaySuccessCallback);}#pragma mark -#pragma mark Memory management- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application {    /*     Free up as much memory as possible by purging cached data objects that can be recreated (or reloaded from disk) later.     */     cocos2d::Director::getInstance()->purgeCachedData();    cocos2d::LuaObjcBridge::pushLuaFunctionById(self->nLuaFunctionMemoryWarningCallback);    cocos2d::LuaObjcBridge::getStack()->executeFunction(0);    //cocos2d::LuaObjcBridge::releaseLuaFunctionById(self->nLuaFunctionMemoryWarningCallback);}- (void)dealloc {    [super dealloc];}@end

最后贴一下lua代码中调用的片段:

function IsIOS()    --Lua的区分了iPad和iPhone,估计是历史包袱。    return (cc.Application:getInstance():getTargetPlatform() == cc.PLATFORM_OS_IPHONE) or (cc.Application:getInstance():getTargetPlatform() == cc.PLATFORM_OS_IPAD)end--下面的是函数里的片段if IsIOS() then    local ok, ret = LuaObjcBridge.callStaticMethod("AppController", "Charge",{            ["productId"]=InfoAboutSDKPay[id],            ["quantity"]=1,            ["callback"]=PaySuccess        })    if(not ok) then        print("AppController.Charge() err", ret)    endend
2 0
原创粉丝点击