vue uses Wechat JS-SDK to realize sharing function

Keywords: Javascript SDK npm Android axios

Recently, we have developed a project built with vue and embedded H5 pages in the public number of Wechat. Because of business requirements, we need to implement the custom sharing function of Wechat, so we integrate Wechat JS-SDK in the project. Wechat JS-SDK is a web development toolkit based on Wechat provided by Wechat Public Platform for web developers. By using Wechat JS-SDK, web developers can use the ability of Wechat to efficiently use mobile phone systems such as photography, map selection, voice and location, and directly use the unique capabilities of Wechat such as sharing, sweeping, card vouchers, payment, etc. to provide better web page experience for Wechat users.

1. Binding domain names

Wechat Public Number Development Test Account: http://mp.weixin.qq.com/debug... You need to fill in the interface configuration, a domain name that can be accessed by the public network, and recommend natapp / Router. After filling in the JS interface security domain name and setting up the JS interface security domain, by paying attention to the test number, developers can call the open JS interface of Wechat under this domain name. Read Wechat JSSDK Development Document
1) Router is used here to achieve intranet penetration. http://www.luyouxia.com/ After downloading and installing, configure the corresponding intranet mapping address

2) Setting up JS interface security domain

2. Introducing JS files

Install Wechat's js-sdk through npm, or add script tag directly to index.html page to refer to it. Here, we use NPM installation.
npm install weixin-js-sdk
Introduce in pages that need to be shared
import wx from 'weixin-js-sdk'

3. Implementing js-sdk privilege signature algorithm in Java

1)jsapi_ticket
Before generating signatures, you must know about jsapi_ticket, which is a temporary ticket used by the public number to call the Wechat JS interface. Normally, jsapi_ticket has a validity of 7200 seconds, which is obtained by access_token. Because the number of api calls to obtain jsapi_ticket is very limited, frequent refresh of jsapi_ticket will result in limited api calls and affect their own business. Developers must cache jsapi_ticket globally in their own services.

2) Get access_token (validity 7200 seconds, developers must access_token in their own service global cache)
Access_token is the globally unique interface invocation credential of public number. When public number invokes each interface, access_token should be used. Official documents: https://mp.weixin.qq.com/wiki...

@RequestMapping(value = "/get_access_token", method = RequestMethod.GET)
public String getAssessToken() {
    String url = "https://api.weixin.qq.com/cgi-bin/token";
    String str = HttpClientUtil.sendGet(url, "grant_type=" + Constants.GRANTTYPE + "&secret=" + Constants.APPSECRET + "&appid=" + Constants.APPID);
    JSONObject jsonObject = JSONObject.fromObject(str);
    return jsonObject.toString();
}

3) After obtaining access_token, request jsapi_ticket by http GET

@RequestMapping(value = "/get_ticket", method = RequestMethod.GET)
public String getTicket() {
    String urlToken = "https://api.weixin.qq.com/cgi-bin/token";
    String tokenObj = HttpClientUtil.sendGet(urlToken, "grant_type=" + Constants.GRANTTYPE + "&secret=" + Constants.APPSECRET + "&appid=" + Constants.APPID);
    JSONObject jsonToken = JSONObject.fromObject(tokenObj);
    String access_token = jsonToken.getString("access_token");

    String urlTicket = "https://api.weixin.qq.com/cgi-bin/ticket/getticket";
    String strTicket = HttpClientUtil.sendGet(urlTicket, "type=jsapi" + "&access_token=" + access_token);
    JSONObject jsonTicket = JSONObject.fromObject(strTicket); 
    return jsonTicket.toString();
}

4) Signature algorithm
The rules for signature generation are as follows: the fields participating in signature include noncestr (random string), valid jsapi_ticket, timestamp (timestamp), URL (the URL of the current web page, does not contain # and the following parts). After sorting all parameters to be signed according to ASCII codes of field names from small to large (dictionary order), use the format of URL key-value pairs (key1 = value1 & key2 = value2...) Stitching into string 1. Note here that all parameter names are lowercase characters. string1 is encrypted by sha1. The field name and field value are all original values, and no URL escaping is performed.

  //Main code
  @RequestMapping(value = "/get_signature", method = RequestMethod.GET)
public Map<String, String> getSignature(String url) {
    Map<String, String> ret = new HashMap<String, String>();

    String wxTicket = getWxApiTicket();
    String nonce_str = create_nonce_str();
    String timestamp = create_timestamp();
    String str;
    String signature = "";
    //Note that the parameter names here must be all lowercase and ordered
    str = "jsapi_ticket=" + wxTicket +
            "&noncestr=" + nonce_str +
            "&timestamp=" + timestamp +
            "&url=" + url;
    logger.info(str);

    try {
        MessageDigest crypt = MessageDigest.getInstance("SHA-1");
        crypt.reset();
        crypt.update(str.getBytes("UTF-8"));
        signature = byteToHex(crypt.digest());
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    } catch (UnsupportedEncodingException e) {
        e.printStackTrace();
    }

    ret.put("url", url);
    ret.put("jsapi_ticket", wxTicket);
    ret.put("nonceStr", nonce_str);
    ret.put("timestamp", timestamp);
    ret.put("signature", signature);
    ret.put("appId", Constants.APPID);
    return ret;
}

Signature interface returns information

{
    "signature":"4021b3f502e6bd15798a0433af33c4ef1be4ff83",
    "appId":"wx618f45e4948c3889",
    "jsapi_ticket":"sM4AOVdWfPE4DxkXGEs8VOxnOWlkG3Q1qP1pwA8mBLNgkCewNOfFiU8EmlnAx8_Fe0Zh-rGS03Nu8BQZB0a4-g",
    "url":null,
    "nonceStr":"ab5d0e96-429b-4a86-bd88-dc1276dcf76f",
    "timestamp":"1566527616"
}

Matters needing attention
1. Noncestr and timestamp for signature must be the same as nonceStr and timestamp in wx.config.
2. The URL used for signing must be the complete URL for calling the JS interface page.
3. For security reasons, developers must implement signature logic on the server side.

4. Verify configuration by injecting privileges through config interface

All pages that need to use JS-SDK must first inject configuration information, otherwise they will not be invoked (the same url only needs to be invoked once. Web app for SPA with changed url can be invoked every time the url changes. At present, the Android Wechat client does not support the new feature of pushState, so it uses hState to implement web app pages. This will result in signature failure, which will be fixed in Android 6.2.

wx.config({
    debug: true, // When debugging mode is turned on, the return values of all APIs invoked will be displayed in alert on the client side. To view the incoming parameters, it can be opened on the pc side. The parameter information will be typed out through the log and printed only on the pc side.
    appId: '', // Mandatory, Unique Identification of Public Number
    timestamp: , // Mandatory, time stamp for signature generation
    nonceStr: '', // Compulsory, generating random strings of signatures
    signature: '',// Must fill in, sign
    jsApiList: [] // Mandatory, list of JS interfaces to use
});

The parameters appid, timestamp, nonceStr and signature in config configuration are all returned by the background interface, and the front end can be obtained by sending interface requests through axios.

this.axios.get('/wx/get_signature?url=' + encodeURIComponent(location.href.split('#')[0])).then((res) => {
  wx.config({
    debug: true, // Open debugging mode
    appId: res.data.appId, // Mandatory, Unique Identification of Public Number
    timestamp: res.data.timestamp, // Mandatory, time stamp for signature generation
    nonceStr: res.data.nonceStr, // Compulsory, generating random strings of signatures
    signature: res.data.signature,// Must fill in, sign
    jsApiList: [
      "updateAppMessageShareData",//Customize Sharing to Friends and Sharing to QQ buttons
      "updateTimelineShareData",//Customize the sharing content of "Share to Friends Circle" and "Share to QQ Space" buttons
      "onMenuShareWeibo",//Get "Share to Tencent Weibo" button click status and customize sharing content interface
    ] // Mandatory, list of JS interfaces to use
  })
}).catch((error) => {
  console.log(error)
});

//Processing Successful Verification through ready Interface
wx.ready(function(){
    this.wxShareTimeline();
    this.wxShareAppMessage();
// Config information validation will execute the ready method. All interface calls must be obtained after the config interface gets the result. Config is an asynchronous operation of the client. Therefore, if the relevant interface is required when the page is loaded, the relevant interface must be put in the ready function to ensure the correct execution. For the interface that is called only when the user triggers, it can be called directly without being placed in the read function.
});

wx.error(function(res){
//Failure to verify config information will execute error function, such as signature expiration leading to verification failure. Specific error information can be viewed in debug mode of config or in the return res parameter. For SPA, the signature can be updated here.
});

5. Realize Custom Sharing Friends/Friends Circle

  wxShareTimeline() {// Customize Sharing to Friends and Sharing to QQ buttons
    wx.updateAppMessageShareData({
      title: 'The world is so big, I want to see-WeChat test', // Share titles
      desc: 'The world is so big, I want to see-WeChat test', // Sharing Description
      link: location.href.split('#') [0], // Share Link, the link domain name or path must be the same as the public number JS security domain name corresponding to the current page.
      imgUrl: 'http://www.baidu.com/FpEhdOqBzM8EzgFz3ULByxatSacH', //Share Icons
      success: () => {
      }
    })
  },
  wxShareAppMessage() {//Customize the sharing content of "Share to Friends Circle" and "Share to QQ Space" buttons
    wx.updateTimelineShareData({
      title: 'The world is so big, I want to see-WeChat test2', // Share titles
      desc: 'The world is so big, I want to see-WeChat test2', // Sharing Description
      link: location.href.split('#') [0], // Share Link, the link domain name or path must be the same as the public number JS security domain name corresponding to the current page.
      imgUrl: require('./logo.jpg'), // Sharing icons (no relative paths, absolute paths)
      success: () => {
      }
    })
  }

6. Problems encountered
1)invalid signature
The reason for the error in obtaining the signature may be that there is a problem with the configuration of the public number platform or the algorithm for backstage return of the signature interface.

2)invalid url domain
The domain name of the current page is not bound to the appid used. Please make sure that the bound domain name is correctly filled in. Only 80 (http) and 443 (https) ports are supported, so no port number is required.

3) Custom thumbnails are not displayed
The relative path can not be used because of the path error. It must be absolute path. Another reason is the size and type of picture. It is recommended to use jpg format.

4) Secondary sharing makes it impossible to call a custom interface
The signature that the url encodes and passes to the background will not be miscalculated, because Wechat will add the string from = singlemessage & isappinstalled = 0 to the link after sharing.

7. Global cache public numbers access_token and jsapi_ticket
1) Save through database
The method is to save the current system time and access_token to the data table when obtaining access_token. When retrieving it again, query the last time retrieved and compare it with the current system time to see if the time is longer than 2 hours (7200s). If this time limit is exceeded, an access_token is retrieved and access Token and getTime of the data table are updated.

2) Create txt files to save through physical disks

3) Start threads through servlet s, and let threads execute acquisition on time.
For reference https://blog.csdn.net/guobinh...

This is the summary of the call to Wechat js-sdk. For more information, you can read the Wechat JS-SDK documentation. https://mp.weixin.qq.com/wiki...

Posted by Kadanis on Thu, 22 Aug 2019 23:05:23 -0700