微信h5获取用户地址信息

微信h5页面获取用户地址信息(vue+Java)(清风竹语)

前言:

与之前获取用户信息相同,这次获取用户地址信息也是在用户进入该页面之后,通过取得用户经纬度,在调用高德地图的api获得位置信息。

流程:

1.在前端页面引入 微信的sdk
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);
				});
			},
2.后端编码(Java)
1.获取签名
//承接上方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();
    }
2.签名工具类
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;
    }
}

3.得到经纬度,获取地址具体信息(工具类)

来自高德地图的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;
    }

}

4.具体使用
//获取用户地址 getLocation(),摘取小部分代码 查看地址信息
Map stringObjectMap = getLocation(longitude, latitude);
System.out.println(stringObjectMap.toString());
//结果
{address=安徽省合肥市蜀山区三里庵街道水湖路安徽医科大学, province=安徽省, city=合肥市, district=蜀山区}

你可能感兴趣的:(java,html5,vue.js,小程序)