WeChat mini program quickstart
This page builds a minimal native WeChat mini program: create a client, sign in, show the conversation list and send and receive messages. It then covers sending images, voice and files, and using the SDK in Taro React.
Before you start, install the published npm package as described in the overview (or use a locally built package), and make sure your server can issue sign-in tickets for signed-in users.
Create a client
In app.js, create the one client for the whole mini program, and create the Behavior your pages use from the same reference:
const {
createDRMiniProgramClient, createDRClientRef, createDRBehavior, locale,
} = require('@deeprespond/im-miniprogram');
const imRef = createDRClientRef();
App({
behavior: createDRBehavior(imRef),
onLaunch() {
this.im = createDRMiniProgramClient({
appKey: '组织#应用', apiUrl: 'https://im.example.com', autoMarkRead: true,
});
imRef.set(this.im);
},
report(error) {
wx.showToast({ title: locale.describeError(error), icon: 'none' });
},
});When the sign-in page gets a ticket from your server, sign in and wait for the connection to be ready:
await getApp().im.auth.loginWithTicket({ ticket });
await getApp().im.connection.waitUntilReady({ timeoutMs: 20000 });- The client restores the previous sign-in automatically once created; users already signed in don't need to sign in again.
- Your server issues the sign-in ticket. Don't hard-code tickets or the App Secret in the mini program.
- Each
appKeycan have only one client; creating another returnsclient_exists. Destroy it withawait im.destroy()when you're done.
Conversation and chat pages
Once a page includes app.behavior, bind the conversation list to the page's data with this.drList(), and the page updates as the list changes:
const app = getApp();
Page({
behaviors: [app.behavior],
data: {},
onLoad() { this.drList('list', im => im.conversations.list()); },
onShow() { this.drPageShow(); },
onHide() { this.drPageHide(); },
onUnload() { this.drPageUnload(); },
});<view wx:for="{{list.items}}" wx:key="conversation_key">
{{item.peer || item.group_id}}:{{item.unread_count}}
</view>On the chat page, bind the message list with this.drMessageList('chat', conversationKey), and use _key as wx:key when looping over messages with wx:for. To send text:
await app.im.messages.send({ conversation_key: conversationKey }, {
type: 'text', body: { text: '你好' },
});- Lifecycle. A
Componentreceives lifecycle events automatically through the Behavior; aPagemust calldrPageShow(),drPageHide()anddrPageUnload()inonShow,onHideandonUnload, as above. - Switching users. When the signed-in user changes, bindings are released and set up again automatically.
- Performance. Each component's
setDatacalls run one at a time, with at most 512 KiB of data per call; message lists show only the latest 100 messages by default. - Subpackages. Pages that only need bindings can import
createDRClientRef,createDRBehavior,bindSnapshot,bindStateandDR_STATESfrom the separate/bindentry, with the SDK itself in a subpackage; callimRef.set(im)once it loads. - Chat rooms. Bind with
drChatroom. Several bindings to the same room share one entry count, and the room is only left when the last binding is released.
Files by path and recording
In a mini program, files are always given to the SDK as local paths (such as the temporary paths wx.chooseMedia returns), never as Blobs. The example below sends an image, records and sends voice, and downloads and opens a file:
wx.chooseMedia({
count: 1, mediaType: ['image'],
success: result => app.im.messages.send({ to_user: 'alice' }, {
type: 'image', file: { path: result.tempFiles[0].tempFilePath },
}).catch(error => app.report(error)),
});
const recorder = await app.im.files.recordVoice({ maxSeconds: 60 });
await recorder.start();
const voice = await recorder.stop();
await app.im.messages.send({ to_user: 'alice' }, {
type: 'voice', file: voice.file, body: { duration_seconds: voice.duration_seconds },
});
const task = app.im.files.download({ message });
const { path, fileType } = await task;
wx.openDocument({ filePath: path, fileType });- Video. Pass
{ path, width, height, duration, thumbnail: { path } }. - Metadata. Before sending, the SDK removes metadata such as location from JPEG and PNG, and processes MP4 by segment. Formats it can't process reject with
metadata_unremovable; only setkeepMetadata: truewhen your business explicitly accepts keeping metadata. - Caching.
app.im.files.localPath(url)returns the local path of a downloaded file, which you can use as an image cache. Download tasks can be cancelled withcancel(). - Going to the background. Previewing images or opening documents sends the mini program to the background. Call
keepForeground()to keep the connection for up to 60 more seconds, and call the function it returns once the user is back.
Taro React
Taro projects use the Web SDK's mini program entry and React bindings. Import the polyfills entry first, then create the client:
import '@deeprespond/im-web/polyfills';
import { createDRMiniProgramClient } from '@deeprespond/im-web/miniprogram';
import { DRProvider } from '@deeprespond/im-web-react/miniprogram';
const im = createDRMiniProgramClient({ appKey: '组织#应用', apiUrl: 'https://im.example.com' });
export default function App({ children }) {
return <DRProvider client={im}>{children}</DRProvider>;
}- Use the same version for every package.
- Taro doesn't need the native mini program's prebuilt package. For a full example, see
sdk/miniprogram/example-taroin the repository.
Standalone channels
For now, mini programs can only look up channels, the user's own channel session and channel members, and the channel type definitions are exported. LiveKit media isn't integrated yet, so they can't join channels for audio and video. channels.supported is false, and joining is rejected before any seat is taken. See Channel lookups and limits.
