Java 微信JS SDK 入门(网页内获取地理信息)

阅读前,请保证对微信开发有过了解。

1.准备

1.一个微信公众(本文以测试号为例子)

2.微信web开发者工具,官网有下载

2.新建一个jsp

<%@ page language="java" import="java.util.*" pageEncoding="utf-8" %>
<%
    String path = request.getContextPath();
    String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + path + "/";
%>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
    <script src="http://res.wx.qq.com/open/js/jweixin-1.0.0.js"></script>
    <script>
        //用于测试时确保URL与后端的一样,这很重要!!!
        alert("当前URL:"+location.href.split('#')[0]);
        wx.config({
            debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
            appId: '${appId}', // 必填,企业号的唯一标识,此处填写企业号corpid
            timestamp: parseInt("${timestamp}",10), // 必填,生成签名的时间戳
            nonceStr: '${noncestr}', // 必填,生成签名的随机串
            signature: '${signature}',// 必填,签名,见附录1
            jsApiList: ['getLocation'] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2
        });
        wx.ready(function(){
        });

        wx.error(function(res){
        });
    </script>
</head>
<body>
<button id="getBBS" style="width:1000px;height:600px;font-size:150px;" onclick="submitOrderInfoClick();">获取地理位置</button>
</body>
<script type="text/javascript">
    function submitOrderInfoClick(){
        wx.getLocation({
            success: function (res) {
                alert("获取地理位置成功,经纬度为:(" + res.latitude + "," + res.longitude + ")" );
            },
            fail: function(error) {
                AlertUtil.error("获取地理位置失败,请确保开启GPS且允许微信获取您的地理位置!");
            }
        });
    }
</script>
</html>

上面可以看到,前端想要调用js sdk,就需要后台提供下面几个信息

  1. appId 这个不用说了吧
  2. timestamp 时间戳,开发者自己生成
  3. nonceStr 随机字符串,开发者自己生成
  4. signature 签名,需要计算出来,这个才是最重要的

备注一下坑:前端的参数名注意书写规则。前端参数命名以驼峰式命名,后台就以全小写。。。。大公司就不能专业一点吗

 

3.后台Java代码(Spring MVC)

详细的注释代码都有

 @RequestMapping("/wx/jsSDK")
    public String jsSDK(Model model, HttpServletRequest request) {
        //获取jsSDK临时票据ticket
        String ticket = CommonUtil.getJsApiTicket();
        log.info(ticket);
        //计算签名signature
        String noncestr = UUID.randomUUID().toString();//生成一段随机数
        String timestamp = Long.toString(System.currentTimeMillis() / 1000);//生成timestamp
        //获取当前请求url,#前面所有
        String url;
        String queryString = request.getQueryString();//URL参数,即?后的xx=xxx
        if (queryString == null) {
            queryString = "";
        } else {
            queryString = "?" + queryString;
        }

        url = request.getScheme() + "://"
                + request.getServerName() + ":"
                + request.getServerPort()
                + request.getContextPath()
                + request.getServletPath()
                + queryString;
        /*
        注意,无论你的URL是否带参数,都必须判断他是否有参数
        因为有时候微信跳转的时候会在你的URL后面加参数用于统计,
        比如你的URL是 http://域名/项目名/xxx/jsSDK
        跳转的时候微信会在后面加参数,变成 http://域名/项目名/xxx/jsSDK?nsukey=xxxxxxxx
        这样,计算出来的签名就会不正确了,这也是坑之一

        下面几句代码是方便测试用的,为什么?
        以我为例,测试时候URL是http://127.0.0.1:8080/wx/jsSDK
        发布的时候,URL是     http://域名/wx/jsSDK
        发现什么了,端口80自动隐藏了,也就是说发布的时候,是不能把80写进去,不然计算出来的签名会出错
        一句说完,这里的URL与你访问的URL 必须完全一致
        */

        boolean degug = true;
        //如果是正式发布,把“:80” 去掉
        if (degug == false) {
            url = url.replace(":80", "");
        }
        log.info("地址:" + url);


        //把这些信息组合起来,使用SHA1加密,得到 signature
        String str = "jsapi_ticket=" + ticket +
                "&noncestr=" + noncestr +
                "&timestamp=" + timestamp +
                "&url=" + url;
        String signature = SignUtil.SHA1(str).toLowerCase();


        //把信息传到前台
        model.addAttribute("signature", signature);
        model.addAttribute("timestamp", timestamp);
        model.addAttribute("noncestr", noncestr);
        model.addAttribute("appId", wxEnum.APPID.getValue());
        return "jssdk";
    }

上面调用了两个工具的方法

  1. 获取accessToken,这个就不贴出来
  2. 获取ticket的贴出来参考
  3. SHA1加密,这个自己百度
    public static String jsapi_ticket = null;
    public static long time = 0;


    public static String getJsApiTicket() {
        if (jsapi_ticket != null) {
            //ticket有效期7200s,无需在有效时间内重复申请。
            if (((new Date().getTime() - time) / 1000) > 7000) {
                return jsapi_ticket;
            }
        }
        //获取token
        Token token = CommonUtil.getToken(wxEnum.APPID.getValue(), wxEnum.APPSECRET.getValue());
        String accessToken = token.getAccessToken();
        //根据token获取ticket
        String url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi";
        String requestUrl = url.replace("ACCESS_TOKEN", accessToken);
        // 发起GET请求获取凭证
        JSONObject jsonObject = httpsRequest(requestUrl, "GET", null);
        if (null != jsonObject) {
            try {
                jsapi_ticket = jsonObject.getString("ticket");
                time = new Date().getTime();
                return jsapi_ticket;
            } catch (JSONException e) {
                log.error("获取token失败" + jsonObject.getInt("errcode") + jsonObject.getString("errmsg"));
            }
        }
        return null;
    }


	public static JSONObject httpsRequest(String requestUrl, String requestMethod, String outputStr) {
		JSONObject jsonObject = null;
		try {
			// 创建SSLContext对象,并使用我们指定的信任管理器初始化
			TrustManager[] tm = { new MyX509TrustManager() };
			SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
			sslContext.init(null, tm, new java.security.SecureRandom());
			// 从上述SSLContext对象中得到SSLSocketFactory对象
			SSLSocketFactory ssf = sslContext.getSocketFactory();

			URL url = new URL(requestUrl);
			HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
			conn.setSSLSocketFactory(ssf);
			
			conn.setDoOutput(true);
			conn.setDoInput(true);
			conn.setUseCaches(false);
			// 设置请求方式(GET/POST)
			conn.setRequestMethod(requestMethod);

			// 当outputStr不为null时向输出流写数据
			if (null != outputStr) {
				OutputStream outputStream = conn.getOutputStream();
				// 注意编码格式
				outputStream.write(outputStr.getBytes("UTF-8"));
				outputStream.close();
			}

			// 从输入流读取返回内容
			InputStream inputStream = conn.getInputStream();
			InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
			BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
			String str = null;
			StringBuffer buffer = new StringBuffer();
			while ((str = bufferedReader.readLine()) != null) {
				buffer.append(str);
			}

			// 释放资源
			bufferedReader.close();
			inputStreamReader.close();
			inputStream.close();
			inputStream = null;
			conn.disconnect();
			jsonObject = JSONObject.fromObject(buffer.toString());
		} catch (ConnectException ce) {
			log.error("连接超时:{}", ce);
		} catch (Exception e) {
			log.error("https请求异常:{}", e);
		}
		return jsonObject;
	}

开启tomcat,在微信开发工具里测试

看都这个提示,表示代码没问题,还需要到微信公众平台 设置的公众号的JS接口安全域名

为127.0.0.1:8080再次刷新即提示成功

转载于:https://my.oschina.net/yejunxi/blog/721084

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值