微信小游戏开发实战完全指南:从基础配置到高级功能的完整教程

微信小游戏开发实战完全指南

概述

微信小游戏是运行在微信客户端内的HTML5游戏,无需下载安装,即点即玩。凭借微信庞大的用户基础和便捷的分享机制,微信小游戏已成为移动游戏市场的重要组成部分。

本文将详细介绍微信小游戏的开发流程,从基础配置到高级功能实现,帮助开发者快速掌握微信小游戏开发。

一、开发环境配置

1.1 开发者工具

下载安装

  1. 访问微信开发者工具下载页面
  2. 下载对应系统版本
  3. 安装并登录微信扫码

常见问题:服务端口已关闭

错误提示

1
工具的服务端口已关闭

解决方案

  1. 打开微信开发者工具
  2. 点击 设置(齿轮图标)
  3. 选择 安全设置
  4. 开启 服务端口
1
2
设置路径:
微信开发者工具 -> 设置 -> 安全设置 -> 服务端口 -> 开启

1.2 开发者账号注册

  1. 访问微信公众平台
  2. 注册小程序/小游戏账号
  3. 完成邮箱验证和主体认证
  4. 获取AppID

1.3 Cocos Creator配置

构建发布

1
2
3
4
5
6
// 1. 构建面板选择"微信小游戏"
// 2. 填写AppID
// 3. 配置远程服务器地址(如需要)
// 4. 点击构建

// 构建完成后,在build/wechatgame目录下找到项目

二、服务器域名配置

2.1 配置要求

微信小游戏只能与指定的服务器域名进行网络通信,包括:

  • 普通HTTPS请求(wx.request
  • 上传文件(wx.uploadFile
  • 下载文件(wx.downloadFile
  • WebSocket通信(wx.connectSocket

2.2 配置流程

配置路径

1
小程序后台 -> 开发 -> 开发设置 -> 服务器域名

配置规则

协议 说明 示例
https 用于request/upload/download https://api.example.com
wss 用于WebSocket wss://ws.example.com

注意事项

  1. 必须使用HTTPS/WSS协议
  2. 不能使用IP地址(小程序的局域网IP除外)
  3. 不能使用localhost
  4. 域名必须经过ICP备案
  5. 不支持配置父域名,只能配置子域名

2.3 端口配置

协议 端口配置 说明
HTTPS 可选配置 配置后只能访问该端口
WSS 无需配置 默认允许所有端口

示例

1
2
3
4
5
6
7
8
配置:https://api.example.com:8080
请求:https://api.example.com:8080 成功
请求:https://api.example.com 失败
请求:https://api.example.com:443 失败

配置:https://api.example.com
请求:https://api.example.com 成功
请求:https://api.example.com:443 失败(即使443是默认端口)

2.4 开发环境跳过校验

在微信开发者工具中,可以临时跳过服务器域名校验:

1
2
开发者工具 -> 详情 -> 本地设置 ->
勾选"不校验合法域名、web-view(业务域名)、TLS版本以及HTTPS证书"

注意:此设置只在开发工具中有效,真机调试仍需配置域名。

三、用户登录与OpenID获取

3.1 登录流程

1
2
3
4
5
6
7
8
9
10
┌─────────────┐     ┌─────────────┐     ┌─────────────┐
│ 小游戏 │ --> │ 微信服务器 │ --> │ 开发者服务器│
│ wx.login() │ │ 返回code │ │ code2Session│
└─────────────┘ └─────────────┘ └──────┬──────┘

v
┌─────────────┐
│ 返回OpenID │
│ session_key │
└─────────────┘

3.2 客户端登录代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
// 微信登录
function wxLogin() {
return new Promise((resolve, reject) => {
wx.login({
success: (res) => {
if (res.code) {
console.log("登录code:", res.code);
// 发送code到开发者服务器
requestOpenId(res.code)
.then(resolve)
.catch(reject);
} else {
console.log("登录失败:", res.errMsg);
reject(res.errMsg);
}
},
fail: reject
});
});
}

// 请求OpenID
async function requestOpenId(code) {
try {
const response = await wx.request({
url: 'https://your-domain.com/api/login',
method: 'POST',
data: { code: code }
});

if (response.data.openid) {
// 保存OpenID
wx.setStorageSync('openid', response.data.openid);
return response.data;
}
} catch (error) {
console.error("获取OpenID失败:", error);
throw error;
}
}

3.3 服务端获取OpenID

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
// Node.js服务端示例
const axios = require('axios');

async function getOpenId(code) {
const appId = 'YOUR_APP_ID';
const secret = 'YOUR_APP_SECRET';

const url = `https://api.weixin.qq.com/sns/jscode2session`;

try {
const response = await axios.get(url, {
params: {
appid: appId,
secret: secret,
js_code: code,
grant_type: 'authorization_code'
}
});

const data = response.data;

if (data.openid) {
return {
openid: data.openid,
session_key: data.session_key,
unionid: data.unionid
};
} else {
throw new Error(data.errmsg);
}
} catch (error) {
console.error("获取OpenID失败:", error);
throw error;
}
}

3.4 返回数据示例

1
2
3
4
5
6
7
{
"openid": "oN_9x5O5WQ2xxxxxxxxxx",
"session_key": "xxxxx+xxxxxxxxxx==",
"unionid": "o6_bmasdasdsad6_2sgVt7hMZOPfL",
"errcode": 0,
"errmsg": "ok"
}
字段 说明
openid 用户在该小程序的唯一标识
session_key 会话密钥,用于数据加密
unionid 用户在微信开放平台的唯一标识(需绑定)

四、用户信息获取

4.1 获取方式对比

方式 适用场景 需要用户授权
wx.getUserInfo 已废弃,不建议使用
wx.getUserProfile 获取用户信息
Button.open-type=”getUserInfo” 按钮触发
开放数据校验 服务端验证

4.2 使用按钮获取用户信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
// 创建授权按钮
function createUserInfoButton() {
const button = wx.createUserInfoButton({
type: 'text',
text: '获取用户信息',
style: {
left: 10,
top: 76,
width: 200,
height: 40,
lineHeight: 40,
backgroundColor: '#ff0000',
color: '#ffffff',
textAlign: 'center',
fontSize: 16,
borderRadius: 4
}
});

button.onTap((res) => {
if (res.errMsg.indexOf(':ok') > -1 && res.rawData) {
console.log("用户信息:", res.userInfo);
console.log("加密数据:", res.encryptedData);
console.log("IV:", res.iv);

// 发送到服务端解密
decryptUserData(res.encryptedData, res.iv);
}
});

return button;
}

4.3 推荐的使用方式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
// 先检查是否已授权
wx.getSetting({
success: (res) => {
if (res.authSetting['scope.userInfo'] === true) {
// 已授权,直接获取
wx.getUserInfo({
success: (res) => {
console.log("用户信息:", res.userInfo);
}
});
} else {
// 未授权,创建按钮
const button = wx.createUserInfoButton({
type: "image",
image: "images/login.png",
style: {
left: 100,
top: 100,
width: 100,
height: 100
}
});

button.onTap((res) => {
if (res.errMsg.indexOf(':ok') > -1 && res.rawData) {
console.log("用户信息:", res.userInfo);
button.destroy(); // 获取成功后销毁按钮
}
});
}
}
});

4.4 服务端数据解密

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// 使用session_key解密用户数据
const crypto = require('crypto');

function decryptData(sessionKey, encryptedData, iv) {
const sessionKeyBuffer = Buffer.from(sessionKey, 'base64');
const encryptedBuffer = Buffer.from(encryptedData, 'base64');
const ivBuffer = Buffer.from(iv, 'base64');

try {
const decipher = crypto.createDecipheriv(
'aes-128-cbc',
sessionKeyBuffer,
ivBuffer
);
decipher.setAutoPadding(true);

let decoded = decipher.update(encryptedBuffer, 'binary', 'utf8');
decoded += decipher.final('utf8');

return JSON.parse(decoded);
} catch (err) {
throw new Error('解密失败');
}
}

五、广告接入

5.1 开通条件

条件 要求
独立访客(UV) 累计不低于1000
违规记录 无严重违规

5.2 开通方法

1
小程序后台 -> 推广 -> 流量主 -> 申请开通

5.3 广告类型

类型 特点 eCPM
Banner广告 常驻显示,占用空间 较低
激励视频广告 用户主动观看,收益高
插屏广告 全屏展示,打断性强

5.4 Banner广告

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
// 创建Banner广告
let bannerAd = null;

function createBannerAd() {
if (wx.createBannerAd) {
bannerAd = wx.createBannerAd({
adUnitId: 'your-ad-unit-id',
style: {
left: 10,
top: 76,
width: 320
}
});

bannerAd.onLoad(() => {
console.log('Banner广告加载成功');
});

bannerAd.onError((err) => {
console.error('Banner广告加载失败:', err);
});

bannerAd.onResize((res) => {
console.log('Banner尺寸:', res.width, res.height);
});
}
}

// 显示广告
function showBannerAd() {
if (bannerAd) {
bannerAd.show();
}
}

// 隐藏广告
function hideBannerAd() {
if (bannerAd) {
bannerAd.hide();
}
}

// 销毁广告
function destroyBannerAd() {
if (bannerAd) {
bannerAd.destroy();
bannerAd = null;
}
}

5.5 激励视频广告

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
// 激励视频广告是全局单例
let rewardedVideoAd = null;

function initRewardedVideoAd() {
if (wx.createRewardedVideoAd) {
rewardedVideoAd = wx.createRewardedVideoAd({
adUnitId: 'your-ad-unit-id'
});

rewardedVideoAd.onLoad(() => {
console.log('激励视频广告加载成功');
});

rewardedVideoAd.onError((err) => {
console.error('激励视频广告加载失败:', err);
});

rewardedVideoAd.onClose((res) => {
// 用户点击了【关闭广告】按钮
if (res && res.isEnded) {
// 正常播放结束,发放奖励
console.log('广告播放完成,发放奖励');
grantReward();
} else {
// 播放中途退出,不发放奖励
console.log('广告未播放完成');
}
});
}
}

// 播放激励视频
function showRewardedVideoAd() {
return new Promise((resolve, reject) => {
if (!rewardedVideoAd) {
reject('广告未初始化');
return;
}

rewardedVideoAd.show().catch(() => {
// 失败重试
rewardedVideoAd.load().then(() => {
rewardedVideoAd.show();
}).catch(err => {
console.error('激励视频广告显示失败:', err);
reject(err);
});
});
});
}

5.6 插屏广告

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
let interstitialAd = null;

function initInterstitialAd() {
if (wx.createInterstitialAd) {
interstitialAd = wx.createInterstitialAd({
adUnitId: 'your-ad-unit-id'
});

interstitialAd.onLoad(() => {
console.log('插屏广告加载成功');
});

interstitialAd.onError((err) => {
console.error('插屏广告加载失败:', err);
});

interstitialAd.onClose(() => {
console.log('插屏广告关闭');
});
}
}

// 显示插屏广告
function showInterstitialAd() {
if (interstitialAd) {
interstitialAd.show().catch((err) => {
console.error('插屏广告显示失败:', err);
});
}
}

5.7 广告最佳实践

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
// 广告管理器
class AdManager {
constructor() {
this.rewardedAd = null;
this.bannerAd = null;
this.init();
}

init() {
this.initRewardedAd();
this.initBannerAd();
}

// 预加载激励视频
preloadRewardedAd() {
if (this.rewardedAd) {
this.rewardedAd.load().catch(console.error);
}
}

// 显示激励视频(带奖励回调)
showRewardedAd(onReward) {
if (!this.rewardedAd) {
onReward(false);
return;
}

// 保存回调
this.onRewardCallback = onReward;

this.rewardedAd.show().catch(() => {
this.rewardedAd.load().then(() => {
this.rewardedAd.show();
}).catch(() => {
onReward(false);
});
});
}

// 关卡结束显示插屏
onLevelComplete(level) {
// 每3关显示一次插屏
if (level % 3 === 0) {
this.showInterstitialAd();
}
}
}

// 使用示例
const adManager = new AdManager();

// 复活时显示激励视频
function onRevive() {
adManager.showRewardedAd((success) => {
if (success) {
revivePlayer();
} else {
showToast('广告加载失败,请重试');
}
});
}

六、性能优化

6.1 包体优化

1
2
主包大小限制:4MB
总包大小限制:20MB(通过分包)

优化建议

  1. 图片压缩:使用TinyPNG等工具
  2. 代码压缩:开启代码混淆
  3. 资源分包:将非必需资源放在分包
  4. 音频压缩:使用合适格式和采样率

6.2 性能监控

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 获取性能数据
const performance = wx.getPerformance();

// 内存警告
wx.onMemoryWarning((res) => {
console.log('内存警告级别:', res.level);
// level: 0(轻微), 1(中等), 2(严重)
});

// 帧率监控
const fpsMonitor = wx.createCameraFrameListener({
success: (res) => {
console.log('当前帧率:', res.fps);
}
});

七、发布流程

7.1 提审前检查清单

  • 包体大小符合要求
  • 无敏感内容
  • 用户协议和隐私政策
  • 适龄提示
  • 健康游戏忠告
  • 版号(如需要)

7.2 提审流程

1
2
3
4
5
1. 开发者工具上传代码
2. 小程序后台提交审核
3. 填写版本信息
4. 等待审核(1-7个工作日)
5. 审核通过后发布

八、常见问题

8.1 网络请求失败

问题request:fail url not in domain list

解决方案

  1. 检查域名是否在服务器域名配置中
  2. 检查域名是否已完成ICP备案
  3. 开发环境可开启”不校验域名”选项

8.2 用户拒绝授权

1
2
3
4
5
6
7
8
9
10
11
12
wx.getSetting({
success: (res) => {
if (!res.authSetting['scope.userInfo']) {
// 引导用户开启授权
wx.openSetting({
success: (res) => {
console.log(res.authSetting);
}
});
}
}
});

8.3 真机调试

1
开发者工具 -> 真机调试 -> 扫码调试

总结

本文详细介绍了微信小游戏的开发要点:

  1. 环境配置:开发者工具、服务端口、Cocos Creator
  2. 域名配置:HTTPS/WSS协议要求、端口配置
  3. 用户系统:登录流程、OpenID获取、用户信息
  4. 广告变现:Banner、激励视频、插屏广告
  5. 性能优化:包体大小、内存管理
  6. 发布流程:提审检查、审核流程
  7. 常见问题:网络请求、授权问题

微信小游戏具有庞大的用户基础和便捷的传播机制,是游戏开发者不可忽视的平台。建议持续关注微信官方文档更新,及时适配新功能和政策变化。


参考资源