Java微信公众平台开发之获取地理位置
本部分需要用到微信的JS-SDK,微信JS-SDK是微信公众平台面向网页开发者提供的基于微信内的网页开发工具包。
通过使用微信JS-SDK,网页开发者可借助微信高效地使用拍照、选图、语音、位置等手机系统的能力,同时可以直接使用微信分享、扫一扫、卡券、支付等微信特有的能力,为微信用户提供更优质的网页体验。
一、JS-SDK引入
1.先登录微信公众平台进入“公众号设置”的“功能设置”里填写“JS接口安全域名”,和网页授权一样只是个域名。
2.在需要调用JS接口的页面引入如下JS文件之一
<script src="http://res.wx.qq.com/open/js/jweixin-1.2.0.js"></script>
<script src="https://res.wx.qq.com/open/js/jweixin-1.2.0.js"></script>
二、通过config接口注入权限验证配置
wx.config({
debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
appId: '', // 必填,公众号的唯一标识
timestamp: , // 必填,生成签名的时间戳
nonceStr: '', // 必填,生成签名的随机串
signature: '',// 必填,签名
jsApiList: [] // 必填,需要使用的JS接口列表
});
首先生成这个signature之前需要获取到一个临时票据jsapi_ticket,jsapi_ticket是公众号用于调用微信JS接口的临时票据。正常情况下,jsapi_ticket的有效期为7200秒,通过access_token来获取。由于获取jsapi_ticket的api调用次数非常有限,频繁刷新jsapi_ticket会导致api调用受限,影响自身业务,同样也需要个中控服务器控制刷新。
1、获取临时票据
package com.phil.wechatauth.model.resp; import com.phil.common.result.ResultState; /**
* jsapi_ticket是公众号用于调用微信JS接口的临时票据
* @author phil
* @date 2017年8月21日
*
*/
public class JsapiTicket extends ResultState { /**
*
*/
private static final long serialVersionUID = -357009110782376503L; private String ticket; //jsapi_ticket private String expires_in; public String getTicket() {
return ticket;
} public void setTicket(String ticket) {
this.ticket = ticket;
} public String getExpires_in() {
return expires_in;
} public void setExpires_in(String expires_in) {
this.expires_in = expires_in;
}
}
获取方法
/**
* 获取jsapi_ticket 调用微信JS接口的临时票据
* @return
*/
public String getTicket(String accessToken) {
JsapiTicket jsapiTicket = null;
Map<String,String> params = new TreeMap<String,String>();
params.put("access_token",accessToken);
params.put("type", "jsapi");
String result = HttpReqUtil.HttpDefaultExecute(HttpReqUtil.GET_METHOD, WechatConfig.GET_TICKET_URL, params,"");
if(StringUtils.isNotBlank(result)){
jsapiTicket = JsonUtil.fromJson(result, JsapiTicket.class);
}
if(jsapiTicket.getErrcode()==0){
return jsapiTicket.getTicket();
}
return null;
}
2、生成签名并返回参数
signature生成规则如下:参与签名的字段包括noncestr(随机字符串), 有效的jsapi_ticket, timestamp(时间戳), url(当前网页的URL,不包含#及其后面部分) 。对所有待签名参数按照字段名的ASCII 码从小到大排序(字典序)后,使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串string1。这里需要注意的是所有参数名均为小写字符。对string1作sha1加密,字段名和字段值都采用原始值,不进行URL 转义。
string1示例如下
jsapi_ticket=sM4AOVdWfPE4DxkXGEs8VMCPGGVi4C3VM0P37wVUCFvkVAy_90u5h9nbSlYy3-Sl-HhTdfl2fzFy1AOcHKP7qg&noncestr=Wm3WZYTPz0wzccnW×tamp=1414587457&url=http://mp.weixin.qq.com?params=value
这里有个坑,页面是nonceStr,但是签名的字段是noncestr,注意大小写
简单封装下JS-SDK config配置信息
package com.phil.wechatauth.model.resp; /**
* JS-SDK的页面配置信息
* @author phil
* @date 2017年8月22日
*
*/
public class JsWechatConfig { private String appId; private long timestamp; private String noncestr; private String signature; public String getAppId() {
return appId;
} public void setAppId(String appId) {
this.appId = appId;
} public long getTimestamp() {
return timestamp;
} public void setTimestamp(long timestamp) {
this.timestamp = timestamp;
} public String getNoncestr() {
return noncestr;
} public void setNoncestr(String noncestr) {
this.noncestr = noncestr;
} public String getSignature() {
return signature;
} public void setSignature(String signature) {
this.signature = signature;
}
}
添加配置信息到页面
/**
*
*/
package com.phil.wechatauth.controller; import java.util.SortedMap;
import java.util.TreeMap; import javax.servlet.http.HttpServletRequest; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping; import com.phil.common.config.SystemConfig;
import com.phil.common.config.WechatConfig;
import com.phil.common.util.DateTimeUtil;
import com.phil.common.util.PayUtil;
import com.phil.common.util.SignatureUtil;
import com.phil.wechatauth.model.resp.JsWechatConfig;
import com.phil.wechatauth.service.WechatAuthService; /**
* JS-SDK
* @author phil
* @date 2017年8月21日
*
*/
@Controller
@RequestMapping("/auth")
public class WechatAuthController { @Autowired
private WechatAuthService wechatAuthService; /**
* 获取地理位置
* @param request
* @return
* @throws Exception
*/
@RequestMapping("/getLocation")
public String getLocation(HttpServletRequest request) throws Exception{
JsWechatConfig jsWechatConfig = new JsWechatConfig();
jsWechatConfig.setAppId(WechatConfig.APP_ID);
jsWechatConfig.setTimestamp(DateTimeUtil.currentTime());
jsWechatConfig.setNoncestr(PayUtil.createNonceStr());
SortedMap<Object,Object> map = new TreeMap<Object,Object>();
map.put("jsapi_ticket", wechatAuthService.getTicket(wechatAuthService.findlastestToken()));
map.put("noncestr", jsWechatConfig.getNoncestr());
map.put("timestamp", jsWechatConfig.getTimestamp());
map.put("url", request.getRequestURL().toString());
String signature = SignatureUtil.createSha1Sign(map, null, SystemConfig.CHARACTER_ENCODING);
jsWechatConfig.setSignature(signature);
request.setAttribute("jsWechatConfig", jsWechatConfig);
return "wechatauth/getLocation";
}
}
签名方法
/**
* 通过Map<SortedMap,Object>中的所有元素参与签名
*
* @param map 待参与签名的map集合
* @params apikey apikey中 如果为空则不参与签名,如果不为空则参与签名
* @return
*/
public static String createSha1Sign(SortedMap<Object, Object> map, String apiKey, String characterEncoding) {
String result = notSignParams(map, apiKey);
MessageDigest md = null;
try {
md = MessageDigest.getInstance("SHA-1");
byte[] digest = md.digest(result.getBytes());
result = byteToStr(digest);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return result;
}
其他的签名方法点击查看
三、通过ready接口处理成功验证
以上执行完成,进入的完整的页面
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>获取地理位置</title>
<!-- 微信 js-sdk -->
<script src="http://res.wx.qq.com/open/js/jweixin-1.2.0.js"></script>
<link rel="stylesheet" href="http://cdn.bootcss.com/bootstrap/3.3.5/css/bootstrap.min.css">
<script src="http://cdn.bootcss.com/jquery/1.11.3/jquery.min.js"></script>
</head>
<body>
<br>
<div class="container">
<div class="form-group">
<label for="firstname" class="col-sm-2 control-label">地址:</label>
<div class="col-sm-10" id="item-ifo">
<input type="text" value="" class="form-control"
name="location.address" id="address" placeholder="正在获取地理位置" tabindex="1" autocomplete="off" />
<div class="i-name ico" id="i-name"></div>
</div>
</div>
</div> </body>
<script type="text/javascript">
wx.config({
debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
appId: '${jsWechatConfig.appId}', // 必填,公众号的唯一标识
timestamp: '${jsWechatConfig.timestamp}' , // 必填,生成签名的时间戳
nonceStr: '${jsWechatConfig.noncestr}', // 必填,生成签名的随机串
signature: '${jsWechatConfig.signature}',// 必填,签名,见附录1
jsApiList: [ 'checkJsApi', 'openLocation', 'getLocation'] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2
}); wx.checkJsApi({
jsApiList: ['getLocation'], // 需要检测的JS接口列表,所有JS接口列表见附录2,
success: function(res) {
if (res.checkResult.getLocation == false) {
alert('你的微信版本太低,不支持微信JS接口,请升级到最新的微信版本!');
return;
}
}
});
var latitude;
var longitude;
var speed;
var accuracy;
wx.ready(function(){
// config信息验证后会执行ready方法,所有接口调用都必须在config接口获得结果之后,config是一个客户端的异步操作,所以如果需要在页面加载时就调用相关接口,则须把相关接口放在ready函数中调用来确保正确执行。对于用户触发时才调用的接口,则可以直接调用,不需要放在ready函数中。
wx.getLocation({
success : function(res) {
latitude = res.latitude; // 纬度,浮点数,范围为90 ~ -90
longitude = res.longitude; // 经度,浮点数,范围为180 ~ -180。
speed = res.speed; // 速度,以米/每秒计
accuracy = res.accuracy; // 位置精度
alert(latitude);
alert(accuracy);
},
cancel : function(res) {
alert('未能获取地理位置');
}
});
}); wx.error(function(res){
// config信息验证失败会执行error函数,如签名过期导致验证失败,具体错误信息可以打开config的debug模式查看,也可以在返回的res参数中查看,对于SPA可以在这里更新签名。
alert("验证出错");
});
</script>
</html>
可以通过微信官方提供的微信web开发者工具调试,如果提示无效的签名的话检查下签名字段是否是小写
工具类我已经上传到Github,点击参考
Java微信公众平台开发之获取地理位置的更多相关文章
- Java微信公众平台开发_02_启用服务器配置
源码将在晚上上传到 github 一.准备阶段 需要准备事项: 1.一个能在公网上访问的项目: 见:[ Java微信公众平台开发_01_本地服务器映射外网 ] 2.一个微信公众平台账号: 去注册: ...
- Java微信公众平台开发_07_JSSDK图片上传
一.本节要点 1.获取jsapi_ticket //2.获取getJsapiTicket的接口地址,有效期为7200秒 private static final String GET_JSAPITIC ...
- Java微信公众平台开发--番外篇,对GlobalConstants文件的补充
转自:http://www.cuiyongzhi.com/post/63.html 之前发过一个[微信开发]系列性的文章,也引来了不少朋友观看和点评交流,可能我在写文章时有所疏忽,对部分文件给出的不是 ...
- 微信公众平台开发-access_token获取及应用(含源码)
微信公众平台开发-access_token获取及应用(含源码)作者: 孟祥磊-<微信公众平台开发实例教程> 很多系统中都有access_token参数,对于微信公众平台的access_to ...
- Java微信公众平台开发【番外篇】(七)--公众平台测试帐号的申请
转自:http://www.cuiyongzhi.com/post/45.html 前面几篇一直都在写一些比较基础接口的使用,在这个过程中一直使用的都是我个人微博认证的一个个人账号,原本准备这篇是写[ ...
- 微信公众平台开发2-access_token获取及应用(含源码)
微信公众平台开发-access_token获取及应用(含源码) 很多系统中都有access_token参数,对于微信公众平台的access_token参数,微信服务器判断该公众平台所拥有的权限,允许或 ...
- Java微信公众平台开发(十二)--微信用户信息的获取
转自:http://www.cuiyongzhi.com/post/56.html 前面的文章有讲到微信的一系列开发文章,包括token获取.菜单创建等,在这一篇将讲述在微信公众平台开发中如何获取微信 ...
- Java微信公众平台开发(十)--微信用户信息的获取
前面的文章有讲到微信的一系列开发文章,包括token获取.菜单创建等,在这一篇将讲述在微信公众平台开发中如何获取微信用户的信息,在上一篇我们有说道微信用户和微信公众账号之间的联系可以通过Openid关 ...
- ***微信公众平台开发: 获取用户基本信息+OAuth2.0网页授权
本文介绍如何获得微信公众平台关注用户的基本信息,包括昵称.头像.性别.国家.省份.城市.语言.本文的方法将囊括订阅号和服务号以及自定义菜单各种场景,无论是否有高级接口权限,都有办法来获得用户基本信息, ...
随机推荐
- HTML5+CSS3静态页面项目-BusinessTheme的总结
因为期末考试.调整心态等等的种种原因,距离上一次的项目练习已经过了很久了,今天终于有时间继续练习HTML5+CSS3的页面架构和设计稿还原.设计图很长,整个页面分为了好几个区域,所以就不放完整的设计图 ...
- 构建混合应用方式之 - Azure混合连接
前面介绍了通过WCF中继构建混合应用的方式,由于对WCF的依赖,使得其使用有一定的局限性,基本上只适用于本地服务是WCF的.NET应用.而混合连接则弥补了这一块的缺陷,除了支持原有WCF中继的功能之外 ...
- rang enumerate
叨逼叨: 小知识点 rang enumerate # 1. 请输出1-10# 2.7: 立即生成所有数字# range(1,11) # 生成 1,23,,4,56.10# 3.x: 不会立即生成,只有 ...
- one plus 1(一加1)刷 kali nethunter 教程
刚刚入手的一加1,刷成了h2os再进行的本次刷机. 用到以下资源: 链接:http://pan.baidu.com/s/1o7S0xzs 密码:2gvm 好了,开始正题,如果你的系统不是H2OS建议先 ...
- 或许你不知道的10条SQL技巧(转自58沈剑原创)
这几天在写索引,想到一些有意思的TIPS,希望大家有收获. 一.一些常见的SQL实践 (1)负向条件查询不能使用索引 select * from order where status!=0 and s ...
- jenkins - ssh Server Groups Center
- 平方根的C语言实现(一)
曾经做一个硬件成本极度控制的项目,因为硬件成本极低,并且还需要实现较高的精度测量,过程中也自己用C语言实现了正弦.余弦.反正切.平方根等函数. 以下,无论是在我的实际项目中还是本地的计算机系统,int ...
- 决策树(C4.5)原理
决策树c4.5算法是在决策树ID3上面演变而来. 在ID3中: 信息增益 按属性A划分数据集S的信息增益Gain(S,A)为样本集S的熵减去按属性A划分S后的样本子集的熵,即 在此基础上,C4.5计算 ...
- 函数响应式编程及ReactiveObjC学习笔记 (四)
今天我们继续看其他的类别 UIImagePickerController+RACSignalSupport.h #import <UIKit/UIKit.h> @class RACDele ...
- maven单元测试设置代理
背景 环境需要设置代理才能够访问外部网络,如果只是运行java程序来访问网络,我们可以通过java -jar test.jar -DproxyHost=proxy_ip -DproxyPort=pro ...