日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) >

Cocos 2d-X Lua 游戏添加苹果内购(二) OC和Lua交互代码详解

發(fā)布時(shí)間:2025/7/25 49 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Cocos 2d-X Lua 游戏添加苹果内购(二) OC和Lua交互代码详解 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

這是第二篇


?

? ? ??Cocos 2d-X Lua 游戲添加蘋果內(nèi)購(gòu)(一) 圖文詳解準(zhǔn)備流程

? ? ? 這是前面的第一篇,詳細(xì)的說(shuō)明了怎樣添加內(nèi)購(gòu)項(xiàng)目以及填寫銀行信息提交以及沙盒測(cè)試員的添加使用以及需要我們注意的東西,結(jié)果,被移除首頁(yè)了!前面第一篇的內(nèi)容是這篇的基礎(chǔ),前面那些不弄好,下面的商品信息你是請(qǐng)求不到的,這點(diǎn)需要大家特別注意...有需要前面提到的內(nèi)容的孩子可以點(diǎn)擊鏈接進(jìn)去自己看看!!

? ? ? 這篇就具體的總結(jié)我們Lua和OC交互的內(nèi)容以及內(nèi)購(gòu)具體的代碼以及結(jié)果的測(cè)試說(shuō)明:

?

內(nèi)購(gòu)部分OC的代碼實(shí)現(xiàn)


?

? ? ? 先自己總結(jié)一下整個(gè)支付的流程,下面的代碼部分我們也就按照這個(gè)支付流程來(lái)解讀:

?

最開(kāi)始你首先要做的就是給你的項(xiàng)目添加: StoreKit.framework 框架 ?

以及在你需要寫支付的類中導(dǎo)入:?#import <StoreKit/StoreKit.h>

并且你還得遵守?<SKPaymentTransactionObserver,SKProductsRequestDelegate > 兩個(gè)協(xié)議,后面會(huì)實(shí)現(xiàn)他們相應(yīng)的代理方法。

?

接下來(lái)你初始化了你支付類需要你初始化的東西之后,就開(kāi)始判斷用戶有沒(méi)有禁止了蘋果支付,代碼如下:

// 在這里先判斷是否可以調(diào)用支付 -(void)isPay{// 判斷用戶是否禁止了蘋果支付if ([SKPaymentQueue canMakePayments]) {// 1.獲取產(chǎn)品信息列表[self requestProductData:PRODUCTID];}else{self.alertTitle = @"充值失敗";self.alertMessage = @"您禁止了支付權(quán)限!";#if __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_8_0// 不能進(jìn)行支付進(jìn)行提示[self.viewController presentViewController:self.alertController animated:YES completion:nil]; #else[self.viewController.view addSubview:self.alertView]; #endif} }

?

按照我們最開(kāi)始時(shí)候的流程,接下來(lái)就需要我們?nèi)?chuàng)建?SKProductsRequest?向蘋果服務(wù)器請(qǐng)求商品的信息,具體的代碼如下:

- (void)requestProductData:(NSString *)productId{NSArray * productArray = [[NSArray alloc]initWithObjects:productId, nil];NSSet * productSet = [NSSet setWithArray:productArray];// 創(chuàng)建支付請(qǐng)求SKProductsRequest * productRequest = [[SKProductsRequest alloc]initWithProductIdentifiers:productSet];productRequest.delegate = self;[productRequest start]; }

?

注意: 上面代碼中的?productId 就是我們剛開(kāi)始在開(kāi)發(fā)者后臺(tái)創(chuàng)建新的內(nèi)購(gòu)產(chǎn)品時(shí)候的產(chǎn)品ID,要是不理解的強(qiáng)烈建議先看第一篇文章,得知道什么是產(chǎn)品ID。

#pragma mark -- SKRequestDelegate // 下面的方法會(huì)接收蘋果服務(wù)器返回的商品的產(chǎn)品信息 // Sent immediately before -requestDidFinish: - (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response {// 接收商品的信息NSArray * productInfo = response.products;if (productInfo.count ==0) {NSLog(@"接收到的商品的信息為空!");return;}else{// 打印出商品信息 以下的信息全都是在你開(kāi)發(fā)者賬號(hào)下面添加了內(nèi)購(gòu)項(xiàng)目中填寫for (SKProduct *pro in productInfo) {NSLog(@"顯示名稱:%@", [pro localizedTitle]);NSLog(@"描述:%@", [pro localizedDescription]);NSLog(@"你設(shè)置的價(jià)格單位:%@", [pro price]); // 注意這里的單位,是用你在內(nèi)購(gòu)項(xiàng)目里面設(shè)置的定價(jià)NSLog(@"單位:%@", [pro.priceLocale objectForKey:NSLocaleCurrencySymbol]);NSLog(@"CNY:%@", [pro.priceLocale objectForKey:NSLocaleCurrencyCode]);NSLog(@"測(cè)試商品ID:%@", [pro productIdentifier]);}}// SKProduct對(duì)象包含了在App Store上注冊(cè)的商品的本地化信息。SKProduct *storeProduct = nil;for (SKProduct * pro in productInfo) {if ([pro.productIdentifier isEqualToString:PRODUCTID]) {storeProduct = pro;}}//創(chuàng)建一個(gè)支付對(duì)象,并放到隊(duì)列中self.skMutablePayment = [SKMutablePayment paymentWithProduct:storeProduct];//設(shè)置購(gòu)買的數(shù)量 具體的交易金額就是這里的 數(shù)量 * 開(kāi)發(fā)者賬號(hào)定價(jià)if (self.payParments != 0) {//開(kāi)始調(diào)用支付 self.skMutablePayment.quantity = self.payParments;[[SKPaymentQueue defaultQueue] addPayment:self.skMutablePayment];// 開(kāi)始一個(gè)內(nèi)購(gòu)監(jiān)聽(tīng)[self startObserver];}else{NSLog(@"沒(méi)有設(shè)置購(gòu)買的數(shù)量!!");} }

這一步就走到我們接收到了商品的信息,接下來(lái)要做的事按照前面給的流程圖,就需要我們開(kāi)啟一個(gè)內(nèi)購(gòu)的監(jiān)聽(tīng)。再給大家看到你請(qǐng)求到的商品的基本信息,如下:

?

?

具體的上面的內(nèi)容是什么,大家可以對(duì)比上面的輸出的時(shí)候循環(huán)里面我加了它們各自的信息。

可以看到我們現(xiàn)在是添加了一個(gè)監(jiān)控,開(kāi)始監(jiān)控和結(jié)束監(jiān)控的代碼如下:

- (void)startObserver {if (!self.isObserver) {[[SKPaymentQueue defaultQueue] addTransactionObserver:self];NSLog(@"開(kāi)始監(jiān)聽(tīng) ------ 內(nèi)購(gòu)");self.isObserver = YES;} }- (void)stopObserver {if (self.isObserver) {[[SKPaymentQueue defaultQueue] removeTransactionObserver:self];NSLog(@"移除監(jiān)聽(tīng) ------ 內(nèi)購(gòu)");self.isObserver = NO;} }

?

上面我們就開(kāi)啟了監(jiān)聽(tīng),也開(kāi)始了支付,中間的怎樣使用沙盒測(cè)試賬號(hào)進(jìn)行購(gòu)買的測(cè)試,以及過(guò)程中需要注意的事項(xiàng)我們已經(jīng)總結(jié)過(guò)了,可以看前面的文章。

等支付完成之后,我們就可以收到來(lái)自蘋果支付結(jié)果的回調(diào)了,具體的回調(diào)處理下面的代碼中有詳細(xì)的注釋:?

#pragma mark -- SKPaymentTransactionObserver //<SKPaymentTransactionObserver>千萬(wàn)不要忘記綁定,代碼如下: //監(jiān)聽(tīng)購(gòu)買結(jié)果 //[[SKPaymentQueue defaultQueue] addTransactionObserver:self]; - (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray<SKPaymentTransaction *> *)transactions {SKPaymentTransaction *transaction = transactions.lastObject;switch (transaction.transactionState) {// 購(gòu)買成功case SKPaymentTransactionStatePurchased: {NSData *data = [NSData dataWithContentsOfFile:[[[NSBundle mainBundle] appStoreReceiptURL] path]];// 剛才交易的內(nèi)購(gòu)的清單NSString *receipt = [data base64EncodedStringWithOptions:0];NSLog(@"剛才交易的內(nèi)購(gòu)的清單:%@",receipt);// 對(duì)交易結(jié)果進(jìn)行二次驗(yàn)證[self verifyPruchase];}break;// 交易失敗case SKPaymentTransactionStateFailed: {NSLog(@"交易失敗");// 交易失敗也要回調(diào)服務(wù)端// 將交易從交易隊(duì)列中刪除[[SKPaymentQueue defaultQueue] finishTransaction:transaction];}break;case SKPaymentTransactionStateRestored: {NSLog(@"這是你已經(jīng)購(gòu)買過(guò)該商品!");[[SKPaymentQueue defaultQueue] finishTransaction:transaction];}break;case SKPaymentTransactionStatePurchasing: {NSLog(@"商品添加進(jìn)列表");}break;default: {NSLog(@"這是什么情況啊?");}break;} }

?

接下來(lái)在按照流程走的話就到二次驗(yàn)證支付結(jié)果的,其實(shí)我覺(jué)得這個(gè)過(guò)程放在移動(dòng)端問(wèn)題也不大,整個(gè)過(guò)程走Https,也沒(méi)有什么關(guān)鍵的數(shù)據(jù)怕數(shù)問(wèn)題,不像支付寶和微信支付簽名的過(guò)程一樣那么重要,不過(guò)需要注意的是驗(yàn)證這個(gè)結(jié)果得地址是分開(kāi)的,也就是在開(kāi)發(fā)測(cè)試階段和上線階段的地址是不同的,發(fā)送網(wǎng)絡(luò)POST請(qǐng)求,對(duì)購(gòu)買憑據(jù)進(jìn)行驗(yàn)證:

測(cè)試驗(yàn)證地址:https://sandbox.itunes.apple.com/verifyReceipt

正式驗(yàn)證地址:https://buy.itunes.apple.com/verifyReceipt

下面是具體的支付結(jié)果的驗(yàn)證代碼:

?

#pragma mark 驗(yàn)證購(gòu)買憑據(jù) - (void)verifyPruchase {// 驗(yàn)證憑據(jù),獲取到蘋果返回的交易憑據(jù)// appStoreReceiptURL iOS7.0增加的,購(gòu)買交易完成后,會(huì)將憑據(jù)存放在該地址NSURL *receiptURL = [[NSBundle mainBundle] appStoreReceiptURL];// 從沙盒中獲取到購(gòu)買憑據(jù)NSData *receiptData = [NSData dataWithContentsOfURL:receiptURL];// 發(fā)送網(wǎng)絡(luò)POST請(qǐng)求,對(duì)購(gòu)買憑據(jù)進(jìn)行驗(yàn)證//測(cè)試驗(yàn)證地址:https://sandbox.itunes.apple.com/verifyReceipt//正式驗(yàn)證地址:https://buy.itunes.apple.com/verifyReceiptNSURL *url = [NSURL URLWithString:@"https://sandbox.itunes.apple.com/verifyReceipt"];NSMutableURLRequest *urlRequest =[NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:10.0f];urlRequest.HTTPMethod = @"POST";NSString *encodeStr = [receiptData base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithLineFeed];NSString *payload = [NSString stringWithFormat:@"{\"receipt-data\" : \"%@\"}", encodeStr];NSData *payloadData = [payload dataUsingEncoding:NSUTF8StringEncoding];urlRequest.HTTPBody = payloadData;// 提交驗(yàn)證請(qǐng)求,并獲得官方的驗(yàn)證JSON結(jié)果 iOS9后更改了另外的一個(gè)方法NSData *result = [NSURLConnection sendSynchronousRequest:urlRequest returningResponse:nil error:nil];// 官方驗(yàn)證結(jié)果為空if (result == nil) {NSLog(@"交易驗(yàn)證失敗");return;}// 二次驗(yàn)證返回,在這里給服務(wù)端返回驗(yàn)證結(jié)果NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:result options:NSJSONReadingAllowFragments error:nil];if (dict != nil) {// 比對(duì)字典中以下信息基本上可以保證數(shù)據(jù)安全// bundle_id , application_version , product_id , transaction_idNSLog(@"驗(yàn)證成功!購(gòu)買的商品的信息是:%@", dict);// 在這里回調(diào)Lua文件支付的結(jié)果NSDictionary * receipt = dict[@"receipt"];// 在連續(xù)的交易中,會(huì)有多筆交易產(chǎn)生NSArray * in_app = receipt[@"in_app"];if (in_app.count !=0) {for (NSDictionary * dic in in_app) {// 訂單號(hào)回調(diào)LuaNSString * transaction_id = dic[@"transaction_id"];[self toLuaFunc:self.handlerID backMsg:[transaction_id UTF8String]];} }}else{// 交易不成功,回調(diào)LuaNSString * transaction_id = @" ";[self toLuaFunc:self.handlerID backMsg:[transaction_id UTF8String]];} }

這樣整個(gè)支付其實(shí)已經(jīng)算是完成了的,看的仔細(xì)的朋友應(yīng)該看到請(qǐng)求到回調(diào)結(jié)果之后我們OC回調(diào)Lua了,在這里成功之后我們是回調(diào)了Lua,在Lua倆面利用Socket向服務(wù)器去發(fā)送一個(gè)支付的確定的結(jié)果,下面我們說(shuō)說(shuō)Lua和OC的相互調(diào)用。

?

Lua 調(diào)用 OC


?

? ? ? 下面是自己在做的一個(gè)Lua文件和OC交互的一個(gè)大概的示意圖,如下:

? ? ?

? ? ? 通過(guò)上面的一個(gè)示意圖,在對(duì)比下面的代碼,我們一句句的分析一下整個(gè)流程:

? ? ? 首先是第一步: Lua 文件調(diào)用 Bridge_ios ?著重看一下下面幾句代碼:

-- 點(diǎn)擊跳轉(zhuǎn)到蘋果支付界面 function Bridge_ios.presentApplePayWithParams(payParam, callback)--quantity 價(jià)格 callback回調(diào)local params = {quantity = payParam, scriptHandler = callback}local ok,ret = luaoc.callStaticMethod(BRIDGE_CLASS,"presentApplePayController",params)if not ok then-- 返回值print("luaj error:"..ret) end end

?

其實(shí)直接調(diào)用OC的就是 ?luaoc.callStaticMethod 這個(gè)方法,這個(gè)方法解釋一下:

? ? ? 1、luaoc ? ?local luaoc = require "cocos.cocos2d.luaoc"? ?這個(gè)Lua引入就像OC 的#import 一樣!

? ? ? 2、BRIDGE_CLASS ?這個(gè)表示你和OC的那個(gè)類進(jìn)行交互。

? ? ? 3、"presentApplePayController" 接下來(lái)的這個(gè)參數(shù),就是你OC類里面寫的類方法!

? ? ? 4、params 顧名思義就是參數(shù)的意思,Lua 這里傳過(guò)去的是以 表 的形式,相信懂Lua 的你也清楚,什么是表!?

?再說(shuō)說(shuō)這個(gè)參數(shù):看這一句 ? ?local params = {quantity = payParam, scriptHandler = callback}

? ? ? ?我們把參數(shù)寫成了表的形式,用OC理解牛把它當(dāng)成一個(gè)字典!quantity 是鍵 ?payParam 就是你要傳的值 ?,?scriptHandler 是鍵,callback是值,只不過(guò)它是函數(shù),OC需要回調(diào)的函數(shù),具體的用法我們下面說(shuō)回調(diào)的時(shí)候再說(shuō)。

? ? ? 在上面的調(diào)用中:BRIDGE_CLASS 就是 AppController。

?

?OC 回調(diào) Lua?


?? ??

? ? ? 前面說(shuō)完了Lua 調(diào)用OC,下面接著說(shuō)說(shuō) OC是怎樣回調(diào)Lua 的,具體的根據(jù)下面的代碼解釋:

// Lua 回調(diào)函數(shù) - (void) toLuaFunc: (int)funC backMsg:(std::string)msg{ #if CC_ENABLE_SCRIPT_BINDINGint handler = funC;if (-1 != handler){auto sc = cocos2d::Director::getInstance()->getScheduler();sc->performFunctionInCocosThread([handler, msg](){cocos2d::LuaBridge::pushLuaFunctionById(handler);cocos2d::LuaStack *stack = cocos2d::LuaBridge::getStack();stack->pushString(msg.c_str());stack->executeFunction(1);cocos2d::LuaBridge::releaseLuaFunctionById(handler);});} #endif }

?

最后我們一句一句的解釋一下上面這個(gè)OC回調(diào)Lua的過(guò)程:

LuaBridge::pushLuaFunctionById(handlerID); //壓入需要調(diào)用的方法id(假設(shè)方法為XG)

LuaStack *stack = LuaBridge::getStack(); //獲取lua棧

stack->pushString("oc call lua method..."); //將需要通過(guò)方法XG傳遞給lua的參數(shù)壓入lua棧,這里也就是設(shè)置OC回調(diào)給Lua的參數(shù)

stack->executeFunction(1); //根據(jù)壓入的方法id調(diào)用方法XG,并把XG方法參數(shù)傳遞給lua代碼

LuaBridge::releaseLuaFunctionById(handlerID); //最后記得釋放一下function

?

上面的這整個(gè)過(guò)程,再結(jié)合我們第一篇文章寫得蘋果內(nèi)購(gòu)的圖文詳解流程,基本上一個(gè)完整的游戲添加內(nèi)購(gòu)的過(guò)程就算是結(jié)束了,要是有什么問(wèn)題可以在我的主頁(yè)找我的QQ或者下面留言給我!!

Cocos 2d-X Lua 游戲添加蘋果內(nèi)購(gòu)(一) 圖文詳解準(zhǔn)備流程

?

轉(zhuǎn)載于:https://www.cnblogs.com/zhangxiaoxu/p/7729693.html

總結(jié)

以上是生活随笔為你收集整理的Cocos 2d-X Lua 游戏添加苹果内购(二) OC和Lua交互代码详解的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。