Wechat development: configure Wx Config implements the image interface (configure the wx.config interface in detail)

Posted by jlsports on Mon, 17 Jan 2022 03:51:47 +0100

preface

   describe the general application scenario, that is, the mobile terminal of wechat needs to capture real-time images, upload them, and then transmit them to the background. Because we need images that can be displayed directly, we need to convert them into base encrypted images, and then display them in the img tag

summary

   let's briefly talk about the role of JS-SDK. Wechat JS-SDK is a wechat based web development kit provided by wechat public platform for web developers. You can use the capabilities of mobile phone systems such as photography, map selection, voice and location through JS-SDK. At the same time, you can directly use the unique capabilities of wechat such as wechat sharing, scanning, card voucher and payment, The first step to using the JS SDK is to configure Wx Config interface. The first step is to reference jweixin-1.6.0.js File. If the above file is not available, download this file jweixin-1.6.0.js , the following is about how to configure Wx Config interface

Configure Wx Config interface

  first Wx Config is equivalent to a master switch, or a global object. You can only use the interface attached to JS-SDK through correct authorization verification. In fact, it is equivalent to a permission verification. If the verification is successful, you can pass Wx The ready interface is implemented. If the verification fails, it enters Wx Error interface

wx.config interface injection permission verification configuration

wx.config({
  debug: true, // When the debugging mode is enabled, the return values of all APIs called will be displayed in the client alert
  appId: '', // Required, the only sign of official account.
  timestamp: , // Required, time stamp to generate signature
  nonceStr: '', // Required, generate random string of signature
  signature: '',// Required, signature
  jsApiList: [] // Required, list of JS interfaces to be used
});

   get the timestamp of the signature generated by the first parameter (in fact, get the current time)

// time stamp
String timestamp = Long.toString((new Date().getTime()) / 1000);

   get the second signature random string (nothing special, UUID)

// Random string
String nonceStr = UUID.randomUUID().toString();

  get the third parameter signature!! This is more important. Signature = random string + ticket + timestamp + URL (current page), but we have obtained the random string and timestamp at the top. At the bottom, we only obtain the ticket and the URL of the current page. Finally, put them together

/** 
   Four steps to obtain signature
       1.Get current page URL
       2.Get access_token parameter
       3.Through access_token gets the ticket parameter
       4.Put all the parameters together to get the signature 
**/
// 1.url (judge whether there are parameters. If there are parameters, splice the parameters, and the path must be configured in the white list)
String params = request.getQueryString();
if(StringUtils.isEmpty(params)){
    params="";
}else{
    params="?"+params;
}
String url = "https://hb.sdpicc.com.cn"+request.getRequestURI()+params;

// 2. toekn
String access_token = AccessTokenAPI.getAccessToken(appId,appsecret);

// 3.ticket
String urlStr = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token="+access_token+"&type=jsapi";
JSONObject jsonObject = HttpRequestUtil.httpRequest(urlStr, EnumMethod.GET.name(), null);
String ticket = jsonObject.getString("ticket");

// 4.signature 
String signature = getsig(nonceStr,ticket,timestamp,url);

// Finally, put it into the map and transfer it to the page
Map<String,Object> map = new HashMap<String,Object>();
map.put("appId",appId);
map.put("timestamp",timestamp);
map.put("nonceStr",nonceStr);
map.put("signature",signature);

  define the AccessToken entity class and obtain access_tocken parameter (step 2)

// AccessToken entity class
@Data
public class AccessToken {
    // Obtained credentials  
    private String token;  
    // Voucher validity time, unit: seconds  
    private int expiresIn;    
}
/**
 * Public platform common interface tool class
 *
 */
public class AccessTokenAPI {
    
	// GET WeChat official account: access_ The interface address (GET) of token is limited to 2000 (times / day)
	public final static String access_token_url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET";

	/**
	 * Get access_token
	 */
	public static AccessToken getAccessToken(String appid, String appsecret) {
		AccessToken accessToken = null;
		String requestUrl = access_token_url.replace("APPID", appid).replace("APPSECRET", appsecret);
		JSONObject jsonObject = HttpRequestUtil.httpRequest(requestUrl,EnumMethod.GET.name(), null);
		if (jsonObject == null) {
			jsonObject = HttpRequestUtil.httpRequest(requestUrl,EnumMethod.GET.name(), null);
		}
		// If the request is successful
		if (null != jsonObject) {
			try {
				accessToken = new AccessToken();
				accessToken.setToken(jsonObject.getString("access_token"));
				accessToken.setExpiresIn(jsonObject.getInteger("expires_in"));
			} catch (JSONException e) {
				accessToken = null;
				// Failed to get token
			}
		}
		return accessToken;
	}
}

  tool class for splicing signature (step 4)

private static String getsig(String noncestr,String jsapi_ticket,String timestamp,String url){
    String[] paramArr = new String[] { "jsapi_ticket=" + jsapi_ticket,
            "timestamp=" + timestamp, "noncestr=" + noncestr, "url=" + url };
    Arrays.sort(paramArr);
    // Concatenate the sorted results into a string
    String content = paramArr[0].concat("&"+paramArr[1]).concat("&"+paramArr[2])
            .concat("&"+paramArr[3]);
    String gensignature = null;
    try {
        MessageDigest md = MessageDigest.getInstance("SHA-1");
        // sha1 encrypt the spliced string
        System.out.println("Splice encrypted signature:"+content);
        byte[] digest = md.digest(content.getBytes());
        gensignature = byteToStr(digest);
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    }
    // Compare sha1 encrypted string with signature
    if (gensignature != null) {
        return gensignature;// Return signature
    } else {
        return "false";
    }
}

/**
 * Converts a byte array to a hexadecimal string
 *
 * @param byteArray
 * @return
 */
private static String byteToStr(byte[] byteArray) {
    String strDigest = "";
    for (int i = 0; i < byteArray.length; i++) {
        strDigest += byteToHexStr(byteArray[i]);
    }
    return strDigest;
}

/**
 * Converts bytes to hexadecimal strings
 *
 * @param mByte
 * @return
 */
private static String byteToHexStr(byte mByte) {
    char[] Digit = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A',
            'B', 'C', 'D', 'E', 'F' };
    char[] tempArr = new char[2];
    tempArr[0] = Digit[(mByte >>> 4) & 0X0F];
    tempArr[1] = Digit[mByte & 0X0F];
    String s = new String(tempArr);
    return s;
}

  the fourth jsApiList is actually the name of the interface to be called. Just put it in it

Complete code

  this is to get Wx Config authorization verification complete code

@Service
public class WxConfigUtils {

    @Value("${appId}")
    private String appId;
	
	@Value("${appSecret}")
    private String appSecret;

    public Map<String,Object> getWxconfig(HttpServletRequest request){
        String params = request.getQueryString();
        if(StringUtils.isEmpty(params)){
            params="";
        }else{
            params="?"+params;
        }
        String url = "https://xxx.xx.cn"+request.getRequestURI()+params;
        //request.getRequestURL().toString();
        Map<String,Object> map = new HashMap<String,Object>();
        // time stamp
        String timestamp = Long.toString((new Date().getTime()) / 1000);
        // Random string
        String nonceStr = UUID.randomUUID().toString();
        // Get access_token
        String access_token = AccessTokenAPI.getAccessToken(appId,appSecret);
        // Get jstl according to Toker
        String urlStr = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token="+access_token+"&type=jsapi";
        JSONObject jsonObject = HttpRequestUtil.httpRequest(urlStr, EnumMethod.GET.name(), null);
        String ticket = jsonObject.getString("ticket");
        System.out.println("Parameters to encrypt:"+nonceStr+" "+ticket+" "+timestamp+" "+url);
        String signature = getsig(nonceStr,ticket,timestamp,url);
        map.put("appId",appId);
        map.put("timestamp",timestamp);
        map.put("nonceStr",nonceStr);
        map.put("signature",signature);
        return map;
    }

    private static String getsig(String noncestr,String jsapi_ticket,String timestamp,String url){
        String[] paramArr = new String[] { "jsapi_ticket=" + jsapi_ticket,
                "timestamp=" + timestamp, "noncestr=" + noncestr, "url=" + url };
        Arrays.sort(paramArr);
        // Concatenate the sorted results into a string
        String content = paramArr[0].concat("&"+paramArr[1]).concat("&"+paramArr[2])
                .concat("&"+paramArr[3]);
        String gensignature = null;
        try {
            MessageDigest md = MessageDigest.getInstance("SHA-1");
            // sha1 encrypt the spliced string
            System.out.println("Splice encrypted signature:"+content);
            byte[] digest = md.digest(content.getBytes());
            gensignature = byteToStr(digest);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        // Compare sha1 encrypted string with signature
        if (gensignature != null) {
            return gensignature;// Return signature
        } else {
            return "false";
        }
    }

    /**
     * Converts a byte array to a hexadecimal string
     *
     * @param byteArray
     * @return
     */
    private static String byteToStr(byte[] byteArray) {
        String strDigest = "";
        for (int i = 0; i < byteArray.length; i++) {
            strDigest += byteToHexStr(byteArray[i]);
        }
        return strDigest;
    }

    /**
     * Converts bytes to hexadecimal strings
     *
     * @param mByte
     * @return
     */
    private static String byteToHexStr(byte mByte) {
        char[] Digit = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A',
                'B', 'C', 'D', 'E', 'F' };
        char[] tempArr = new char[2];
        tempArr[0] = Digit[(mByte >>> 4) & 0X0F];
        tempArr[1] = Digit[mByte & 0X0F];
        String s = new String(tempArr);
        return s;
    }
}

Front end page implementation

   the complete front-end interface does not upload style files. Just write styles and put a picture

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Call the enterprise wechat image upload interface</title>
  <!--Upload pictures css-->
  <link rel="stylesheet" href="../css/style.css" />
</head>
<body>
  <header class="upload-hedaer">
    <a href="javaScript:history.back(-1)" class="upload-fh"></a>
    <div>upload</div>
    <div>ยทยทยท</div>
  </header>
  <section class="upload-section">
      <article class="upload-piclist">
          <div class="upload-file" id="uploadfile"></div>
      </article>
  </section>
  <script src="../js/jweixin-1.2.0.js" type="text/javascript" charset="utf-8"></script>
  <script src="../js/jquery-3.0.0.min.js" type="text/javascript" charset="utf-8"></script>
  <script src="../js/wxconfig.js" type="text/javascript" charset="utf-8"></script>
</body>
<script type="text/javascript">
	/** 
		In this place, we only need to refer to the page to be used
	       1.chooseImage: And the interface for taking pictures or selecting pictures from mobile photo albums
	       2.getLocalImgData: Get local picture interface
	**/ 
   wx.config({
       debug: true, // The production environment needs to turn off the debug mode
       appId: "[[${appId}]]", // appID = corpID, viewed through wechat service number / enterprise wechat background
       timestamp: "[[${timestamp}]]", // Timestamp when the signature was generated
       nonceStr: "[[${nonceStr}]]", // Generate a signed random string
       signature: "[[${signature}]]", // autograph
       jsApiList: [ // List of JS interfaces to be called
           'chooseImage',
           'getLocalImgData'
       ]
   });
</script>
</html>

  our Wx The ready interface is written as a separate JS file. Considering that more than one page will use this function, it is written as a public method

wx.ready(function(){
    var piclist = document.getElementsByClassName('upload-piclist')[0];
    //Bind onclick event to upload Icon
    $("#uploadfile").click(function(){
        // Call interface
        wx.chooseImage({
            count: 1, // Default 9
            sizeType: ['original', 'compressed'], // You can specify whether to use the original or compressed image. Both are available by default
            sourceType: ['album', 'camera'], // You can specify whether the source is an album or a camera. Both are available by default
            success: function(res) {
                wx.getLocalImgData({
					localId: res.localIds[0], // localID of the picture
					success: function(res) {
						var localData = res.localData;
						var imageBase64 = '';
						if (localData.indexOf('data:image') == 0) {
							//The direct assignment of Apple generates' data: image / jpeg 'by default; Base64, 'head splice
							imageBase64 = localData;
						} else {
							//This is the only pit in Andrews! Before splicing, you need to globally replace the newline character of localData
							//At this time, a normal base64 image path is perfectly generated and assigned to the src of img
							imageBase64 = 'data:image/jpeg;base64,' + localData.replace(/\n/g, '');
						}
						var html = document.createElement('div');
						html.innerHTML = '<img id="image" src=' + imageBase64 + ' alt="">'
						piclist.appendChild(html);
					}
				});
            }
        });
    })
});

Screenshot example