cocos2dx lua在IOS实现支付机制

ios支付需要用到storekit

以下是xcode支付代码:

//
// IosPay.m
// blue
//
// Created by pyair on 2021/8/13.
//

#import <Foundation/Foundation.h>
#import <StoreKit/StoreKit.h>
#include "scripting/lua-bindings/manual/CCLuaBridge.h"
#include "scripting/lua-bindings/manual/CCLuaEngine.h"
#include "cocos2d.h"

#import "IosPay.h"

@implementation IosPay

+(void) setStoreReview{
NSLog(@"call setStoreReview");
[SKStoreReviewController requestReview];
}

+(void) buyVip_1:(NSDictionary *)dict{
IosPay * my = [IosPay new];
NSString *orderId = [dict valueForKey : @"orderId" ];
int handlerID = (int)[[dict objectForKey:@"callBack"] integerValue];
[my requestPay_1:orderId handleId:handlerID];
}

-(void) requestPay_1:(NSString *)productId handleId:(int) handleId{
//如果app允许applepay
if ([SKPaymentQueue canMakePayments]) {
NSLog(@"canMakePayments");
self->orderId = productId;
self->callBack_HandleID = handleId;
self->buyOrRestore = 1;
//7.这里的VIP_1,他们是通过这个ID进行联系的。
NSArray *product = [[NSArray alloc] initWithObjects:productId,nil];
NSSet *nsset = [NSSet setWithArray:product];
// 8.初始化请求
SKProductsRequest *request = [[SKProductsRequest alloc] initWithProductIdentifiers:nsset];
request.delegate = self;
// 9.开始请求
[request start];
}
else{
NSLog(@"canNotMakePayments");
}
}

// 下面的方法会接收苹果服务器返回的商品的产品信息
// Sent immediately before -requestDidFinish:
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response {
// 接收商品的信息
NSArray * productInfo = response.products;
if (productInfo.count ==0) {
NSLog(@"接收到的商品的信息为空!");
return;
}else{
//打印出商品信息以下的信息全都是在你开发者账号下面添加了内购项目中填写
for (SKProduct *pro in productInfo) {
NSLog(@"显示名称:%@", [pro localizedTitle]);
NSLog(@"描述:%@", [pro localizedDescription]);
NSLog(@"你设置的价格单位:%@", [pro price]);
//注意这里的单位,是用你在内购项目里面设置的定价
NSLog(@"单位:%@", [pro.priceLocale objectForKey:NSLocaleCurrencySymbol]);
NSLog(@"CNY:%@", [pro.priceLocale objectForKey:NSLocaleCurrencyCode]);
NSLog(@"测试商品ID:%@", [pro productIdentifier]);
}
}
// SKProduct对象包含了在App Store上注册的商品的本地化信息。
SKProduct *storeProduct = nil;
for (SKProduct * pro in productInfo) {
if ([pro.productIdentifier isEqualToString:self->orderId]) {
storeProduct = pro;
}
}

// 开始一个内购监听
[self startObserver];
//创建一个支付对象,并放到队列中
SKPayment *payment = [SKPayment paymentWithProduct:storeProduct];
[[SKPaymentQueue defaultQueue] addPayment:payment];
}

- (void)startObserver {
if (!self->isObserver) {

[[SKPaymentQueue defaultQueue] addTransactionObserver:self];
NSLog(@"开始监听 ------ 内购");
self->isObserver = YES;
}
}

- (void)stopObserver {
if (self->isObserver) {

[[SKPaymentQueue defaultQueue] removeTransactionObserver:self];
NSLog(@"移除监听 ------ 内购");
self->isObserver = NO;
}
}

//<SKPaymentTransactionObserver>千万不要忘记绑定,代码如下:
//监听购买结果
//[[SKPaymentQueue defaultQueue] addTransactionObserver:self];
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray<SKPaymentTransaction *> *)transactions
{

//SKPaymentTransaction *transaction = transactions.lastObject;
for (SKPaymentTransaction *transaction in transactions){
switch (transaction.transactionState) {
// 购买成功
case SKPaymentTransactionStatePurchased: {
if (self->buyOrRestore == 1){
NSString *productID = transaction.payment.productIdentifier;
if([productID isEqualToString:self->orderId]){

NSData *data = [NSData dataWithContentsOfFile:[[[NSBundle mainBundle] appStoreReceiptURL] path]];
// 刚才交易的内购的清单
NSString *receipt = [data base64EncodedStringWithOptions:0];
NSLog(@"刚才交易的内购的清单:%@",receipt);

[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
[self stopObserver];
// 对交易结果进行二次验证
[self verifyPruchase];
}
}
}
break;

// 交易失败
case SKPaymentTransactionStateFailed: {
NSLog(@"交易失败");
// 交易失败也要回调服务端
// 将交易从交易队列中删除
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
[self stopObserver];
}
break;
case SKPaymentTransactionStateRestored: {
NSLog(@"这是你已经购买过该商品");

[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
}
break;
case SKPaymentTransactionStatePurchasing: {
NSLog(@"商品添加进列表");
}
break;
default: {
NSLog(@"这是什么情况啊?");
}
break;
}
}
}

//验证购买凭据
-(void)verifyPruchase {
// 验证凭据,获取到苹果返回的交易凭据
// appStoreReceiptURL iOS7.0增加的,购买交易完成后,会将凭据存放在该地址
NSURL *receiptURL = [[NSBundle mainBundle] appStoreReceiptURL];
// 从沙盒中获取到购买凭据
NSData *receiptData = [NSData dataWithContentsOfURL:receiptURL];
// 发送网络POST请求,对购买凭据进行验证
//测试验证地址:https://sandbox.itunes.apple.com/verifyReceipt
//正式验证地址:https://buy.itunes.apple.com/verifyReceipt
NSURL *url = [NSURL URLWithString:@"https://buy.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;

[[[NSURLSession sharedSession] dataTaskWithRequest:urlRequest completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
NSLog(@"%@",[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
// 官方验证结果为空
if (data == nil) {
NSLog(@"交易验证失败");
return;
}

// 二次验证返回,在这里给服务端返回验证结果
NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:nil];
if (dict != nil) {
// 比对字典中以下信息基本上可以保证数据安全
// bundle_id , application_version , product_id , transaction_id
NSLog(@"验证成功!购买的商品的信息是:%@", dict);
// 在这里回调Lua文件支付的结果
NSDictionary * receipt = dict[@"receipt"];
// 在连续的交易中,会有多笔交易产生
NSArray * in_app = receipt[@"in_app"];
if (in_app.count !=0) {
for (NSDictionary * dic in in_app) {
if([dic[@"product_id"] isEqualToString:self->orderId]){
NSDictionary *result = @{
@"result":@"1",
@"bundle_id":receipt[@"bundle_id"],
@"transaction_id":dic[@"transaction_id"],
@"product_id":dic[@"product_id"]};
NSLog(@"购买成功:%@",dic[@"transaction_id"]);
// 订单号回调Lua
//NSString * transaction_id = dic[@"transaction_id"];
[self toLuaFunc:result];
break;
}
}
}
}else{
NSLog(@"交易不成功");
//[self stopObserver];
// 交易不成功,回调Lua
NSDictionary *result = @{
@"result":@"0"};
[self toLuaFunc:result];
//NSString * transaction_id = @" ";
//[self toLuaFunc:self.handlerID backMsg:[transaction_id UTF8String]];
}
}] resume];
}

// Lua 回调函数
-(void) toLuaFunc:(NSDictionary *) result{
int handler = self->callBack_HandleID;
if (-1 != handler)
{
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:result options:0 error:0];
NSString *dataStr = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
auto sc = cocos2d::Director::getInstance()->getScheduler();
sc->performFunctionInCocosThread([handler, dataStr](){
cocos2d::LuaBridge::pushLuaFunctionById(handler);
cocos2d::LuaStack *stack = cocos2d::LuaBridge::getStack();
stack->pushString([dataStr cStringUsingEncoding:NSASCIIStringEncoding]);

stack->executeFunction(1);
cocos2d::LuaBridge::releaseLuaFunctionById(handler);
});

}
}

+(void)restorePruchase:(NSDictionary *)dict{
IosPay * my = [IosPay new];
int handlerID = (int)[[dict objectForKey:@"callBack"] integerValue];
[my restoreBuy:handlerID];
}

-(void) restoreBuy:(int) handleId{
NSLog(@"开始恢复交易");
self->callBack_HandleID = handleId;
self->buyOrRestore = 2;
// 开始一个内购监听
[self startObserver];
//恢复购买
[[SKPaymentQueue defaultQueue] restoreCompletedTransactions];
}

- (void) paymentQueueRestoreCompletedTransactionsFinished:(SKPaymentQueue *)queue
{
[self stopObserver];
//purchasedItemIDs = [[NSMutableArray alloc] init];
NSLog(@"received restored transactions: %i", queue.transactions.count);

for (SKPaymentTransaction *transaction in queue.transactions)
{
NSString *productID = transaction.payment.productIdentifier;
//[purchasedItemIDs addObject:productID];
NSLog(@"恢复交易产品ID%@ ",productID);
}
NSDictionary *result = @{
@"result":@"1",
--返回数据
[self toLuaFunc:result];
}
}

@end

 

lua层调用代码:

--购买物品

local luaoc = require("cocos.cocos2d.luaoc");
local className = "IosPay";
local methodName = "buyVip_1";
local function buyCallBack( params)

  --购买成功处理代码以josn字符串传回
  local data=json.decode(params);

  --do other

end
local argcs = {orderId="VIP_1",callBack=buyCallBack};
luaoc.callStaticMethod(className, methodName,argcs);

 

--恢复购买(用于非消耗物品恢复)

local luaoc = require("cocos.cocos2d.luaoc");
local className = "IosPay";
local methodName = "restorePruchase";
local function restoreCallBack( params)
  --恢复购买数据以josn字符串传回

  local data=json.decode(params);

  --do other

end
local argcs = {callBack=restoreCallBack};
luaoc.callStaticMethod(className, methodName,argcs);

posted @ 2021-09-04 14:46  阿锋1979  阅读(240)  评论(0)    收藏  举报