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开发者工具调试。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

您可能感兴趣的文章:

  • Java微信公众平台开发(15) 微信JSSDK的使用
  • Java微信公众平台开发(14) 微信web开发者工具使用
  • Java微信公众平台开发(12) 微信用户信息的获取
  • Java微信公众平台开发(10) 微信自定义菜单的创建实现
  • Java微信公众平台开发(9) 关键字回复以及客服接口实现
  • Java微信公众平台开发(8) 多媒体消息回复
  • Java微信公众平台开发(7) 公众平台测试帐号的申请
  • Java微信公众平台开发(5) 文本及图文消息回复的实现
  • Java微信公众平台之素材管理
  • Java微信公众平台之群发接口(高级群发)
(0)

相关推荐

  • Java微信公众平台之素材管理

    微信素材管理和群发这块文档对Java很不友好.本文只对新增临时素材,新增永久素材做介绍,其余获取.删除.修改自行补充 公众号经常有需要用到一些临时性的多媒体素材的场景,例如在使用接口特别是发送消息时,对多媒体文件.多媒体消息的获取和调用等操作,是通过media_id来进行的.素材管理接口对所有认证的订阅号和服务号开放. 素材的限制 图片(image): 2M,支持PNG\JPEG\JPG\GIF格式 语音(voice):2M,播放长度不超过60s,支持AMR\MP3格式 视频(video):10

  • Java微信公众平台开发(9) 关键字回复以及客服接口实现

    我们在微信公众号的后台可以发现微信给我们制定了两种模式,一种是开发者模式(也就是我们一直在做的开发),还有一种模式是编辑模式,然而很蛋疼的是有些功能一旦我们切换到开发者模式下就无法使用了,比较典型的就是关键字回复以及服务器无响应的时候返回的[服务器无法响应]等问题 ,这里我给出的解决方案是:①对关键字给出关键字回复的代码实现:②[服务器5s无响应]解决方案是接入多客服,以方便我们的消息处理! (一)关键字自动回复 在前面的文章中我们已经完成对消息回复的分类以及实现,这里说的关键字回复只是对消息回

  • Java微信公众平台开发(7) 公众平台测试帐号的申请

    前面几篇一直都在写一些比较基础接口的使用,在这个过程中一直使用的都是我个人微博认证的一个个人账号,原本准备这篇是写[多媒体消息回复]的,后来主要到我个人账号的接口权限不够,所以在这里插入一篇[公众平台测试帐号的申请]的文章,同时也提醒各位开发者一定要注意在开发过程中需要注意接口权限,以防想当然的写完代码才发现接口不能使用,但是同样的我们也可以先预演接口的功能然后再将其应用到实际中! ①登入到微信公众平台,我们到[开发]-->[开发者工具]-->[公众平台测试账号]--进入: 首次进入可能会需要

  • Java微信公众平台开发(14) 微信web开发者工具使用

    为帮助开发者更方便.更安全地开发和调试基于微信的网页,微信推出了 web 开发者工具.它是一个桌面应用,通过模拟微信客户端的表现,使得开发者可以使用这个工具方便地在 PC 或者 Mac 上进行开发和调试工作.你可以: 使用自己的微信号来调试微信网页授权 调试.检验页面的 JS-SDK 相关功能与权限,模拟大部分 SDK 的输入和输出 使用基于 weinre 的移动调试功能 利用集成的 Chrome DevTools 协助开发 该工具界面主要由几大部分组成,如下图所示: 顶部菜单栏是刷新.后退.选

  • Java微信公众平台之群发接口(高级群发)

    再次吐槽下,微信素材管理和群发这块文档对Java很不友好,此文需要结合我前文和官方文档. 测试号调试群发只需看是否群发消息是否能组装成功,不需要看结果如何(反正不会发送成功的),因为微信还没开放这个功能(估计也不会开放的). 一.群发说明 在公众平台网站上,为订阅号提供了每天一条的群发权限,为服务号提供每月(自然月)4条的群发权限. 1.对于认证订阅号,群发接口每天可成功调用1次,此次群发可选择发送给全部用户或某个标签: 2.对于认证服务号虽然开发者使用高级群发接口的每日调用限制为100次,但是

  • Java微信公众平台开发(10) 微信自定义菜单的创建实现

    自定义菜单这个功能在我们普通的编辑模式下是可以直接在后台编辑的,但是一旦我们进入开发模式之后我们的自定义菜单就需要自己用代码实现,所以对于刚开始接触的人来说可能存在一定的疑惑,这里我说下平时我们在开发模式下常用的两种自定义菜单的实现方式:①不用写实现代码,直接用网页测试工具Post json字符串生成菜单:②就是在我们的开发中用代码实现菜单生成!(参考文档:http://mp.weixin.qq.com/wiki/10/0234e39a2025342c17a7d23595c6b40a.html 

  • Java微信公众平台开发(5) 文本及图文消息回复的实现

    上篇我们说到回复消息可以根据是否需要上传文件到微信服务器可划分为[普通消息]和[多媒体消息],这里我们来讲述普通消息的回复实现,在消息回复中存在一个关键字段[openid],它是微信用户对于公众号的唯一标识,这里不做过多解释后面将给出时间专门来讲解微信生态中的关键字! (一)回复文本消息 在前面我们已经完成了对消息的分类和回复消息实体的建立,这里回复文本消息需要用到的就是我们的TextMessage,我们把回复文本消息在[文本消息]类型中给出回复!在我们做消息回复的时候需要设置消息的接收人ToU

  • Java微信公众平台开发(15) 微信JSSDK的使用

    在前面的文章中有介绍到我们在微信web开发过程中常常用到的 [微信JSSDK中Config配置] ,但是我们在真正的使用中我们不仅仅只是为了配置Config而已,而是要在我们的项目中真正去使用微信JS-SDK给我们带来便捷,那么这里我们就简述如何在微信web开发中使用必要的方法!微信的JS-SDk中为我们提供的方法很多,这里我有一个简单截图如下: 在上图的提供的所有口中我们可以按照接口实现的难易程度分成两个部分: 较易实现:基础接口.分享接口.设备信息接口.地理位置接口.界面操作接口.微信扫一扫

  • Java微信公众平台开发(12) 微信用户信息的获取

    前面的文章有讲到微信的一系列开发文章,包括token获取.菜单创建等,在这一篇将讲述在微信公众平台开发中如何获取微信用户的信息,在上一篇我们有说道微信用户和微信公众账号之间的联系可以通过Openid关联,所以在这里我们就采用openid去获取用户微信信息,并实现一个简单场景应用:当微信新用户关注我们的微信公众平台的时候我们自动回复一篇图文消息,然后在图文消息中标题为:[尊敬的:XXX,你好!],而且在图文消息中的图片就是用户的微信头像,如下图: 有关获取微信用户信息的文档我们可以参照:http:

  • Java微信公众平台开发(8) 多媒体消息回复

    之前我们在做消息回复的时候我们对回复的消息简单做了分类,前面也有讲述如何回复[普通消息类型消息],这里将讲述多媒体消息的回复方法,[多媒体消息]包含回复图片消息/回复语音消息/回复视频消息/回复音乐消息,这里以图片消息的回复为例进行讲解! 还记得之前将消息分类的标准就是一种是不需要上传多媒体资源到腾讯服务器的而另外一种是需要的,所以在这里我们所需要做的第一步就是上传资源到腾讯服务器,这里我们调用[素材管理]接口(后面将会有专门的章节讲述)进行图片的上传,同样的这个接口可以提供我们对语音.视频.音

随机推荐