插件功能页

插件功能页从微信小程序基础库版本 2.1.0 开始支持。

某些接口不能在插件中直接调用(如 wx.login),但插件开发者可以使用插件功能页的方式来实现功能。目前,插件功能页包括:

  • 获取用户信息,包括 openid 和昵称等(相当于 wx.login 和 wx.getUserInfo 的功能),详见 用户信息功能页;

从基础库版本 2.22.1 起,以下功能页已经废弃,可以直接调用对应接口实现功能:

  • 支付(直接使用 wx.requestPluginPayment)

从基础库版本 2.16.1 起,以下三个功能页已经废弃,可以直接调用对应接口实现功能;原有和新使用的 <functional-page-navigator> 在点击后将不会跳到功能页,而是直接生效:

  • 收货地址功能页(直接使用 wx.chooseAddress)
  • 发票抬头功能页(直接使用 wx.chooseInvoiceTitle)
  • 发票功能页(直接使用 wx.chooseInvoice)

要使用插件功能页,需要先激活功能页特性,配置对应的功能页函数,再使用 functional-page-navigator 组件跳转到插件功能页,从而实现对应的功能。详情请参考下文。

使用插件功能页前,需要确定插件已经 开通,否则可能出现 functional-page-navigator 点击后无响应等情况

插件所有者微信小程序

开始开发之前,我们需要知道,插件功能页是指 插件所有者微信小程序 中的一个特殊页面。

插件所有者微信小程序,指的是与插件 AppID 相同的微信小程序。例如,“微信小程序示例”微信小程序开发了一个“微信小程序示例插件”,那么无论这个插件被哪个微信小程序使用,这个插件的 插件所有者微信小程序 都是“微信小程序示例”。下文中会继续使用 插件所有者微信小程序 这个说法。

插件所有者微信小程序开发方法

通常,在开始使用插件功能页的时候,需要开启两个开发者工具窗口,其中一个打开插件项目,另一个打开插件所有者微信小程序的微信小程序项目。例如,一个打开“微信小程序示例插件”项目,另一个打开“微信小程序示例”项目。

这两个窗口,前者用于编辑插件,后者用于编辑插件所有者微信小程序。下文中所有需要编辑插件所有者微信小程序的内容,都是在后者中进行。

激活功能页特性

要在插件中调用插件功能页,需要先激活插件所有者微信小程序的功能页特性。具体来说,在插件所有者微信小程序的 app.json 文件中添加 functionalPages 定义段,并令其值为 true ,例如:

代码示例:

{
  "functionalPages": {
    "independent": true
  }
}

目前,兼容旧式写法:

{
  "functionalPages": true
}

旧式写法将在未来将被移除支持,未来将不能编译上传。

这两种写法的区别在于,新式的写法 "independent": true 会使得插件功能页的代码独立于其他代码,这意味着插件功能页可以被独立下载、加载,具有更好的性能表现。 但也同时使得插件功能页目录 functional-pages/ (支付功能页会使用其中的文件)不能 require 这个目录以外的文件(反之亦然:这个目录以外的文件也不能调用这个目录内的)。

注意,新增或改变这个字段时,需要这个微信小程序发布新版本,才能在正式环境中使用插件功能页。

跳转到功能页

功能页不能使用 wx.navigateTo 来进行跳转,而是需要一个名为 functional-page-navigator 的组件。以获取用户信息为例,可以在插件中放置如下的 functional-page-navigator:

代码示例:

<functional-page-navigator name="loginAndGetUserInfo" args="" version="develop" bind:success="loginSuccess">
  <button>登录到插件</button>
</functional-page-navigator>

用户在点击这个 navigator 时,会自动跳转到插件所有者微信小程序的对应功能页。功能页会提示用户进行登录或其他相应的操作。操作结果会以组件事件的方式返回。

functional-page-navigator 的参数和详细使用方法可以参考 组件说明 。

从微信小程序基础库版本 2.4.0 开始,支持插件所有者微信小程序跳转到自己的功能页。在基础库版本低于 2.4.0 时,点击跳转到自己的功能页的 functional-page-navigator 将没有任何反应。

真机开发测试的常规步骤

目前,功能页的跳转目前不支持在开发者工具中调试,请在真机上测试。初次进行真机开发测试时,通常步骤如下:

  1. 在开发者工具上打开插件所有者微信小程序项目,并点击“预览”;
  2. 用测试用的真机扫一下预览二维码,此时会进入插件所有者微信小程序,进入后就可以直接退出这个微信小程序;
  3. 在开发者工具上打开插件项目,将插件中 functional-page-navigator 中的 version 属性设置为 develop
  4. 点击预览可以生成插件预览二维码,用测试用的真机扫码即可预览功能页;如果更改了插件代码,重新生成并扫描插件的预览二维码即可;
  5. 如果过了一段时间之后,跳转功能页时出现“开发版已过期”这样的提示,从第 1 步开始重试一次。

注意functional-page-navigatorversion=develop 仅用于调试,因此在插件提审前,需要:

  1. 确保已发布设置了 "functionalPages": true 的插件所有者微信小程序;
  2. 确保所有的 functional-page-navigator 组件属性设置为 version="release"

功能页常见问题 FAQ

如何正确编辑插件所有者微信小程序?

  • 应该在开发者工具的“微信小程序”类型项目中编辑,而不是在“插件”类型的项目中编辑。比如,“微信小程序示例插件”的所有者微信小程序是“微信小程序示例”,它们的 AppID 都是 wxidxxxxxxxxxxxxxx ,如果是初次开发“微信小程序示例”微信小程序,可以在开发者工具中创建一个微信小程序项目,其 AppID 为 wxidxxxxxxxxxxxxxx ;如果之前开发过“微信小程序示例”微信小程序,直接打开之前的微信小程序项目即可。

点击 functional-page-navigator 之后没有任何反应。

  • 请检查引用插件的微信小程序和插件本身是不是同一个 AppID ,如果是,跳转到自己的功能页需要基础库 2.4.0 支持,否则使用 functional-page-navigator 不会有任何反应。

点击 functional-page-navigator 之后,展示了一个页面提示“页面不存在”。

  • 这种情况是因为插件所有者微信小程序没有正确设置 "functionalPages": true 。如果 functional-page-navigatorversion="develop" ,这部手机需要扫码并进入插件所有者微信小程序一次;如果 version="release" ,请确保包含 "functionalPages": true 的插件所有者微信小程序已被发布。

点击 <functional-page-navigator version="develop"> 之后,弹窗提示“微信小程序开发版已过期”。

  • 遇到这种情况,重新扫码并进入插件所有者微信小程序一次即可。

点击 <functional-page-navigator name="requestPayment"> 之后,展示了一个页面提示“该功能无法使用”。

  • 在使用插件功能页时,微信小程序不能是个人微信小程序,同时,插件也需要额外的步骤申请开通插件支付权限(位于 管理后台 -> 微信小程序插件 -> 基本设置 -> 支付能力 )。

点击 <functional-page-navigator name="requestPayment"> 之后,点击页面中的“支付”按钮,立刻退出了支付功能页。

  • 这通常是因为没有找到功能页函数 beforeRequestPayment ,请检查插件所有者微信小程序的 functional-pages/request-payment.js 文件和其中的 beforeRequestPayment 函数是否存在。

点击 functional-page-navigator 之后,展示了一个仅有返回按钮的页面。

  • 请检查 functional-page-navigator 的 name 属性是否被正确设置。

开发版可以正常跳转,但审核反馈不能跳转。

  • 请发布设置了 "functionalPages": true 的插件所有者微信小程序,且所有的 functional-page-navigator 组件属性设置为 version="release"

Bugs & Tip

  • 功能页是插件所有者微信小程序中的一个特殊页面,开发者不能自定义这个页面的外观。
  • 插件所有者微信小程序本身也可以引用这个插件,此时,functional-page-navigator 组件的 version 属性将不会生效,而是取决于当前运行的插件所有者微信小程序的版本。
  • functional-page-navigator 可以在开发者工具中使用,但功能页的跳转目前不支持在开发者工具中调试,请在真机上测试。
  • Bug:在微信版本 6.6.7 中,功能页被拉起时会触发 App 的部分生命周期并使得功能页启动时间变得比较长。在后续的微信版本中这一行为会发生变更,使 App 生命周期不再被触发。

用户信息功能页

用户信息功能页用于帮助插件获取用户信息,包括 openid 和昵称等,相当于 wx.login 和 wx.getUserInfo 的功能。

在基础库版本 2.3.1 前,用户信息功能页是插件中唯一的获取 code 和用户信息的方式;

自基础库版本 2.3.1 起,用户在该功能页中进行过授权后,插件可以直接调用 wx.login 和 wx.getUserInfo:

  • 授权是以【用户 + 微信小程序 + 插件】为维度进行授权的,即同一个用户在不同微信小程序中使用同一个插件,或同一个微信小程序中使用不同插件,都需要单独进行授权
  • 自基础库版本 2.6.3 起,可以使用 wx.getSetting 来查询用户是否授权过

另外,在满足以下任一条件时,插件可以直接调用 wx.login:

  1. 使用插件的微信小程序与插件拥有相同的 AppId
  2. 使用插件的微信小程序与插件绑定了同一个 微信开放平台 账号,且使用插件的微信小程序与插件均与开放平台账号为同主体或关联主体

不满足以上条件时,wx.login 和 wx.getUserInfo 将返回失败。

调用参数

用户信息功能页使用 functional-page-navigator 进行跳转时,对应的参数 name 应为固定值 loginAndGetUserInfo,其余参数与 wx.getUserInfo 相同,具体来说:

args 参数说明:

参数名 类型 必填 说明
withCredentials Boolean 是否带上登录态信息
lang String 指定返回用户信息的语言,zh_CN 简体中文,zh_TW 繁体中文,en 英文。默认为 en。
timeout Number 超时时间,单位 ms

注:当 withCredentials 为 true 时,返回的数据会包含 encryptedData, iv 等敏感信息。

bindsuccess 返回参数说明:

参数 类型 说明
code String 同 wx.login 获得的用户登录凭证(有效期五分钟)。开发者需要在开发者服务器后台调用 api,使用 code 换取 openid 和 session_key 等信息
errMsg String 调用结果
userInfo OBJECT 用户信息对象,不包含 openid 等敏感信息
rawData String 不包括敏感信息的原始数据字符串,用于计算签名。
signature String 使用 sha1( rawData + sessionkey ) 得到字符串,用于校验用户信息,参考文档 signature。
encryptedData String 包括敏感数据在内的完整用户信息的加密数据,详细见 加密数据解密算法
iv String 加密算法的初始向量,详细见 加密数据解密算法

userInfo 参数说明:

参数 类型 说明
nickName String 用户昵称
avatarUrl String 用户头像,最后一个数值代表正方形头像大小(有 0、46、64、96、132 数值可选,0 代表 132*132 正方形头像),用户没有头像时该项为空。若用户更换头像,原有头像 URL 将失效。
gender String 用户的性别,值为 1 时是男性,值为 2 时是女性,值为 0 时是未知
city String 用户所在城市
province String 用户所在省份
country String 用户所在国家
language String 用户的语言,简体中文为 zh_CN

示例代码

<!--plugin/components/hello-component.wxml-->
  <functional-page-navigator
    name="loginAndGetUserInfo"
    args="{{ args }}"
    version="develop"
    bind:success="loginSuccess"
    bind:fail="loginFail"
  >
    <button class="login">登录到插件</button>
  </functional-page-navigator>
// plugin/components/hello-component.js
Component({
  properties: {},
  data: {
    args: {
      withCredentials: true,
      lang: 'zh_CN'
    }
  },
  methods: {
    loginSuccess: function (res) {
      console.log(res.detail);
    },
    loginFail: function (res) {
      console.log(res);
    }
  }
});

用户点击该 navigator 后,将跳转到如下的用户信息功能页:

用户信息功能页

在微信开发者工具中查看示例

  1. 由于插件需要 appid 才能工作,请填入一个 appid;
  2. 由于当前代码片段的限制,打开该示例后请 手动将 appid 填写到 miniprogram/app.json 中(如下图)使示例正常运行。

手动填写 appid

微信小程序支付功能页

自2025年6月26日起,不再支持新申请插件支付功能,如果要在微信小程序中实现给向第三方支付,请使用「打开半屏微信小程序」功能

支付功能页用于帮助插件完成支付,相当于 wx.requestPayment 的功能。

自基础库版本 2.22.1 起,可以直接在插件中调用 wx.requestPluginPayment 实现跳转支付;通过 functional-page-navigator 跳转将会被废弃。

在满足以下条件时,调用 wx.requestPluginPayment 或点击 navigator 都将直接拉起支付收银台,跳过支付功能页:

  • 微信小程序与插件绑定在同一个 open 平台账号上

  • 微信小程序与插件均为 open 账号的同主体 / 关联主体时。

需要注意的是:插件使用支付功能,需要进行额外的权限申请,申请位置位于 管理后台 的“微信小程序插件 -> 基本设置 -> 支付能力”设置项中。另外,无论是否通过申请,主体为个人微信小程序在使用插件时,都无法正常使用插件里的支付功能。

调用参数

参数说明:

参数名 类型 必填 说明
fee Number 需要显示在页面中的金额,单位为分
paymentArgs Object 任意数据,传递给功能页中的响应函数
currencyType String 需要显示在页面中的货币符号的代码,默认为 CNY

currencyType 的合法值:

说明 最低版本
CNY 货币符号 ¥
USD 货币符号 US$
JPY 货币符号 J¥
EUR 货币符号 €
HKD 货币符号 HK$
GBP 货币符号 £
AUD 货币符号 A$
MOP 货币符号 MOP$
KRW 货币符号 ₩

示例代码

wx.requestPluginPayment 方式

自基础库版本 2.22.1 起,推荐使用该方式。

<!-- plugin/components/pay.wxml -->
<button bindtap="handlePay">支付 0.01 元</button>
// plugin/components/pay.js
Component({
  data: {
    fee: 1,             // 支付金额,单位为分
    paymentArgs: 'A', // 将传递到功能页函数的自定义参数
    currencyType: 'USD' // 货币符号,页面显示货币简写 US$ 
    version: 'develop', // 上线时,version 应改为 "release",并确保插件所有者微信小程序已经发布
  },
  methods: {
    handlePay() {
        const { fee, paymentArgs, currencyType, version } = this.data
        wx.requestPluginPayment({
            fee,
            paymentArgs,
            currencyType,
            version,
            success(r) {
                console.log(r)
            },
            fail(e) {
                console.error(e)
            }
        })
    }
  }
})

functionl-page-navigator 方式(将废弃)

该方式将会被废弃,仅供参考

<!-- plugin/components/pay.wxml -->
<!-- 上线时,version 应改为 "release",并确保插件所有者微信小程序已经发布 -->
<!-- name 参数固定为 "requestPayment" -->
<functional-page-navigator
  version="develop"
  name="requestPayment"
  args="{{ args }}"
  bind:success="paymentSuccess"
  bind:fail="paymentFailed"
>
  <button class="payment-button">支付 0.01 元</button>
</functional-page-navigator>
// plugin/components/pay.js
Component({
  data: {
    args: {
      fee: 1,             // 支付金额,单位为分
      paymentArgs: 'A', // 将传递到功能页函数的自定义参数
      currencyType: 'USD' // 货币符号,页面显示货币简写 US$ 
    }
  },
  methods: {
    // 支付成功的回调接口
    paymentSuccess: function (e) {
      console.log(e);
      e.detail.extraData.timeStamp // 用 extraData 传递数据,详见下面功能页函数代码
    },
    // 支付失败的回调接口
    paymentFailed: function (e) {
      console.log(e);
    }
  }
})

用户调用 wx.requestPluginPayment 或点击 navigator 后,将会进行权限判断,然后直接拉起支付收银台或跳转到如下的支付功能页:

支付功能页

配置功能页函数

支付功能页需要插件开发者在插件所有者微信小程序中提供一个函数来响应插件中的支付调用。即,在插件中跳转到支付功能页或调用 wx.requestPluginPayment 时,这个函数就会在合适的时机被调用,来帮助完成支付。如果不提供功能页函数,功能页调用将通过 fail 事件返回失败。

支付功能页函数应以导出函数的形式提供在插件所有者微信小程序的根目录下的 functional-pages/request-payment.js 文件中,名为 beforeRequestPayment。该函数应接收两个参数:

参数名 类型 说明
paymentArgs Object 即通过 functional-page-navigator 的 arg 参数中的 paymentArgs 字段传递到功能页的自定义数据
callback Function 回调函数,调用该函数后,微信小程序将发起支付(类似于 wx.requestPayment)

callback 函数的参数:

参数名 类型 说明
error Object 失败信息,若无失败,应返回 null
requestPaymentArgs Object 支付参数,用于调用 wx.requestPayment,参数如下

requestPaymentArgs 的参数:

用于发起支付,和 wx.requestPayment 的参数相同,但没有回调函数(success, fail, complete):

参数 类型 必填 说明
timeStamp String 时间戳从 1970 年 1 月 1 日 00:00:00 至今的秒数,即当前的时间
nonceStr String 随机字符串,长度为 32 个字符以下。
package String 统一下单接口返回的 prepay_id 参数值,提交格式如:prepay_id=***
signType String 签名算法,暂支持 MD5
paySign String 签名,具体签名方案参见 微信小程序支付接口文档;
extraData any 由开发者决定的自定义数据段,该字段将被无修改地透传到支付成功的回调参数中,具体见代码示例中的使用方法。基础库 2.9.1 开始支持

了解更多信息,请查看 微信支付接口文档

功能页函数代码示例:

// functional-pages/request-payment.js
exports.beforeRequestPayment = function (paymentArgs, callback) {
  // 注意:
  // 功能页函数(这个函数)不应 require 其他非 functional-pages 目录中的文件,
  // 其他非 functional-pages 目录中的文件也不应 require 这个目录中的文件,
  // 这样的 require 调用在未来将不被支持。
  //
  // 同在 functional-pages 中的文件可以 require
  var getOpenIdURL = require('./URL').getOpenIdURL;
  var paymentURL = require('./URL').paymentURL;

  // 自定义的参数,此处应为从插件传递过来的 'A'
  var customArgument = paymentArgs.customArgument;

  // 第一步:调用 wx.login 方法获取 code,然后在服务端调用微信接口使用 code 换取下单用户的 openId
  // 具体文档参考 https://mp.weixin.qq.com/debug/wxadoc/dev/api/api-login.html?t=20161230#wxloginobject
  wx.login({
    success: function (data) {
      wx.request({
        url: getOpenIdURL,
        data: { code: data.code },
        success: function (res) {
          // 拉取用户 openid 成功
          // 第二步:在服务端调用支付统一下单,返回支付参数。这里的开发和普通的 wx.requestPayment 相同
          // 文档可以参考 https://pay.weixin.qq.com/doc/v2/merchant/4011938514
          wx.request({
            url: paymentURL,
            data: { openid: res.data.openid },
            method: 'POST',
            success: function (res) {
              console.log('unified order success, response is:', res);
              var payargs = res.data.payargs;
              // 第三步:调用回调函数 callback 进行支付
              // 在 callback 中需要返回两个参数: err 和 requestPaymentArgs:
              // err 应为 null (或者一些失败信息);
              // requestPaymentArgs 将被用于调用 wx.requestPayment,除了 success/fail/complete 不被支持外,
              // 应与 wx.requestPayment 参数相同。
              var error = null;
              var requestPaymentArgs = {
                timeStamp: payargs.timeStamp,
                nonceStr: payargs.nonceStr,
                package: payargs.package,
                signType: payargs.signType,
                paySign: payargs.paySign,
                extraData: { // 用 extraData 传递自定义数据
                  timeStamp: payargs.timeStamp
                },
              };
              callback(error, requestPaymentArgs);
            }
          });
        },
        fail: function (res) {
          console.log('拉取用户 openid 失败,将无法正常使用开放接口等服务', res);
          // callback 第一个参数为错误信息,返回错误信息
          callback(res);
        }
      });
    },
    fail: function (err) {
      console.log('wx.login 接口调用失败,将无法正常使用开放接口等服务', err)
      // callback 第一个参数为错误信息,返回错误信息
      callback(err);
    }
  });
}

注意:功能页函数不应 require 其他非 functional-pages 目录中的文件,其他非 functional-pages 目录中的文件也不应 require 这个目录中的文件。这样的 require 调用在未来将不被支持。

这个目录和文件应当被放置在插件所有者微信小程序代码中(而非插件代码中),它是插件所有者微信小程序的一部分(而非插件的一部分)。 如果需要新增或更改这段代码,需要发布插件所有者微信小程序,才能在正式版中生效;需要重新预览插件所有者微信小程序,才能在开发版中生效。

微信小程序收货地址功能页

从基础库版本 2.16.1 起,该功能页已经废弃,可以直接使用 wx.chooseAddress 实现对应的功能;点击 functional-page-navigator 也将不再进入功能页,直接进入收货地址选择页。

文档

收货地址功能页用于展示用户的收货地址列表,用户可以选择其中的收货地址。自基础库版本 2.4.0 开始支持。

调用参数

用户信息功能页使用 functional-page-navigator 进行跳转时,对应的参数 name 应为固定值 chooseAddress ,返回参数与 wx.chooseAddress 相同。

bindsuccess 返回参数说明:

属性 类型 说明 最低版本
userName string 收货人姓名
postalCode string 邮编
provinceName string 国标收货地址第一级地址
cityName string 国标收货地址第一级地址
countyName string 国标收货地址第一级地址
detailInfo string 详细收货地址信息
nationalCode string 收货地址国家码
telNumber string 收货人手机号码
errMsg string 错误信息

示例代码

<!--plugin/components/hello-component.wxml-->
  <functional-page-navigator
    name="chooseAddress"
    version="develop"
    bind:success="onSuccess"
    bind:fail="onFail"
  >
    <button>选择收货地址</button>
  </functional-page-navigator>
// plugin/components/hello-component.js
Component({
  methods: {
    onSuccess: function (res) {
      console.log(res.detail);
    },
    onFail: function (res) {
      console.log(res);
    }
  }
});

发票功能页

从基础库版本 2.16.1 起,该功能页已经废弃,可以直接使用 wx.chooseInvoice 实现对应的功能;点击 functional-page-navigator 也将不再进入功能页,直接进入发票选择页。

文档

发票功能页用于展示用户的发票列表,用户可以选择其中的发票。自基础库版本 2.14.1 开始支持。

调用参数

发票功能页使用 functional-page-navigator 进行跳转时,对应的参数 name 应为固定值 chooseInvoice ,返回参数与 wx.chooseInvoice 相同。

bindsuccess 返回参数说明:

属性 类型 说明
invoiceInfo String 用户选中的发票信息,格式为一个 JSON 字符串,包含三个字段: card_id:所选发票卡券的 cardId,encrypt_code:所选发票卡券的加密 code,报销方可以通过 cardId 和 encryptCode 获得报销发票的信息,app_id: 发票方的 appId。

示例代码

<!--plugin/components/hello-component.wxml-->
  <functional-page-navigator
    name="chooseInvoice"
    version="develop"
    bind:success="onSuccess"
    bind:fail="onFail"
  >
    <button>选择发票</button>
  </functional-page-navigator>
// plugin/components/hello-component.js
Component({
  methods: {
    onSuccess: function (res) {
      console.log(res.detail);
    },
    onFail: function (res) {
      console.log(res);
    }
  }
});

发票抬头功能页

从基础库版本 2.16.1 起,该功能页已经废弃,可以直接使用 wx.chooseInvoiceTitle 实现对应的功能;点击 functional-page-navigator 也将不再进入功能页,直接进入发票抬头选择页。

文档

发票抬头功能页用于展示用户的发票抬头列表,用户可以选择其中的发票抬头。自基础库版本 2.14.1 开始支持。

调用参数

发票抬头功能页使用 functional-page-navigator 进行跳转时,对应的参数 name 应为固定值 chooseInvoiceTitle ,返回参数与 wx.chooseInvoiceTitle 相同。

bindsuccess 返回参数说明:

属性 类型 说明
type string 抬头类型
title string 抬头名称
taxNumber string 抬头税号
companyAddress string 单位地址
telephone string 手机号码
bankName string 银行名称
bankAccount string 银行账号
errMsg string 错误信息

res.type 的合法值

说明 最低版本
0 单位
1 个人

示例代码

<!--plugin/components/hello-component.wxml-->
  <functional-page-navigator
    name="chooseInvoiceTitle"
    version="develop"
    bind:success="onSuccess"
    bind:fail="onFail"
  >
    <button>选择发票抬头</button>
  </functional-page-navigator>
// plugin/components/hello-component.js
Component({
  methods: {
    onSuccess: function (res) {
      console.log(res.detail);
    },
    onFail: function (res) {
      console.log(res);
    }
  }
});

网络

在微信小程序/小游戏中使用网络相关的 API 时,需要注意下列问题,请开发者提前了解。

1. 服务器域名配置

每个微信小程序需要事先设置通讯域名,微信小程序只可以跟指定的域名进行网络通信。包括普通 HTTPS 请求(wx.request)、上传文件(wx.uploadFile)、下载文件(wx.downloadFile) 和 WebSocket 通信(wx.connectSocket)。

从基础库 2.4.0 开始,网络接口允许与局域网 IP 通信,但要注意 不允许与本机 IP 通信

从 2.7.0 开始,提供了 UDP 通信(wx.createUDPSocket)。

从 2.18.0 开始,提供了 TCP 连接(wx.createTCPSocket),只允许与同个局域网内的非本机 IP 以及配置过的服务器域名通信。

如使用微信云托管作为后端服务,则可无需配置通讯域名(在微信小程序内通过callContainer和connectContainer通过微信私有协议向云托管服务发起 HTTPS 调用和 WebSocket 通信)。

配置流程

服务器域名请在 「微信小程序后台-开发-开发设置-服务器域名」 中进行配置,配置时需要注意:

  • 域名只支持 https (wx.request、wx.uploadFile、wx.downloadFile) 和 wss (wx.connectSocket) 协议;
  • 域名不能使用 IP 地址(微信小程序的局域网 IP 除外)或 localhost;
  • 对于 https 域名,可以配置端口,如 https://myserver.com:8080,但是配置后只能向 https://myserver.com:8080 发起请求。如果向 https://myserver.com、https://myserver.com:9091 等 URL 请求则会失败。如果不配置端口。如 https://myserver.com,那么请求的 URL 中也不能包含端口,甚至是默认的 443 端口也不可以。如果向 https://myserver.com:443 请求则会失败。
  • 对于 wss 域名,无需配置端口,默认允许请求该域名下所有端口。
  • 域名必须经过 ICP 备案;
  • 出于安全考虑,api.weixin.qq.com 不能被配置为服务器域名,相关API也不能在微信小程序内调用。 开发者应将 AppSecret 保存到后台服务器中,通过服务器使用 getAccessToken 接口获取 access_token,并调用相关 API;
  • 不支持配置父域名,使用子域名。

2. DNS预解析域名

微信客户端 iOS 8.0.24,Android 8.0.23)开始支持。

微信小程序一般会依赖一些网络请求(如逻辑层的wx.request、渲染层的图片等网络资源),优化请求速度将会提升用户体验,而网络请求耗时中就包括DNS解析。DNS预解析域名,是框架提供的一种在微信小程序启动时,提前解析业务域名的技术。

配置流程

DNS域名配置请求「微信小程序后台-开发-开发设置-服务器域名」 中进行配置,配置时需要注意:

  • 预解析域名无需填写协议头
  • 预解析域名最多可添加 5 个
  • 其他安全策略同服务器域名配置策略

3. 网络请求

超时时间

  • 默认超时时间是 60s
  • 超时时间可以在 app.jsongame.json 中通过 networktimeout 配置
  • 也可以在接口调用时指定超时时间,如 wx.request({ timeout: 5000 }),单位为ms。接口调用的timeout配置优先级高于app.json中的配置

使用限制

  • 网络请求的 referer header 不可设置。其格式固定为 https://servicewechat.com/{appid}/{version}/page-frame.html,其中 {appid} 为微信小程序的 appid,{version} 为微信小程序的版本号,版本号为 表示为开发版、体验版以及审核版本,版本号为 devtools 表示为开发者工具,其余为正式版本;
  • wx.request、wx.uploadFile、wx.downloadFile 的最大并发限制是 10 个;
  • wx.connectSocket 的最大并发限制是 5 个。
  • 微信小程序进入后台运行后,如果 5s 内网络请求没有结束,会回调错误信息 fail interrupted;在回到前台之前,网络请求接口调用都会无法调用。

返回值编码

  • 建议服务器返回值使用 UTF-8 编码。对于非 UTF-8 编码,微信小程序会尝试进行转换,但是会有转换失败的可能。
  • 微信小程序会自动对 BOM 头进行过滤(只过滤一个BOM头)。

回调函数

  • 只要成功接收到服务器返回,无论 statusCode 是多少,都会进入 success 回调。请开发者根据业务逻辑对返回值进行判断。

4. 常见问题

HTTPS 证书

微信小程序必须使用 HTTPS/WSS 发起网络请求。请求时系统会对服务器域名使用的 HTTPS 证书进行校验,如果校验失败,则请求不能成功发起。由于系统限制,不同平台对于证书要求的严格程度不同。为了保证微信小程序的兼容性,建议开发者按照最高标准进行证书配置,并使用相关工具检查现有证书是否符合要求。

对证书要求如下:

  • HTTPS 证书必须有效;
    • 证书必须被系统信任,即根证书已被系统内置
    • 部署 SSL 证书的网站域名必须与证书颁发的域名一致
    • 证书必须在有效期内
    • 证书的信任链必需完整(需要服务器配置)
  • iOS 不支持自签名证书;
  • iOS 下证书必须满足苹果 App Transport Security (ATS) 的要求;
  • TLS 必须支持 1.2 及以上版本。部分旧 Android 机型还未支持 TLS 1.2,请确保 HTTPS 服务器的 TLS 版本支持 1.2 及以下版本;
  • 部分 CA 可能不被操作系统信任,请开发者在选择证书时注意微信小程序和各系统的相关通告。
    • Chrome 56/57 内核对 WoSign、StartCom 证书限制周知

业务域名

基础库 1.6.4 开始支持,低版本需做 兼容处理

承载网页的容器。会自动铺满整个微信小程序页面,小游戏和个人类型的微信小程序暂不支持使用。 客户端 6.7.2 版本开始, navigationStyle: custom 对 web-view 组件无效 微信小程序插件中不能使用。

为便于开发者灵活配置微信小程序,现开放微信小程序内嵌网页能力。

使用流程

1. 在管理后台配置业务域名

开发者登录微信小程序后台mp.weixin.qq.com,选择开发管理->开发设置->业务域名,点击新增,按照要求配置业务域名。目前微信小程序内嵌网页能力暂不开放给个人类型账号和小游戏账号。

2. 调用web-view组件实现微信小程序内嵌网页

在微信小程序管理后台成功配置业务域名后,才可使用web-view组件。微信小程序内调用web-view组件实现内嵌的网页,目前仅支持部分jsapi能力,关于web-view接口具体使用说明和限制,请 点击查看

限制说明

1)每个微信小程序账号支持配置最多300个域名;

2)每个域名支持绑定最多100个主体的微信小程序;

3)域名只支持https协议,不支持IP地址;

4)业务域名需经过ICP备案,新备案域名需24小时后才可配置;

5)域名格式只支持英文大小写字母、数字及“- ”;

6)配置业务域名后,可打开任意合法的子域名;

局域网通信

基础库 2.4.0 提供了 wx.startLocalServiceDiscovery 等一系列 mDNS API,可以用来获取局域网内提供 mDNS 服务的设备的 IP。 wx.request/wx.connectSocket/wx.uploadFile/wx.downloadFile 的 url 参数允许为 ${IP}:${PORT}/${PATH} 的格式,当且仅当 IP 与手机 IP 处在同一网段且不与本机 IP 相同(一般来说,就是同一局域网,如连接在同一个 wifi 下)时,请求/连接才会成功。

在这种情况下,不会进行安全域的校验,不要求必须使用 https/wss,也可以使用 http/ws。

wx.request({
  url: 'http://10.9.176.40:828'
  // 省略其他参数
})

wx.connectSocket({
  url: 'ws://10.9.176.42:828'
  // 省略其他参数
})

基础库 2.7.0 开始,提供了 wx.createUDPSocket 接口用于进行 UDP 通信。通信规则同上,仅允许同一局域网下的非本机 IP。

mDNS

目前微信小程序只支持通过 mDNS 协议获取局域网内其他设备的 IP。iOS 上 mDNS API 的实现基于 Bonjour,Android 上则是基于 Android 系统接口

由于操作系统相关能力变更,iOS 微信客户端 7.0.18 及以上版本无法使用 mDNS 相关接口,安卓版本不受影响

serviceType

发起 mDNS 服务搜索 wx.startLocalServiceDiscovery 的接口有 serviceType 参数,指定要搜索的服务类型。

serviceType 的格式和规范,iOS Bonjour OverviewBonjour Names for Existing Service Types 有提及。

Bonjour serviceType.png

Android 文档 对此也有提及。

Android serviceType.png

移动解析HttpDNS

从基础库 2.19.2 开始支持

开发者调用 wx.request 时,可以开启移动解析 HttpDNS 服务。 该服务基于 Http 协议向服务商的 DNS 服务器发送域名解析请求,替代了基于 DNS 协议向运营商 Local DNS 发起解析请求的传统方式,可以避免 Local DNS 造成的域名劫持和跨网访问问题,解决移动互联网服务中域名解析异常带来的困扰。

微信小程序开发者使用移动解析说明

  1. 前往微信服务市场选购 HttpDNS 资源,并在服务详情页-接入文档获取 Service ID。
  2. 微信小程序调用 wx.request,将 enableHttpDNS 参数设置为 true,并在 httpDNSServiceId 参数中填入选用的服务商 Service ID。

代码示例

wx.request({
  url: 'example.php', //仅为示例,并非真实的接口地址
  enableHttpDNS: true,
  httpDNSServiceId: 'wxa410372c837a5f26',
  success(res) {
    console.log('request success', res)
  },
  fail(res) {
    console.error('request fail', res)
  }
})

计费说明

  1. 使用服务所产生的费用会按照实际调用服务商接口情况进行计费,定价策略由服务提供方制定,开发者需自行前往微信服务市场进行购买、续费等操作。
  2. 微信侧每次代开发者调用服务商接口时,微信侧会进行缓存,缓存策略由服务商返回的 ttl 决定,因此不一定每次调用 request 接口都会产生费用。
  3. 从基础库 v2.32.1 开始,若开发者的服务可用额度为 0,仍在 wx.request 接口中声明使用服务商提供的移动解析能力时,会使用 localDNS 解析来兜底,并在 success 回调参数 exception.reasons ( reasons 是数组) 中返回 httpdns 欠费的错误信息和错误码,类似 [{ "errMsg": "getDNSInfo:fail no enough httpdns quota", "errno": 602103 }]

注意事项

  1. HttpDNS 不兼容网络代理

在基础库 v2.22.1 版本之前,当用户设备使用了网络代理,同时又开启了 enableHttpDNS 时,request 接口会调用失败,fail 回调 errMsg 中会包含 ERR_PROXY_CONNECTION_FAILED 字样,如{"errno":600001,"errMsg":"request:fail -130:net::ERR_PROXY_CONNECTION_FAILED"}{"errno":600001,"errMsg":"request:fail errcode:-130 cronet_error_code:-130 error_msg:net::ERR_PROXY_CONNECTION_FAILED"}

为解决此问题,从基础库 v2.22.1 开始,若用户使用了网络代理,基础库会主动强制关闭 enableHttpDNS。开发者也可以通过 wx.getNetworkType 接口检查用户是否开启了网络代理。用法:

wx.getNetworkType({
  success(res) {
    console.log(res.hasSystemProxy) // 开启网络代理时为 true,否则为 false
  }
})

HttpDNS 相关错误码

错误码 说明
600000 网络错误
602000 网络请求错误
602001 系统错误
602002 http请求httpdns服务商错误
602101 微信小程序未在服务市场购买httpdns服务
602102 微信小程序在httpdns服务市场资源包过期
602103 微信小程序在httpdns服务市场额度不足
602104 httpdns服务商返回结果为空
602105 调用httpdns服务商结果超时
602106 httpdns服务商返回数据不合法
602107 httpdns域名解析结果为空
602108 不支持的httpdns服务商id

移动解析服务提供商接入说明

为了保护微信客户端的安全,微信小程序使用的移动解析服务需要通过微信侧安全认证,认证后可在微信服务市场上架。

微信侧欢迎更多服务商为微信小程序提供移动解析服务。申请接入按照以下模板发送邮件,我们会有专人与您联系。

收件人:servicemarket@tencent.com
主题:【上架服务市场】XXX(服务商)申请上架HttpDNS服务
正文:需要写明服务商的基本资料,包括不仅限于服务商名称、业务范围、技术证书、合作意向、联系方式等