Resolve WeChat JS-SDK configuration authorization, achieve sharing interface, js-sdk Interface

Source: Internet
Author: User
Tags crypt sha1 encryption

Parse JS-SDK configuration authorization, realize sharing interface, js-sdk Interface

Open JS-SDK for Web developers provides an internal-based Web Development Kit, the most direct advantage is that we can use sharing, scanning, coupons, payment and other unique capabilities. In May July, the problem of obtaining the shared certificate was deeply rooted. When I saw "config: OK", it was really a stone, and I felt the world was wonderful ..

This article is a lot of prerequisites for development, including obtaining and caching global access_token from the server based on JAVA, obtaining and caching global jsapi_ticket, and configuring authorization component encapsulation at the front end, call the shared component encapsulation.

Configure authorization ideas: first, obtain jsapi_ticket Based on access_token, and encrypt SHA-1 Based on the obtained jsapi_ticket, the randomly generated string and timestamp, And the url of the page to be authorized, return the encrypted string, and call the provided config Interface Based on the encrypted string.

Configure the JS interface Security Domain Name

Public platform-public account settings-function settings-js interface Security Domain Name

Obtain and cache global access_token

/*** Global ticket ---- >>> access_token * @ return * @ throws ClientProtocolException * @ throws IOException */public String getBaseAccessToken () throws ClientProtocolException, IOException {try {String value = redisService. get ("WEIXIN_BASE_ACCESS_TOKEN"); if (! StringUtils. isEmpty (value) {LOGGER.info ("Get base access_token from redis is successful. value: {} ", value); return value;} else {synchronized (this) {// No in cache, or has expired String url =" https://api.weixin.qq.com/cgi-bin/token? Grant_type = client_credential & appid = "+ WX_APPID +" & secret = "+ WX_APPSECRET; String rs = apiService. doGet (url); JSONObject obj_content = JSONObject. parseObject (rs); String accessToken = obj_content.getString ("access_token"); Integer time = Integer. parseInt (obj_content.getString ("expires_in "). toString (); // write cache redisService. set ("WEIXIN_BASE_ACCESS_TOKEN", accessToken, time-3600); LOGGER.info ("Set base access_token to redis is successful. parameters time: {}, realtime ", time, time-3600); return accessToken ;}} catch (Exception e) {LOGGER. error ("Get base access_token from redis is error. ");} return null ;}

First, the key is "WX_BASE_ACCESS_TOKEN" from the cache. If the key is hit, the return value is directly returned. Otherwise, the system sends a GET request to call the provided interface to obtain the global access_token and writes the obtained value to the cache.

Obtain and cache global jsapi_ticket

/*** Jsapi_ticket is a temporary ticket used by the public account to call the JS interface * @ return * @ throws IOException * @ throws ClientProtocolException */public String getJsapiTicket () throws ClientProtocolException, IOException {try {String value = redisService. get ("WEIXIN_JS_API_TICKET"); if (! StringUtils. isEmpty (value) {return value;} else {synchronized (this) {// no in the cache, or has expired // obtain the global access_token, unique ticket String accessToken = getBaseAccessToken (); String url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket? Access_token = "+ accessToken +" & type = jsapi "; String rs = apiService. doGet (url); JSONObject obj_content = JSONObject. parseObject (rs); String jsapi_ticket = obj_content.getString ("ticket"); Integer time = Integer. parseInt (obj_content.getString ("expires_in "). toString (); // write cache redisService. set ("WEIXIN_JS_API_TICKET", jsapi_ticket, time-3600); return jsapi_ticket ;}} catch (Exception e) {LOGGER. error ("Get js_api_ticket from redis is error :{}", e);} return null ;}

Since jsapi_ticket can be obtained for 100000 times, the cache must be used. Similarly, if you get the access_token, I set the cache expiration time to the officially provided time minus one hour for the sake of insurance.

Jssdk encrypted string to get restful

1. Controller

/*** Obtain the shared certificate * @ param * @ return signature * @ throws IOException */@ RequestMapping (value = "/signature", method = RequestMethod. GET) public @ ResponseBody String createSignature (@ RequestParam String url) throws IOException {LOGGER.info ("RestFul of createSignature parameters url :{}", url); try {String rs = wechatService. createSignature (url); LOGGER.info ("RestFul of signature is successful. ", rs); return rs;} catch (Exception e) {LOGGER. error ("RestFul of signature is error. ", e);} return null ;}

2. Service

/*** Perform SHA1 encryption based on parameters such as jsapi_ticket * @ param nonceStr random String * @ param timestamp current timestamp * @ param url current page url */public String createSignature (String url) throws ClientProtocolException, IOException {String nonceStr = create_nonce_str (); String timestamp = create_timestamp (); String signature = "jsapi_ticket =" + getJsapiTicket (); signature + = "& noncestr =" + nonceStr; signature + = "& timestamp =" + timestamp; signature + = "& url =" + url; try {MessageDigest crypt = MessageDigest. getInstance ("SHA-1"); crypt. reset (); crypt. update (signature. getBytes ("UTF-8"); signature = byteToHex (crypt. digest ();} catch (Exception e) {LOGGER. error ("Signature for SHA-1 is error :{}", e) ;}map <String, String> Map = new HashMap <String, String> (); map. put ("timestamp", timestamp); map. put ("nonceStr", nonceStr); map. put ("signature", signature); map. put ("appid", WX_APPID); return JSON. toJSONString (map, true);} private static String byteToHex (final byte [] hash) {Formatter formatter = new Formatter (); for (byte B: hash) {formatter. format ("% 02x", B);} String result = formatter. toString (); formatter. close (); return result ;}

WX_APPID is the public ID appid, which is obtained from the configuration file through the spring @ value annotation.

3. generate random strings

private static String create_nonce_str() {  return UUID.randomUUID().toString(); }

4. Time formatting

private static String create_timestamp() {  return Long.toString(System.currentTimeMillis() / 1000); }

So far, the background has been fully completed. In fact, there is not much explanation. Read the code carefully and the readability should be okay!

Encapsulate the authorization component for sharing

Require. config ({urlArgs: "v = 20161116", baseUrl: "/static", paths: {jweixin: 'component/jweixin/jweixin-1.0.0 ', share: 'component/wechat/share' // share component }})

First, call the background interface to obtain the encrypted string and call the wx. config () method provided.

// JsSDK authorization $. signature = function (wx, opts, currentUrl, callback) {$. ajax ({data: {url: currentUrl}, type: "GET", url: WX_ROOT + "wechat/signature", success: function (json) {if (json) {var data = JSON. parse (json); wx. config ({debug: false, appId: data. appid, timestamp: data. timestamp, nonceStr: data. nonceStr, signature: data. signature, jsApiList: ['onmenusharetimeline', 'onmenushareappmessage', 'onmenushareqq', 'onmenushareweibo ', 'onmenushareqzone']}); wechatShare. options. isSignature = true; callback & callback (opts, wx );}}});}

Suggestion: We recommend that you enable the debug mode in the development environment to facilitate log printing and locate the problem debug: true.

All interfaces must be called after the config interface obtains the result. config is a client-side asynchronous operation. Here I use the global variable isSignature to cache whether authorization has been configured, and then execute the callback. For example, implement the sharing interface:

// Share $. share = function (opts, wx) {var options = {currentUrl: window. location. href. split ('#') [0], imgUrl: null, title: 'agricultural insurance ', desc: null, country URL: null} $. extend (true, options, opts ||{}); // checks whether the if (! WechatShare. options. isSignature) {$. signature (wx, opts, options. currentUrl, $. share)} else {wx. ready (function () {// share it with your friends wx. onMenuShareTimeline ({title: options. title, link: options. invalid URL, imgUrl: options. imgUrl, success: function () {// share statistics, share source 1 circle of friends 2 Share with friends 3 share to QQ 4 share to QQ space}); // share with friends wx. onMenuShareAppMessage ({title: options. title, desc: options. desc, link: options. invalid URL, imgUrl: options. imgUrl });});}}

First, check whether authorization is configured. If authorization is not configured, call $. input $. share, which is similar to recursive call. When the share method is returned again, the isSignature is already true, and the wx is executed. the ready () method, call the interface that needs to be called, and provide many interfaces to us. Sharing is only one of them. Only unexpected ones can't be realized ....

Note: currentUrl must be dynamically obtained through window. location. href method. Because the page is shared, the client will add other parameters at the end of your link. Therefore, you need to use '#' to cut the url and take the first one, use encodeURIComponent to escape Chinese characters to ensure that the signature is obtained successfully. If the message "invalid signature" is reported, most of the reasons are the passed url and the encryption algorithm. Check carefully!

Call:

Var ua = navigator. userAgent. toLowerCase (), isWechat = ua. indexOf ('micromessenger ')! =-1; // determine whether the browser is var shareData = {title: 'test share', desc: 'Here is the description, which is not displayed in the circle of friends.', link: APP_ROOT + '/base/downloadApp, // The Link opened after sharing, must be imgUrl: PIC_PATH + (self. data. shareListData [0]. imgSmall | '/static/img/coupon/getTicPic.png'), // success: function () {setTimeout (function () {// operation data statistics}, 0) // call in pseudo-asynchronous mode} // the browser shares and loads if (isWechat) {require (['jweixin'], function (wx) {require (['share'], function () {$. share (invalid data, wx );})})}

Complete js: https://github.com/helijun/component/blob/master/wechat/share.js

Summary of common problems:

At the beginning of this sharing function, the reason for a failed Certificate acquisition (invalid signature) was really intermittent for several days, and sometimes there was no clue. I checked the code repeatedly and read it line by line. I did not find any exceptions. I also returned a ture test by using the provided JavaScript interface signature verification tool. However, I reported a certificate failure! The official documentation is a bit ambiguous. On the afternoon of the last Saturday, I calmed down and checked the background SHA1 encryption algorithm patiently. Finally, I saw config true .. sugon.

During development, we always encounter various problems. programmers and bugs are always good friends and enemies, and we are always on the edge of bugs, sometimes, when you encounter a very strange problem, you may wish to let it go first, shift your attention first, and blow a hair on the balcony. maybe at some point in time, the problem will suddenly be solved ..

Interface signature verification tool

Https://mp.weixin.qq.com/debug/cgi-bin/sandbox? T = jsapisign

The above is all the content of this article. I hope this article will help you in your study or work. I also hope to provide more support to the customer's home!

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.