調用微信的掃一掃功能詳解說明---(java 排坑版)


最近碰到了這么一個需求,說是在前端頁面調用手機本地的相機,掃描二維碼這么一個需求,對於我一個后端來說,

這實在是難,難於上青天,但是決不能說一個不字.我說可以使用微信的掃碼工具嗎,這樣可以方便一點,...(起碼有個思路)

看着微信文檔,一步一步坑下去.不對,是走下去.

這里我們用測試是公眾號,方便測試.

首先配置自己的appID和appsecret,這里的測試帳號直接就給出了

image

第二步: 驗證服務器,這個很簡單,按照文檔的規則驗證就好了

image

 

第三步: 直接使用二級域名,不能添加http://前綴,或者是/XXX你自己寫的接口(親測)

image

這里還有個問題就是下載一個XXXXX.txt文件放在項目的根目錄下,這個txt文件在公眾號里面設置js安全域名下面可以下載

第四步: 生成微信簽名,這個很坑,要小心生成,這里面我使用的是google的guava做緩存,結合網上大佬的一個案例,僅限參考

 

public static Map<String, Object> sign(String url) throws Exception {
String ticket = getTicketToken(WeChatConstant.TICKET_TOKEN);
Map<String, Object> ret = new HashMap<String, Object>();
String nonce_str = create_nonce_str();
String timestamp = create_timestamp();
String string1;
String signature = "";
//注意這里參數名必須全部小寫,且必須有序
string1 = "jsapi_ticket=" + ticket +"&noncestr=" + nonce_str +"&timestamp=" + timestamp +"&url=" + url;

System.out.println(string1);
try{
MessageDigest crypt = MessageDigest.getInstance("SHA-1");
crypt.reset();
crypt.update(string1.getBytes("UTF-8"));
signature = byteToHex(crypt.digest());
System.out.println(signature+"=====================");
}catch (NoSuchAlgorithmException e){
e.printStackTrace();
}catch (UnsupportedEncodingException e)
{
e.printStackTrace();
}
ret.put("url", url);
ret.put("nonceStr", nonce_str);
ret.put("timestamp", timestamp);
ret.put("signature", signature);
ret.put("jsapi_ticket", ticket);
ret.put("appId", WeChatConstant.APPID);
return ret;
}
/**
* 緩存其accessToken 和 ticketToken 的值
*
* @param key
* @return
* @throws Exception
*/
public static String getTicketToken(String key) throws Exception{
if (Objects.isNull(cache) || getCacheAccessToken(key).equals(WeChatConstant.TICKET_TOKEN)){
Gson gson = new Gson();
cache = CacheBuilder.newBuilder().expireAfterWrite(7100,TimeUnit.SECONDS).build();
String accessToken = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid="+WeChatConstant.APPID +"&secret="+WeChatConstant.SECRET;
String httpResult = getHttpResult(accessToken);
AccessToken aT = gson.fromJson(httpResult, AccessToken.class);
String signUrl = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token="+aT.getAccess_token()+"&type=jsapi";
String resultSign = getHttpResult(signUrl);
TicketToken ticket = gson.fromJson(resultSign, TicketToken.class);
cache.put(WeChatConstant.TICKET_TOKEN,ticket.getTicket());
return ticket.getTicket();
}else{
return getCacheAccessToken(key);
}
}

/**
* token失效,返回key值
*
* @param key
* @return
* @throws ExecutionException
*/
private static String getCacheAccessToken(String key) throws ExecutionException {
return cache.get(key, () -> {
return key;
});
}

/**
* 隨機加密
* @param hash
* @return
*/
private static String byteToHex(final byte[] hash) {
Formatter formatter = new Formatter();
for (byte b : hash)
{
formatter.format("%02x", b);
}
String result = formatter.toString();
formatter.close();
return result;
}
/**
* 獲取訪問地址鏈接返回值
*/
private static String getHttpResult(String url) {
String result = "";
HttpGet httpRequest = new HttpGet(url);
try {
HttpResponse httpResponse = HttpClients.createDefault().execute(httpRequest);
if (httpResponse.getStatusLine().getStatusCode() == 200) {
result = EntityUtils.toString(httpResponse.getEntity());
}
} catch (ClientProtocolException e) {
e.printStackTrace();
result = e.getMessage().toString();
} catch (IOException e) {
e.printStackTrace();
result = e.getMessage().toString();
}
return result;
}
/**
* 產生隨機串--由程序自己隨機產生
* @return
*/
private static String create_nonce_str() {
return UUID.randomUUID().toString();
}
/**
* 由程序自己獲取當前時間
* @return
*/
private static String create_timestamp() {
return Long.toString(System.currentTimeMillis() / 1000);
}

第五步:返回數據給前端校驗

/**
* 調用掃一掃 驗證用戶信息
*
* @param request
* @return
*/
@GetMapping("/signature")
public WeChatEntity signature(HttpServletRequest request) throws Exception {
Map<String, Object> resMap = new HashMap<String, Object>();
resMap = SignatureUtil.sign(request.getRequestURL().);
request.setAttribute("nonceStr", resMap.get("nonceStr"));
request.setAttribute("timestamp", resMap.get("timestamp"));
request.setAttribute("signature", resMap.get("signature"));
request.setAttribute("appId", resMap.get("appId"));
request.setAttribute("url", resMap.get("url"));
request.setAttribute("jsapi_ticket",resMap.get("jsapi_ticket"));
WeChatEntity weChatEntity = new WeChatEntity(
resMap.get("appId").toString(),
resMap.get("timestamp").toString(),
resMap.get("nonceStr").toString(),
resMap.get("signature").toString());
return weChatEntity;
}

這里有個坑的地方就是url的設定,這是你請求當前頁面的url,可以在前端使用

location.href.split('#')[0]打印出來.看看是否符合.

 
至此后端程序告一段落,下面就是前端程序了

1.導入依賴

<script type="text/javascript" src="http://res.wx.qq.com/open/js/jweixin-1.0.0.js"></script>
<script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
 

html代碼:

<input type="button" value="掃一掃" id="scanQRCode">
 

js代碼:

$(function() {
$.get("/signature", function(data){
alert(location.href.split('#')[0]);
// alert(data.appId
// +"======"+ data.timestamp
// +"======"+data.nonceStr
// +"======"+data.signature);
//上面是查看傳來的數據是否符合要求
wx.config({
// 開啟調試模式,調用的所有api的返回值會在客戶端alert出來,若要查看傳入的參數,可以在pc端打開,參數信息會通過log打出,僅在pc端時才會打印。
debug: false,
// 必填,公眾號的唯一標識
appId: data.appId,
// 必填,生成簽名的時間戳
timestamp: "" + data.timestamp,
// 必填,生成簽名的隨機串
nonceStr: data.nonceStr,
// 必填,簽名
signature: data.signature,
// 必填,需要使用的JS接口列表
jsApiList: ['checkJsApi', 'scanQRCode']
});
});
wx.error(function(res) {
alert("出錯了:" + res.errMsg); //這個地方的好處就是wx.config配置錯誤,會彈出窗口哪里錯誤,然后根據微信文檔查詢即可。
});
wx.ready(function() {
wx.checkJsApi({
jsApiList: ['scanQRCode'],
success: function(res) {

}
});
//點擊按鈕掃描二維碼
document.querySelector('#scanQRCode').onclick = function() {
wx.scanQRCode({
needResult: 1, // 默認為0,掃描結果由微信處理,1則直接返回掃描結果,
scanType: ["qrCode"], // 可以指定掃二維碼還是一維碼,默認二者都有
success: function(res) {
var result = res.resultStr; // 當needResult 為 1 時,掃碼返回的結果

alert("掃描結果:" + result);
window.location.href = result; //因為我這邊是掃描后有個鏈接,然后跳轉到該頁面
}
});
};

});
});

以上就是網上一些大佬還有結合 詳細說明的官方文檔,花費了一下午時間,踩了N個坑總結出來的,希望大家都可以完成功能,這樣就可以開心的掃一掃啦,我先去掃一下了

 

有問題可以一起溝通,交流哈

 

放幾個連接,大家可以參考下

微信簽名工具
微信公眾平台, config:invalid signature一直爆這個錯誤,求教如何解決?
 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM