Skip to main content

Midasbuy Minigame SDK API Protocol

1. Overview

Midasbuy Minigame SDK is a unified mini-game SDK loader and adapter that provides consistent API interfaces for Menu, Payment, and Login function modules.

2. SDK Integration

<script src="https://cdn.midasbuy.com/js/minigame.stable.js"></script>

3. API Protocol

3.1 Initialization midas.minigame(options)

const minigameApi = midas.minigame({
// Basic Configuration
appid: '1460000904',
region: 'us',
language: 'en',
sandbox: 1,
shopcode: 'ludoinapp',

// Menu Module Configuration, optional
menu: {
isWithPcHeader: true
},

// Payment Module Configuration, optional
payment: {
openid: '1018553529511732', // optional, to reduce bad debt rate
charac_name: 'Player1', // optional, to reduce bad debt rate
},

// Login Module Configuration, optional
login: {
debug: true,
timeout: 30000
}
});

Parameter Description

ParameterTypeRequiredDescription
appidstringYesApplication ID
regionstringYesRegion code, 2 characters
languagestringNoLanguage code, default 'en'
sandboxnumberNoEnvironment: 0-production, 1-sandbox, 2-test, default 0
shopcodestringNoShop code
menuMenuConfigNoMenu module configuration
paymentPaymentConfigNoPayment module configuration
loginLoginConfigNoLogin module configuration
interface MenuConfig {
isWithPcHeader?: boolean; // Whether to include top header on PC
}

PaymentConfig Type

interface PaymentConfig {
openid?: string; // User openid
charac_name?: string; // Character name
}

LoginConfig Type

interface LoginConfig {
debug?: boolean; // Debug mode
timeout?: number; // Request timeout (milliseconds)
}

3.2 Menu Functions

3.2.1 Show Menu minigameApi.showMenu(options)

// Show game menu
minigameApi.showMenu({
gradually: true
});
Parameter Description
ParameterTypeRequiredDescription
graduallybooleanNoWhether to show progressively, default true

3.2.2 Hide Menu minigameApi.hideMenu(options)

// Hide game menu
minigameApi.hideMenu({
gradually: true
});
Parameter Description
ParameterTypeRequiredDescription
graduallybooleanNoWhether to hide progressively, default true

3.3 Payment Functions

3.3.1 Show Payment Page minigameApi.showPayment(options)

Event-based Style (Legacy):

// Show payment page with event listeners
minigameApi.on('payment:success', (data) => {
console.log('Payment successful:', data);
});

minigameApi.on('payment:failed', (error) => {
console.log('Payment failed:', error);
});

minigameApi.showPayment({
params: {
game_openid: '1018553529511732',
role_id: '1555629938',
product_id: 'coins_01-midasbuy'
},
extra: {
hideResultPage: true
}
});

Promise Style (Recommended):

// Show payment page with Promise
minigameApi.showPayment({
params: {
game_openid: '1018553529511732',
role_id: '1555629938',
product_id: 'coins_01-midasbuy',
server_id: 'server_001'
},
extra: {
hideResultPage: true
}
})
.then(data => {
console.log('Payment successful:', data);
// data contains: { order_no, openid, order_no_hash }
})
.catch(error => {
console.log('Payment error:', error);

// Handle different error types
switch(error.type) {
case 'failed':
console.log('Payment failed:', error.data);
break;
case 'hide':
console.log('Payment dialog was closed');
break;
case 'queryChannelsFailed':
console.log('Failed to load payment channels:', error.data);
break;
}
});

// Using async/await
async function handlePayment() {
try {
const result = await minigameApi.showPayment({
params: {
game_openid: '1018553529511732',
role_id: '1555629938',
product_id: 'coins_01-midasbuy',
server_id: 'server_001'
}
});
console.log('Payment successful:', result);
} catch (error) {
console.log('Payment failed:', error.type, error.message);
}
}
Parameter Description
ParameterTypeRequiredDescription
paramsPaymentParamsYesPayment parameters
extraPaymentExtraNoAdditional payment parameters

PaymentParams Type

interface PaymentParams {
game_openid: string; // Game user ID
role_id: string; // Role ID
product_id: string; // Product ID
server_id?: string; // Server ID for game partitioning
is_vip_product?: boolean; // Whether it's a VIP product
}

PaymentExtra Type

interface PaymentExtra {
hideResultPage?: boolean; // Whether to hide result page
}

PaymentError Type

interface PaymentError extends Error {
code: string; // Error code
type: 'failed' | 'hide' | 'queryChannelsFailed'; // Error type
data?: any; // Additional error data
timestamp: number; // Error timestamp
}
Error Types
TypeDescriptionWhen it occurs
failedPayment transaction failedUser payment was unsuccessful
hidePayment dialog closedUser closed the payment dialog
queryChannelsFailedFailed to load payment channelsNetwork error or invalid product

3.3.2 Hide Payment Page minigameApi.hidePayment()

// Hide payment page
minigameApi.hidePayment();

3.4 Login Functions

3.4.1 User Login minigameApi.login(options)

Callback Style:

// User login with callbacks
minigameApi.login({
success: function(result) {
console.log('Login successful:', result);
},
fail: function(error) {
console.log('Login failed:', error);
}
});

Promise Style:

// User login with Promise
minigameApi.login()
.then(result => {
console.log('Login successful, jwtToken:', result.data.jwtToken);
})
.catch(error => {
console.log('Login failed:', error);
});

// Or using async/await
async function handleLogin() {
try {
const result = await minigameApi.login();
console.log('Login successful:', result);
} catch (error) {
console.log('Login failed:', error);
}
}

Parameter Description:

ParameterTypeRequiredDescription
successFunctionNoLogin success callback function
failFunctionNoLogin failure callback function

Note: When using Promise style, you can omit the success and fail callbacks and use .then() and .catch() instead.

Success Callback Parameters:

{
code: 0,
message: 'success',
data: {
jwtToken: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...',
expiresIn: 3600,
refreshToken: 'rt_xxxxxxxxxxxxxxxx'
}
}

Failure Callback Parameters:

{
code: -1,
message: 'Error description',
error: 'ERROR_CODE'
}

3.5 Products Functions

3.5.1 Get Products Data minigameApi.getProductsData(params)

Get the product shelf information for display in the game.

Promise Style:

// Get products data
minigameApi.getProductsData({
game_openid: '1018553529511732',
role_id: '1555629938',
server_id: 'server_001'
})
.then(data => {
console.log('getProductsData successful:', data);
// data contains: { products: ProductItem[] }
})
.catch(error => {
console.log('getProductsData failed:', error);
});

// Using async/await
async function handleGetProducts() {
try {
const result = await minigameApi.getProductsData({
game_openid: '1018553529511732',
role_id: '1555629938',
server_id: 'server_001'
});
console.log('Products data:', result.products);
} catch (error) {
console.log('Failed to get products:', error);
}
}
Parameter Description
ParameterTypeRequiredDescription
game_openidstringYesGame user ID
role_idstringYesRole ID
server_idstringNoServer ID for game partitioning
ProductItem Type
interface ProductItem {
product_id: string; // Unique identification of the item within Midasbuy
game_product_id: string; // Unique identification of the item within game
quantity: number; // Game coins or items amount (combined with product_type)
product_type: 'currency' | 'item'; // Product type: currency or item
product_icon: string; // Product image URL
name: string; // Product name
price_info: {
price: string; // Current price, e.g.: '69.99'
original_price: string; // Original price, e.g.: '77.99'
currency: string; // Currency code, e.g.: 'HKD'
display_price: string; // Display price with currency, e.g.: '69.99 HKD'
display_original_price: string; // Display original price with currency, e.g.: '77.99 HKD'
};
bonus: {
virtual_currency_quantity: number; // Bonus virtual currency amount
virtual_item_list: {
product_id: string; // Unique identification of the item within Midasbuy in bonus item
game_product_id: string; // Unique identification of the item within game in bonus item
name: string; // Bonus item name
quantity: number; // Bonus item quantity
icon: string; // Bonus item image URL
}[]; // Bonus virtual items list
};
meta: any; // Original shelf data, generally no attention required
}

product_id and game_product_id are generally one-to-one.

Example ProductItem:

const exampleProduct: ProductItem = {
product_id: "600_coins_vip",
game_product_id: "600_coins",
quantity: 600,
product_type: "currency",
product_icon: "https://cdn.midasbuy.com/images/apps/pubgm/1599546041426W8hmErMS.png",
name: "600 UnknownCash",
price_info: {
price: "69.99",
original_price: "77.99",
currency: "HKD",
display_price: "69.99 HKD",
display_original_price: "77.99 HKD"
},
bonus: {
virtual_currency_quantity: 60,
virtual_item_list: [
{
product_id: "MP_DEFAULT_MOBILE_COIN",
game_product_id: "MP_DEFAULT_MOBILE_COIN",
name: "Event Voucher (Use in event)",
quantity: 1,
icon: "https://cdn.midasbuy.com/images/4113%20%281%29.2c5fa435.png"
}
]
},
meta: { /* original shelf data */ }
};

meta is original shelf data, generally no attention required. Refer to https://midasbuy-develop.pages.woa.com/master/%E5%BE%AE%E6%9C%8D%E5%8A%A1%E4%BB%8B%E7%BB%8D/%E8%B4%A7%E6%9E%B6%E6%9C%8D%E5%8A%A1/3.%20%E5%8D%8F%E8%AE%AE%E8%AE%BE%E8%AE%A1/%E8%B4%A7%E6%9E%B6%E6%9C%8D%E5%8A%A1%E5%8D%8F%E8%AE%AE/#shelfproduct

ProductsResult Type
interface ProductsResult {
products: ProductItem[]; // Array of product items
}

3.6 Event Listening minigameApi.on(event, callback)

// Game menu events
minigameApi.on('menu:show', (data) => {
console.log('Game menu shown successfully', data);
});

minigameApi.on('menu:hide', () => {
console.log('Game menu hidden');
});

minigameApi.on('menu:error', (error) => {
console.error('Game menu error', error);
});

// Payment events
minigameApi.on('payment:success', (data) => {
console.log('Payment successful', data);
});

minigameApi.on('payment:failed', (error) => {
console.log('Payment failed', error);
});

minigameApi.on('payment:hide', () => {
console.log('Payment page hidden');
});

minigameApi.on('payment:queryChannelsFailed', (error) => {
console.log('Query channels failed', error);
});

// Login events
minigameApi.on('login:success', (data) => {
console.log('Login successful', data);
// data: { jwtToken }
});

minigameApi.on('login:failed', (error) => {
console.log('Login failed', error);
});

minigameApi.on('login:statusChanged', (status) => {
console.log('Login status changed', status);
});

minigameApi.on('login:tokenExpired', () => {
console.log('Token expired');
});

// Products events
minigameApi.on('products:success', (data) => {
console.log('Products data loaded successfully', data);
});

minigameApi.on('products:failed', (error) => {
console.log('Failed to load products data', error);
});

// Common events
minigameApi.on('sdk:loaded', (modules) => {
console.log('SDK loaded successfully', modules);
});

minigameApi.on('sdk:error', (error) => {
console.error('SDK error', error);
});

Event Types

Event NameDescriptionCallback Parameters
menu:showGame menu shown successfully{ res: string, size?: { width?: string, height?: string } }
menu:hideGame menu hiddenNone
menu:errorGame menu errorError
payment:successPayment successful{ order_no: string, openid: string, order_no_hash: string }
payment:failedPayment failedError
payment:hidePayment page hiddenNone
payment:queryChannelsFailedQuery channels failedError
login:successLogin successful{ jwtToken: string }
login:failedLogin failedError
login:statusChangedLogin status changed'logged_in' | 'logged_out' | 'token_expired'
login:tokenExpiredToken expiredNone
products:successProducts data loaded successfullyProductsResult
products:failedFailed to load products dataError
sdk:loadedSDK loaded successfullystring[] (List of loaded modules)
sdk:errorSDK errorError

3.7 Remove Event Listener minigameApi.off(event, callback?)

// Remove specific callback
minigameApi.off('payment:success', callback);

// Remove all callbacks
minigameApi.off('payment:success');

3.8 Utility Methods

3.8.1 Get Module Instance minigameApi.getModule(module)

Get direct access to specific module instances for advanced usage.

// Get menu module instance
const menuModule = minigameApi.getModule('menu');
if (menuModule) {
// Direct access to menu module methods
menuModule.show({ gradually: false });
}

// Get payment module instance
const paymentModule = minigameApi.getModule('payment');
if (paymentModule) {
// Direct access to payment module methods
paymentModule.emit('checkout', params);
}

// Get login module instance
const loginModule = minigameApi.getModule('login');
if (loginModule) {
// Direct access to login module methods
const token = await minigameApi.getLoginToken?.();
}
Parameter Description
ParameterTypeRequiredDescription
modulestringYesModule name: 'menu', 'payment', or 'login'
Return Value

Returns the corresponding module instance, or null if the module is not loaded or invalid.

3.8.2 Hide All Modules minigameApi.hideAll()

// Hide all modules (menu, payment, etc.)
minigameApi.hideAll();

4. Error Handling

4.1 Error Types

```typescript
interface MinigameError extends Error {
code: string;
module?: 'menu' | 'payment' | 'login' | 'core';
details?: any;
}

4.2 Error Codes

Error CodeDescription
INIT_FAILEDInitialization failed
MODULE_NOT_LOADEDModule not loaded
INVALID_PARAMSInvalid parameters
SHOW_FAILEDShow failed
HIDE_FAILEDHide failed
PAYMENT_FAILEDPayment failed
NETWORK_ERRORNetwork error

4.3 Global Error Handling

minigameApi.setErrorHandler((error) => {
console.error('Minigame SDK Error:', error);
// Custom error handling logic
});

5. Type Definitions

declare namespace midas {
interface MinigameAPI {
showMenu(options?: MenuShowOptions): Promise<ShowResult>;
hideMenu(options?: MenuHideOptions): void;
showPayment(options: PaymentShowOptions): Promise<PaymentResult>;
hidePayment(): void;
hideAll(): void;
login(options: LoginOptions): Promise<LoginResult>;
getLoginStatus(): boolean;
logout(): void;
getProductsData(params: ProductsParams): Promise<ProductsResult>;
on(event: string, callback: Function): void;
off(event: string, callback?: Function): void;
getModule(module: 'menu' | 'payment' | 'login'): any;
setErrorHandler(handler: (error: MinigameError) => void): void;
}

interface MenuShowOptions {
gradually?: boolean;
}

interface MenuHideOptions {
gradually?: boolean;
}

interface PaymentShowOptions {
params: PaymentParams;
extra?: PaymentExtra;
}

interface ShowResult {
res: string;
size?: {
width?: string;
height?: string;
};
}

interface LoginOptions {
success?: (result: LoginResult) => void;
fail?: (error: LoginError) => void;
}

interface LoginError {
code: number;
message: string;
error: string;
}

interface LoginResult {
code: number;
message: string;
data: {
jwtToken: string;
expiresIn: number;
refreshToken: string;
};
}

interface PaymentResult {
order_no: string; // Order number
openid: string; // User ID
order_no_hash: string; // Order hash
}

interface PaymentError extends Error {
code: string;
type: 'failed' | 'hide' | 'queryChannelsFailed';
data?: any;
timestamp: number;
}

interface ProductsParams {
game_openid: string;
role_id: string;
server_id?: string;
}

interface ProductItem {
id: string;
price: string;
oldPrice: string;
productIcon: string;
baseCoinsNum: number;
sendCoinsNum: number;
name: string;
discount: string;
extraList: any[];
meta: any;
}

interface ProductsResult {
products: ProductItem[];
}

function minigame(options: MinigameOptions): MinigameAPI;
}

6. Usage Examples

6.1 Complete Example

// Initialize SDK
const minigameApi = midas.minigame({
appid: '1460000904',
region: 'us',
language: 'en',
sandbox: 1,
shopcode: 'ludoinapp',
menu: {
isWithPcHeader: true
},
payment: {
openid: '1018553529511732'
},
login: {
debug: true,
timeout: 30000
}
});

// Listen to events
minigameApi.on('sdk:loaded', (modules) => {
console.log('SDK loaded successfully:', modules);

// Get module instances for direct access
const menuModule = minigameApi.getModule('menu');
const paymentModule = minigameApi.getModule('payment');
const loginModule = minigameApi.getModule('login');

console.log('Menu module:', menuModule);
console.log('Payment module:', paymentModule);
console.log('Login module:', loginModule);
});

minigameApi.on('payment:success', (data) => {
console.log('Payment successful:', data);
// Hide payment page
minigameApi.hidePayment();
});

minigameApi.on('login:success', (data) => {
console.log('Login successful:', data);
// Show game menu after login
minigameApi.showMenu({
gradually: true
});
});

minigameApi.on('login:statusChanged', (status) => {
console.log('Login status changed:', status);
});

minigameApi.on('products:success', (data) => {
console.log('Products loaded successfully:', data);
data.products.forEach(product => {
console.log(`Product: ${product.name}, Price: ${product.price}`);
});
});

minigameApi.on('products:failed', (error) => {
console.log('Failed to load products:', error);
});

// User login - Callback style
minigameApi.login({
success: function(result) {
console.log('Login successful:', result);
},
fail: function(error) {
console.log('Login failed:', error);
}
});

// User login - Promise style
minigameApi.login()
.then(result => {
console.log('Login successful:', result);
// Show game menu after successful login
return minigameApi.showMenu({ gradually: true });
})
.catch(error => {
console.log('Login failed:', error);
});

// Show game menu
minigameApi.showMenu({
gradually: true
});

// Show payment page - Promise style (recommended)
minigameApi.showPayment({
params: {
game_openid: '1018553529511732',
role_id: '1555629938',
product_id: 'coins_01-midasbuy',
server_id: 'server_001'
},
extra: {
hideResultPage: true
}
})
.then(result => {
console.log('Payment successful:', result);
// result contains: { order_no, openid, order_no_hash }
})
.catch(error => {
console.log('Payment error:', error.type, error.message);

// Handle specific error types
if (error.type === 'queryChannelsFailed') {
console.log('Please check your network connection');
} else if (error.type === 'hide') {
console.log('Payment was cancelled by user');
}
});

// Get products data
minigameApi.getProductsData({
game_openid: '1018553529511732',
role_id: '1555629938',
server_id: 'server_001'
})
.then(result => {
console.log('Products data loaded:', result);
result.products.forEach(product => {
console.log(`Product: ${product.name} - ${product.price} (${product.baseCoinsNum}+${product.sendCoinsNum} UC)`);
});
})
.catch(error => {
console.log('Failed to load products:', error);
});

7. Best Practices

7.1 Error Handling

minigameApi.setErrorHandler((error) => {
// Report error to monitoring system
reportError(error);

// User-friendly error messages
if (error.code === 'PAYMENT_FAILED') {
showToast('Payment failed, please try again later');
}
});

7.2 Promise-based Payment Flow

// Modern async/await payment flow
class PaymentManager {
constructor(minigameApi) {
this.minigameApi = minigameApi;
}

async processPayment(productId, userId, roleId) {
try {
console.log('Starting payment process...');

const result = await this.minigameApi.showPayment({
params: {
game_openid: userId,
role_id: roleId,
product_id: productId,
server_id: 'server_001'
},
extra: {
hideResultPage: true
}
});

// Payment successful
console.log('Payment completed successfully:', result);
this.handlePaymentSuccess(result);
return result;

} catch (error) {
console.log('Payment error occurred:', error);
this.handlePaymentError(error);
throw error;
}
}

handlePaymentSuccess(result) {
// Update game state, unlock content, etc.
console.log(`Order ${result.order_no} completed for user ${result.openid}`);

// Show success message
this.showNotification('Payment successful! Your purchase is now available.');
}

handlePaymentError(error) {
switch (error.type) {
case 'failed':
this.showNotification('Payment failed. Please try again.');
this.trackEvent('payment_failed', error.data);
break;

case 'hide':
this.showNotification('Payment was cancelled.');
this.trackEvent('payment_cancelled');
break;

case 'queryChannelsFailed':
this.showNotification('Unable to load payment options. Please check your connection.');
this.trackEvent('payment_channels_failed', error.data);
break;
}
}

showNotification(message) {
// Show user-friendly notification
console.log(`[Notification] ${message}`);
}

trackEvent(eventName, data = null) {
// Track analytics event
console.log(`[Analytics] ${eventName}`, data);
}
}

7.3 Promise-based Login Flow

// Modern async/await login flow
class GameManager {
constructor() {
this.minigameApi = midas.minigame(config);
this.setupEventListeners();
}

async initializeGame() {
try {
// Wait for SDK to load
await this.waitForSDKLoad();

// Attempt login
const loginResult = await this.minigameApi.login();
console.log('User logged in, jwtToken:', loginResult.data.jwtToken);

// Show game menu after successful login
await this.minigameApi.showMenu({ gradually: true });

} catch (error) {
console.error('Game initialization failed:', error);
this.handleInitError(error);
}
}

waitForSDKLoad() {
return new Promise((resolve) => {
this.minigameApi.on('sdk:loaded', resolve);
});
}

handleInitError(error) {
// Handle initialization errors
if (error.code === 'MODULE_NOT_LOADED') {
console.error('SDK modules not loaded properly');
}
}
}

7.4 Event Management

// Use event delegation pattern
class GameManager {
constructor() {
this.minigameApi = midas.minigame(config);
this.setupEventListeners();
}

setupEventListeners() {
this.minigameApi.on('payment:success', this.handlePaymentSuccess.bind(this));
this.minigameApi.on('menu:show', this.handleMenuShow.bind(this));
}

handlePaymentSuccess(data) {
// Handle payment success
this.updateGameState(data);
}

handleMenuShow(data) {
// Handle menu show
this.trackEvent('menu_show', data);
}
}