一、說明如果用戶在微信客戶端中訪問第三方網(wǎng)頁,公眾號可以通過微信網(wǎng)頁授權(quán)機制,通過獲得普通access_token(此處普通access_token和支付所用的access_token不同)、jsapi_ticket,通過 config 接口注入權(quán)限驗證后可調(diào)用微信掃一掃功能。 1.更多內(nèi)容參考微信開發(fā)文檔:(1) 普通access_token獲?。?/span>https://developers.weixin.qq.com/doc/offiaccount/Basic_Information/Get_access_token.html
(2) jsapi_ticket獲取和掃一掃等功能接口:https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/JS-SDK.html 二、實現(xiàn)1.nodejs后端實現(xiàn)(1)定義全局存儲變量 jsapi_ticket,由于獲取jsapi_ticket的 api 調(diào)用次數(shù)非常有限,須在自己的服務(wù)全局緩存jsapi_ticket://jsapi_ticket,由于獲取jsapi_ticket的 api 調(diào)用次數(shù)非常有限,須在自己的服務(wù)全局緩存jsapi_ticket
let JsapiTicket = {
ticket: '',
time: new Date().valueOf()
} (2)獲取普通access_token:const access_token_url = `https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=${config.app_id}&secret=${config.app_secret}`;
request.post({url: access_token_url}, function (error, response, body) {
let access_token = JSON.parse(body).access_token;
}); (3)獲取普通jsapi_ticket全部代碼(包含獲取普通access_token)://jsapi_ticket,由于獲取jsapi_ticket的 api 調(diào)用次數(shù)非常有限,須在自己的服務(wù)全局緩存jsapi_ticket
let JsapiTicket = {
ticket: '',
time: new Date().valueOf()
}
/**
* 獲取 jsapi_ticket
* IN: 無
* OUT: jsapi_ticket
*/
function getJsapiTicket() {
return new Promise((resolve, reject) => {
//此處公用access_token和openid那個access_token不一樣
const access_token_url = `https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=${config.app_id}&secret=${config.app_secret}`;
if ((new Date().valueOf() - JsapiTicket.time <= 7000000) && (JsapiTicket.ticket != '')) {//jsapi_ticket的有效期為7200秒,小于7000都可以繼續(xù)用
resolve(JsapiTicket.ticket);
} else {
request.post({url: access_token_url}, function (error, response, body) {
let access_token = JSON.parse(body).access_token;
const jsapi_ticket_url = `https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=${access_token}&type=jsapi`;
request.post({url: jsapi_ticket_url}, function (error, response, ticketbody) {
let jsapiticketbody = JSON.parse(ticketbody);
JsapiTicket = {
ticket: jsapiticketbody.ticket,
time: new Date().valueOf()
}
resolve(jsapiticketbody.ticket);
});
});
}
})
} (4)簽名生成 (規(guī)則:參與簽名的字段包括noncestr(隨機字符串), 有效的jsapi_ticket, timestamp(時間戳), url(當(dāng)前網(wǎng)頁的URL,不包含#及其后面部分) 。對所有待簽名參數(shù)按照字段名的ASCII 碼從小到大排序(字典序)后,使用 URL 鍵值對的格式(即key1=value1&key2=value2…)拼接成字符串string1。這里需要注意的是所有參數(shù)名均為小寫字符。對string1作sha1加密,字段名和字段值都采用原始值,不進行URL 轉(zhuǎn)義。)
/**
* 獲取簽名的實際實現(xiàn)
* IN: 無
* OUT: 加密簽名后signature
*/
async function getJsapiTicketSign(url) {
let JsapiTicket = await getJsapiTicket();
let params = {
appId: config.app_id,
jsapi_ticket: JsapiTicket,
noncestr: Formatter.nonce(),
timestamp: `${Formatter.timestamp()}`,
url: url,
}
let comstring = "jsapi_ticket=" + params.jsapi_ticket +
"&noncestr=" + params.noncestr +
"×tamp=" + params.timestamp +
"&url=" + params.url;
// console.log(comstring);
params.signature = sha1(comstring);
return params;
}
(5)補充說明,引用等:
const {Wechatpay} = require('wechatpay-axios-plugin');
const request = require('request'); // HTTP 請求庫
const {Hash: {sha1}} = require('wechatpay-axios-plugin')//sha1加密方法 (6)留給前端可訪問的接口://引入
const weixin_PAY = require('../weixin_PAY.js');//微信
/**
* jsapi_ticket獲取接口,微信掃一掃調(diào)用需要
*/
router.post('/getJsapiTicketSign', function (req, res) {
//SQL語句命令
(async function () {
try {
let params = await weixin_PAY.getJsapiTicketSign(req.body.tokenUrl);
// console.log(JSON.stringify(params));
res.json(params);
} catch (e) {
console.log(e);
}
})();
}); 2.前端頁面相關(guān)代碼
(1)需要引入的:
<script src="http://res2.wx.qq.com/open/js/jweixin-1.6.0.js"> </script>
<script src="js/jquery.js"></script> (2)獲取后端接口getJsapiTicketSign生成的簽名數(shù)據(jù)://獲取簽名
$.ajax({
method: 'post',
url: '/trade/getJsapiTicketSign',//后端接口
data: {
tokenUrl:tokenUrl,
}
})
.done(function (res) {
console.log(res);
//獲得簽名之后傳入配置中進行配置
wxConfig(res.appId,res.timestamp,res.noncestr,res.signature);
})
.fail(function (err) {
console.log(err);
}); (3)通過 config 接口注入權(quán)限驗證配置:
function wxConfig(_appId,_timestamp, _nonceStr, _signature) {
console.log('獲取數(shù)據(jù):' + _timestamp +'\n' + _nonceStr +'\n' + _signature);
wx.config({
debug:false,// 是否開啟調(diào)試模式,調(diào)用的所有api的返回值會在客戶端alert出來,若要查看傳入的參數(shù),可以在pc端打開,參數(shù)信息會通過log打出,僅在pc端時才會打印。
appId: _appId,// 必填,公眾號的唯一標識
timestamp: _timestamp,// 必填,生成簽名的時間戳
nonceStr: _nonceStr,// 必填,生成簽名的隨機串
signature: _signature,// 必填,簽名,見附錄1
jsApiList: ['checkJsApi','scanQRCode']
// 必填,需要使用的JS接口列表,所有JS接口列表見附錄2
});
} (4)微信內(nèi)打開頁面時,調(diào)用微信掃一掃:$("#scanQRCode").click(function(event){
wx.scanQRCode({
desc: 'scanQRCode desc',
needResult : 1, // 默認為0,掃描結(jié)果由微信處理,1則直接返回掃描結(jié)果,
scanType : [ "qrCode", "barCode" ], // 可以指定掃二維碼還是一維碼,默認二者都有
success : function(res) {
console.log("調(diào)用掃描成功",res);
var result = res.resultStr; // 當(dāng)needResult 為 1 時,掃碼返回的結(jié)果
$("#codeValue").val(result);//顯示結(jié)果
// alert("掃碼結(jié)果為:" + result);
},
error:function(res){
console.log(res)
}
});
}) (5)附,前端頁面全部代碼:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>微信掃一掃demo</title>
<meta name="viewport" content="width=device-width, initial-scale=1 user-scalable=0">
<script src="http://res2.wx.qq.com/open/js/jweixin-1.6.0.js"> </script>
<script src="js/jquery.js"></script>
</head>
<body>
<div class="lbox_close wxapi_form">
<h3>微信掃一掃</h3>
<input id="codeValue">
<button id="scanQRCode">掃碼</button>
</div>
<script type="text/javascript">
$(function() {
//需要把當(dāng)前頁面的url地址傳到后臺,生成簽名信息時需要使用到。下面的地址是controller層調(diào)用當(dāng)前頁面的路徑
var tokenUrl= window.location.href;
$(document).ready(function(){
//獲取簽名
$.ajax({
method: 'post',
url: '/trade/getJsapiTicketSign',
data: {
tokenUrl:tokenUrl,
}
})
.done(function (res) {
console.log(res);
//獲得簽名之后傳入配置中進行配置
wxConfig(res.appId,res.timestamp,res.noncestr,res.signature);
})
.fail(function (err) {
console.log(err);
});
})
function wxConfig(_appId,_timestamp, _nonceStr, _signature) {
console.log('獲取數(shù)據(jù):' + _timestamp +'\n' + _nonceStr +'\n' + _signature);
wx.config({
debug:false,// 開啟調(diào)試模式,調(diào)用的所有api的返回值會在客戶端alert出來,若要查看傳入的參數(shù),可以在pc端打開,參數(shù)信息會通過log打出,僅在pc端時才會打印。
appId: _appId,// 必填,公眾號的唯一標識
timestamp: _timestamp,// 必填,生成簽名的時間戳
nonceStr: _nonceStr,// 必填,生成簽名的隨機串
signature: _signature,// 必填,簽名,見附錄1
jsApiList: ['checkJsApi','scanQRCode']
// 必填,需要使用的JS接口列表,所有JS接口列表見附錄2
});
}
$("#scanQRCode").click(function(event){
wx.scanQRCode({
desc: 'scanQRCode desc',
needResult : 1, // 默認為0,掃描結(jié)果由微信處理,1則直接返回掃描結(jié)果,
scanType : [ "qrCode", "barCode" ], // 可以指定掃二維碼還是一維碼,默認二者都有
success : function(res) {
console.log("調(diào)用掃描成功",res);
var result = res.resultStr; // 當(dāng)needResult 為 1 時,掃碼返回的結(jié)果
$("#codeValue").val(result);//顯示結(jié)果
// alert("掃碼結(jié)果為:" + result);
},
error:function(res){
console.log(res)
}
});
})
});
</script>
</body>
</html>
|