增加ios内购
This commit is contained in:
parent
13bd51e38e
commit
1c5faa5afd
@ -66,11 +66,11 @@ bool AppDelegate::applicationDidFinishLaunching()
|
||||
|
||||
se->start();
|
||||
se::AutoHandleScope hs;
|
||||
jsb_run_script("js/jsb-adapter/jsb-builtin.js");
|
||||
jsb_run_script("js/jcwallet.js");
|
||||
jsb_run_script("js/platform.js");
|
||||
jsb_run_script("js/main.js");
|
||||
jsb_run_script("js/wallet.js");
|
||||
jsb_run_script("Data/js/jsb-adapter/jsb-builtin.js");
|
||||
jsb_run_script("Data/js/jcwallet.js");
|
||||
jsb_run_script("Data/js/platform.js");
|
||||
jsb_run_script("Data/js/main.js");
|
||||
jsb_run_script("Data/js/wallet.js");
|
||||
se->addAfterCleanupHook([]() {
|
||||
JSBClassType::destroy();
|
||||
});
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include "AppDelegate.h"
|
||||
#import "UIViewController+Wallet.h"
|
||||
#import "UIViewController+QR.h"
|
||||
#import "UIViewController+Purchase.h"
|
||||
#endif
|
||||
|
||||
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
|
||||
@ -460,6 +461,110 @@ bool jsb_showWebPage(se::State& s) {
|
||||
}
|
||||
SE_BIND_FUNC(jsb_showWebPage)
|
||||
|
||||
static bool JSB_queryProducts(se::State& s)
|
||||
{
|
||||
const auto& args = s.args();
|
||||
size_t argc = args.size();
|
||||
CC_UNUSED bool ok = true;
|
||||
if (argc > 1) {
|
||||
std::string funid;
|
||||
ok = seval_to_std_string(args[0], &funid);
|
||||
SE_PRECONDITION2(ok, false, "funid is invalid!");
|
||||
std::string param0;
|
||||
ok = seval_to_std_string(args[1], ¶m0);
|
||||
SE_PRECONDITION2(ok, false, "param0 is invalid!");
|
||||
NSString *nParams = [NSString stringWithCString:param0.c_str() encoding: NSUTF8StringEncoding];
|
||||
NSString *nfunid = [NSString stringWithCString:funid.c_str() encoding: NSUTF8StringEncoding];
|
||||
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
UIWindow* window = [[[UIApplication sharedApplication] delegate] window];
|
||||
[window.rootViewController queryProducts:nfunid products: nParams];
|
||||
});
|
||||
return true;
|
||||
}
|
||||
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", (int)argc, 2);
|
||||
return false;
|
||||
}
|
||||
SE_BIND_FUNC(JSB_queryProducts)
|
||||
|
||||
static bool JSB_queryPurchase(se::State& s)
|
||||
{
|
||||
const auto& args = s.args();
|
||||
size_t argc = args.size();
|
||||
CC_UNUSED bool ok = true;
|
||||
if (argc > 0) {
|
||||
std::string funid;
|
||||
ok = seval_to_std_string(args[0], &funid);
|
||||
SE_PRECONDITION2(ok, false, "funid is invalid!");
|
||||
NSString *nfunid = [NSString stringWithCString:funid.c_str() encoding: NSUTF8StringEncoding];
|
||||
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
UIWindow* window = [[[UIApplication sharedApplication] delegate] window];
|
||||
[window.rootViewController queryPurchase:nfunid ];
|
||||
});
|
||||
return true;
|
||||
}
|
||||
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", (int)argc, 1);
|
||||
return false;
|
||||
}
|
||||
SE_BIND_FUNC(JSB_queryPurchase)
|
||||
|
||||
static bool JSB_finishTransaction(se::State& s)
|
||||
{
|
||||
const auto& args = s.args();
|
||||
size_t argc = args.size();
|
||||
CC_UNUSED bool ok = true;
|
||||
if (argc > 1) {
|
||||
std::string funid;
|
||||
ok = seval_to_std_string(args[0], &funid);
|
||||
SE_PRECONDITION2(ok, false, "funid is invalid!");
|
||||
std::string transactionid;
|
||||
ok = seval_to_std_string(args[1], &transactionid);
|
||||
SE_PRECONDITION2(ok, false, "transactionid is invalid!");
|
||||
NSString *nfunid = [NSString stringWithCString:funid.c_str() encoding: NSUTF8StringEncoding];
|
||||
NSString *ntransactionid = [NSString stringWithCString:transactionid.c_str() encoding: NSUTF8StringEncoding];
|
||||
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
UIWindow* window = [[[UIApplication sharedApplication] delegate] window];
|
||||
[window.rootViewController finishTransaction:nfunid transactionId:ntransactionid ];
|
||||
});
|
||||
return true;
|
||||
}
|
||||
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", (int)argc, 2);
|
||||
return false;
|
||||
}
|
||||
SE_BIND_FUNC(JSB_finishTransaction)
|
||||
|
||||
static bool JSB_beginBuy(se::State& s)
|
||||
{
|
||||
const auto& args = s.args();
|
||||
size_t argc = args.size();
|
||||
CC_UNUSED bool ok = true;
|
||||
if (argc > 2) {
|
||||
std::string funid;
|
||||
ok = seval_to_std_string(args[0], &funid);
|
||||
SE_PRECONDITION2(ok, false, "funid is invalid!");
|
||||
std::string param0;
|
||||
ok = seval_to_std_string(args[1], ¶m0);
|
||||
SE_PRECONDITION2(ok, false, "param0 is invalid!");
|
||||
std::string param1;
|
||||
ok = seval_to_std_string(args[2], ¶m1);
|
||||
SE_PRECONDITION2(ok, false, "param1 is invalid!");
|
||||
NSString *nParam0 = [NSString stringWithCString:param0.c_str() encoding: NSUTF8StringEncoding];
|
||||
NSString *nParam1 = [NSString stringWithCString:param1.c_str() encoding: NSUTF8StringEncoding];
|
||||
NSString *nfunid = [NSString stringWithCString:funid.c_str() encoding: NSUTF8StringEncoding];
|
||||
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
UIWindow* window = [[[UIApplication sharedApplication] delegate] window];
|
||||
[window.rootViewController beginBuy:nfunid productId: nParam0 orderId:nParam1];
|
||||
});
|
||||
return true;
|
||||
}
|
||||
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", (int)argc, 3);
|
||||
return false;
|
||||
}
|
||||
SE_BIND_FUNC(JSB_beginBuy)
|
||||
|
||||
|
||||
bool jsb_register_walletevent_modules(se::Object* global) {
|
||||
getOrCreatePlainObject_r("jsb", global, &__jsbObj);
|
||||
@ -473,6 +578,10 @@ bool jsb_register_walletevent_modules(se::Object* global) {
|
||||
__jsbObj->defineFunction("signOutGoogle", _SE(jsb_signOutGoogle));
|
||||
__jsbObj->defineFunction("showQRCode", _SE(JSB_showQRCode));
|
||||
__jsbObj->defineFunction("showWebPage", _SE(jsb_showWebPage));
|
||||
__jsbObj->defineFunction("queryProducts", _SE(JSB_queryProducts));
|
||||
__jsbObj->defineFunction("queryPurchase", _SE(JSB_queryPurchase));
|
||||
__jsbObj->defineFunction("finishTransaction", _SE(JSB_finishTransaction));
|
||||
__jsbObj->defineFunction("beginBuy", _SE(JSB_beginBuy));
|
||||
// JSB_signWithEmail
|
||||
// JSB_beginBuyJNI
|
||||
return true;
|
||||
|
@ -1,5 +1,5 @@
|
||||
//
|
||||
// UIViewController+Logger.h
|
||||
// UIViewController+Purchase.h
|
||||
// Unity-iPhone
|
||||
//
|
||||
// Created by Hl Zhang on 2023/3/21.
|
||||
@ -9,8 +9,10 @@
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
|
||||
@interface UIViewController (Purchase)
|
||||
- (void)initPurchaseEnv;
|
||||
- (void)queryProducts:(NSString *)funId products:(NSString *)products;
|
||||
- (void)queryPurchase:(NSString *)funId;
|
||||
- (void)finishTransaction:(NSString *)funId transactionId: (NSString *) transactionId;
|
||||
- (void)beginBuy:(NSString *)funId productId:(NSString *)productId orderId:(NSString *)orderId;
|
||||
@end
|
||||
|
||||
|
@ -1,64 +1,157 @@
|
||||
//
|
||||
// UIViewController+Logger.cpp
|
||||
// UIViewController+Purchase.cpp
|
||||
// Unity-iPhone
|
||||
//
|
||||
// Created by Hl Zhang on 2023/3/21.
|
||||
//
|
||||
|
||||
#import "UIViewController+Purchase.h"
|
||||
#import "UIViewController+Wallet.h"
|
||||
#import "Utilities.h"
|
||||
#import "StoreManager.h"
|
||||
#import "StoreObserver.h"
|
||||
#import "AppConfiguration.h"
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "SKProduct+SKProductAdditions.h"
|
||||
#include <string>
|
||||
#import "NSString+Customer.h"
|
||||
#include "JcWallet.h"
|
||||
|
||||
static Utilities *utility;
|
||||
static Utilities *utility = nil;
|
||||
|
||||
@interface UIViewController (Purchase)
|
||||
@property (nonatomic) NSString *currentFunId;
|
||||
@end
|
||||
|
||||
@implementation UIViewController (Purchase)
|
||||
|
||||
-(void)initPurchaseEnv {
|
||||
utility = [[Utilities alloc] init];
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(handleProductRequestNotification:)
|
||||
name:PCSProductRequestNotification
|
||||
object:[StoreManager sharedInstance]];
|
||||
// [[NSNotificationCenter defaultCenter] addObserver:self
|
||||
// selector:@selector(handleProductRequestNotification:)
|
||||
// name:PCSProductRequestNotification
|
||||
// object:[StoreManager sharedInstance]];
|
||||
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(handlePurchaseNotification:)
|
||||
name:PCSPurchaseNotification
|
||||
object:[StoreObserver sharedInstance]];
|
||||
}
|
||||
#pragma mark - Query products
|
||||
/// Retrieves product information from the App Store.
|
||||
-(void)fetchProductInformation {
|
||||
- (void)queryProducts:(NSString *) funId products: (NSString *) products {
|
||||
if (utility == nil) {
|
||||
[self initPurchaseEnv];
|
||||
}
|
||||
if (products == nil || [products isEqualToString:@""]) {
|
||||
NSLog(@"queryProducts with empty products: %@", products);
|
||||
[self nativeCb:funId hasErr:YES dataStr:@"queryProducts with empty products"];
|
||||
return;
|
||||
}
|
||||
// split products to array
|
||||
NSArray *identifiers = [products componentsSeparatedByString:@","];
|
||||
// First, let's check whether the user is allowed to make purchases. Proceed if they are allowed. Display an alert, otherwise.
|
||||
if ([StoreObserver sharedInstance].isAuthorizedForPayments) {
|
||||
NSArray *identifiers = utility.identifiers;
|
||||
|
||||
if (identifiers != nil) {
|
||||
if (identifiers.count > 0) {
|
||||
Section *section = [[Section alloc] initWithName:PCSProductsInvalidIdentifiers elements:identifiers];
|
||||
|
||||
// Refresh the UI with identifiers to be queried.
|
||||
// [self switchToViewController:ParentViewControllerSegmentProducts];
|
||||
// [self.products reloadWithData:[NSMutableArray arrayWithObject:section]];
|
||||
|
||||
// Fetch the product information.
|
||||
[[StoreManager sharedInstance] startProductRequestWithIdentifiers:identifiers];
|
||||
} else {
|
||||
// Warn the user that the resource file does not contain anything.
|
||||
[self alertWithTitle:PCSMessagesStatus message:[NSString stringWithFormat:@"%@.%@ %@", PCSProductIdsPlistName, PCSProductIdsPlistFileExtension, PCSMessagesEmptyResource]];
|
||||
[[StoreManager sharedInstance] fetchProductsMatchingIdentifiers:identifiers completionBlock: ^(PCSProductRequestStatus status, NSMutableArray *storeResponse){
|
||||
if (status == PCSStoreResponse) {
|
||||
// define json array to return
|
||||
NSMutableArray *jsonArray = [[NSMutableArray alloc] init];
|
||||
for (Section *section in storeResponse) {
|
||||
NSArray *content = section.elements;
|
||||
if ([section.name isEqualToString:PCSProductsAvailableProducts]) {
|
||||
for (SKProduct *product in content) {
|
||||
NSMutableDictionary *json = [[NSMutableDictionary alloc] init];
|
||||
[json setObject:product.productIdentifier forKey:@"id"];
|
||||
[json setObject:product.localizedTitle forKey:@"name"];
|
||||
[json setObject:product.localizedDescription forKey:@"description"];
|
||||
[json setObject:product.priceLocale.currencyCode forKey:@"currencyCode"];
|
||||
[json setObject:product.price.stringValue forKey:@"priceValue"];
|
||||
[json setObject:product.regularPrice forKey:@"priceShow"];
|
||||
[jsonArray addObject:json];
|
||||
}
|
||||
} else {
|
||||
// Warn the user that the resource file could not be found.
|
||||
[self alertWithTitle:PCSMessagesStatus message:[NSString stringWithFormat:@"%@ %@.%@.", PCSMessagesResourceNotFound, PCSProductIdsPlistName, PCSProductIdsPlistFileExtension]];
|
||||
} else if ([section.name isEqualToString:PCSProductsInvalidIdentifiers]) {
|
||||
// if there are invalid product identifiers, show them.
|
||||
NSLog(@"Invalid product identifiers: %@", section.name);
|
||||
// [self nativeCb:funId hasErr:YES dataStr: section.name];
|
||||
}
|
||||
}
|
||||
NSError *error;
|
||||
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:jsonArray options:NSJSONWritingPrettyPrinted error:&error];
|
||||
NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
|
||||
if (!jsonData) {
|
||||
NSLog(@"Got an error: %@", error);
|
||||
[self nativeCb:funId hasErr:YES dataStr: [NSString stringWithFormat:@"%@", error]];
|
||||
} else {
|
||||
NSLog(@"jsonString: %@", jsonString);
|
||||
[self nativeCb:funId hasErr:NO dataStr: jsonString];
|
||||
}
|
||||
|
||||
} else if (status == PCSRequestFailed) {
|
||||
NSLog(@"Product request failed with message: %@", [StoreManager sharedInstance].message);
|
||||
[self nativeCb:funId hasErr:YES dataStr: [StoreManager sharedInstance].message];
|
||||
}
|
||||
}];
|
||||
|
||||
} else {
|
||||
// Warn the user that they are not allowed to make purchases.
|
||||
[self alertWithTitle:PCSMessagesStatus message:[NSString stringWithFormat:@"%@", PCSMessagesCannotMakePayments]];
|
||||
NSLog(@"User is not allowed to make payments (Payments are disabled in Settings).");
|
||||
[self nativeCb:funId hasErr:YES dataStr: [NSString stringWithFormat:@"%@", PCSMessagesCannotMakePayments]];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#pragma mark - Query Purchase
|
||||
- (void)queryPurchase:(NSString *)funId {
|
||||
if (utility == nil) {
|
||||
[self initPurchaseEnv];
|
||||
}
|
||||
NSArray *transations = [[StoreObserver sharedInstance] queryPendingTransactions];
|
||||
// convert to json string
|
||||
NSError *error;
|
||||
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:transations options:NSJSONWritingPrettyPrinted error:&error];
|
||||
NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
|
||||
[self nativeCb:funId hasErr:NO dataStr:jsonString];
|
||||
}
|
||||
|
||||
#pragma mark - Begin Buy Product
|
||||
- (void)beginBuy:(NSString *)funId productId:(NSString *)productId orderId:(NSString *)orderId {
|
||||
if (utility == nil) {
|
||||
[self initPurchaseEnv];
|
||||
}
|
||||
if (productId == nil || [productId isEqualToString:@""]) {
|
||||
NSLog(@"beginBy with empty productId: %@", productId);
|
||||
[self nativeCb:funId hasErr:YES dataStr:@"beginBy with empty productId"];
|
||||
return;
|
||||
}
|
||||
// check if currentFunId is empty
|
||||
if (self.currentFunId != nil && ![self.currentFunId isEqualToString:@""]) {
|
||||
NSLog(@"beginBy with currentFunId: %@", self.currentFunId);
|
||||
[self nativeCb:funId hasErr:YES dataStr:@"other purchase is processing"];
|
||||
return;
|
||||
}
|
||||
self.currentFunId = funId;
|
||||
SKProduct *product = [[StoreManager sharedInstance] productMatchingIdentifier: productId];
|
||||
if (product == nil) {
|
||||
NSLog(@"beginBy with empty product: %@", productId);
|
||||
self.currentFunId = nil;
|
||||
[self nativeCb:funId hasErr:YES dataStr:@"beginBy with empty product"];
|
||||
return;
|
||||
}
|
||||
if (orderId == nil || [orderId isEqualToString:@""]) {
|
||||
NSLog(@"beginBy with empty orderId: %@", orderId);
|
||||
self.currentFunId = nil;
|
||||
[self nativeCb:funId hasErr:YES dataStr:@"beginBy with empty orderId"];
|
||||
return;
|
||||
}
|
||||
[[StoreObserver sharedInstance] buy:product orderId: orderId];
|
||||
}
|
||||
|
||||
#pragma mark - Finish Transaction
|
||||
- (void)finishTransaction:(NSString *)funId transactionId: (NSString *) transactionId {
|
||||
[[StoreObserver sharedInstance] finishTransaction: transactionId];
|
||||
[self nativeCb:funId hasErr:NO dataStr:@""];
|
||||
}
|
||||
|
||||
/// Creates and displays an alert.
|
||||
-(void)alertWithTitle:(NSString *)title message:(NSString *)message {
|
||||
UIAlertController *alertController = [utility alertWithTitle:title message:message];
|
||||
@ -71,33 +164,27 @@ static Utilities *utility;
|
||||
-(void)handleProductRequestNotification:(NSNotification *)notification {
|
||||
StoreManager *productRequestNotification = (StoreManager*)notification.object;
|
||||
PCSProductRequestStatus status = (PCSProductRequestStatus)productRequestNotification.status;
|
||||
|
||||
if (status == PCSStoreResponse) {
|
||||
// Switch to the Products view controller.
|
||||
// [self switchToViewController:ParentViewControllerSegmentProducts];
|
||||
// [self.products reloadWithData:productRequestNotification.storeResponse];
|
||||
// self.segmentedControl.selectedSegmentIndex = ParentViewControllerSegmentProducts;
|
||||
} else if (status == PCSRequestFailed) {
|
||||
[self alertWithTitle:PCSMessagesProductRequestStatus message:productRequestNotification.message];
|
||||
}
|
||||
NSLog(@"handleProductRequestNotification status: %ld", (long)status);
|
||||
}
|
||||
|
||||
#pragma mark - Handle PCSPurchase Notification
|
||||
|
||||
/// Updates the UI according to the purchase request notification result.
|
||||
-(void)handlePurchaseNotification:(NSNotification *)notification {
|
||||
StoreObserver *purchasesNotification = (StoreObserver *)notification.object;
|
||||
PCSPurchaseStatus status = (PCSPurchaseStatus)purchasesNotification.status;
|
||||
|
||||
switch (status) {
|
||||
case PCSNoRestorablePurchases:
|
||||
case PCSPurchaseFailed:
|
||||
case PCSRestoreFailed: [self alertWithTitle:PCSMessagesPurchaseStatus message:purchasesNotification.message];
|
||||
break;
|
||||
// Switch to the Purchases view when receiving a successful restore notification.
|
||||
case PCSRestoreSucceeded: [self handleRestoredSucceededTransaction];
|
||||
break;
|
||||
default: break;
|
||||
NSDictionary* dic = notification.userInfo;
|
||||
NSNumber *errcode = dic[@"errcode"];
|
||||
NSLog(@"handlePurchaseNotification status: %@", errcode);
|
||||
// check if errcode is zero or not
|
||||
self.currentFunId = nil;
|
||||
if (errcode != nil && [errcode intValue] != 0) {
|
||||
[self nativeCb:self.currentFunId hasErr:YES dataStr: [NSString stringWithFormat:@"%@", dic[@"errmsg"]]];
|
||||
} else {
|
||||
NSString *tid = dic[@"dataid"];
|
||||
NSMutableArray *transactions = [[NSMutableArray alloc] init];
|
||||
[transactions addObject:tid];
|
||||
NSError *error;
|
||||
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:transactions options:NSJSONWritingPrettyPrinted error:&error];
|
||||
NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
|
||||
[self nativeCb:self.currentFunId hasErr:NO dataStr: jsonString];
|
||||
}
|
||||
}
|
||||
|
||||
@ -112,5 +199,5 @@ static Utilities *utility;
|
||||
// [self.purchases reloadWithData:self.utility.dataSourceForPurchasesUI];
|
||||
// self.segmentedControl.selectedSegmentIndex = ParentViewControllerSegmentPurchases;
|
||||
}
|
||||
@end
|
||||
|
||||
@end
|
||||
|
@ -6,6 +6,7 @@
|
||||
//
|
||||
|
||||
#import "UIViewController+QR.h"
|
||||
#import "UIViewController+Wallet.h"
|
||||
#import "QRCodeReaderViewController.h"
|
||||
#import "QRCodeReader.h"
|
||||
#import "QRCodeReaderDelegate.h"
|
||||
@ -132,21 +133,5 @@ static SimpleQRViewController *sqrVC = nil;
|
||||
}];
|
||||
}
|
||||
|
||||
-(void)nativeCb:(NSString *)funid hasErr: (BOOL) hasErr dataStr:(NSString *) dataStr {
|
||||
if ([NSString isStringEmpty:funid]) {
|
||||
NSLog(@"nativeCallBack with empty funid: %@", funid);
|
||||
return;
|
||||
}
|
||||
std::string methodName = "nativeCallBack";
|
||||
NSString *paramStr;
|
||||
if (hasErr) {
|
||||
paramStr = [NSString stringWithFormat:@"{\"errcode\": 1, \"errmessage\": \"%@\"}", dataStr];
|
||||
} else {
|
||||
paramStr = [NSString stringWithFormat:@"{\"errcode\": 0, \"data\": \"%@\"}", dataStr];
|
||||
}
|
||||
std::string sfunid = std::string([funid UTF8String], [funid lengthOfBytesUsingEncoding:NSUTF8StringEncoding]);
|
||||
std::string sparam = std::string([paramStr UTF8String], [paramStr lengthOfBytesUsingEncoding:NSUTF8StringEncoding]);
|
||||
cocos2d::nativeCallBack(sfunid.c_str(), methodName.c_str(), sparam.c_str());
|
||||
}
|
||||
|
||||
@end
|
||||
|
@ -22,5 +22,5 @@
|
||||
-(void)saveKey:(NSString *) account key:(NSString *) key;
|
||||
-(NSString *)loadKey:(NSString *) account;
|
||||
-(void)showPage:(NSString *)url;
|
||||
//-(void)nativeCb:(NSString *)funid hasErr: (BOOL) hasErr dataStr:(NSString *) dataStr;
|
||||
-(void)nativeCb:(NSString *)funid hasErr: (BOOL) hasErr dataStr:(NSString *) dataStr;
|
||||
@end
|
||||
|
@ -176,14 +176,26 @@ static WebPageViewController *webpageVC = nil;
|
||||
return;
|
||||
}
|
||||
std::string methodName = "nativeCallBack";
|
||||
NSString *paramStr;
|
||||
NSMutableDictionary *json = [[NSMutableDictionary alloc] init];
|
||||
if (hasErr) {
|
||||
paramStr = [NSString stringWithFormat:@"{\"errcode\": 1, \"errmessage\": \"%@\"}", dataStr];
|
||||
json[@"errcode"] = @1;
|
||||
json[@"errmessage"] = dataStr;
|
||||
} else {
|
||||
paramStr = [NSString stringWithFormat:@"{\"errcode\": 0, \"data\": \"%@\"}", dataStr];
|
||||
json[@"errcode"] = @0;
|
||||
json[@"data"] = dataStr;
|
||||
}
|
||||
NSError *error;
|
||||
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:json options:NSJSONWritingPrettyPrinted error:&error];
|
||||
NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
|
||||
std::string sfunid = std::string([funid UTF8String], [funid lengthOfBytesUsingEncoding:NSUTF8StringEncoding]);
|
||||
std::string sparam = std::string([paramStr UTF8String], [paramStr lengthOfBytesUsingEncoding:NSUTF8StringEncoding]);
|
||||
if (error) {
|
||||
NSLog(@"Got an error: %@", error);
|
||||
NSString *errorStr = [NSString stringWithFormat:@"{\"errcode\": 1, \"errmessage\": \"%@\"}", error];
|
||||
std::string sparam = std::string([errorStr UTF8String], [errorStr lengthOfBytesUsingEncoding:NSUTF8StringEncoding]);
|
||||
cocos2d::nativeCallBack(sfunid.c_str(), methodName.c_str(), sparam.c_str());
|
||||
return;
|
||||
}
|
||||
std::string sparam = std::string([jsonString UTF8String], [jsonString lengthOfBytesUsingEncoding:NSUTF8StringEncoding]);
|
||||
cocos2d::nativeCallBack(sfunid.c_str(), methodName.c_str(), sparam.c_str());
|
||||
}
|
||||
|
||||
|
@ -322,6 +322,7 @@
|
||||
D59AB8522A68FEB700433200 /* Section.m in Sources */ = {isa = PBXBuildFile; fileRef = D59AB8502A68FEB700433200 /* Section.m */; };
|
||||
D59AB8552A690BC300433200 /* UIViewController+Purchase.mm in Sources */ = {isa = PBXBuildFile; fileRef = D59AB8542A690BC300433200 /* UIViewController+Purchase.mm */; };
|
||||
D59AB8582A690C9900433200 /* Utilities.m in Sources */ = {isa = PBXBuildFile; fileRef = D59AB8572A690C9900433200 /* Utilities.m */; };
|
||||
D59AB85E2A6A500900433200 /* SKProduct+SKProductAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = D59AB85C2A6A500900433200 /* SKProduct+SKProductAdditions.m */; };
|
||||
D5BF397629C9B79400EC6351 /* UIViewController+Logger.mm in Sources */ = {isa = PBXBuildFile; fileRef = D5BF397529C9B79400EC6351 /* UIViewController+Logger.mm */; };
|
||||
D5BF397829C9B8C000EC6351 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = D5BF397729C9B8C000EC6351 /* GoogleService-Info.plist */; };
|
||||
D5C03B702A49A808002E758D /* Data in Resources */ = {isa = PBXBuildFile; fileRef = D5C03B6F2A49A808002E758D /* Data */; };
|
||||
@ -1369,6 +1370,9 @@
|
||||
D59AB8542A690BC300433200 /* UIViewController+Purchase.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = "UIViewController+Purchase.mm"; sourceTree = "<group>"; };
|
||||
D59AB8562A690C9900433200 /* Utilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Utilities.h; sourceTree = "<group>"; };
|
||||
D59AB8572A690C9900433200 /* Utilities.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Utilities.m; sourceTree = "<group>"; };
|
||||
D59AB85A2A6A387A00433200 /* test-in-app-purchase.storekit */ = {isa = PBXFileReference; lastKnownFileType = text; path = "test-in-app-purchase.storekit"; sourceTree = "<group>"; };
|
||||
D59AB85C2A6A500900433200 /* SKProduct+SKProductAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "SKProduct+SKProductAdditions.m"; sourceTree = "<group>"; };
|
||||
D59AB85D2A6A500900433200 /* SKProduct+SKProductAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "SKProduct+SKProductAdditions.h"; sourceTree = "<group>"; };
|
||||
D5BF397429C9B77E00EC6351 /* UIViewController+Logger.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "UIViewController+Logger.h"; sourceTree = "<group>"; };
|
||||
D5BF397529C9B79400EC6351 /* UIViewController+Logger.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = "UIViewController+Logger.mm"; sourceTree = "<group>"; };
|
||||
D5BF397729C9B8C000EC6351 /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = "<group>"; };
|
||||
@ -1469,6 +1473,7 @@
|
||||
29B97314FDCFA39411CA2CEA /* CustomTemplate */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D59AB85A2A6A387A00433200 /* test-in-app-purchase.storekit */,
|
||||
D59AB8482A68FC2900433200 /* purchase */,
|
||||
D5C03B6F2A49A808002E758D /* Data */,
|
||||
D526FA3C299498E3002A2290 /* cocos2d_libs.xcodeproj */,
|
||||
@ -3500,6 +3505,8 @@
|
||||
D59AB8482A68FC2900433200 /* purchase */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D59AB85D2A6A500900433200 /* SKProduct+SKProductAdditions.h */,
|
||||
D59AB85C2A6A500900433200 /* SKProduct+SKProductAdditions.m */,
|
||||
D59AB8492A68FC5200433200 /* StoreObserver.h */,
|
||||
D59AB8462A68FC2200433200 /* StoreObserver.m */,
|
||||
D59AB84A2A68FC7200433200 /* AppConfiguration.h */,
|
||||
@ -3817,6 +3824,7 @@
|
||||
D55759902A5FAC16009369FC /* Generics5.cpp in Sources */,
|
||||
D59AB84F2A68FE8E00433200 /* StoreManager.m in Sources */,
|
||||
D55759D12A5FAC16009369FC /* UnityEngine.InputLegacyModule.cpp in Sources */,
|
||||
D59AB85E2A6A500900433200 /* SKProduct+SKProductAdditions.m in Sources */,
|
||||
D507C9412994A0A800CF3953 /* UIView+Toast.m in Sources */,
|
||||
D55759E12A5FAC16009369FC /* UnityEngine.TextCoreTextEngineModule.cpp in Sources */,
|
||||
D507D5E92994C62A00CF3953 /* UnityAdsUtilities.m in Sources */,
|
||||
|
Binary file not shown.
@ -142,8 +142,8 @@
|
||||
filePath = "Classes_cocos/JcWallet.mm"
|
||||
startingColumnNumber = "9223372036854775807"
|
||||
endingColumnNumber = "9223372036854775807"
|
||||
startingLineNumber = "182"
|
||||
endingLineNumber = "182"
|
||||
startingLineNumber = "183"
|
||||
endingLineNumber = "183"
|
||||
landmarkName = "JcWallet::jsToUnity(funId, msg)"
|
||||
landmarkType = "7">
|
||||
</BreakpointContent>
|
||||
@ -238,8 +238,8 @@
|
||||
filePath = "Classes_cocos/JcWallet.mm"
|
||||
startingColumnNumber = "9223372036854775807"
|
||||
endingColumnNumber = "9223372036854775807"
|
||||
startingLineNumber = "188"
|
||||
endingLineNumber = "188"
|
||||
startingLineNumber = "189"
|
||||
endingLineNumber = "189"
|
||||
landmarkName = "initEnv()"
|
||||
landmarkType = "9">
|
||||
</BreakpointContent>
|
||||
@ -254,11 +254,267 @@
|
||||
filePath = "Classes_cocos/JcWallet.mm"
|
||||
startingColumnNumber = "9223372036854775807"
|
||||
endingColumnNumber = "9223372036854775807"
|
||||
startingLineNumber = "114"
|
||||
endingLineNumber = "114"
|
||||
startingLineNumber = "115"
|
||||
endingLineNumber = "115"
|
||||
landmarkName = "JcWallet::initEnv()"
|
||||
landmarkType = "7">
|
||||
</BreakpointContent>
|
||||
</BreakpointProxy>
|
||||
<BreakpointProxy
|
||||
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
|
||||
<BreakpointContent
|
||||
uuid = "4D59F0BA-B8D8-4997-82C4-0E290B339761"
|
||||
shouldBeEnabled = "No"
|
||||
ignoreCount = "0"
|
||||
continueAfterRunningActions = "No"
|
||||
filePath = "Classes_cocos/UIViewController+Purchase.mm"
|
||||
startingColumnNumber = "9223372036854775807"
|
||||
endingColumnNumber = "9223372036854775807"
|
||||
startingLineNumber = "44"
|
||||
endingLineNumber = "44"
|
||||
landmarkName = "-queryProducts:products:"
|
||||
landmarkType = "7">
|
||||
</BreakpointContent>
|
||||
</BreakpointProxy>
|
||||
<BreakpointProxy
|
||||
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
|
||||
<BreakpointContent
|
||||
uuid = "EFF0CD4A-8153-4757-B4A4-357559BA0D1B"
|
||||
shouldBeEnabled = "No"
|
||||
ignoreCount = "0"
|
||||
continueAfterRunningActions = "No"
|
||||
filePath = "Classes_cocos/UIViewController+Purchase.mm"
|
||||
startingColumnNumber = "9223372036854775807"
|
||||
endingColumnNumber = "9223372036854775807"
|
||||
startingLineNumber = "97"
|
||||
endingLineNumber = "97"
|
||||
landmarkName = "-queryProducts:products:"
|
||||
landmarkType = "7">
|
||||
</BreakpointContent>
|
||||
</BreakpointProxy>
|
||||
<BreakpointProxy
|
||||
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
|
||||
<BreakpointContent
|
||||
uuid = "4FBF6B08-08A0-4695-995A-211586F5A6CF"
|
||||
shouldBeEnabled = "No"
|
||||
ignoreCount = "0"
|
||||
continueAfterRunningActions = "No"
|
||||
filePath = "Classes_cocos/UIViewController+Purchase.mm"
|
||||
startingColumnNumber = "9223372036854775807"
|
||||
endingColumnNumber = "9223372036854775807"
|
||||
startingLineNumber = "25"
|
||||
endingLineNumber = "25"
|
||||
landmarkName = "unknown"
|
||||
landmarkType = "0">
|
||||
</BreakpointContent>
|
||||
</BreakpointProxy>
|
||||
<BreakpointProxy
|
||||
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
|
||||
<BreakpointContent
|
||||
uuid = "6CDA02A2-8D28-4324-BFE6-7B2F4037BCB7"
|
||||
shouldBeEnabled = "No"
|
||||
ignoreCount = "0"
|
||||
continueAfterRunningActions = "No"
|
||||
filePath = "Classes_cocos/UIViewController+Purchase.mm"
|
||||
startingColumnNumber = "9223372036854775807"
|
||||
endingColumnNumber = "9223372036854775807"
|
||||
startingLineNumber = "74"
|
||||
endingLineNumber = "74"
|
||||
landmarkName = "-queryProducts:products:"
|
||||
landmarkType = "7">
|
||||
</BreakpointContent>
|
||||
</BreakpointProxy>
|
||||
<BreakpointProxy
|
||||
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
|
||||
<BreakpointContent
|
||||
uuid = "E24AA442-B796-47C7-B2EC-28713FB595F3"
|
||||
shouldBeEnabled = "No"
|
||||
ignoreCount = "0"
|
||||
continueAfterRunningActions = "No"
|
||||
filePath = "Classes_cocos/UIViewController+Purchase.mm"
|
||||
startingColumnNumber = "9223372036854775807"
|
||||
endingColumnNumber = "9223372036854775807"
|
||||
startingLineNumber = "46"
|
||||
endingLineNumber = "46"
|
||||
landmarkName = "-queryProducts:products:"
|
||||
landmarkType = "7">
|
||||
</BreakpointContent>
|
||||
</BreakpointProxy>
|
||||
<BreakpointProxy
|
||||
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
|
||||
<BreakpointContent
|
||||
uuid = "41E5D281-1A9D-4031-AF76-9BDCF83C9611"
|
||||
shouldBeEnabled = "No"
|
||||
ignoreCount = "0"
|
||||
continueAfterRunningActions = "No"
|
||||
filePath = "Classes_cocos/UIViewController+Purchase.mm"
|
||||
startingColumnNumber = "9223372036854775807"
|
||||
endingColumnNumber = "9223372036854775807"
|
||||
startingLineNumber = "80"
|
||||
endingLineNumber = "80"
|
||||
landmarkName = "-queryProducts:products:"
|
||||
landmarkType = "7">
|
||||
</BreakpointContent>
|
||||
</BreakpointProxy>
|
||||
<BreakpointProxy
|
||||
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
|
||||
<BreakpointContent
|
||||
uuid = "79F18C2C-0D3F-41EE-BCEC-0A1B0D6DDC2F"
|
||||
shouldBeEnabled = "No"
|
||||
ignoreCount = "0"
|
||||
continueAfterRunningActions = "No"
|
||||
filePath = "Classes_cocos/UIViewController+Wallet.mm"
|
||||
startingColumnNumber = "9223372036854775807"
|
||||
endingColumnNumber = "9223372036854775807"
|
||||
startingLineNumber = "174"
|
||||
endingLineNumber = "174"
|
||||
landmarkName = "-nativeCb:hasErr:dataStr:"
|
||||
landmarkType = "7">
|
||||
</BreakpointContent>
|
||||
</BreakpointProxy>
|
||||
<BreakpointProxy
|
||||
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
|
||||
<BreakpointContent
|
||||
uuid = "8B87105F-C5EE-489F-BF1E-00FDF62602D0"
|
||||
shouldBeEnabled = "No"
|
||||
ignoreCount = "0"
|
||||
continueAfterRunningActions = "No"
|
||||
filePath = "purchase/StoreObserver.m"
|
||||
startingColumnNumber = "9223372036854775807"
|
||||
endingColumnNumber = "9223372036854775807"
|
||||
startingLineNumber = "131"
|
||||
endingLineNumber = "131"
|
||||
landmarkName = "-paymentQueue:updatedTransactions:"
|
||||
landmarkType = "7">
|
||||
</BreakpointContent>
|
||||
</BreakpointProxy>
|
||||
<BreakpointProxy
|
||||
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
|
||||
<BreakpointContent
|
||||
uuid = "6E8F3D37-5AC6-454A-8526-57B1C343F168"
|
||||
shouldBeEnabled = "No"
|
||||
ignoreCount = "0"
|
||||
continueAfterRunningActions = "No"
|
||||
filePath = "Classes_cocos/UIViewController+Purchase.mm"
|
||||
startingColumnNumber = "9223372036854775807"
|
||||
endingColumnNumber = "9223372036854775807"
|
||||
startingLineNumber = "111"
|
||||
endingLineNumber = "111"
|
||||
landmarkName = "-queryPurchase:"
|
||||
landmarkType = "7">
|
||||
</BreakpointContent>
|
||||
</BreakpointProxy>
|
||||
<BreakpointProxy
|
||||
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
|
||||
<BreakpointContent
|
||||
uuid = "298A81F7-4B66-40D1-8EA3-BE7606FB25D2"
|
||||
shouldBeEnabled = "Yes"
|
||||
ignoreCount = "0"
|
||||
continueAfterRunningActions = "No"
|
||||
filePath = "purchase/StoreObserver.m"
|
||||
startingColumnNumber = "9223372036854775807"
|
||||
endingColumnNumber = "9223372036854775807"
|
||||
startingLineNumber = "190"
|
||||
endingLineNumber = "190"
|
||||
landmarkName = "-handleTransactionPurchased:"
|
||||
landmarkType = "7">
|
||||
</BreakpointContent>
|
||||
</BreakpointProxy>
|
||||
<BreakpointProxy
|
||||
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
|
||||
<BreakpointContent
|
||||
uuid = "E989D350-F926-417F-BB88-2C17D5DDE9F2"
|
||||
shouldBeEnabled = "No"
|
||||
ignoreCount = "0"
|
||||
continueAfterRunningActions = "No"
|
||||
filePath = "purchase/StoreObserver.m"
|
||||
startingColumnNumber = "9223372036854775807"
|
||||
endingColumnNumber = "9223372036854775807"
|
||||
startingLineNumber = "50"
|
||||
endingLineNumber = "50"
|
||||
landmarkName = "-getAppReceipt"
|
||||
landmarkType = "7">
|
||||
</BreakpointContent>
|
||||
</BreakpointProxy>
|
||||
<BreakpointProxy
|
||||
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
|
||||
<BreakpointContent
|
||||
uuid = "69659E6C-1EDA-428A-A479-A7139FF808A3"
|
||||
shouldBeEnabled = "No"
|
||||
ignoreCount = "0"
|
||||
continueAfterRunningActions = "No"
|
||||
filePath = "purchase/StoreObserver.m"
|
||||
startingColumnNumber = "9223372036854775807"
|
||||
endingColumnNumber = "9223372036854775807"
|
||||
startingLineNumber = "56"
|
||||
endingLineNumber = "56"
|
||||
landmarkName = "-getAppReceipt"
|
||||
landmarkType = "7">
|
||||
</BreakpointContent>
|
||||
</BreakpointProxy>
|
||||
<BreakpointProxy
|
||||
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
|
||||
<BreakpointContent
|
||||
uuid = "E2F34C60-2F85-4D8F-8A0A-75BD5B33C607"
|
||||
shouldBeEnabled = "No"
|
||||
ignoreCount = "0"
|
||||
continueAfterRunningActions = "No"
|
||||
filePath = "Classes_cocos/UIViewController+Purchase.mm"
|
||||
startingColumnNumber = "9223372036854775807"
|
||||
endingColumnNumber = "9223372036854775807"
|
||||
startingLineNumber = "158"
|
||||
endingLineNumber = "158"
|
||||
landmarkName = "-alertWithTitle:message:"
|
||||
landmarkType = "7">
|
||||
</BreakpointContent>
|
||||
</BreakpointProxy>
|
||||
<BreakpointProxy
|
||||
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
|
||||
<BreakpointContent
|
||||
uuid = "9119790E-EDB6-49DA-B186-43B0CE2E3876"
|
||||
shouldBeEnabled = "No"
|
||||
ignoreCount = "0"
|
||||
continueAfterRunningActions = "No"
|
||||
filePath = "Classes_cocos/UIViewController+Purchase.mm"
|
||||
startingColumnNumber = "9223372036854775807"
|
||||
endingColumnNumber = "9223372036854775807"
|
||||
startingLineNumber = "159"
|
||||
endingLineNumber = "159"
|
||||
landmarkName = "-alertWithTitle:message:"
|
||||
landmarkType = "7">
|
||||
</BreakpointContent>
|
||||
</BreakpointProxy>
|
||||
<BreakpointProxy
|
||||
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
|
||||
<BreakpointContent
|
||||
uuid = "A9CA3DDC-6205-4BD4-8933-EA7A3B91A6F3"
|
||||
shouldBeEnabled = "No"
|
||||
ignoreCount = "0"
|
||||
continueAfterRunningActions = "No"
|
||||
filePath = "purchase/StoreObserver.m"
|
||||
startingColumnNumber = "9223372036854775807"
|
||||
endingColumnNumber = "9223372036854775807"
|
||||
startingLineNumber = "206"
|
||||
endingLineNumber = "206"
|
||||
landmarkName = "-handleTransactionFailed:"
|
||||
landmarkType = "7">
|
||||
</BreakpointContent>
|
||||
</BreakpointProxy>
|
||||
<BreakpointProxy
|
||||
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
|
||||
<BreakpointContent
|
||||
uuid = "15FCA0D4-7E42-43F6-9DC2-FB0643322A2D"
|
||||
shouldBeEnabled = "Yes"
|
||||
ignoreCount = "0"
|
||||
continueAfterRunningActions = "No"
|
||||
filePath = "purchase/StoreObserver.m"
|
||||
startingColumnNumber = "9223372036854775807"
|
||||
endingColumnNumber = "9223372036854775807"
|
||||
startingLineNumber = "264"
|
||||
endingLineNumber = "264"
|
||||
landmarkName = "-onPurchaseResult:errorCode:errorDescription:"
|
||||
landmarkType = "7">
|
||||
</BreakpointContent>
|
||||
</BreakpointProxy>
|
||||
</Breakpoints>
|
||||
</Bucket>
|
||||
|
@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<VariablesViewState
|
||||
version = "1.0">
|
||||
<ContextStates>
|
||||
<ContextState
|
||||
contextName = "-[StoreObserver handlePurchasedTransaction:]:StoreObserver.m">
|
||||
<PersistentStrings>
|
||||
<PersistentString
|
||||
value = " transaction.originalID">
|
||||
</PersistentString>
|
||||
</PersistentStrings>
|
||||
</ContextState>
|
||||
</ContextStates>
|
||||
</VariablesViewState>
|
File diff suppressed because one or more lines are too long
38
js/main.js
38
js/main.js
@ -363,6 +363,20 @@ function tokenPrice(funId, tokenName, amount) {
|
||||
function fiatList(funId) {
|
||||
promiseCb(funId, jc.wallet.paySvr.fetchFiatList());
|
||||
}
|
||||
/**
|
||||
* query price of crypto -> usd
|
||||
* @param {string} crypto
|
||||
* @param {number} chain chain id,
|
||||
*/
|
||||
function getCryptoPriceOfUSD(funId, crypto, chain) {
|
||||
let chainData = jc.wallet.currentChain;
|
||||
if (chain) {
|
||||
chainData = jc.wallet.chainList.find((v) => v.chainId === +chain);
|
||||
}
|
||||
let network = chainData.type !== 'Testnet' ? chainData.network || chainData.symbol : 'ARBITRUM';
|
||||
network = network || 'ARBITRUM';
|
||||
promiseCb(funId, jc.wallet.paySvr.queryTokenPrice(network, crypto));
|
||||
}
|
||||
|
||||
/**
|
||||
* format price
|
||||
@ -493,20 +507,34 @@ function nftMallBuy(funId, currency, addresses, ids, amounts, values, signature,
|
||||
|
||||
// end of NFT mall
|
||||
|
||||
// begin of token mall
|
||||
// buy ceg with usdt, usdc
|
||||
function buyTokenWithErc20(funId, currency, amount, gas, estimate) {
|
||||
promiseCb(
|
||||
funId,
|
||||
jc.wallet.jcStandard.buyTokenWithErc20({
|
||||
currency,
|
||||
amount,
|
||||
estimate,
|
||||
}),
|
||||
(v) => JSON.stringify(v)
|
||||
);
|
||||
}
|
||||
// begin of token mall
|
||||
|
||||
// begin of google pay
|
||||
function queryGoogleProducts(funId, productIds) {
|
||||
let ids = JSON.parse(productIds);
|
||||
console.log('queryGoogleProducts:: ' + productIds);
|
||||
promiseCb(funId, jc.wallet.paySvr.queryGoogleProducts(ids));
|
||||
console.log('queryAppleProducts:: ' + productIds);
|
||||
promiseCb(funId, jc.wallet.paySvr.queryIOSProducts(ids));
|
||||
}
|
||||
|
||||
function queryGooglePurchases(funId) {
|
||||
promiseCb(funId, jc.wallet.paySvr.queryGooglePurchases());
|
||||
promiseCb(funId, jc.wallet.paySvr.queryIOSPurchases());
|
||||
}
|
||||
|
||||
function beginGoogleBuy(funId, productId, orderId) {
|
||||
promiseCb(funId, jc.wallet.paySvr.buyGoogleProduct(productId, orderId));
|
||||
promiseCb(funId, jc.wallet.paySvr.beginIOSPurchase(productId, orderId));
|
||||
}
|
||||
|
||||
// end of google pay
|
||||
|
||||
|
13
purchase/SKProduct+SKProductAdditions.h
Normal file
13
purchase/SKProduct+SKProductAdditions.h
Normal file
@ -0,0 +1,13 @@
|
||||
/*
|
||||
See LICENSE folder for this sample’s licensing information.
|
||||
|
||||
Abstract:
|
||||
Creates a category for the SKProduct class.
|
||||
*/
|
||||
|
||||
@import StoreKit;
|
||||
|
||||
@interface SKProduct (SKProductAdditions)
|
||||
/// - returns: The cost of the product formatted in the local currency.
|
||||
-(NSString *)regularPrice;
|
||||
@end
|
19
purchase/SKProduct+SKProductAdditions.m
Normal file
19
purchase/SKProduct+SKProductAdditions.m
Normal file
@ -0,0 +1,19 @@
|
||||
/*
|
||||
See LICENSE folder for this sample’s licensing information.
|
||||
|
||||
Abstract:
|
||||
Creates a category for the SKProduct class.
|
||||
*/
|
||||
|
||||
#import "SKProduct+SKProductAdditions.h"
|
||||
|
||||
@implementation SKProduct (SKProductAdditions)
|
||||
/// - returns: The cost of the product formatted in the local currency.
|
||||
-(NSString *)regularPrice {
|
||||
NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
|
||||
[formatter setNumberStyle:NSNumberFormatterCurrencyStyle];
|
||||
[formatter setLocale: self.priceLocale];
|
||||
return [formatter stringFromNumber:self.price];
|
||||
}
|
||||
|
||||
@end
|
@ -23,11 +23,13 @@ Retrieves product information from the App Store using SKRequestDelegate, SKProd
|
||||
@property (strong) NSMutableArray *storeResponse;
|
||||
|
||||
/// Starts the product request with the specified identifiers.
|
||||
-(void)startProductRequestWithIdentifiers:(NSArray *)identifiers;
|
||||
-(void)fetchProductsMatchingIdentifiers:(NSArray *)identifiers completionBlock: (nullable void (^) (PCSProductRequestStatus status, NSMutableArray * _Nullable storeResponse))completionBlock;
|
||||
|
||||
/// - returns: Existing product's title matching the specified product identifier.
|
||||
-(NSString *)titleMatchingIdentifier:(NSString *)identifier;
|
||||
|
||||
-(SKProduct *)productMatchingIdentifier:(NSString *)identifier;
|
||||
|
||||
/// - returns: Existing product's title associated with the specified payment transaction.
|
||||
-(NSString *)titleMatchingPaymentTransaction:(SKPaymentTransaction *)transaction;
|
||||
@end
|
||||
|
@ -19,6 +19,9 @@ Retrieves product information from the App Store using SKRequestDelegate, SKProd
|
||||
|
||||
/// Keeps a strong reference to the product request.
|
||||
@property (strong) SKProductsRequest *productRequest;
|
||||
|
||||
@property (copy, nonatomic) void (^completionBlock) (PCSProductRequestStatus, NSMutableArray *);
|
||||
|
||||
@end
|
||||
|
||||
@implementation StoreManager
|
||||
@ -47,13 +50,10 @@ Retrieves product information from the App Store using SKRequestDelegate, SKProd
|
||||
|
||||
#pragma mark - Request Information
|
||||
|
||||
/// Starts the product request with the specified identifiers.
|
||||
-(void)startProductRequestWithIdentifiers:(NSArray *)identifiers {
|
||||
[self fetchProductsMatchingIdentifiers:identifiers];
|
||||
}
|
||||
|
||||
/// Fetches information about your products from the App Store.
|
||||
-(void)fetchProductsMatchingIdentifiers:(NSArray *)identifiers {
|
||||
-(void)fetchProductsMatchingIdentifiers:(NSArray *)identifiers completionBlock: (void (^) (PCSProductRequestStatus status, NSMutableArray *resultAsString))completionBlock{
|
||||
self.completionBlock = completionBlock;
|
||||
// Create a set for the product identifiers.
|
||||
NSSet *productIdentifiers = [NSSet setWithArray:identifiers];
|
||||
|
||||
@ -89,7 +89,9 @@ Retrieves product information from the App Store using SKRequestDelegate, SKProd
|
||||
|
||||
if (self.storeResponse.count > 0) {
|
||||
self.status = PCSStoreResponse;
|
||||
|
||||
if (_completionBlock) {
|
||||
_completionBlock(self.status, self.storeResponse);
|
||||
}
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:PCSProductRequestNotification object:self];
|
||||
});
|
||||
@ -123,6 +125,16 @@ Retrieves product information from the App Store using SKRequestDelegate, SKProd
|
||||
return title;
|
||||
}
|
||||
|
||||
-(SKProduct *) productMatchingIdentifier:(NSString *)identifier {
|
||||
SKProduct *result = nil;
|
||||
for (SKProduct *product in self.availableProducts) {
|
||||
if ([product.productIdentifier isEqualToString:identifier]) {
|
||||
result = product;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/// - returns: Existing product's title associated with the specified payment transaction.
|
||||
-(NSString *)titleMatchingPaymentTransaction:(SKPaymentTransaction *) transaction {
|
||||
NSString *title = [self titleMatchingIdentifier:transaction.payment.productIdentifier];
|
||||
|
@ -27,13 +27,23 @@ Implements the SKPaymentTransactionObserver protocol. Handles purchasing and res
|
||||
/// Keeps track of all restored purchases.
|
||||
@property(strong) NSMutableArray *productsRestored;
|
||||
|
||||
@property(strong) NSMutableDictionary *pendingTransactions;
|
||||
|
||||
@property(strong) NSMutableSet *finishedTransactions;
|
||||
|
||||
/// Indicates the purchase status.
|
||||
@property(nonatomic) PCSPurchaseStatus status;
|
||||
|
||||
/// Implements the purchase of a product.
|
||||
-(void)buy:(SKProduct *)product;
|
||||
- (void)buy:(SKProduct *)product orderId:(NSString *)orderId;
|
||||
|
||||
- (void)finishTransaction:(NSString *)transactionIdentifier;
|
||||
|
||||
- (NSArray *)queryPendingTransactions;
|
||||
|
||||
/// Implements the restoration of previously completed purchases.
|
||||
- (void)restore;
|
||||
@end
|
||||
|
||||
- (NSString *)getAppReceipt;
|
||||
|
||||
@end
|
||||
|
@ -28,8 +28,9 @@ Implements the SKPaymentTransactionObserver protocol. Handles purchasing and res
|
||||
|
||||
if (self != nil) {
|
||||
_hasRestorablePurchases = NO;
|
||||
_productsPurchased = [[NSMutableArray alloc] initWithCapacity:0];
|
||||
_productsRestored = [[NSMutableArray alloc] initWithCapacity:0];
|
||||
_pendingTransactions = [[NSMutableDictionary alloc] init];
|
||||
_finishedTransactions = [[NSMutableSet alloc] init];
|
||||
_status = PCSPurchaseStatusNone;
|
||||
}
|
||||
return self;
|
||||
@ -43,11 +44,73 @@ Implements the SKPaymentTransactionObserver protocol. Handles purchasing and res
|
||||
return [SKPaymentQueue canMakePayments];
|
||||
}
|
||||
|
||||
- (NSString*)getAppReceipt
|
||||
{
|
||||
NSBundle* bundle = [NSBundle mainBundle];
|
||||
if ([bundle respondsToSelector: @selector(appStoreReceiptURL)])
|
||||
{
|
||||
NSURL *receiptURL = [bundle appStoreReceiptURL];
|
||||
if ([[NSFileManager defaultManager] fileExistsAtPath: [receiptURL path]])
|
||||
{
|
||||
NSData *receipt = [NSData dataWithContentsOfURL: receiptURL];
|
||||
|
||||
#if MAC_APPSTORE
|
||||
// The base64EncodedStringWithOptions method was only added in OSX 10.9.
|
||||
NSString* result = [receipt mgb64_base64EncodedString];
|
||||
#else
|
||||
NSString* result = [receipt base64EncodedStringWithOptions: 0];
|
||||
#endif
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
NSLog(@"No App Receipt found");
|
||||
return @"";
|
||||
}
|
||||
#if !MAC_APPSTORE
|
||||
- (BOOL)isiOS6OrEarlier
|
||||
{
|
||||
float version = [[[UIDevice currentDevice] systemVersion] floatValue];
|
||||
return version < 7;
|
||||
}
|
||||
|
||||
#endif
|
||||
// Retrieve a receipt for the transaction, which will either
|
||||
// be the old style transaction receipt on <= iOS 6,
|
||||
// or the App Receipt in OSX and iOS 7+.
|
||||
- (NSString*)selectReceipt:(SKPaymentTransaction*)transaction
|
||||
{
|
||||
#if MAC_APPSTORE
|
||||
return [self getAppReceipt];
|
||||
#else
|
||||
if ([self isiOS6OrEarlier])
|
||||
{
|
||||
if (nil == transaction)
|
||||
{
|
||||
return @"";
|
||||
}
|
||||
NSString* receipt;
|
||||
receipt = [[NSString alloc] initWithData: transaction.transactionReceipt encoding: NSUTF8StringEncoding];
|
||||
|
||||
return receipt;
|
||||
}
|
||||
else
|
||||
{
|
||||
return [self getAppReceipt];
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#pragma mark - Submit Payment Request
|
||||
|
||||
/// Creates and adds a payment request to the payment queue.
|
||||
-(void)buy:(SKProduct *)product {
|
||||
-(void)buy:(SKProduct *)product orderId: (NSString *) orderId {
|
||||
SKMutablePayment *payment = [SKMutablePayment paymentWithProduct:product];
|
||||
// payment.applicationUsername = orderId;
|
||||
// generate UUID for order id
|
||||
NSString *testOrderId = [[NSUUID UUID] UUIDString];
|
||||
[payment performSelector: @selector(setApplicationUsername:) withObject: testOrderId];
|
||||
[[SKPaymentQueue defaultQueue] addPayment:payment];
|
||||
}
|
||||
|
||||
@ -72,13 +135,13 @@ Implements the SKPaymentTransactionObserver protocol. Handles purchasing and res
|
||||
case SKPaymentTransactionStateDeferred: NSLog(@"%@", PCSMessagesDeferred);
|
||||
break;
|
||||
// The purchase was successful.
|
||||
case SKPaymentTransactionStatePurchased: [self handlePurchasedTransaction:transaction];
|
||||
case SKPaymentTransactionStatePurchased: [self handleTransactionPurchased:transaction];
|
||||
break;
|
||||
// The transaction failed.
|
||||
case SKPaymentTransactionStateFailed: [self handleFailedTransaction:transaction];
|
||||
case SKPaymentTransactionStateFailed: [self handleTransactionFailed:transaction];
|
||||
break;
|
||||
// There are restored products.
|
||||
case SKPaymentTransactionStateRestored: [self handleRestoredTransaction:transaction];
|
||||
case SKPaymentTransactionStateRestored: [self handleTransactionRestored:transaction];
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
@ -94,75 +157,119 @@ Implements the SKPaymentTransactionObserver protocol. Handles purchasing and res
|
||||
|
||||
/// Called when an error occur while restoring purchases. Notifies the user about the error.
|
||||
- (void)paymentQueue:(SKPaymentQueue *)queue restoreCompletedTransactionsFailedWithError:(NSError *)error {
|
||||
if (error.code != SKErrorPaymentCancelled) {
|
||||
self.status = PCSRestoreFailed;
|
||||
self.message = error.localizedDescription;
|
||||
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:PCSPurchaseNotification object:self];
|
||||
});
|
||||
}
|
||||
NSLog(@"%@\n%@", PCSMessagesFailed, error.localizedDescription);
|
||||
// if (error.code != SKErrorPaymentCancelled) {
|
||||
// self.status = PCSRestoreFailed;
|
||||
// self.message = error.localizedDescription;
|
||||
//
|
||||
// dispatch_async(dispatch_get_main_queue(), ^{
|
||||
// [[NSNotificationCenter defaultCenter] postNotificationName:PCSPurchaseNotification object:self];
|
||||
// });
|
||||
// }
|
||||
}
|
||||
|
||||
/// Called when all restorable transactions have been processed by the payment queue.
|
||||
- (void)paymentQueueRestoreCompletedTransactionsFinished:(SKPaymentQueue *)queue {
|
||||
NSLog(@"%@", PCSMessagesRestorable);
|
||||
|
||||
if (!self.hasRestorablePurchases) {
|
||||
self.status = PCSNoRestorablePurchases;
|
||||
self.message = [NSString stringWithFormat:@"%@\n%@", PCSMessagesNoRestorablePurchases, PCSMessagesPreviouslyBought];
|
||||
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:PCSPurchaseNotification object:self];
|
||||
});
|
||||
}
|
||||
NSLog(@"%@\n%@", PCSMessagesNoRestorablePurchases, PCSMessagesPreviouslyBought);
|
||||
// if (!self.hasRestorablePurchases) {
|
||||
// self.status = PCSNoRestorablePurchases;
|
||||
// self.message = [NSString stringWithFormat:@"%@\n%@", PCSMessagesNoRestorablePurchases, PCSMessagesPreviouslyBought];
|
||||
//
|
||||
// dispatch_async(dispatch_get_main_queue(), ^{
|
||||
// [[NSNotificationCenter defaultCenter] postNotificationName:PCSPurchaseNotification object:self];
|
||||
// });
|
||||
// }
|
||||
}
|
||||
|
||||
#pragma mark - Handle Payment Transactions
|
||||
|
||||
/// Handles successful purchase transactions.
|
||||
-(void)handlePurchasedTransaction:(SKPaymentTransaction*)transaction {
|
||||
[self.productsPurchased addObject:transaction];
|
||||
-(void)handleTransactionPurchased:(SKPaymentTransaction*)transaction {
|
||||
NSString *transactionId = transaction.transactionIdentifier;
|
||||
NSLog(@"%@ %@.", PCSMessagesDeliverContent, transaction.payment.productIdentifier);
|
||||
NSLog(@"original transaction id: %@", transactionId);
|
||||
NSLog(@"order id: %@", transaction.payment.applicationUsername);
|
||||
[self onTransactionSucceeded: transaction];
|
||||
}
|
||||
|
||||
// Finish the successful transaction.
|
||||
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
|
||||
/// Handles restored purchase transactions.
|
||||
-(void)handleTransactionRestored:(SKPaymentTransaction*)transaction {
|
||||
self.status = PCSRestoreSucceeded;
|
||||
self.hasRestorablePurchases = true;
|
||||
[self onTransactionSucceeded: transaction];
|
||||
}
|
||||
|
||||
/// Handles failed purchase transactions.
|
||||
-(void)handleFailedTransaction:(SKPaymentTransaction*)transaction {
|
||||
-(void)handleTransactionFailed:(SKPaymentTransaction*)transaction {
|
||||
self.status = PCSPurchaseFailed;
|
||||
self.message = [NSString stringWithFormat:@"%@ %@ %@",PCSMessagesPurchaseOf, transaction.payment.productIdentifier, PCSMessagesFailed];
|
||||
|
||||
if (transaction.error) {
|
||||
[self.message stringByAppendingString:[NSString stringWithFormat:@"\n%@ %@", PCSMessagesError, transaction.error.localizedDescription]];
|
||||
NSLog(@"%@ %@", PCSMessagesError, transaction.error.localizedDescription);
|
||||
}
|
||||
|
||||
// Do not send any notifications when the user cancels the purchase.
|
||||
if (transaction.error.code != SKErrorPaymentCancelled) {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:PCSPurchaseNotification object:self];
|
||||
});
|
||||
}
|
||||
[self onPurchaseResult: transaction.payment.productIdentifier errorCode: 200 + transaction.error.code errorDescription: [NSString stringWithFormat:@"\n%@ %@", PCSMessagesError, transaction.error.localizedDescription]];
|
||||
|
||||
// Finish the failed transaction.
|
||||
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
|
||||
}
|
||||
|
||||
/// Handles restored purchase transactions.
|
||||
-(void)handleRestoredTransaction:(SKPaymentTransaction*)transaction {
|
||||
self.status = PCSRestoreSucceeded;
|
||||
self.hasRestorablePurchases = true;
|
||||
[self.productsRestored addObject:transaction];
|
||||
NSLog(@"%@ %@.", PCSMessagesRestoreContent, transaction.payment.productIdentifier);
|
||||
// Handle a new or restored purchase transaction by informing Unity.
|
||||
- (void)onTransactionSucceeded:(SKPaymentTransaction*)transaction
|
||||
{
|
||||
NSString* transactionId = transaction.transactionIdentifier;
|
||||
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:PCSPurchaseNotification object:self];
|
||||
});
|
||||
// This should never happen according to Apple's docs, but it does!
|
||||
if (nil == transactionId)
|
||||
{
|
||||
// Make something up, allowing us to identifiy the transaction when finishing it.
|
||||
transactionId = [[NSUUID UUID] UUIDString];
|
||||
NSLog(@"Missing transaction Identifier!");
|
||||
[self onPurchaseResult: transactionId errorCode: 101 errorDescription: @"Missing transaction Identifier!"];
|
||||
}
|
||||
|
||||
// Finish the restored transaction.
|
||||
// This transaction was marked as finished, but was not cleared from the queue. Try to clear it now, then pass the error up the stack as a DuplicateTransaction
|
||||
if ([self.finishedTransactions containsObject: transactionId])
|
||||
{
|
||||
[[SKPaymentQueue defaultQueue] finishTransaction: transaction];
|
||||
NSLog(@"DuplicateTransaction error with product %@ and transactionId %@", transaction.payment.productIdentifier, transactionId);
|
||||
[self onPurchaseResult: transaction.payment.productIdentifier errorCode: 100 errorDescription: @"Duplicate transaction occurred"];
|
||||
return; // EARLY RETURN
|
||||
}
|
||||
|
||||
// Item was successfully purchased or restored.
|
||||
if (nil == [self.pendingTransactions objectForKey: transactionId])
|
||||
{
|
||||
[self.pendingTransactions setObject: transaction forKey: transactionId];
|
||||
}
|
||||
[self onPurchaseResult: transactionId errorCode: 0 errorDescription: @""];
|
||||
}
|
||||
|
||||
- (NSArray *)queryPendingTransactions{
|
||||
return [self.pendingTransactions allKeys];
|
||||
}
|
||||
|
||||
- (void)finishTransaction:(NSString *)transactionIdentifier{
|
||||
SKPaymentTransaction* transaction = [self.pendingTransactions objectForKey: transactionIdentifier];
|
||||
if (nil != transaction) {
|
||||
NSLog(@"Finishing transaction %@", transactionIdentifier);
|
||||
[[SKPaymentQueue defaultQueue] finishTransaction: transaction]; // If this fails (user not logged into the store?), transaction is already removed from pendingTransactions, so future calls to finishTransaction will not retry
|
||||
[self.pendingTransactions removeObjectForKey: transactionIdentifier];
|
||||
[self.finishedTransactions addObject: transactionIdentifier];
|
||||
}
|
||||
else {
|
||||
NSLog(@"Transaction %@ not pending, nothing to finish here", transactionIdentifier);
|
||||
}
|
||||
}
|
||||
|
||||
- (void)onPurchaseResult:(NSString*)productId errorCode:(NSInteger)errorCode errorDescription:(NSString*)errorDescription
|
||||
{
|
||||
NSMutableDictionary* dic = [[NSMutableDictionary alloc] init];
|
||||
[dic setObject: productId forKey: @"dataid"];
|
||||
[dic setObject: [NSNumber numberWithInteger: errorCode] forKey: @"errcode"];
|
||||
[dic setObject: errorDescription forKey: @"errmsg"];
|
||||
|
||||
// NSData* data = [NSJSONSerialization dataWithJSONObject: dic options: 0 error: nil];
|
||||
// NSString* result = [[NSString alloc] initWithData: data encoding: NSUTF8StringEncoding];
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:PCSPurchaseNotification object: self userInfo:dic];
|
||||
});
|
||||
}
|
||||
|
||||
@end
|
||||
|
33
test-in-app-purchase.storekit
Normal file
33
test-in-app-purchase.storekit
Normal file
@ -0,0 +1,33 @@
|
||||
{
|
||||
"identifier" : "E7768E5D",
|
||||
"nonRenewingSubscriptions" : [
|
||||
|
||||
],
|
||||
"products" : [
|
||||
{
|
||||
"displayPrice" : "0.99",
|
||||
"familyShareable" : false,
|
||||
"internalID" : "07066426",
|
||||
"localizations" : [
|
||||
{
|
||||
"description" : "buy 100ceg",
|
||||
"displayName" : "100ceg",
|
||||
"locale" : "en_US"
|
||||
}
|
||||
],
|
||||
"productID" : "2999",
|
||||
"referenceName" : "100d",
|
||||
"type" : "Consumable"
|
||||
}
|
||||
],
|
||||
"settings" : {
|
||||
|
||||
},
|
||||
"subscriptionGroups" : [
|
||||
|
||||
],
|
||||
"version" : {
|
||||
"major" : 2,
|
||||
"minor" : 0
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user