import wx from "weixin-js-sdk";
//引入之前,记得再 ui目录下 执行npm i weixin-js-sdk命令
因为使用h5页面获取用户地址信息,需要使用微信已经设计好的方法模板。
下方为设计在method方法中的获取地址方法
建议了解方法调用思路,后再C+V
为了方便,下方代码块,有直接写的代码介绍
//下方的参数分别介绍
//timestamp ,noncestr,signature是必须的 如果signature错误,是无法获得地址信息的,getAddressParent()有具体 //介绍:注:三个参数需要后台进行编码设置
//jsApiList:[] 记录的是要调用的方法
getAddress(timestamp,noncestr,signature){
console.log("进入方法getAddress")
wx.config({
beta : true, // 开启内测接口调用,注入wx.invoke方法
debug : false, // 开启调试模式
appId : 'wx3e517dbdbfe8e497', // 第三方app唯一标识
timestamp : timestamp, // 生成签名的时间戳
nonceStr : noncestr, // 生成签名的随机串
signature : signature,// 签名
jsApiList : [
//添加使用的函数 ---这里的函数调用微信有说明
'checkJsApi', 'getLocation' ],
//'checkJsApi', 'openLocation', 'getLocation'
});
wx.checkJsApi({
jsApiList : [ 'getLocation' ],
success : function(res) {
console.log("进入方法checkJsApi")
if (res.checkResult.getLocation == false) {
alert('你的微信版本太低,不支持微信JS接口,请升级到最新的微信版本!');
return;
}
}
});
var code=code;
var latitude;
var longitude;
var speed;
var accuracy;
//ready权限验证 --正确就得到微信经纬度
console.log("是不是出在验证错误上")
wx.ready(function() {
// wx.invoke('getLocation', 'openLocation', {}, function(res) {
// // alert(res.err_msg + "唯一");
// });
wx.getLocation({
success : function(res) {
var _self = this;
latitude = res.latitude; // 纬度,浮点数,范围为90 ~ -90
longitude = res.longitude; // 经度,浮点数,范围为180 ~ -180。
speed = res.speed; // 速度,以米/每秒计
accuracy = res.accuracy; // 位置精度
console.log("纬度,浮点数,范围为90 ~ -90",longitude)
//下方为个人业务代码可随意(有情提示,尽量不要在这里使用外界方法:如直接getCode(),应为你 //已经在微信sdk设计的方法中,直接使用可能获取不到外界方法对象,可以直接将业务代码写在里面,或者将外界对象引入)
//可以调用后端方法传递 latitude维度 longitude精度 获得具体信息 如:某某省 某某市 某某区(某某县)
},
cancel : function(res) {
alert('用户拒绝授权获取地理位置');
}
});
});
wx.error(function(res) {
alert(Json.toString(res) + "验证出错");
});
},
//得到地址信息
//signature(签名) 是决定能否得到经纬度的关键
getAddressParent(){
//当前页面地址信息
let url = window.location.href.split('#')[0];
//引入部对象
var _self = this;
//encodeURIComponent()(重)对url地址进行编码,后台需要进行解码。如果url错误,通常signature也会错误,比 //较常见的是invalid signature/invalid url domain /63002错误。微信文档给出了6种情况。如果出现可以依 //依对比
//这里给出文档地址:https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/JS-SDK.html
//详情可见 附录5
//下方可用Ajax向后台传递参数,方法自定义;但要获取timestamp,noncestr,signature三个参数,并调用上方方法
Api.methods.getAddressAuth(encodeURIComponent(url)).then(function(res){
_self.getAddress(res.data.timestamp,res.data.noncestr,res.data.signature);
});
},
//承接上方getAddressParent()的方法
/**
* @method getAddress
* @author 逐月而行
* @version 1.0
* @description 获取签名
* @param url 前端页面
* @param response
* @return void
* @date 2021/3/18 13:39
*/
@ApiOperation(value = "获取签名")
@GetMapping(value = "/getAddress")
public void getAddress(@RequestParam("url") String url,HttpServletResponse response) throws IOException {
//获取请求地址的token
//获取 noncestr
String noncestr = UUID.randomUUID().toString();
//获取 timestamp 编码
String timestamp = Long.toString(System.currentTimeMillis() / 1000);
//获取 signature 后台解码:URLDecoder.decode(url, "UTF-8") //getSignature()方法写在下方工具类中
String signature = getSignature(noncestr, timestamp, URLDecoder.decode(url, "UTF-8"));
//下方为瞎写的向前端传递数据方法,大佬们随意
ModelMap modelMap = new ModelMap();
modelMap.addAttribute("noncestr", noncestr);
modelMap.addAttribute("timestamp", timestamp);
modelMap.addAttribute("signature", signature);
modelMap.addAttribute("code", code);
PrintWriter writer = response.getWriter();
writer.print(JSONObject.toJSON(modelMap));
writer.flush();
writer.close();
}
package co.yixiang.modules.shop.config;
import net.sf.json.JSONObject;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.boot.web.servlet.server.Session;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.net.HttpURLConnection;
/**
* @author 逐月而行
* @version 1.0
* @date 2021/3/15 18:08
**/
public class WxConstant {
/**
* @author 逐月而行
* @description //正式版位置
* @date 9:18 2021/3/18
* @param SERVICE_APPID 微信 appid
* @return SERVICE_APPID
**/
//public static final String SERVICE_APPID = "wx51f761*********";
/**
* @author 逐月而行
* @description //正式版位置
* @date 9:18 2021/3/18
* @param SERVICE_APPSECRET 微信 appsecret
* @return SERVICE_APPSECRET
**/
//public static final String SERVICE_APPSECRET = "51443df29011e*************";
/**
* @author 逐月而行
* @description //测试版
* @date 9:18 2021/3/18
* @param SERVICE_APPID 微信 appid
* @return SERVICE_APPID
**/
public static final String SERVICE_APPID = "w****************";
/**
* @author 逐月而行
* @description //测试版
* @date 9:18 2021/3/18
* @param SERVICE_APPSECRET 微信 appsecret
* @return SERVICE_APPSECRET
**/
public static final String SERVICE_APPSECRET = "de795*****************";
//上方数据appid和appsecret可 去微信测试账号页面获取
/**
* @method SHA1
* @author 逐月而行
* @version 1.0
* @description SHA1 加密
* @param str
* @return java.lang.String
* @date 2021/3/18 11:06
*/
public static String SHA1(String str) {
//简单来说,下方代码是对最后一次signature的加工方法,微信文档要求对signature进行一次SHA—1编码
try {
//如果是SHA加密只需要将"SHA-1"改成"SHA"即可
MessageDigest digest = java.security.MessageDigest
.getInstance("SHA-1");
digest.update(str.getBytes());
byte messageDigest[] = digest.digest();
// Create Hex String
StringBuffer hexStr = new StringBuffer();
// 字节数组转换为 十六进制 数
for (int i = 0; i < messageDigest.length; i++) {
String shaHex = Integer.toHexString(messageDigest[i] & 0xFF);
if (shaHex.length() < 2) {
hexStr.append(0);
}
hexStr.append(shaHex);
}
return hexStr.toString();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return null;
}
/**
* @method getSignature
* @author 逐月而行
* @version 1.0
* @description 获取签名 signature
* @param noncestr
* @param timestamp
* @param url
* @return java.lang.String
* @date 2021/3/18 13:53
*/
public static String getSignature(String noncestr, String timestamp, String url) {
//之前调用的方法,给出signature的最后答案
StringBuffer str1 = new StringBuffer();
String jsapi_ticket = getTicket();
System.out.println("jsapi_ticket" + jsapi_ticket);
str1.append("jsapi_ticket=" + jsapi_ticket);
str1.append("&noncestr=" + noncestr);
str1.append("×tamp=" + timestamp);
str1.append("&url=" + url);
return DigestUtils.shaHex(str1.toString());
}
/**
* @method getTicket
* @author 逐月而行
* @version 1.0
* @description 获取 tiket
* @param
* @return java.lang.String
* @date 2021/3/18 11:07
*/
public static String getTicket() {
//相对上方比较麻烦,这边要调用api接口,获得微信的jsapi_ticket(tiket)信息,是组成signature的重要元素之一
//得到getToken的前提之一,得到微信的token ,由下方的getToken()方法提供
String jsapi_ticket = "";
BufferedReader in = null;
try {
String res = "";
URL url = new URL("https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=" + getToken() + "&type=jsapi");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setDoOutput(true);
conn.setRequestMethod("GET");
in = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8"));
String line;
while ((line = in.readLine()) != null) {
res += line;
}
in.close();
JSONObject jo = JSONObject.fromObject(res);
System.out.println("jsapi_ticket=======");
System.out.println(jo);
jsapi_ticket = jo.getString("ticket");
System.out.println("jsapi_ticket==" + jsapi_ticket);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (in != null) {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return jsapi_ticket;
}
/**
* @method getToken
* @author 逐月而行
* @version 1.0
* @description 获取用户的地址的 token,不能与个人信息的混用:微信提供了两个获取token的接口,这个不需要code
* @param
* @return java.lang.String
* @date 2021/3/18 11:05
*/
public static String getToken() {
String token = "";
BufferedReader in = null;
try {
String res = "";
URL url = new URL("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + SERVICE_APPID + "&secret=" + SERVICE_APPSECRET);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setDoOutput(true);
conn.setRequestMethod("GET");
in = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8"));
String line;
while ((line = in.readLine()) != null) {
res += line;
}
in.close();
JSONObject jo = JSONObject.fromObject(res);
token = jo.getString("access_token");
System.out.println("token==" + token);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (in != null) {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return token;
}
/**
* @method getTokenAuth
* @author 逐月而行
* @version 1.0
* @description 用户信息的token 微信有两种token 混用会出现40001错误
* @param code
* @return com.alibaba.fastjson.JSONObject
* @date 2021/3/18 10:54
*/
public static com.alibaba.fastjson.JSONObject getTokenAuth(String code) {
//为了获得用户个人信息的封装方法,提供另一种token和openId,只是获取地址,不用使用
String urlToken = "https://api.weixin.qq.com/sns/oauth2/access_token";
String accessTokenObj = HttpUtil.sendGet(urlToken, "appid=" + WxConstant.SERVICE_APPID + "&secret="
+ WxConstant.SERVICE_APPSECRET + "&code=" + code + "&grant_type=authorization_code");
com.alibaba.fastjson.JSONObject jsonToken = com.alibaba.fastjson.JSONObject.parseObject(accessTokenObj);
return jsonToken;
}
}
来自高德地图的api接口
package co.yixiang.modules.shop.config;
import co.yixiang.utils.StringUtils;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
/**
* @Author: zhuqiang
* @Description: 定位工具类
* @Date: 2019-11-14 17:08
*/
public class LocationUtil {
/**
* @Author: zhuqiang
* @Description: 经纬度偏转
* @Date: 2019-11-14 17:11
*/
public static Map locationConvert(String lng, String lat) {
Map result = new HashMap();
BufferedReader in = null;
try {
String res = "";
URL url = new URL("https://restapi.amap.com/v3/assistant/coordinate/convert?locations=" + lng + "," + lat + "&coordsys=gps&output=JSON&key=9a6c1f0eff2e5aa91989ca9d4c21e262");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setDoOutput(true);
conn.setRequestMethod("GET");
in = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8"));
String line;
while ((line = in.readLine()) != null) {
res += line;
}
in.close();
JSONObject jo = JSONObject.fromObject(res);
if ("1".equals(jo.getString("status"))) {
lng = jo.getString("locations").split(",")[0];
lat = jo.getString("locations").split(",")[1];
result.put("lng", lng);
result.put("lat", lat);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (in != null) {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return result;
}
/**
* @Author: zhuqiang
* @Description: 获取位置 高德地图api
* @Date: 2019-11-14 17:11
*/
public static Map getLocation(String lng, String lat) {
Map point = locationConvert(lng, lat);
if (point == null) {
return null;
}
Map result = new HashMap();
result.put("province", null);
result.put("city", null);
result.put("district", null);
result.put("address", null);
lng = String.valueOf(point.get("lng"));
lat = String.valueOf(point.get("lat"));
BufferedReader in = null;
try {
String res = "";
URL url = new URL("https://restapi.amap.com/v3/geocode/regeo?location=" + lng + "," + lat + "&key=9a6c1f0eff2e5aa91989ca9d4c21e262");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setDoOutput(true);
conn.setRequestMethod("GET");
in = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8"));
String line;
while ((line = in.readLine()) != null) {
res += line;
}
in.close();
JSONObject jo = JSONObject.fromObject(res);
if ("1".equals(jo.getString("status"))) {
JSONObject comp = jo.getJSONObject("regeocode").getJSONObject("addressComponent");
String province = comp.getString("province");
String city = comp.getString("city");
String district = comp.getString("district");
String address = jo.getJSONObject("regeocode").getString("formatted_address");
if (StringUtils.isEmpty(address)) {
JSONArray areas = comp.getJSONArray("businessAreas");
if (areas.size() > 0) {
address = province + city + district + JSONObject.fromObject(areas.get(0)).getString("name");
}
}
result.put("province", province);
result.put("city", city);
result.put("district", district);
result.put("address", address);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (in != null) {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return result;
}
}
//获取用户地址 getLocation(),摘取小部分代码 查看地址信息
Map stringObjectMap = getLocation(longitude, latitude);
System.out.println(stringObjectMap.toString());
//结果
{address=安徽省合肥市蜀山区三里庵街道水湖路安徽医科大学, province=安徽省, city=合肥市, district=蜀山区}