Definition
Virtual payment refers to consumers using currency (including legal tender or its digital forms) to purchase virtual goods or virtual services. The items involved in virtual payment transactions are digital and intangible.
Characteristics of virtual payment:
Intangibility: The goods have no physical form and cannot be delivered through logistics.
Digital delivery: The goods or services are created, distributed, and consumed directly via the internet.
Usage rights instead of ownership: Users usually purchase a “license” or “service” rather than permanent ownership. For example, buying a Tencent Video membership grants video viewing rights during the membership period but not permanent ownership of the videos themselves.
Note:
1. Mini program virtual payment currently only supports direct in-game item purchases.
2. Direct in-game item purchase refers to the behavior in mini programs where players use virtual payment to directly buy virtual items, such as memberships, e-books, online music, and digital products.
3. Most platforms require developers to use their built-in payment systems for virtual payment transactions (for example, Apple App Store and Google Play require the use of Apple Pay and Google Play Billing), and different platforms have varying commission rates for virtual payments.
Implementation path for virtual payments in superapps
Prerequisites
Ensure your superapp meets the following conditions:
The superapp has implemented or integrated a payment channel.
The payment channel supports merchant management.
Technical solution for virtual payment in mini games
Differences between virtual payment and standard payment solutions
The virtual payment process in mini programs is generally similar to the standard payment process, with only minor differences in the flow:
The key and merchant account application methods are the same as with standard payments; however, the corresponding field names may differ.
For standard payments, the request to the SAS background is triggered directly by the foreground, whereas virtual payments are initiated by the mini program background.
When purchasing items, virtual payment requires developers to pre-register the in-game items for sale within the console.
During the purchase process, virtual payment does not generate an order ID; instead, it directly triggers the payment flow.
Before you start
Encryption, decryption and signature
Virtual item adding
Example payment flowchart
The overall flowchart for mini game payments is illustrated below, divided into three main processes: Order placement and payment, delivery notification, and payment result confirmation.
Order placement and payment
1. Order placement:
When developing a mini game, developers must configure the push notification settings in the console under Commercialization - Virtual payment - Basic configurations, and enable the item delivery push notifications under Commercialization - Virtual payment - Virtual item management to receive the callback requests after a successful order placement. For additional development considerations, see Virtual Payment - Technical Instructions. When a user initiates an item purchase in the mini game, the mini game foreground should first confirm payment-related information with the mini game background, passing all item purchase data to it.
Upon receiving the order request, the mini program background must sign the data using the secret key and create the order (the order is initially unpaid as payment is not complete). The signing key must be securely stored on the mini program background. For data security, developers should never expose this key to the mini program foreground or share it externally. For data security, the developer’s server should never send the key to the mini game foreground or expose it externally.
The mini game server returns the generated signature data (signData , paySig, signature) to the mini game foreground. An example of mini program server signing is as follows:
signData
is a JSON string generated by the mini game background using the item purchase data passed from the mini game foreground during the order placement. For parameter descriptions, see signData parameter description. Example: '{"mode":"goods","buyQuantity":1,"env":0,"currencyType":"USD","platform":"android","productId":"testproductId","goodsPrice":10,"outTradeNo":"xxxxxx","attach":"testdata"}'
paySig generation parameters are as follows:
Field | Type | Description |
signData | string | Original payment string. |
appkey | string | Payment signing key (stored securely on the mini program background and exchanged with the superapp background) |
method | string | Fixed format: requestMidasPaymentGameItem. |
Example:
import hmac
import hashlib
import urllib.parse
def gen_pay_sig(signData, appkey, method):
need_encode_body = method + '&' + sign_data
print(need_encode_body)
return hmac.new(key=appkey.encode('utf-8'), msg=need_encode_body.encode('utf-8'),
digestmod=hashlib.sha256).hexdigest()
signature generation parameters are as follows:
Field | Type | Description |
session_key | string | |
post_body | string | signData original payment string |
Example:
import hmac
import hashlib
import json
import time
def calc_signature(post_body, session_key):
"""
need_sign_msg = post_body
signature = hmac.new(key = session_key.encode('utf-8'), msg = need_sign_msg.encode('utf-8'),
digestmod=hashlib.sha256).hexdigest()
return signature
2. Payment:
After the mini program foreground receives the successful order creation callback from the mini program background, it can call the SDK API wx.requestVirtualPayment provided by the SAS to initiate superapp payment by passing the signature data returned from the background.
wx.requestVirtualPayment({
signData: JSON.stringify({
offerId: '123',
buyQuantity: 1,
currencyType: 'USD',
productId: 'testproductId',
goodsPrice: 10,
outTradeNo: 'xxxxxx',
attach: 'testdata',
}),
paySig: 'd0b8bbccbe109b11549bcfd6602b08711f46600965253a949cd6a2b895152f9d',
signature: 'd0b8bbccbe109b11549bcfd6602b08711f46600965253a949cd6a2b895152f9d',
mode: 'short_series_goods',
success(res) {
console.log('requestVirtualPayment success', res)
},
fail({ errMsg, errCode }) {
console.error(errMsg, errCode)
},
})
After the SAS SDK receives the payment request, it will act on behalf of the mini program to send a request to the SAS background (openServer).
Upon receiving the request, the SAS background (openServer) will verify whether the virtual item has been registered on SAS and check if each item's ID and price match the registered data. It will then forward the request to the superapp background's /requestVirtualPayment API. For the API parameters, see Mini program virtual payment order APIs. Upon receiving the direct purchase payment request for the game item, the superapp background must verify the signature and thoroughly validate the payment information and related business parameters of the order to ensure that the purchase can be executed.
The superapp background implements the RequestVirtualPayment API, verifies whether the item is eligible for purchase, and returns a valid response. The SAS SDK will then notify the superapp to continue with the payment process. The superapp needs to implement the following code logic:
Android:
Android client developers need to implement the proxy for MiniOpenApiProxy provided by the SDK and override the requestMidasPaymentGameItem method. In this method, they should complete the business logic for the mini game payment and return the payment result to the mini game via AsyncResult. Example code (Android-1):
@ProxyService(proxy = MiniOpenApiProxy.class)
public class MiniOpenApiProxyImpl extends MiniOpenApiProxy {
@Override
public void requestVirtualPayment(IMiniAppContext miniAppContext, JSONObject params, AsyncResult result) {
boolean paySuccess = PaymentManagerV2.g().startMidasPayment(miniAppContext, params, result);
if(paySuccess){
result.onReceiveResult(true,successData);
}else{
result.onReceiveResult(false,failedData);
}
}
}
iOS:
The superapp needs to implement the requestMidasPaymentGameItem proxy API to receive the parameters passed by the SDK and then request the superapp background. Example code (iOS-1):
- (void)requestVirtualPayment:(TMFMiniAppInfo *)app params:(NSDictionary *)params completionHandler:(MACommonCallback)completionHandler{
[[TCMPPDemoPayManager sharedInstance] checkPreOrder:params appType:1 completionHandler:^(NSError * _Nullable err, PayResponseData * _Nullable result) {
if (!err) {
dispatch_async(dispatch_get_main_queue(), ^{
TCMPPDemoPaymentMethodsController *payMethodVC = [[TCMPPDemoPaymentMethodsController alloc]init];
payMethodVC.payResponseData = result;
payMethodVC.app = app;
[[[DebugInfo sharedInstance] topViewController].navigationController pushViewController:payMethodVC animated:NO];
payMethodVC.completeHandle = ^(NSDictionary * _Nullable result, NSError * _Nullable error) {
completionHandler(result,error);
};
});
}
}];
}
In the example code, TCMPPDemoPayManager is a utility class that encapsulates requests sent to the superapp background.
When the user enters their payment authorization information on the payment page, the superapp will notify its background that the mini game item direct purchase payment has been completed after validating the payment.
Delivery notification
After the mini game item direct purchase payment is completed, the superapp background should proactively notify the SAS background (OpenServer). For the API and parameters, see Mini program virtual payment callback, and ensure that the response's returnCode is 0. If multiple retry attempts fail, an alert notification should be sent promptly. Upon receiving the delivery notification, the SAS background (OpenServer) will immediately call the callback URL provided during the order placement. If the mini game background does not respond correctly, the SAS background will continue to retry until a correct response is received.
Payment result confirmation
The superapp should implement the logic to callback the payment result to the SAS SDK upon successful payment.
On Android, the payment result executed by the superapp for the mini game is returned via the AsyncResult parameter of the requestMidasPaymentGameItem method. For details, see example code (Android-1). TCMPPDemoPaymentMethodsController serves as the payment page. After the user completes the payment, the completeHandle is executed to pass the payment result back to the SDK via the completionHandler, as shown in the example code (iOS-1). Subsequently, the SAS SDK will call the success callback function that was passed during the requestMidasPaymentGameItem function call at the time of order placement.
Strongly recommended: The mini program foreground should query the mini program background again to confirm that the payment result is genuine and completed.
Mini game virtual payment operations in the console
Once the technical solution is implemented in the superapp, the superapp admin needs to enable the payment feature in the console. After that, mini game developers can integrate virtual payment. For payment management, see: Payment Management. After the superapp enables the payment feature, mini game developers can bind a merchant in the console and add virtual items. Once the virtual items are released, they will be available for use in the mini game. For mini game developer operation guidelines, see: