本人自己寫(xiě)完全棧小項(xiàng)目序芦,想在微信分享時(shí)帶標(biāo)題臭杰、描述和縮略圖,沒(méi)想到搞了3天谚中,才搞定渴杆!所以寫(xiě)篇文章,記錄浪費(fèi)的時(shí)間宪塔,以此為戒磁奖,以后要多讀書(shū)。某筐。比搭。
技術(shù)棧:vue 2.9.2, node v8.11.1南誊, express 4.15.5
一身诺、前期準(zhǔn)備:
一定要看到微信的開(kāi)發(fā)者文檔,本人最后發(fā)現(xiàn)掉進(jìn)去的坑抄囚,都是開(kāi)發(fā)文檔沒(méi)看仔細(xì)霉赡。。
二隅津、動(dòng)手實(shí)踐
1诬垂、后端代碼
/getwe 這個(gè)接口是用來(lái),接受微信服務(wù)器驗(yàn)證的伦仍;/getsignature是供前端調(diào)用的接口结窘,可以獲取簽名等信息。
var express = require('express');
var crypto = require('crypto')
var router = express.Router();
var sha1 = require('sha1');
var wxShare = require('./wxShare')
var token = "403106220Asd"
/* GET home page. */
router.get('/getwe', function(req, res, next) {
? console.log();
? ? var signature = req.query.signature;
? ? var timestamp = req.query.timestamp;
? ? var nonce = req.query.nonce;
? ? var echostr = req.query.echostr;
? ? console.log(signature, timestamp, nonce, echostr);
? ? /*? 加密/校驗(yàn)流程如下: */
? ? //1. 將token充蓝、timestamp隧枫、nonce三個(gè)參數(shù)進(jìn)行字典序排序
? ? var array = new Array(token,timestamp,nonce);
? ? array.sort();
? ? var str = array.toString().replace(/,/g,"");
? ? //2. 將三個(gè)參數(shù)字符串拼接成一個(gè)字符串進(jìn)行sha1加密
? ? var sha1Code = crypto.createHash("sha1");
? ? var code = sha1Code.update(str,'utf-8').digest("hex");
? ? //3. 開(kāi)發(fā)者獲得加密后的字符串可與signature對(duì)比,標(biāo)識(shí)該請(qǐng)求來(lái)源于微信
? ? if(code===signature){
? ? ? ? res.send(echostr)
? ? }else{
? ? ? ? res.send("error");
? ? }
});
/**
* 分享
*/
router.post('/getsignature', function(req, res, next) {
? ? let hrefURL = req.body.urlhref;
? ? wxShare.prototype.accessToken(hrefURL, function(data) {
? ? ? ? res.json(data);
? ? });
});
module.exports = router;
wxShare:
var url = require('url');
var request = require('request');
var sha1 = require('sha1');
let config = {
? ? ? ? appID: "",// 微信公眾號(hào)ID
? ? ? ? appSecret: "" //微信公眾號(hào)里有
? ? },
? ? configEnd = {
? ? ? ? appID: '',
? ? ? ? access_token: '',
? ? ? ? ticket: '',
? ? ? ? timestamp: '', // 必填谓苟,生成簽名的時(shí)間戳
? ? ? ? nonceStr: '', // 必填官脓,生成簽名的隨機(jī)串
? ? ? ? signature: '', // 必填,簽名涝焙,見(jiàn)附錄1
? ? };
/**
* 微信分享
*/
class wxShare {
? ? /**
? ? * 請(qǐng)求獲取access_token 方法入口
? ? * @param {* URL鏈接} hrefURL
? ? * @param {* 回調(diào)請(qǐng)求方法} callback
? ? */
? ? accessToken(hrefURL, callback) { // 獲取access_token
? ? ? ? let _this = this;
? ? ? ? var tokenUrl = 'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=' + config.appID + '&secret=' + config.appSecret;
? ? ? ? request(tokenUrl, function(error, response, body) {
? ? ? ? ? ? if (response.statusCode && response.statusCode === 200) {
? ? ? ? ? ? ? ? body = JSON.parse(body);
? ? ? ? ? ? ? ? configEnd.access_token = body.access_token;
? ? ? ? ? ? ? ? _this.upJsapiTicket(hrefURL, body.access_token, callback)
? ? ? ? ? ? }
? ? ? ? });
? ? };
? ? /**
? ? * 獲取Jsapi_Ticket
? ? * @param {* URL鏈接} hrefURL
? ? * @param {* token} access_Ttoken
? ? * @param {* 回調(diào)請(qǐng)求方法} callback
? ? */
? ? upJsapiTicket(hrefURL, access_Ttoken, callback) { // Jsapi_ticket
? ? ? ? let _this = this;
? ? ? ? var ticketUrl = 'https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=' + access_Ttoken + '&type=jsapi';
? ? ? ? request(ticketUrl, function(err, response, content) {
? ? ? ? ? ? content = JSON.parse(content);
? ? ? ? ? ? if (content.errcode == 0) {
? ? ? ? ? ? ? ? configEnd.appID = config.appID;
? ? ? ? ? ? ? ? configEnd.ticket = content.ticket; // ticket
? ? ? ? ? ? ? ? configEnd.timestamp = _this.createTimestamp(); // 時(shí)間戳
? ? ? ? ? ? ? ? configEnd.nonceStr = _this.createNonceStr(); // 隨機(jī)數(shù)
? ? ? ? ? ? ? ? configEnd.signature = _this.sign(hrefURL); // 簽名
? ? ? ? ? ? ? ? callback && callback(configEnd); // 回調(diào)前端JS方法
? ? ? ? ? ? }
? ? ? ? })
? ? };
? ? /**
? ? * 隨機(jī)字符串
? ? */
? ? createNonceStr() {
? ? ? ? return Math.random().toString(36).substr(2, 15);
? ? };
? ? /**
? ? * 時(shí)間戳
? ? */
? ? createTimestamp() {
? ? ? ? return parseInt(new Date().getTime() / 1000).toString();
? ? };
? ? /**
? ? * 拼接字符串
? ? * @param {*} args
? ? */
? ? rawString(args) {
? ? ? ? var keys = Object.keys(args);
? ? ? ? keys = keys.sort()
? ? ? ? var newArgs = {};
? ? ? ? keys.forEach(function(key) {
? ? ? ? ? ? newArgs[key.toLowerCase()] = args[key];
? ? ? ? });
? ? ? ? var string = '';
? ? ? ? for (var k in newArgs) {
? ? ? ? ? ? string += '&' + k + '=' + newArgs[k];
? ? ? ? }
? ? ? ? string = string.substr(1);
? ? ? ? return string;
? ? };
? ? /**
? ? * 簽名
? ? * @param {*} url
? ? */
? ? sign(url) {
? ? ? ? let _this = this;
? ? ? ? var ret = {
? ? ? ? ? ? jsapi_ticket: configEnd.ticket,
? ? ? ? ? ? nonceStr: configEnd.nonceStr,
? ? ? ? ? ? timestamp: configEnd.timestamp,
? ? ? ? ? ? url: url
? ? ? ? };
? ? ? ? var string = _this.rawString(ret);
? ? ? ? var shaObjs = sha1(string);
? ? ? ? return shaObjs;
? ? };
}
module.exports = wxShare;
2卑笨、前端代碼
在想要分享的頁(yè)面的mounted寫(xiě)上調(diào)用,同時(shí)引入已經(jīng)封裝好的js仑撞。
這里有個(gè)小坑就是赤兴,當(dāng)用npm i weixin-js-sdk? 在2019年2月17日下載的是1.40 test版本,可能不是很穩(wěn)定隧哮,在測(cè)試時(shí)候桶良,wx.config總是顯示錯(cuò)誤信息error massage “config ok”,最后發(fā)現(xiàn)目前開(kāi)發(fā)文檔推薦的updateAppMessageShareData和updateTimelineShareData根本返回不了數(shù)據(jù)沮翔,所以用以前版本的接口函數(shù)艺普,就通過(guò)了。
import wxshare from '@/utils/wxshare'
export default {
? data() {
? ? return {
? ? ? // jsonurl: ''
? ? }
? },
? // created() {
? //? // console.log('self.router', this.$route)
? //? this.jsonurl = this.$route.query
? // },
? mounted() {
? ? wxshare.do(this.$route.query, '縮略圖url', '想用的標(biāo)題', '這是一段描述')
? }
wxshare:
import axios from 'axios'
import wx from 'weixin-js-sdk'
const wxshare = {
? do(queryId, icon = '', title = '', desc = '') {
??? const url = location.href.split('#')[0] // ruoter是hash模式的時(shí)候 獲取錨點(diǎn)之前的鏈接
??? console.log('前端傳輸前的url地址', location.href)
??? console.log('前端傳輸前的url地址', url)
??? axios.post('https:/..../getsignature', { // 服務(wù)端獲取配置jssdk 簽名等 文件
????? urlhref: url
??? }).then(response => {
????? const res = response.data
????? console.log('調(diào)用微信js接口返回的簽名:', res)
????? this.wxInit(res, queryId, icon, title, desc)
??? })
? },
? // 微信分享
? wxInit(res, queryId, icon = '', title = '', desc = '') {
??? const url = location.href.split('#')[0] // 獲取錨點(diǎn)之前的鏈接
??? // let links = url+'#/Food/' + this.$route.params.id;??? //用于簽名的url 和 用于微信分享的url可以不同
??? // const links = url + '#/?jsonurl=' + queryId
??? const links = url
??? console.log('url link:', links)
??? wx.config({
????? debug: false,
????? appId: res.appID,
????? timestamp: res.timestamp,
????? nonceStr: res.nonceStr,
????? signature: res.signature,
????? jsApiList: ['onMenuShareAppMessage', 'onMenuShareTimeline']
??? })
??? wx.ready(function() {
????? wx.onMenuShareAppMessage({
??????? title: title, // 分享標(biāo)題
??????? desc: desc, // 分享描述
??????? link: links, // 分享鏈接鉴竭,該鏈接域名或路徑必須與當(dāng)前頁(yè)面對(duì)應(yīng)的公眾號(hào)JS安全域名一致
??????? imgUrl: icon, // 分享圖標(biāo)
??????? success: function() {
????????? // 設(shè)置成功
????????? console.log('設(shè)置成功')
??????? }
????? })
????? // 微信分享菜單測(cè)試
????? wx.onMenuShareTimeline({
??????? title: title, // 分享標(biāo)題
??????? link: links, // 分享鏈接,該鏈接域名或路徑必須與當(dāng)前頁(yè)面對(duì)應(yīng)的公眾號(hào)JS安全域名一致
??????? imgUrl: icon, // 分享圖標(biāo)
??????? success: function() {
????????? // 設(shè)置成功
????????? console.log('設(shè)置成功')
??????? }
????? })
??? })
??? wx.error(function(err) {
????? alert(JSON.stringify(err))
??? })
? }
}
export default wxshare
PS:本人此次也是站在了巨人的肩膀上岸浑,所以避免了二次分享的坑搏存、router是否是history的坑……如可以更優(yōu)化代碼地方,可以指正矢洲,共同進(jìn)步璧眠!
文末奉上友情鏈接:
這位大神已經(jīng)把vue前端如何設(shè)置寫(xiě)的明明白白 https://github.com/SevenChen/VueWxShare
后臺(tái)部分借鑒了 https://blog.csdn.net/baidu_31333625/article/details/72673958