在前端艱難爬行之H5網(wǎng)頁支持微信分享

微信真坑观挎,鼓搗了一天松捉,眼睛都瞎了,最后發(fā)現(xiàn)個(gè)人微信公眾賬號(hào)沒有權(quán)限蔑歌,尼瑪震叙。掀鹅。。

1. 注冊(cè)微信公眾平臺(tái)

為了能夠使用微信的接口媒楼,需要注冊(cè)開發(fā)者賬號(hào)身份淫半, 這個(gè)自行百度

2.搭建一個(gè)服務(wù)器

我們需要一個(gè)服務(wù)器,來獲取訪問微信API的簽名匣砖,這里使用NodeJS服務(wù)器:

const request = require('request')
var express = require('express');
var app = express();
const sha1 = require('sha1')
const waterfall = require('async/waterfall')
const NodeCache = require('node-cache')
const cache = new NodeCache({stdTTL: 3600, checkperiod: 3600})

// app.get('/wxJssdk', function (req, res) {
//     let wx = req.query

//     // 1)將token科吭、timestamp、nonce三個(gè)參數(shù)進(jìn)行字典序排序
//     let token = 'jegfjaeghfuyawegfgjdbh'
//     let timestamp = wx.timestamp
//     let nonce = wx.nonce

//     // 2)將三個(gè)參數(shù)字符串拼接成一個(gè)字符串進(jìn)行sha1加密
//     let list = [token, timestamp, nonce]
//     let result = sha1(list.sort().join(''))

//     // 3)開發(fā)者獲得加密后的字符串可與signature對(duì)比猴鲫,標(biāo)識(shí)該請(qǐng)求來源于微信
//     if (result === wx.signature) {
//         res.send(wx.echostr)
//     } else {
//         res.send(false)
//     }
// })

app.get('/wxJssdk/getJssdk', function (req, res) {
    let grant_type = 'client_credential'
    let appid = 'xxxx'
    let secret = 'xxxx' // appscret

    let steps = []

    // 第一步对人,獲取access_token
    steps.push((cb) => {

        let steps1 = []

        // 第1.1步,從緩存中讀取access_token
        steps1.push((cb1) => {
            let access_token = cache.get('access_token', (err, access_token) => {
                cb1(err, access_token)
            })
        })

        // 第1.2步拂共,緩存中有access_token則直接返回牺弄,如果沒有,則從服務(wù)器中讀取access_token
        steps1.push((access_token, cb1) => {
            if (access_token) {
                cb1(null, access_token, 'from_cache')
            } else {
                request('https://api.weixin.qq.com/cgi-bin/token?grant_type=' + grant_type + '&appid=' + appid + '&secret=' + secret, (err, response, body) => {
                    cb1(err, JSON.parse(body).access_token, 'from_server')
                })
            }
        })

        // 第1.3步宜狐,如果是新從服務(wù)器取的access_token势告,則緩存起來,否則直接返回
        steps1.push((access_token, from_where, cb1) => {
            if (from_where === 'from_cache') {
                console.log(' === 成功從緩存中讀取access_token: ' + access_token + ' ===')
                cb1(null, access_token)
            } else if (from_where === 'from_server') {
                cache.set('access_token', access_token, (err, success) => {
                    if (!err && success) {
                        console.log(' === 緩存已過期抚恒,從服務(wù)器中讀取access_token: ' + access_token + ' ===')
                        cb1(null, access_token)
                    } else {
                        cb1(err || 'cache設(shè)置access_token時(shí)咱台,出現(xiàn)未知錯(cuò)誤')
                    }
                })
            } else {
                cb1('1.3獲取from_where時(shí),from_where值為空')
            }
        })


        waterfall(steps1, (err, access_token) => {
            cb(err, access_token)
        })
    })


    // 第二步俭驮,獲取ticket
    steps.push((access_token, cb) => {
        let steps1 = []

        // 第2.1步回溺,從緩存中讀取ticket
        steps1.push((cb1) => {
            let ticket = cache.get('ticket', (err, ticket) => {
                cb1(err, ticket)
            })
        })

        // 第2.2步,緩存中有ticket則直接返回混萝,如果沒有遗遵,則從服務(wù)器中讀取ticket
        steps1.push((ticket, cb1) => {
            if (ticket) {
                cb1(null, ticket, 'from_cache')
            } else {
                request('https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=' + access_token + '&type=jsapi', (err, response, body) => {
                    cb1(err, JSON.parse(body).ticket, 'from_server')
                })
            }
        })

        // 第2.3步,如果新從服務(wù)器取的ticket逸嘀,則緩存起來车要,否則直接返回
        steps1.push((ticket, from_where, cb1) => {
            if (from_where === 'from_cache') {
                console.log(' === 成功從緩存中讀取ticket: ' + ticket + ' ===')
                cb1(null, ticket)
            } else if (from_where === 'from_server') {
                cache.set('ticket', ticket, (err, success) => {
                    if (!err && success) {
                        console.log(' === 緩存已過期,從服務(wù)器中讀取ticket: ' + ticket + ' ===');
                        cb1(null, ticket)
                    } else {
                        cb1(err || 'cache設(shè)置ticket時(shí)崭倘,出現(xiàn)未知錯(cuò)誤')
                    }
                })
            } else {
                cb1('2.3獲取from_where時(shí)翼岁,from_where值為空')
            }
        })

        waterfall(steps1, (err, ticket) => {
            cb(err, ticket)
        })
    })


    // 第三步维哈,生成簽名
    steps.push((ticket, cb) => {
        let jsapi_ticket = ticket
        let nonce_str = '123456'
        let timestamp = Math.floor((new Date().getTime())/1000)
        let url = req.query.url

        let str = 'jsapi_ticket=' + jsapi_ticket + '&noncestr=' + nonce_str + '&timestamp=' + timestamp + '&url=' + url
        console.log('signature ' + str)
        let signature = sha1(str)
        console.log('==> ' + signature)
        cb(null, {
            appId: appid,
            timestamp: timestamp,
            nonceStr: nonce_str,
            signature: signature,
            ticket: ticket
        })
    })

    waterfall(steps, (err, data) => {
        res.setHeader("Content-Type", "text/json");
        res.setHeader("Access-Control-Allow-Origin", "*");
        if (err) {
            res.send({status: 'error', data: err})
        } else {
            res.send({status: 'success', data: data})
        }
    })
})

app.use('/wxJssdk/public', express.static('public'))

var server = app.listen(3000, function () {
    var host = server.address().address;
    var port = server.address().port;

    console.log('Example app listening at http://%s:%s', host, port);
})

出處是:https://www.jb51.net/article/118729.htm

一定要注意,生成簽名的部分打log登澜,然后和微信公眾平臺(tái)上的簽名驗(yàn)證工具對(duì)比一下阔挠,比如時(shí)間戳位數(shù),url對(duì)不對(duì)等

3. 在H5中導(dǎo)入

<script src="./js/jquery-1.11.1.js"></script>
<script src="http://res.wx.qq.com/open/js/jweixin-1.2.0.js"></script>
<script>

    var currentUrl =  encodeURIComponent(location.href.split('#')[0])
    $.get('http://xxxx.com/wxJssdk/getJssdk?url=' + currentUrl, function (data, status) {

        wx.config({
            debug: false, // 開啟調(diào)試模式,調(diào)用的所有api的返回值會(huì)在客戶端alert出來脑蠕,若要查看傳入的參數(shù)购撼,可以在pc端打開,參數(shù)信息會(huì)通過log打出谴仙,僅在pc端時(shí)才會(huì)打印迂求。
            appId: data.data.appId, // 必填,公眾號(hào)的唯一標(biāo)識(shí)
            timestamp: data.data.timestamp, // 必填晃跺,生成簽名的時(shí)間戳
            nonceStr: data.data.nonceStr, // 必填揩局,生成簽名的隨機(jī)串
            signature: data.data.signature,// 必填,簽名
            jsApiList: ['onMenuShareTimeline','onMenuShareAppMessage'] // 必填掀虎,需要使用的JS接口列表
        });

        console.log('wx finish');
        wx.ready(function(){
            console.log('wx ready');
            // alert('wx ready')

            wx.error(function(res){
                // config 信息驗(yàn)證失敗會(huì)執(zhí)行 error 函數(shù)凌盯,如簽名過期導(dǎo)致驗(yàn)證失敗,具體錯(cuò)誤信息可以打開 config 的 debug 模式查看烹玉,也可以在返回的 res 參數(shù)中查看驰怎,對(duì)于 SPA 可以在這里更新簽名。
                console.log("errorMSG:"+res);
            });

            wx.checkJsApi({
                jsApiList: ['onMenuShareTimeline','onMenuShareAppMessage'], // 需要檢測的JS接口列表二打,所有JS接口列表見附錄2,
                success: function(res) {
                    // 以鍵值對(duì)的形式返回县忌,可用的api值true,不可用為false
                    // 如:{"checkResult":{"chooseImage":true},"errMsg":"checkJsApi:ok"}
                    console.log('res'+ res);
                }
            });

            var shareParam = {
                title: '劉彥博李茜婷的結(jié)婚請(qǐng)柬', // 分享標(biāo)題
                // desc: '邀請(qǐng)您的參加', // 分享描述
                link: 'http://www.realank.com/wedding/', // 分享鏈接继效,該鏈接域名或路徑必須與當(dāng)前頁面對(duì)應(yīng)的公眾號(hào)JS安全域名一致
                imgUrl: 'http://www.realank.com/wedding/headimgwx.jpg', // 分享圖標(biāo)
                // type: 'link', // 分享類型,music症杏、video或link,不填默認(rèn)為link
                // dataUrl: '', // 如果type是music或video瑞信,則要提供數(shù)據(jù)鏈接厉颤,默認(rèn)為空
                trigger: function (res) {
                    console.log('用戶點(diǎn)擊發(fā)送給朋友');
                },
                success: function (res) {
                    console.log('已分享');
                },
                cancel: function (res) {
                    console.log('已取消');
                },
                fail: function (res) {
                    console.log(JSON.stringify(res));
                }
            };

            wx.onMenuShareTimeline(shareParam);
            wx.onMenuShareAppMessage(shareParam);

        });

    })
</script>

這里使用的是ajax請(qǐng)求的,請(qǐng)求簽名的時(shí)候喧伞,需要加上一個(gè)url參數(shù)走芋,取當(dāng)前url一定要使用encodeURIComponent(location.href.split('#')[0])方法啊绩郎,忘記從哪個(gè)網(wǎng)站上看到的了潘鲫,試了好幾個(gè)小時(shí),因?yàn)檫@個(gè)大哥茅塞頓開肋杖,好人啊

然后在微信web開發(fā)者工具中測試就能通過溉仑,但是真機(jī)沒法通過,因?yàn)?strong>個(gè)人微信公眾號(hào)沒有權(quán)限W粗病W蔷埂怨喘!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市振定,隨后出現(xiàn)的幾起案子必怜,更是在濱河造成了極大的恐慌,老刑警劉巖后频,帶你破解...
    沈念sama閱讀 206,839評(píng)論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件梳庆,死亡現(xiàn)場離奇詭異,居然都是意外死亡卑惜,警方通過查閱死者的電腦和手機(jī)膏执,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來露久,“玉大人更米,你說我怎么就攤上這事『梁郏” “怎么了征峦?”我有些...
    開封第一講書人閱讀 153,116評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長消请。 經(jīng)常有香客問我眶痰,道長,這世上最難降的妖魔是什么梯啤? 我笑而不...
    開封第一講書人閱讀 55,371評(píng)論 1 279
  • 正文 為了忘掉前任竖伯,我火速辦了婚禮,結(jié)果婚禮上因宇,老公的妹妹穿的比我還像新娘七婴。我一直安慰自己,他們只是感情好察滑,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,384評(píng)論 5 374
  • 文/花漫 我一把揭開白布打厘。 她就那樣靜靜地躺著,像睡著了一般贺辰。 火紅的嫁衣襯著肌膚如雪户盯。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,111評(píng)論 1 285
  • 那天饲化,我揣著相機(jī)與錄音莽鸭,去河邊找鬼。 笑死吃靠,一個(gè)胖子當(dāng)著我的面吹牛硫眨,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播巢块,決...
    沈念sama閱讀 38,416評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼礁阁,長吁一口氣:“原來是場噩夢啊……” “哼巧号!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起姥闭,我...
    開封第一講書人閱讀 37,053評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤丹鸿,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后棚品,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體卜高,經(jīng)...
    沈念sama閱讀 43,558評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,007評(píng)論 2 325
  • 正文 我和宋清朗相戀三年南片,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了掺涛。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,117評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡疼进,死狀恐怖薪缆,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情伞广,我是刑警寧澤拣帽,帶...
    沈念sama閱讀 33,756評(píng)論 4 324
  • 正文 年R本政府宣布,位于F島的核電站嚼锄,受9級(jí)特大地震影響减拭,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜区丑,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,324評(píng)論 3 307
  • 文/蒙蒙 一拧粪、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧沧侥,春花似錦可霎、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,315評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至旺罢,卻和暖如春旷余,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背扁达。 一陣腳步聲響...
    開封第一講書人閱讀 31,539評(píng)論 1 262
  • 我被黑心中介騙來泰國打工正卧, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人罩驻。 一個(gè)月前我還...
    沈念sama閱讀 45,578評(píng)論 2 355
  • 正文 我出身青樓穗酥,卻偏偏與公主長得像,于是被迫代替她去往敵國和親惠遏。 傳聞我的和親對(duì)象是個(gè)殘疾皇子砾跃,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,877評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn)节吮,斷路器抽高,智...
    卡卡羅2017閱讀 134,600評(píng)論 18 139
  • 1. 準(zhǔn)備工作 1.1 查看公眾號(hào)分享接口權(quán)限 要使用微信SDK必須要有經(jīng)過微信認(rèn)證的非個(gè)人服務(wù)號(hào) 登陸服務(wù)號(hào)后,...
    sxplus閱讀 6,220評(píng)論 0 2
  • 先引入JS 文件 this.wxShare() 在created里調(diào)用 首先登陸微信公眾號(hào) JSSDK使用步驟 步...
    寄魚予海與你閱讀 6,678評(píng)論 1 3
  • 不知道有沒有人和我一樣喜歡奇幻電影? 從看了《碟形世界帚豪,》《加勒比海盜》之后碳竟,我簡直是不可救藥了,接著把《魔戒》狸臣,...
    書猶藥也閱讀 393評(píng)論 0 0
  • 用戶的歷史分享(1) 1. 業(yè)務(wù)描述: 查看用戶的歷史分享記錄莹桅,用戶可以查看自己的,也可以查看他人的烛亦,支持分頁 2...
    花園兜閱讀 182評(píng)論 0 0