# WeCard 码组件

# 简介

此组件用于集成 wecard 码相关的能力,包括但不限于展示二维码、签约、补缴等。

# 如何使用

# 申请组件

小程序开发者可以在"小程序管理后台-设置-第三方服务-插件管理"中查找插件,并进行申请。在发起申请24小时内,微卡会根据应用的资质进行审核。

# 引入插件

  1. 在app.json中声明需要使用的插件
{
   "plugins": {
    "wecard-code-plugin": {
      "version": "0.0.7",
      "provider": "wx15949dc6d9b035d2"
    }
  },
}

需指插件的version(当前版本号:0.0.7)和provider(插件提供方:wx15949dc6d9b035d2)

  1. 在使用的页面的json文件(如index.json)中引用自定义组件
{
  "usingComponents": {
    "wecard-code": "plugin://wecard-code-plugin/wecard-code"
  }
}

# 使用插件

# 1. 安装 wecard-code-sdk

npm install wecard-code-sdk

# 2. 在页面的 js 文件中引入 sdk

引用后在 onLoad 中进行注册

import { wecardInit } from "wecard-code-sdk";

Page({
  data: {
    userinfo: {},
    wecardInitData: false
  },

  onLoad: function () {
    this.wecardInit();
  },

  wecardInit(e){
    wecardInit(this,e);
  },

  onShow(){
    this.getUserInfo();
  },

  getUserInfo(){
    // 获取 userinfo 的接口,并且 setData
  }
}

  1. 在页面上使用组件
<wecard-code 
    userInfo="{{userinfo}}" 
    initData="{{wecardInitData}}"
    bindInit="wecardInit"
    bindLoginStatusExpired="getUserInfo"
>
</wecard-code>
参数 type 必填 说明
userInfo Object 用户信息,参考后文的userinfo的获取说明
initData Object 插件初始化信息(直接填写 wecardInitData 即可)
bindInit fun(e) 直接写 wecardInit 即可,wecard 插件初始化函数
bindLoginStatusExpired fun(e) 身份过期后会触发,请重新获取 userinfo 并且 setData 新的 userinfo
showOpenPayTip boolean 是否展示开通支付功能的提示,默认为 true
isCaptureScreenEnabled boolean 是否开启截屏功能,默认为 true (表示开启截屏风控,安全性高)。 警告:如果设置为 false,表示关闭截屏风控,安全性大幅降低,建议保持此设置为 true

# 其他

# 签约组件

另外提供一个发起签约的按钮组件,使用方式如下:

使用前请先在页面上使用 wecard-code-sdk 进行 init 操作,方法同上

在页面级别 json 声明使用签约按钮组件

{
  "usingComponents": {
    "sign-button": "plugin://wecard-code-plugin/sign-button"
  }
}

页面 wxml 声明:

<sign-button
  userInfo="{{userinfo}}"
  initData="{{wecardInitData}}"
  bindInit="wecardInit"
  bindSignBack="signBack"
  buttonText="开通支付功能"
/>

其中参数如下:

参数 type 必填 说明
userInfo Object 用户信息,参考后文的userinfo的获取说明
initData Object 插件初始化信息(直接填写 wecardInitData 即可)
bindInit fun(e) 直接写 wecardInit 即可,wecard 插件初始化函数
bindSignBack fun(e) 获取签约结果
buttonText string 按钮文案,默认为“前往开通支付功能”

在 js 中绑定 function 获取前端签约结果(如果需要保存签约状态,请以服务端为准,不建议保存,微校来维持此状态)

signBack(e){
    console.log("[signBack]", e.detail);

    // return_code === SUCCESS 为成功
    // 更加详细的信息,请查看: https://pay.weixin.qq.com/wiki/doc/api/pap.php?chapter=18_14&index=3
    const { return_code, return_msg, contract_id } = e.detail;
  }

# 小钱包功能页面

# 功能简介

小钱包功能页,可用于用户的福利券、余额、优惠券的展示。

# 使用方式

通过wx.navigateTo方法跳转,并通过该方法的内置的events进行事件通信。 事件通信类型:

  • 宿主 -> 插件
    • updateUserInfo: 传递用户信息
  • 插件 -> 宿主
    • loginStatusExpired : 登录态过期,通知宿主重新获取身份态

代码示例如下,完整代码可见(pages/wallet/index):

     
    wx.navigateTo({
      url: 'plugin://wecard-code-plugin/wallet',
      events: {
        loginStatusExpired: (data) => {
          this.fetchData();
        }
      },
      success: (res) => {
        this.walletEventChannel = res.eventChannel;
        res.eventChannel.emit('updateUserInfo', this.data.userinfo)
      }
    })

# request 安全域名添加

若使用了支付功能,请向微卡开发人员咨询需要添加的 request 安全域名

  • https://api.unipay.qq.com
  • https://midas.weixiao.qq.com

# 用户信息userinfo的获取

1、电子码组件的核心参数是userInfo,这个参数类型为 object,表明了当前 业务侧小程序需要渲染哪个用户的电子码,userInfo的相关属性为:

参数 type 必填 说明
ocode string 电子码侧客服提供的主体编码
timestamp string 时间戳,从1970年1月1日00:00:00至今的秒数,即当前时间(北京时间)
nonce string 随机字符串,长度32字符以下
userid string 业务侧定义的用户标识,用来传递至微卡侧
openid string 业务侧小程序的openid;非必填;不填时无法使用支付相关功能
appid string 业务侧小程序的appid,和openid对应;非必填;不填时无法使用支付相关功能
origin string 来源:0 微信 1 企业微信
signature string 签名,详情见下一小节userinfo签名算法

2、userinfo签名算法

1)准备一对 2048位PKCS#8格式 的RSA公私钥,保存好私钥(切勿放入小程序客户端),并将公钥提交给 微卡侧

2)删选并排序:获取所有请求参数,不包括字节类型参数,如文件、字节流等,剔除signature字段,剔除值为空的参数,并按照第一个字符的键值ASCII码递增排序(字母升序排序),如果遇到相同字符则按照第二个字符的键值ASCII码递增排序,以此类推

3)拼接:将排序后的参数与其对应值,组合成“参数=参数值”的格式,并且把这些参数用&字符连接起来,此时生成的字符串为 待签名字符串

4)签名:使用各自语言的 SHA256WithRSA 签名函数,并利用步骤1中生成的 私钥 对 待签名字符串 进行签名,并进行 BASE64 的编码,得到 signature 值,放入数据包中

3、签名DEMO

PHP:

<?php

//生成的私钥
$privateKey = '-----BEGIN PRIVATE KEY-----
MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDN5Ikc1bACyZqA
VxNAxmblHd0CaIi/EVlvp3eqQ82raT//XqbYar/Db7lDoIamwJyK0Hf2mzpisdXP
spuvUOYNuU0TjBN+flC85AFElS3sZhsAolFXQBUk4IEKfD2fRaLPkIs+v4kHmP7z
A4TkTPl2nvWb3YbKokWbomHwUgXFfnEfj/3cKKZQxwXJFx2Lc71a/+zTcpaEIy12
XcMsQxHBSItJA9U9Gw8RQLbH4tAUzzsXlcH0OFF9NQ/CRRJ6Nep6YVyX+BQx/55U
lOJdKo2h1qQz6rmKCOz5rIBqh3rntsYPbJd7meDts8nWEnGaNS5F+PZdG0I2udTJ
nDk/B8SRAgMBAAECggEAaWoC0WKOtT6m/eKXFuj9sXyytRL0QG8PjVz+pYwFdydx
/rtlTRSKjfNbtUYw6ptfCqtlYDtljzZhs+9MSlxvDMO8tK9ZI8BkcfGCvKxsUMaO
OKriXnuO18yiBM5Ldopeq0rkIAJMlDk+/wjkN0c5ygPk2CJ5arHeVaqz3ikAj3Yc
HrYCzmLxVHoX1IvFd0VEp/7EJjcH8ty1RzJWdM++de5vHAAzLGdZCb4dIUnNHGbn
H97fMOTKYx+0K2tVCjNAoRUejsH22tpj9ospKQ0PydyGB0pzTrURx0/A/BWeKScC
2QHM3/puJrQRoZTi+GwVgQXyaPWp6H9pEim7NWGQgQKBgQDslXEy+MVGehnvURvd
2f7BFe6IQeJIrT2jnvn3wRCUw95oQdxp4RIQJWmAtF/bJIqAfSh+NvjsyaCke0iD
K/Si8WNiiEi/yGXvR3DnXXyaVJNXuw21NomlVjDfbfbhJLZ+XuSo3wQDmdK2WadK
521U1D1fITD8m5rWaA1I********gQDeykiHkAPXC9PbxxoxpaArPhlXeAqqJFDS
w8jy9hU+CKdVKmhSd64xnljExH5QpLyD/ER4IAjRRRLQiuh5t8DeZe3KLfRo/Zpd
PaPp/6W0QoiPYlpJ4g8beeffs8ZfFcWrlwslHlKWMmY5NXm/8xrAhJTxrrFRmShp
aS6FzPuwKQKBgAXlH2H2wuujpTvKWJhpkyh6hGwOwDWxY2TNVEsxG1mpm8QbSAO3
YPzYAc38MJtESNM0yyqB8ifsSj1u+PqTwM/ClghhfvaQZsHUlOKe+LjbvKQl/Ax0
5G8jO6qFke5APO/fK3FtxSrVzWNPzpRWOeowM6tIJ3FT60LGavZSLR0pAoGAD+R4
Jgt06qsyUrQyPyZkdZE5d47dm+N5TH+g3wwE2eb+IMokpPVanLmB9Y9av1/w/q1J
KRSH7H2z6OJv0Pb1sCevPcPncnHcyBf0kGWnKWOxoCDQ9gJFN52Ll96YIQJJloLw
zZYLKCGyPxR8ed/aoa8TfOYMShjV1CcnpW3I6nkCgYBAZrMW+1BZs+wP7oFHygYJ
utcWCq4rDTT9SunA4Kk1Lh4LUjK3JgmrJtoJomNNApXIHlte+hC2cRgYLYP/zO1y
4o5lWuOR8/6tmrGGhSmRv8xuYndRQ7Y3NUmXXPHieOrK3sIEJ15Md7wfSF4cjriS
fSXnNxzJYs4gUNG9XNwGvA==
-----END PRIVATE KEY-----
';

//待签名
$params = [
    'ocode' => '1563506591',
    'timestamp' => '1589720896',
    'nonce' => 'demononce',
    'userid' => 'baronliu',
    'appid' => 'wx15949dc6d9b035d2',
    'openid' => 'demoopenid',
    'origin' => '0',
];

//排序并拼接
ksort($params);
$signString = rawurldecode(http_build_query($params));

//进行签名
$p = openssl_get_privatekey($privateKey, null);
$sign = '';
openssl_sign($signString, $sign, $p, OPENSSL_ALGO_SHA256);
$sign = base64_encode($sign);
openssl_pkey_free($p);
$params['signature'] = $sign;

//在后端计算好签名后将数据包传递至前端码组件内
var_dump($params);