Skip to main content

Call a CloudBase Cloud Function in WeChat Mini Program

In one sentence: Use wx.cloud.callFunction to connect directly to a Cloud Function. The Cloud Function side uses wx-server-sdk to automatically obtain the OPENID/APPID/UNIONID — no custom identity system, no HTTPS domain, and no token validation needed.

Estimated time: 25 minutes | Difficulty: Beginner

Applicable Scenarios

This path follows the WeChat Cloud Development system for calling Cloud Functions from a Mini Program frontend. It is a different chain from the @cloudbase/js-sdk custom login used in add-database-wechat-miniprogram — do not mix the two.

  • Applicable: Cloud Development is already enabled in the Mini Program (wx.cloud.init works), and you want to call server-side logic that obtains the OPENID from the frontend
  • Applicable: Business logic requires the OPENID (sending template/subscribe messages, looking up existing user bindings, generating identity-tagged QR codes)
  • Applicable: You do not want to build an HTTPS service or maintain token refresh logic in the Mini Program
  • Not applicable: Calling the same Cloud Function from H5 / Web — that requires the HTTP trigger covered in connect-openai-api-cloud-function
  • Not applicable: You have already migrated from WeChat Cloud Development to a standalone CloudBase environment — see migrate-wxcloud-to-cloudbase

Prerequisites

DependencyVersion
Mini Program Base Library2.2.3 (minimum version for wx.cloud)
wx-server-sdk3.0.1
@cloudbase/cli (optional)1.27.0+, for deploying via the tcb CLI
WeChat DevTools1.06.x

Also required:

  • An active CloudBase environment with an environment ID in the format your-env-id-1234567
  • The Mini Program AppID is bound to this environment in the CloudBase Console under Environment Settings → Security Settings → Mini Program Association

Step 1: Associate the Mini Program AppID with the CloudBase Environment in the Console

Go to the CloudBase Console → select your environment → Environment Settings → Security Settings → Mini Program Association, and add your Mini Program's AppID.

This step is the root of wx.cloud.init({ env }) authentication: the Mini Program base library asks the cloud whether this AppID is permitted to use this env. If the association record does not exist, it immediately returns "invalid env", and all Cloud Function calls, Cloud Database reads and writes, and Cloud Storage uploads will fail.

Complete this step before writing any code; otherwise Step 3's console will only show a semantically unclear errMsg.

Step 2: Write the Cloud Function (wx-server-sdk + getWXContext)

Create a new Cloud Function directory (in WeChat DevTools, right-click under cloudfunctions/ in the project root → New Node.js Cloud Function, name it add). It contains two files: index.js and package.json.

// cloudfunctions/add/index.js
const cloud = require('wx-server-sdk');

cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV });

exports.main = async (event, context) => {
const wxContext = cloud.getWXContext();
return {
sum: event.x + event.y,
openid: wxContext.OPENID,
appid: wxContext.APPID,
unionid: wxContext.UNIONID,
};
};
// cloudfunctions/add/package.json
{
"name": "add",
"version": "1.0.0",
"main": "index.js",
"dependencies": {
"wx-server-sdk": "3.0.1"
}
}

Three details worth noting:

  • cloud.DYNAMIC_CURRENT_ENV tells the Cloud Function runtime to automatically use the environment it is deployed in. No code change is needed for cross-environment deployments. This is the standard pattern since the latest version.
  • The OPENID/APPID/UNIONID returned by cloud.getWXContext() are propagated end-to-end from the base library through to the Cloud Function. They are not fields in the request body, cannot be modified or forged by business code, and can be used directly as identity.
  • An unauthenticated guest call (e.g., a shared page without authorization) still has an OPENID value (a session-based temporary openid), but UNIONID may be an empty string. Handle the empty-value case in your business logic.

event is a direct pass-through of the data field from the Mini Program; anything JSON-serializable works. The object returned by return becomes res.result on the frontend. Do not return Date instances (serialization loses timezone information; convert to an ISO string before returning).

If the Cloud Function needs to access the database, storage, or call another Cloud Function, wx-server-sdk already encapsulates the clients. Identity is reused directly from the OPENID obtained via getWXContext() — no additional token signing is required:

// Read from the database inside a Cloud Function
const db = cloud.database();
const user = await db.collection('users').where({ _openid: wxContext.OPENID }).get();

// Call another Cloud Function inside a Cloud Function
const res = await cloud.callFunction({ name: 'sendMessage', data: { ... } });

This is the core value of BaaS-style calls: identity flows in a straight line from client to Cloud Function to database. Business code never sees a token and never needs to manage renewal.

Step 3: Mini Program Side — wx.cloud.init + wx.cloud.callFunction

wx.cloud.callFunction supports both Promise and callback styles:

  • Promise / async-await: Use for serial multi-step page logic; exceptions go through try / catch. Best readability — the right choice for 90% of cases.
  • callback (success / fail): Use when the base library is older or when sharing a callback-style utility with other wx.* APIs (e.g., a legacy wx.request wrapper). No extra Promise.resolve layer needed.

Initialize once globally in app.js:

// app.js
App({
onLaunch() {
if (!wx.cloud) {
console.error('请使用 2.2.3 或以上的基础库以使用云能力');
return;
}
wx.cloud.init({
env: 'your-env-id-1234567',
traceUser: true,
});
},
});

traceUser: true records each session's openid and last-active time in the CloudBase Console under User Management, making it easy to view daily DAU directly in the console. Leaving it off does not affect functionality.

Calling from a page using the Promise form:

// pages/index/index.js
Page({
async onTapAdd() {
try {
const res = await wx.cloud.callFunction({
name: 'add',
data: { x: 1, y: 2 },
});
console.log('result:', res.result);
// { sum: 3, openid: 'oABC...', appid: 'wxXXX...', unionid: '' }
} catch (err) {
console.error('callFunction failed', err);
}
},
});

The callback form is also supported — pass success / fail callbacks as an alternative to the Promise form:

wx.cloud.callFunction({
name: 'add',
data: { x: 1, y: 2 },
success: (res) => console.log(res.result),
fail: (err) => console.error(err),
});

name is the Cloud Function name (not a file path). data goes directly into the Cloud Function's event. The size limit is 5 MB. The return value is in res.result, not res.data — this is the most common point of confusion with wx.request.

Two common use cases in business logic:

  • Temporary cross-environment switching: When you have separate test and production environments, specify the environment for a single callFunction call without touching the global wx.cloud.init config:

    await wx.cloud.callFunction({
    name: 'add',
    data: { x: 1, y: 2 },
    config: { env: 'test-env-id-1234567' },
    });
  • Timeout control: wx.cloud.callFunction has no timeout parameter — the frontend waits until the Cloud Function returns. If the Cloud Function may run for 20+ seconds (e.g., calling an external LLM), either cap the timeout inside the Cloud Function and return early, or wrap the frontend call with Promise.race to set a timeout. Do not block the UI indefinitely.

Step 4: Deploy via tcb CLI or WeChat DevTools

Pick one of the two options.

A. WeChat DevTools (recommended for getting started)

Right-click the cloudfunctions/add/ directory → Upload and Deploy: Install Dependencies on Cloud (do not upload node_modules) → wait ~30 seconds → once you see "Upload successful", the Cloud Function is callable from the Mini Program.

B. CLI (tcb command, recommended for CI / automation)

# Install the CLI
npm install -g @cloudbase/cli

# Deploy a single event-triggered function (no --httpFn, since this is for Mini Program callFunction)
tcb fn deploy add -e your-env-id-1234567

After deployment, go to the ConsoleCloud Development → Functions → Function List to find add. Click in to view runtime memory, timeout settings, and recent invocation logs.

Note: --httpFn is for HTTP triggers (called via a public domain). Mini Program callFunction uses "event trigger" mode. Adding --httpFn will make the function unreachable via callFunction from the Mini Program. A Cloud Function can have both event trigger and HTTP trigger attached simultaneously, but requests arriving via the HTTP trigger do not carry wxContext.OPENID — only event-triggered calls automatically propagate identity.

tcb fn deploy reads dependencies from cloudfunctions/<name>/package.json by default and runs npm install on the cloud. No local node_modules installation is required. If you use a private npm registry or need to lock versions, place a .npmrc and package-lock.json in the directory beforehand.

Cloud Functions have no "local console". All console.log / console.error output goes to cloud logs, and debugging depends on them:

exports.main = async (event, context) => {
console.log('[add] event =', event);
const wxContext = cloud.getWXContext();
console.log('[add] wxContext =', wxContext);
// ... business logic
};

Two ways to view logs:

  • WeChat DevTools: left panel → Cloud Development → Functions → Logs — shows the last 24 hours only
  • CloudBase Console → Cloud Development → Functions → Function List → select function → Log Query — filter by time range, keyword, or RequestId; retained for 7 days

During development, log one line of event and wxContext at each Cloud Function entry point. When something goes wrong, the first thing you see is "are the incoming parameters and identity correct?" — far more informative than the errMsg on the frontend side. In production, reduce to logging only error-level messages as appropriate.

Verification

  1. Compile and run in WeChat DevTools; trigger the button that calls wx.cloud.callFunction
  2. The DevTools Console should show result: { sum: 3, openid: 'o...', appid: 'wx...', unionid: '...' }sum must equal 3
  3. Console → Cloud Development → Functions → add → Log Query, select the last 5 minutes; you should see one INFO-level run record where event is { x: 1, y: 2 } and returnValue matches what the frontend received
  4. Comment out the cloud.init line in the Cloud Function, redeploy, and call again — the frontend should return an error saying "please call init first". This confirms the full chain actually reaches the Cloud Function and is not cached by any intermediate layer

Remember to revert the code after Step 4.

If Step 3 shows no log entry in the Console but the frontend Console received res.result, the deployment almost certainly did not take effect — DevTools sometimes caches the previous deployment zip. To force a fresh build: delete the local cloudfunctions/add/node_modules directory, right-click the directory → Clear Cache and Redeploy, then call again.

Common Errors

Error messageCauseFix
errCode: -404011 cloud function execution error or "invalid env" in consoleThe AppID was not associated with this env in Step 1, or the environment ID is wrongIn the Console under Environment Settings → Security Settings → Mini Program Association, add the current Mini Program's AppID. Confirm that the env in wx.cloud.init({ env }) matches the Console environment ID exactly (don't omit the trailing random string)
Cloud API isn't enabled, please call wx.cloud.init firstwx.cloud.callFunction is called directly in a page, but wx.cloud.init was not called in app.js onLaunch, or the base library is below 2.2.3Move wx.cloud.init into app.js onLaunch; also ensure cloudfunctionRoot is set in project.config.json
errCode: -501005 FUNCTIONS_EXECUTE_FAIL function not existsFunction name is mistyped, or the function was written locally but never uploadedCheck that the name field exactly matches the cloud function name (case-sensitive). The function must appear in the Console's function list to be considered successfully deployed
wxContext.OPENID is undefinedcloud.init was not called via wx-server-sdk, or the parameter name in event shadows contextThe Cloud Function must call cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV }) at the top before getWXContext() has data. Do not name the parameter something like (event, wxContext)
First response after deployment is 3–5 seconds slowCold start of the function instanceThis is expected behavior. After the Node.js 12/16 runtime cold-starts once, the instance is kept alive for 5–10 minutes. For high-frequency scenarios, see optimize-cloud-function-wechat-miniprogram
errCode: -601001 RESOURCE_INSUFFICIENTMonthly free quota exhausted, or pay-as-you-go account is in arrearsConsole → Usage → Resource Usage to check the current month's quota. A pay-as-you-go account in arrears is suspended 24 hours after the arrears occur
errMsg: cloud.callFunction:fail Error: errCode: -502005 DATABASE_PERMISSION_DENIEDThe Cloud Function is accessing the database, but the collection permission is "Only creator can read and write" and the calling OPENID is not the document creatorThe Cloud Function's execution identity inherits the caller's OPENID, not admin. To bypass permissions and read the full collection, explicitly obtain an admin client with cloud.database({ env: ... }) inside the Cloud Function, or change the collection permission to "Only admin can read and write"

For the complete error code definitions, see error-code.

The errCode received on the frontend is generally passed through from the cloud. First use the error code to determine whether the issue is "can't reach the function" (-404 / -501) or "reached the function but it crashed" (-502 / -601), then decide whether to check the frontend logs or Cloud Function logs. This is far more efficient than searching the error message directly.