网络知识 娱乐 微信开发:配置 wx.config 实现图像接口(详细配置 wx.config 接口)

微信开发:配置 wx.config 实现图像接口(详细配置 wx.config 接口)

前言

  描述一下大概的应用场景,就是微信的移动端需要拍摄实时图像上传,然后传输到后台,由于我们需要的是直接可以显示的图片,所以要转换成 base 加密后的图片,然后放到 img 标签里进行展示

概述

  简单说一下 JS-SDK 的作用吧,微信 JS-SDK 是微信公众平台 面向网页开发者提供的基于微信内的网页开发工具包,可以通过 JS-SDK 使用拍照、选图、语音、位置等手机系统的能力,同时可以直接使用微信分享、扫一扫、卡券、支付等微信特有的能力,要使用 JS-SDK 的第一步就是配置 wx.config 接口,不对第一步是引用 jweixin-1.6.0.js 文件,如果上述文件不可使用就下载这个 jweixin-1.6.0.js ,下边主要讲一下怎么配置 wx.config 接口

配置 wx.config 接口

  首先 wx.config 相当于一个总开关吧,也可以说是一个全局对象,只有通过正确的授权验证才可以使用 JS-SDK 所附带的接口,实际上就相当于一个权限验证,验证成功就可以通过 wx.ready 接口实现,验证失败就进入到了 wx.error 接口

wx.config 接口注入权限验证配置

wx.config({
  debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来
  appId: '', // 必填,公众号的唯一标识
  timestamp: , // 必填,生成签名的时间戳
  nonceStr: '', // 必填,生成签名的随机串
  signature: '',// 必填,签名
  jsApiList: [] // 必填,需要使用的JS接口列表
});

  获取第一个参数生成签名的时间戳(其实就是获取当前时间)

// 时间戳
String timestamp = Long.toString((new Date().getTime()) / 1000);

  获取第二个签名随机串(也没啥特别的就是 UUID)

// 随机串
String nonceStr = UUID.randomUUID().toString();

  获取第三个参数签名!!这个比较重要,签名 = 随机串 + ticket + 时间戳 + URL(当前页面),但是随机串和时间戳我们在上边已经获取到了,下边我们只获取 ticket和当前页面的 URL 就好了,最后把他们拼到一起

/** 
   获取 signature 的四个步骤
       1.获取当前页面 URL
       2.获取 access_token 参数
       3.通过 access_token 获取 ticket 参数
       4.把所有参数拼在一起获取 signature 签名 
**/
// 1.url(判断是否有参数如果有参数把参数也拼接上,并且这个路径必须是配置在白名单里边的)
String params = request.getQueryString();
if(StringUtils.isEmpty(params)){
    params="";
}else{
    params="?"+params;
}
String url = "https://www.baidu.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);

// 最后放入 map 中传到页面
Map<String,Object> map = new HashMap<String,Object>();
map.put("appId",appId);
map.put("timestamp",timestamp);
map.put("nonceStr",nonceStr);
map.put("signature",signature);

  定义 AccessToken 实体类并获取 access_tocken 参数(第二步骤)

// AccessToken 实体类
@Data
public class AccessToken {
    // 获取到的凭证  
    private String token;  
    // 凭证有效时间,单位:秒  
    private int expiresIn;    
}
/**
 * 公众平台通用接口工具类
 *
 */
public class AccessTokenAPI {
    
	// 获取微信公众号:access_token的接口地址(GET) 限2000(次/天)
	public final static String access_token_url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET";

	/**
	 * 获取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 (null != jsonObject) {
			try {
				accessToken = new AccessToken();
				accessToken.setToken(jsonObject.getString("access_token"));
				accessToken.setExpiresIn(jsonObject.getInteger("expires_in"));
			} catch (JSONException e) {
				accessToken = null;
				// 获取token失败
			}
		}
		return accessToken;
	}
}

  拼接 signature 签名的工具类(第四步骤)

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);
    // 将排序后的结果拼接成一个字符串
    String content = paramArr[0].concat("&"+paramArr[1]).concat("&"+paramArr[2])
            .concat("&"+paramArr[3]);
    String gensignature = null;
    try {
        MessageDigest md = MessageDigest.getInstance("SHA-1");
        // 对拼接后的字符串进行 sha1 加密
        System.out.println("拼接加密签名:"+content);
        byte[] digest = md.digest(content.getBytes());
        gensignature = byteToStr(digest);
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    }
    // 将 sha1 加密后的字符串与 signature 进行对比
    if (gensignature != null) {
        return gensignature;// 返回signature
    } else {
        return "false";
    }
}

/**
 * 将字节数组转换为十六进制字符串
 *
 * @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;
}

/**
 * 将字节转换为十六进制字符串
 *
 * @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;
}

  第四个 jsApiList 实际上是需要调用的接口名字放进去就好了

完整代码

  这是获取 wx.config 授权验证的完整代码

@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>();
        // 时间戳
        String timestamp = Long.toString((new Date().getTime()) / 1000);
        // 随机串
        String nonceStr = UUID.randomUUID().toString();
        // 获取 access_token
        String access_token = AccessTokenAPI.getAccessToken(appId,appSecret);
        // 根据 tocker 获取 jstl
        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("要加密的参数:"+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);
        // 将排序后的结果拼接成一个字符串
        String content = paramArr[0].concat("&"+paramArr[1]).concat("&"+paramArr[2])
                .concat("&"+paramArr[3]);
        String gensignature = null;
        try {
            MessageDigest md = MessageDigest.getInstance("SHA-1");
            // 对拼接后的字符串进行 sha1 加密
            System.out.println("拼接加密签名:"+content);
            byte[] digest = md.digest(content.getBytes());
            gensignature = byteToStr(digest);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        // 将 sha1 加密后的字符串与 signature 进行对比
        if (gensignature != null) {
            return gensignature;// 返回signature
        } else {
            return "false";
        }
    }

    /**
     * 将字节数组转换为十六进制字符串
     *
     * @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;
    }

    /**
     * 将字节转换为十六进制字符串
     *
     * @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;
    }
}

前端页面实现

  完整的前端界面,就不上传样式文件了,随便写写样式放个图片就 ok 了

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>调用企业微信图像上传接口</title>
  
  <link rel="stylesheet" href="../css/style.css" />
</head>
<body>
  <header class="upload-hedaer">
    <a href="javaScript:history.back(-1)" class="upload-fh"></a>
    <div>上传</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.6.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">
	/** 
		这个地方我们只需要在要使用的页面引用就 OK
	       1.chooseImage:和拍照或从手机相册中选图接口
	       2.getLocalImgData:获取本地图片接口
	**/ 
   wx.config({
       debug: true, // 生产环境需要关闭debug模式
       appId: "[[${appId}]]", // appID = corpID 通过微信服务号/企业微信后台查看
       timestamp: "[[${timestamp}]]", // 生成签名的时间戳
       nonceStr: "[[${nonceStr}]]", // 生成签名的随机字符串
       signature: "[[${signature}]]", // 签名
       jsApiList: [ // 需要调用的JS接口列表
           'chooseImage',
           'getLocalImgData'
       ]
   }