• java 生成js接口签名 页面调用JS-SDK


    如果要使用微信公众平台的网页开发,首先要生成签名,其算法也在官方的wiki说明了,网上也有PHP版本,在这里写一下java的生成版本:

    1.因为保密需要,把关键参数隐去了,但签名与公众号接入差不多,只是参数个数变了,下面是参考代码

    package cn.xdf.wlyy.controller;
    
    import java.security.MessageDigest;
    import java.security.NoSuchAlgorithmException;
    import java.util.Arrays;
    import java.util.Date;
    
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.servlet.ModelAndView;
    
    import cn.xdf.wlyy.util.HttpUtils;
    import cn.xdf.wlyy.util.IdUtils;
    
    import com.alibaba.fastjson.JSONObject;
    
    @Controller
    @RequestMapping(value = "/test")
    public class TestController {
    	
    	private static String jsToken = null;
    
    	private static String byteToStr(byte[] byteArray) {
    		String strDigest = "";
    		for (int i = 0; i < byteArray.length; i++) {
    			strDigest += byteToHexStr(byteArray[i]);
    		}
    		return strDigest;
    	}
    	
    	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;
    	}
    	
    	@RequestMapping(value = "/testpage")
    	public ModelAndView page(ModelAndView mav) {
    		String accessTokenUrl = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET";
    		String accessTokenResult = HttpUtils.get(accessTokenUrl);
    		JSONObject accessJsonObject = JSONObject.parseObject(accessTokenResult);
    		String accessToken = accessJsonObject.getString("access_token");
    		
    		String jsTokenUrl = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi";
    		String jsTokenResult = HttpUtils.get(jsTokenUrl.replace("ACCESS_TOKEN", accessToken));
    		
    		JSONObject jsTokenJsonObject = JSONObject.parseObject(jsTokenResult);
    		
    		if (jsTokenJsonObject != null) {
    			int errcode = jsTokenJsonObject.getInteger("errcode");
    			if (errcode == 0) {
    				jsToken = jsTokenJsonObject.getString("ticket");
    			}
    		}
    		
    		String url = "http://xxx.vicp.cc/wechatserver/test/testpage";//因为要使用微信客户微访问本地环境,这里面使用了花生壳做内网映射
    		String timestamp = String.valueOf(new Date().getTime() / 1000);
    		String noncestr = IdUtils.getId();
    		String jsapi_ticket = jsToken;
    		
    		String str1 = "noncestr=" + noncestr;
    		String str2 = "jsapi_ticket=" + jsapi_ticket;
    		String str3 = "timestamp=" + timestamp;
    		String str4 = "url=" + url;
    		
    		String[] paramArr = new String[] { str1, str2, str3, str4 };
    		Arrays.sort(paramArr);
    
    		// 将排序后的结果拼接成一个字符串
    		String content = paramArr[0].concat("&").concat(paramArr[1]).concat("&").concat(paramArr[2]).concat("&").concat(paramArr[3]);
    		String signature = null;
    		try {
    			MessageDigest md = MessageDigest.getInstance("SHA-1");
    			// 对接后的字符串进行sha1加密
    			byte[] digest = md.digest(content.toString().getBytes());
    			signature = byteToStr(digest);
    		} catch (NoSuchAlgorithmException e) {
    			e.printStackTrace();
    		}
    		
    		/*appId: '', // 必填,公众号的唯一标识
    	    timestamp: , // 必填,生成签名的时间戳
    	    nonceStr: '', // 必填,生成签名的随机串
    	    signature: '',// 必填,签名
    	    jsApiList: [] // 必填,需要使用的JS接口列表
    */		
    		mav.addObject("appId", "wxxxxxxxxxxxxxxxxxxxx");
    		mav.addObject("timestamp", timestamp);
    		mav.addObject("nonceStr", noncestr);
    		mav.addObject("signature", signature);
    		
    		mav.setViewName("testPage");
    		return mav;
    	}
    	
    }
    

    2.而在页面中,是直接访问1中的controller,跳转到这个页面,然后直接把appId/timestamp/nonceStr/signatrue等参数返回给页面,让页面调用,页面如下:

    <!DOCTYPE html>
    <%@ page language="java" contentType="text/html; charset=UTF-8"
    	pageEncoding="UTF-8"%>
    <html lang="en">
    
    <head>
    <meta charset="UTF-8" />
    <meta name="viewport"
    	content="width=device-width, initial-scale=1.0, maximum-scale=1.0">
    <meta name="description" content="description about your site" />
    <meta name="keywords" content="" />
    <meta name="author" content="ZTApps" />
    <script src="<%=basePath%>/static/js/jquery-1.11.2.min.js"></script> 
    <script src="http://res.wx.qq.com/open/js/jweixin-1.2.0.js"></script> 
    <title>测试页面</title>
    </head>
    
    <body>
    
    </body>
    <script>
    	$(function() {
    		var appId = '${appId}';
    		var timestamp = ${timestamp};
    		var nonceStr = '${nonceStr}';
    		var signature = '${signature}';
    		wx.config({
    		    debug : true,
    		    appId : appId,
    		    timestamp : timestamp,
    		    nonceStr : nonceStr,
    		    signature : signature,
    		    jsApiList : ['getLocation']
    		});
    		
    		wx.ready(function(){
    			wx.getLocation({
    				type: 'gcj02', // 默认为wgs84的gps坐标,如果要返回直接给openLocation用的火星坐标,可传入'gcj02'
    				success: function (res) {
    					var latitude = res.latitude; // 纬度,浮点数,范围为90 ~ -90
    					var longitude = res.longitude; // 经度,浮点数,范围为180 ~ -180。
    					var speed = res.speed; // 速度,以米/每秒计
    					var accuracy = res.accuracy; // 位置精度
    					alert("纬度:" + latitude);
    					alert("经度:" + longitude);
    					alert("速度:" + speed);
    					alert("accuracy:" + accuracy);
    				}
    			});
    		});
    		
    	});
    </script>
    </html>

    上面主要是想验证签名这个参数是否生成的正确,并通过调用地址位置的接口wx.getLocation来测试是否获取到了位置。

    (因为对浏览器内置的js定位很苦恼,使用android手机,在提示不允许使用位置后,下次还会有提示消息,而允许后下次就不会再有提示信息了;而用ios只会提示一次,允许就一直允许,不允许就一直不允许了,没有反悔的机会。目前还没有很好的解决方案)

  • 相关阅读:
    flask为blueprint增加error_handler
    solr的moreLikeThis实现“相似数据”功能
    pgsql删除重复记录
    sqlalchemy的不区分大小写比较
    logrotate运行时间指定
    远程桌面剪贴板失效的解决方法
    github上关于campbell数据采集的一些代码。
    python 学习笔记
    guestfs-python 手册
    [KVM][guestfs] 安装 guestfs-python 出错
  • 原文地址:https://www.cnblogs.com/dulinan/p/12033043.html
Copyright © 2020-2023  润新知