知識
不管是網(wǎng)站,軟件還是小程序,都要直接或間接能為您產(chǎn)生價值,我們在追求其視覺表現(xiàn)的同時,更側(cè)重于功能的便捷,營銷的便利,運營的高效,讓網(wǎng)站成為營銷工具,讓軟件能切實提升企業(yè)內(nèi)部管理水平和效率。優(yōu)秀的程序為后期升級提供便捷的支持!
您當前位置>首頁 » 新聞資訊 » 公眾號相關(guān) >
手把手教你使用java對接微信公眾號-獲取地理位置信息
發(fā)表時間:2020-10-19
發(fā)布人:葵宇科技
瀏覽次數(shù):101
公眾號需要定位當前用戶的地址位置,需要通過簽名后返回的數(shù)據(jù),前端將參數(shù)回調(diào)到微信服務(wù)器獲取地理位置信息,官方文檔說明(https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/JS-SDK.html)。
這里會告訴你對接JSSDK使用步驟。
可以看出調(diào)用JSSDK需要后端提供四個參數(shù):
appId: '', // 必填,公眾號的唯一標識
timestamp: , // 必填,生成簽名的時間戳
nonceStr: '', // 必填,生成簽名的隨機串
signature: '',// 必填,簽名
1、編寫后端的簽名接口SysWxUserController
前端的url需要encodeURIComponent),因為頁面一旦分享,微信客戶端會在你的鏈接末尾加入其它參數(shù),如果不是動態(tài)獲取當前鏈接,將導致分享后的頁面簽名失敗。
package com.sx.local.govern.controller;
import com.sx.common.result.RestResponse;
import com.sx.common.result.ResultGenerator;
import com.sx.local.govern.service.SysWxUserService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
/**
* <p>
* 微信用戶信息表 前端控制器
* </p>
*
* @author lst
* @since 2020-08-29
*/
@RestController
@RequestMapping("/wx-user")
@Api(value = "SysWxUserController", tags = "微信用戶")
public class SysWxUserController {
@Autowired
private SysWxUserService sysWxUserService;
/**
* @Description 獲取微信地理位置需要的簽名信息
* @author lst
* @date 2020-9-25 17:34
* @param url 當前網(wǎng)頁的URL,不包含#及其后面部分
* @return com.sx.common.result.RestResponse
*/
@GetMapping(value = "/get-config", produces = "application/json; charset=utf-8")
@ApiOperation(value = "獲取微信地理位置需要的簽名信息", notes = "獲取微信地理位置需要的簽名信息", code = 200, produces = "application/json")
@ApiImplicitParam(paramType = "query", dataType = "string", name = "url",required = true ,value = "當前網(wǎng)頁的URL,不包含#及其后面部分")
public RestResponse getConfig(@RequestParam("url") String url) {
return ResultGenerator.genSuccessResult(sysWxUserService.getConfig(url));
}
}
2、SysWxUserServiceImpl
package com.sx.local.govern.service.impl;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sx.common.config.GlobalConfig;
import com.sx.common.constants.Constant;
import com.sx.common.constants.SymbolConstants;
import com.sx.common.exception.SxException;
import com.sx.common.util.HttpClientUtil;
import com.sx.common.util.RedisUtil;
import com.sx.common.util.StringUtil;
import com.sx.local.govern.constants.WxCommonConstants;
import com.sx.local.govern.entity.SysWxUser;
import com.sx.local.govern.exceptionhandler.GovernExceptionEnum;
import com.sx.local.govern.form.WxUserForm;
import com.sx.local.govern.mapper.SysWxUserMapper;
import com.sx.local.govern.service.SysWxUserService;
import com.sx.local.govern.utils.ShaUtil;
import com.sx.system.constants.SystemCommonConstants;
import com.sx.system.entity.SysArea;
import com.sx.system.exceptionhandler.SysExceptionEnum;
import com.sx.system.mapper.SysAreaMapper;
import com.sx.system.shiro.jwt.JwtUtil;
import com.sx.system.vo.WxUserVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
/**
* <p>
* 微信用戶信息表 服務(wù)實現(xiàn)類
* </p>
*
* @author lst
* @since 2020-08-29
*/
@Service
@Slf4j
public class SysWxUserServiceImpl extends ServiceImpl<SysWxUserMapper, SysWxUser> implements SysWxUserService {
@Autowired
private RedisUtil redisUtil;
/**
* @Description 獲取微信地理位置需要的簽名信息
* 微信 JS 接口簽名校驗工具: http://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=jsapisign
* @author lst
* @date 2020-9-25 17:29
* @param url 當前網(wǎng)頁的URL,不包含#及其后面部分
* @return java.util.Map<java.lang.String,java.lang.Object>
*/
@Override
public Map<String,Object> getConfig(String url){
Map<String,Object> resultMap = new HashMap<String,Object>();
String timeStamp = String.valueOf(ShaUtil.getCurrentTimestamp());
String nonceStr = ShaUtil.generateNonceStr();
String jsapiTicket = getTicket();
String signature = getSign(timeStamp,nonceStr,jsapiTicket,url);
resultMap.put("appId",GlobalConfig.getConfig("wx.appid"));
resultMap.put("timestamp",timeStamp);
resultMap.put("nonceStr",nonceStr);
resultMap.put("signature",signature);
return resultMap;
}
/**
* @Description 獲取簽名
* @author lst
* @date 2020-9-25 17:22
* @param timeStamp 當前時間戳,單位毫秒
* @param nonceStr 獲取隨機字符串
* @param jsapiTicket ticket
* @param url 當前網(wǎng)頁的URL,不包含#及其后面部分
* @return java.lang.String
*/
private static String getSign(String timeStamp,String nonceStr,String jsapiTicket,String url){
String arr[] =new String[] {"jsapi_ticket="+jsapiTicket,"noncestr="+nonceStr,"timestamp="+timeStamp,"url="+url};
//字典序排序
Arrays.sort(arr);
String str = "";
str = arr[0]+"&"+arr[1]+"&"+arr[2]+"&"+arr[3];
log.info("str:{}",str);
String mParms = null;//sha1加密
MessageDigest digest = null;
try {
digest = java.security.MessageDigest.getInstance("SHA");
} catch (NoSuchAlgorithmException e) {
log.error("錯誤信息:{}",e);
throw new SxException(GovernExceptionEnum.PARAM_NOT_EXIST.getCode(),e.getMessage());
}
digest.update(str.getBytes());
byte messageDigest[] = digest.digest();
// Create Hex String
StringBuffer hexString = new StringBuffer();
for (int i = 0; i < messageDigest.length; i++) {
String shaHex = Integer.toHexString(messageDigest[i] & 0xFF);
if (shaHex.length() < 2) {
hexString.append(0);
}
hexString.append(shaHex);
}
mParms = hexString.toString();
log.info("簽名:{}",mParms);
return mParms;
}
/**
* @Description 通過access_token獲取 ticket
* @author lst
* @date 2020-9-25 17:22
* @return java.lang.String
*/
private String getTicket(){
JSONObject jsonObject = (JSONObject) redisUtil.getValue(WxCommonConstants.WX_ACCESS_TOKEN);
Map<String,Object> resultMap = new HashMap<String,Object>();
//access_token 獲取
if(null == jsonObject){
Map<String,Object> params = new HashMap<String,Object>();
String url = WxCommonConstants.GET_ACCESS_TOKEN_URL_BY_BACKSTAGE;
String appId = GlobalConfig.getConfig("wx.appid");
String appSecret = GlobalConfig.getConfig("wx.appsecret");
params.put("appid",appId);
params.put("secret",appSecret);
params.put("grant_type","client_credential");
jsonObject = JSONObject.parseObject(HttpClientUtil.doHttpsGet(url,params));
if(StringUtil.isEmpty(jsonObject.get("access_token"))){
throw new SxException(GovernExceptionEnum.WXUSER_OPENID_NOT_EXIST);
}
Integer expiresIn = (Integer) jsonObject.get("expires_in");
redisUtil.setValue(WxCommonConstants.WX_ACCESS_TOKEN,jsonObject, Long.valueOf(expiresIn));
}
log.info("通過code換取access_token、openID:{}",jsonObject);
//ticket 獲取
String accessToken = (String) jsonObject.get("access_token");
JSONObject jsonTicket = (JSONObject) redisUtil.getValue(WxCommonConstants.GET_TICKET);
if(null == jsonTicket){
Map<String,Object> params = new HashMap<String,Object>();
String url = WxCommonConstants.GET_TICKET_URL;
params.put("access_token",accessToken);
params.put("type","jsapi");
jsonTicket = JSONObject.parseObject(HttpClientUtil.doHttpsGet(url,params));
if(StringUtil.isEmpty(jsonTicket.get("ticket"))){
throw new SxException(GovernExceptionEnum.WXUSER_OPENID_NOT_EXIST);
}
Integer expiresIn = (Integer) jsonTicket.get("expires_in");
redisUtil.setValue(WxCommonConstants.GET_TICKET,jsonTicket,Long.valueOf(expiresIn));
}
log.info("獲取jsonTicket:{}",jsonTicket);
String ticket = (String) jsonTicket.get("ticket");
return ticket;
}
}
3、ShaUtil工具類
package com.sx.local.govern.utils;
import lombok.extern.slf4j.Slf4j;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.UUID;
/**
* @Description: 用SHA1算法驗證Token
* @Author: lst
* @Date 2020-08-18
*/
@Slf4j
public class ShaUtil {
/**
* @Description 用SHA1算法驗證Token
* @author lst
* @date 2020-8-20 11:30
* @param token url相關(guān)的token
* @param timestamp 時間戳
* @param nonce 隨機數(shù)
* @return java.lang.String
*/
public static String getSHA1(String token, String timestamp, String nonce){
String[] arr = new String[] { token, timestamp, nonce };
Arrays.sort(arr);
//TODO 2. 將三個參數(shù)字符串拼接成一個字符串進行sha1加密
StringBuilder content = new StringBuilder();
for (int i = 0; i < arr.length; i++) {
content.append(arr[i]);
}
MessageDigest md = null;
String tmpStr = null;
try {
md = MessageDigest.getInstance("SHA-1");
// 將三個參數(shù)字符串拼接成一個字符串進行sha1加密
byte[] digest = md.digest(content.toString().getBytes());
tmpStr = byteToStr(digest);
} catch (NoSuchAlgorithmException e) {
log.info("錯誤信息:{}",e.getMessage());
}
return tmpStr;
}
/**
* @Description 將字節(jié)數(shù)組轉(zhuǎn)換為十六進制字符串
* @author lst
* @date 2020-8-18 11:56
* @param byteArray
* @return java.lang.String
*/
public static String byteToStr(byte[] byteArray) {
StringBuilder strDigest = new StringBuilder();
for (int i = 0; i < byteArray.length; i++) {
strDigest.append(byteToHexStr(byteArray[i]));
}
return strDigest.toString();
}
/**
* @Description 將字節(jié)轉(zhuǎn)換為十六進制字符串
* @author lst
* @date 2020-8-18 11:57
* @param mByte
* @return java.lang.String
*/
private static String byteToHexStr(byte mByte) {
char[] Digit = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A',
'B', 'C', 'D', 'E', 'F' };
char[] tempArr = new char[2];
tempArr[0] = Digit[(mByte >>> 4) & 0X0F];
tempArr[1] = Digit[mByte & 0X0F];
String s = new String(tempArr);
return s;
}
/**
* @Description 獲取當前時間戳,單位秒
* @author lst
* @date 2020-9-25 16:35
* @return long
*/
public static long getCurrentTimestamp() {
return System.currentTimeMillis()/1000;
}
/**
* @Description 獲取隨機字符串 Nonce Str
* @author lst
* @date 2020-9-25 16:35
* @return java.lang.String
*/
public static String generateNonceStr() {
return UUID.randomUUID().toString().replaceAll("-", "").substring(0, 32);
}
}
4、測試
5、通過微信 JS 接口簽名校驗工具驗證(http://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=jsapisign)
相關(guān)案例查看更多
相關(guān)閱讀
- 網(wǎng)站優(yōu)化哪家好
- 云南網(wǎng)站優(yōu)化公司
- 微信分銷系統(tǒng)
- 云南小程序公司
- 網(wǎng)站上首頁
- web服務(wù)
- 云南小程序開發(fā)制作
- 海報插件
- 云南軟件定制
- 手機網(wǎng)站建設(shè)
- 云南網(wǎng)站建設(shè)公司
- 云南軟件定制公司
- 網(wǎng)站建設(shè)公司地址
- 云南省建設(shè)廳官方網(wǎng)站
- 云南網(wǎng)站建設(shè)首選公司
- web學習路線
- 曲靖小程序開發(fā)
- 云南建設(shè)廳網(wǎng)站
- 昆明網(wǎng)站建設(shè)公司
- 小程序密鑰
- 網(wǎng)絡(luò)公司電話
- 云南網(wǎng)站建設(shè)百度
- 云南網(wǎng)站維護
- 云南網(wǎng)站建設(shè)制作
- 云南網(wǎng)站建設(shè)哪家好
- 云南網(wǎng)站建設(shè)費用
- asp網(wǎng)站
- 日歷組件
- 開發(fā)微信小程序
- 云南網(wǎng)站建設(shè)招商