充值
当coins不足时,游戏可以通过调用客户端提供的方法调起充值弹窗。
集成示例
以下是javascript集成的代码示例:
1.1 引入代码
javascript
// 先引入下面的代码
(function(){
const PayBridge = (() => {
const state = { onResultHandler: null };
function onResult(fn) {
state.onResultHandler = typeof fn === 'function' ? fn : null;
}
function _nativeCallback(method, result) {
try {
if (typeof result === 'string') result = JSON.parse(result);
} catch (e) {}
if (state.onResultHandler) state.onResultHandler(method, result);
try {
window.parent && window.parent !== window &&
window.parent.postMessage({ __fromNative: true, type: 'nativePayResult', method, result }, '*');
} catch(e){}
}
function pay(payload) {
payload = payload || {};
payload.requestId = payload.requestId || (Date.now() + '-' + Math.random().toString(16).slice(2));
if (window.webkit && window.webkit.messageHandlers && window.webkit.messageHandlers.pay) {
window.webkit.messageHandlers.pay.postMessage(payload);
} else {
console.warn('In a non-App environment, native payment cannot be invoked');
}
return payload.requestId;
}
return { onResult, _nativeCallback, pay };
})();
window.PayBridge = PayBridge;
try {
if (window.top && window.top !== window && !window.top.PayBridge)
window.top.PayBridge = PayBridge;
} catch(e){}
let callbackCounter = 0;
const CALLBACK_PREFIX = '_gameTok_callback_';
const ANDROID_BRIDGE_NAME = 'GameTok';
const ANDROID_BRIDGE_METHOD = 'gameTokRequestPayment';
function detectPlatform() {
const isAndroid = /Android/i.test(navigator.userAgent);
const isIOS = /iPhone|iPad|iPod/i.test(navigator.userAgent);
const isWKWebView = !!(window.webkit && window.webkit.messageHandlers);
if (isAndroid) {
const available = !!(window[ANDROID_BRIDGE_NAME] && typeof window[ANDROID_BRIDGE_NAME][ANDROID_BRIDGE_METHOD] === 'function');
return { platform: 'android', available };
} else if (isIOS) {
const available = isWKWebView;
return {
platform: 'ios',
available,
isWKWebView,
hasPayHandler: !!(window.webkit && window.webkit.messageHandlers && window.webkit.messageHandlers.pay)
};
} else {
return { platform: 'browser', available: false };
}
}
const iosCallbackManager = {
callbacks: new Map(),
register(requestId, successCallback, failCallback) {
this.callbacks.set(requestId, { successCallback, failCallback });
},
handleCallback(method, result) {
if (method !== 'pay') return;
console.log(method,'method',result,'result');
const requestId = result.requestId;
const callbacks = this.callbacks.get(requestId);
if (callbacks) {
try {
if (result.status === 1 && callbacks.successCallback) {
callbacks.successCallback(result);
} else if (result.status !== 1 && callbacks.failCallback) {
callbacks.failCallback(result.message || 'Payment Fail');
}
} catch (e) {
console.error(e);
} finally {
this.callbacks.delete(requestId);
}
}
}
};
let iosListenerInitialized = false;
function initIOSMessageListener() {
if (iosListenerInitialized) return;
iosListenerInitialized = true;
window.addEventListener('message', (e) => {
const d = e.data || {};
if (d && d.__fromNative === true && d.type === 'nativePayResult' && d.method === 'pay') {
iosCallbackManager.handleCallback(d.method, d.result);
}
});
}
function cleanupCallbacks(successCallback, failCallback) {
try {
delete window[successCallback];
delete window[failCallback];
} catch (e) {
console.warn(e);
}
}
window.gameTokRequestPayment = function(options) {
if (!options || typeof options !== 'object') {
const error = 'Parameter error: options must be an object';
if (typeof options.fail === 'function') {
options.fail(error);
} else {
console.error(error);
}
return;
}
if (typeof options.amount !== 'number' || options.amount <= 0) {
const error = 'Parameter error: The "amount" must be a positive number.';
if (typeof options.fail === 'function') {
options.fail(error);
} else {
console.error(error);
}
return;
}
const platformInfo = detectPlatform();
if (!platformInfo.available) {
const error = `${platformInfo.platform}The platform's native bridge is unavailable`;
if (typeof options.fail === 'function') {
options.fail(error);
} else {
console.error(error);
}
return;
}
if (!options.success && !options.fail) {
return new Promise((resolve, reject) => {
const newOptions = {
...options,
success: resolve,
fail: reject
};
window.gameTokRequestPayment(newOptions);
});
}
if (platformInfo.platform === 'android') {
const successCallbackName = CALLBACK_PREFIX + 'success_' + (++callbackCounter);
const failCallbackName = CALLBACK_PREFIX + 'fail_' + callbackCounter;
window[successCallbackName] = function(result) {
cleanupCallbacks(successCallbackName, failCallbackName);
if (typeof options.success === 'function') {
options.success(result);
}
};
window[failCallbackName] = function(error) {
cleanupCallbacks(successCallbackName, failCallbackName);
if (typeof options.fail === 'function') {
options.fail(error);
}
};
try {
window[ANDROID_BRIDGE_NAME][ANDROID_BRIDGE_METHOD](
options.amount,
successCallbackName,
failCallbackName
);
} catch (error) {
console.error('Failed to invoke the native Android recharge method:', error);
cleanupCallbacks(successCallbackName, failCallbackName);
if (typeof options.fail === 'function') {
options.fail(error);
}
}
} else if (platformInfo.platform === 'ios') {
initIOSMessageListener();
const requestId = Date.now() + '-' + Math.random().toString(16).slice(2);
const payload = {
amount: options.amount,
requestId: requestId
};
iosCallbackManager.register(requestId, options.success, options.fail);
try {
window.PayBridge.pay(payload);
} catch (error) {
console.error('Failed to invoke the native iOS recharge method:', error);
iosCallbackManager.callbacks.delete(requestId);
if (typeof options.fail === 'function') {
options.fail(error);
}
}
}
};
window.gameTokRequestPayment.version = '2.0.1';
window.gameTokRequestPayment.getPlatformInfo = detectPlatform;
window.gameTokRequestPayment.isAvailable = function() {
return detectPlatform().available;
};
window.gameTokRequestPayment.iosCallbackManager = iosCallbackManager;
})();1.2 调用
javascript
// 调用方法
window.gameTokRequestPayment({
amount: 100, //需要充值的数值
success(result) {
console.log('充值成功:', result);
//todo 这儿不会有具体的充值金额,只会收到客户端充值成的通知,一般需要再查询下当前金币,刷新下游戏中金币数量显示
},
fail(error) {
console.log('充值失败:', error);
}
});重要说明
绝对不要覆盖或删除以下全局变量:
window.GameTok(Android充值必需)window.webkit(iOS充值必需)window.gameTokRequestPayment(SDK主接口)
错误示例 ❌
javascript
// 危险!这会导致Android充值功能失效
window.GameTok = null;
window.GameTok = {};
delete window.GameTok;
// 危险!这会覆盖整个充值方法
window.gameTokRequestPayment = function() {};