我的公眾號(hào)開發(fā)(第一步)簡(jiǎn)單功能實(shí)現(xiàn)

作者:JiawuZhang
出品:JiawuLab(ID:jiawulab)

實(shí)驗(yàn)記錄系列是JiawuLab原創(chuàng)欄目,通過真實(shí)項(xiàng)目的操作,記錄整個(gè)實(shí)驗(yàn)過程。
旨在通過一步步過程,無基礎(chǔ)的朋友都能直接上手。

大家好,我是JiawuZhang,本次實(shí)驗(yàn)記錄的項(xiàng)目是--微信公眾號(hào)開發(fā)。

選擇這個(gè)項(xiàng)目的原因有二:
1、微信公眾號(hào)還是大部分人(包括我自己)獲取信息的一個(gè)重要渠道;
2、正好我手上有個(gè)公眾號(hào);

好了,閑話不多說,直接進(jìn)入主題。

效果演示

先放出實(shí)驗(yàn)過程中效果圖,閃耀登場(chǎng):

消息回復(fù)演示
關(guān)注回復(fù)演示
關(guān)鍵字回復(fù)演示

這么有個(gè)性的回復(fù)是不是很好玩,不再是固定的幾個(gè)回復(fù),具體的實(shí)現(xiàn)方法請(qǐng)往下看。

您也可以關(guān)注公眾號(hào):JiawuLab,來體驗(yàn)更多功能。

前期準(zhǔn)備工作

一、準(zhǔn)備一個(gè)微信公眾號(hào),我的是個(gè)人訂閱號(hào),未認(rèn)證。(ps:個(gè)人公眾號(hào),不能認(rèn)證)

認(rèn)不認(rèn)證都不要緊,只是接口權(quán)限多少的問題,未認(rèn)證的接口已經(jīng)能滿足這次實(shí)驗(yàn)?zāi)康摹?/p>

(具體權(quán)限可見-公眾號(hào)后臺(tái)-開發(fā)-接口權(quán)限)

紅框內(nèi)是已獲得的接口權(quán)限

二、準(zhǔn)備一臺(tái)服務(wù)器,現(xiàn)在提供云服務(wù)器的廠家很多,大家可自行準(zhǔn)備。

建議選擇獨(dú)立ip的服務(wù)器,(共享ip會(huì)便宜些,但是不推薦,具體原因后面會(huì)說到。)

我選擇的是某廠的1核2G1M(1核cpu,2G內(nèi)存,1M帶寬)的獨(dú)立ip服務(wù)器,具體品牌就不說了,怕有廣告嫌疑。

這個(gè)配置應(yīng)付常規(guī)公眾號(hào)足夠了,但是如果你的公眾號(hào)的流量特別大,需要根據(jù)自己的情況增加配置。

三、服務(wù)器上安裝python環(huán)境,我的環(huán)境是python3.7.4, Centos7.5。

如果你不清楚怎么安裝,可關(guān)注公眾號(hào):JiawuLab,給我留言,這里不展開。

開發(fā)方向

微信公眾號(hào)開發(fā),官方的技術(shù)文檔,寫的很詳細(xì),也有范例參照。

另外,github上獲得3000多星的WeRoBot,也是一個(gè)很受歡迎的微信公眾號(hào)開發(fā)框架,有興趣的朋友可自行了解。

上面提到的相關(guān)資源鏈接,請(qǐng)到文末獲取

我們這次以官方開發(fā)文檔來進(jìn)行實(shí)驗(yàn)。

實(shí)驗(yàn)開始

首先,進(jìn)入官方開發(fā)文檔-入門指引,如下圖:

我們只用關(guān)注紅框中的內(nèi)容,這里是python2.7版本,服務(wù)器上是python3.7.4版本。

所以后面需要對(duì)該指引所提到的內(nèi)容進(jìn)行版本轉(zhuǎn)化,我會(huì)在后面提到如何轉(zhuǎn),不用擔(dān)心。

然后需要安裝web.py,這是一個(gè)python的輕型web開發(fā)框架,我們只來用,不用特別學(xué)習(xí),如需自行百度。

現(xiàn)在,在服務(wù)器中進(jìn)行安裝web.py,很簡(jiǎn)單,直接用pip安裝就好

# 安裝web.py
pip(3) install web.py

這里需要注意兩點(diǎn):
1、centos自帶python2.7,如果安裝python3版本沒有改軟鏈接,需要用pip3,檢查方式,直接輸入python -V,看版本
2、web.py版本,pip安裝的直接是0.40正式版,支持python3,不用像網(wǎng)上說的那種指定版本

安裝完好,我們測(cè)試一下,拷貝下面的代碼,保存為main.py文件

# -*- coding: utf-8 -*-
# filename: main.py
import web

urls = (
    '/wx', 'Handle',
)

class Handle(object):
    def GET(self):
        return "pika pika pikaqiu!"

if __name__ == '__main__':
    app = web.application(urls, globals())
    app.run()

然后找到當(dāng)前文件所在目錄輸入python(3) main.py 80,服務(wù)器啟動(dòng)成功,本地打開網(wǎng)頁(yè),輸入http://外網(wǎng)ip:80/wx,顯示如下

說明配置沒有問題,這里記得一定要服務(wù)器將80端口放行。到這里,我們就可以正式進(jìn)行公眾號(hào)的配置及操作了。

微信公眾號(hào)配置

打開微信公眾號(hào)后臺(tái),找到-開發(fā)-基本配置-服務(wù)器配置,進(jìn)行如下配置:

ps:這里先按照明文模式進(jìn)行,后面會(huì)改成安全模式,過程都會(huì)涉及的。點(diǎn)擊提交,出現(xiàn)報(bào)錯(cuò),說Token驗(yàn)證失敗,果然和文檔中說的一樣,出現(xiàn)錯(cuò)誤,先不管它。

繼續(xù)看文檔后面的內(nèi)容,原來是服務(wù)器沒有進(jìn)行配置,所以報(bào)錯(cuò),我們按照文檔后面的來。

先將之前的main.py文件改成如下:(注意備注)

# -*- coding: utf-8 -*-
# filename: main.py
import web
from handle import Handle  # 將Handle類放進(jìn)handle.py文件中,再導(dǎo)入進(jìn)來

urls = (
    '/wx', 'Handle',
)

if __name__ == '__main__':
    app = web.application(urls, globals())
    app.run()

然后新建handle.py文件,里面寫入:(注意備注)

# -*- coding: utf-8 -*-
# filename: handle.py

import hashlib
import web

class Handle(object):
    def GET(self):
        try:
            data = web.input()
            if len(data) == 0:
                return "pika pika pikaqiu!"
            signature = data.signature
            timestamp = data.timestamp
            nonce = data.nonce
            echostr = data.echostr
            token = "xxxx" #請(qǐng)按照公眾平臺(tái)官網(wǎng)\基本配置中信息填寫

            list = [token, timestamp, nonce]
            list.sort()
            sha1 = hashlib.sha1()
            # map函數(shù)在python2和3的功能不同,需要轉(zhuǎn)化
            # map(sha1.update, list)
            sha1.update(list[0].encode('utf-8'))
            sha1.update(list[1].encode('utf-8'))
            sha1.update(list[2].encode('utf-8'))
            hashcode = sha1.hexdigest()
            # 這里print轉(zhuǎn)為python3
            print("handle/GET func: hashcode, signature: ", hashcode, signature)
            if hashcode == signature:
                return echostr
            else:
                return ""
        except Exception as Argument:  # 這里加as 轉(zhuǎn)為python3
            return Argument

備注中已提到python3轉(zhuǎn)化的位置, 然后在token中填入微信公眾號(hào)中對(duì)應(yīng)的token。

保存后輸入python(3) main.py 80,服務(wù)器啟動(dòng)。

再次回到微信公眾號(hào)的配置,點(diǎn)擊提交,配置成功,顯示如下:


現(xiàn)在微信公眾號(hào)就配置好了,打通服務(wù)器與微信公眾號(hào)這一步很關(guān)鍵,所有后續(xù)功能都是在此基礎(chǔ)上開發(fā)的。

回復(fù)功能實(shí)現(xiàn)

到這里,指引列出兩個(gè)示例,分別是你說我學(xué)、圖尚往來,展示文字回復(fù)和圖片回復(fù)功能。

另外還展示了獲取accessToken、獲取臨時(shí)素材、獲取永久素材、自定義菜單等四個(gè)功能演示。

現(xiàn)在根據(jù)自己的需求,以及獲得接口權(quán)限來決定選擇哪些功能,比如我沒有自定義菜單權(quán)限,就不用理它。

而圖片回復(fù)需要用到臨時(shí)素材或是永久素材功能,來調(diào)用不同圖片,這些都可根據(jù)實(shí)際需求來選用。

我需要用到的是文字回復(fù),所以這里實(shí)現(xiàn)文字回復(fù)演示。

官方文檔中關(guān)于文字回復(fù)的機(jī)制,以及注意事項(xiàng)很詳細(xì),大家先仔細(xì)研究一下,比如消息體收到和回復(fù)的區(qū)別,消息回復(fù)流程等。

這里只做一個(gè)關(guān)鍵點(diǎn)的提醒,就是回復(fù)success問題
1、假如服務(wù)器無法保證在五秒內(nèi)處理回復(fù),則必須回復(fù)“success”或者“”(空串),否則微信后臺(tái)會(huì)發(fā)起三次重試。
2、三次重試后,依舊沒有及時(shí)回復(fù)任何內(nèi)容,系統(tǒng)自動(dòng)在粉絲會(huì)話界面出現(xiàn)錯(cuò)誤提示“該公眾號(hào)暫時(shí)無法提供服務(wù),請(qǐng)稍后再試”。

這是什么意思呢?是指需要保證你的功能代碼,在服務(wù)器收到消息后,5秒內(nèi)做出反應(yīng),這也是為什么我不推薦共享IP服務(wù)器的緣故。

在功能代碼中,我們可能需要做一些遞歸運(yùn)算,數(shù)據(jù)庫(kù)的查詢等花時(shí)間的事情,而共享IP服務(wù)器會(huì)受到其他網(wǎng)站的很大影響。

到時(shí)可能你寫了很厲害的功能,因?yàn)闊o法在5秒內(nèi)實(shí)現(xiàn),最后給讀者的展示,就是無盡的“該公眾號(hào)暫時(shí)無法提供服務(wù),請(qǐng)稍后再試”

好了,碼代碼的時(shí)間到了,這里直接將示例中的三段代碼保存即可。

分別是接受消息代碼、回復(fù)消息代碼、handle類的改寫,如下:

接受消息代碼,保存為receive.py
# -*- coding: utf-8 -*-
# filename: receive.py

import xml.etree.ElementTree as ET


def parse_xml(web_data):
    if len(web_data) == 0:
        return None
    xmlData = ET.fromstring(web_data)
    msg_type = xmlData.find('MsgType').text
    if msg_type == 'text':
        return TextMsg(xmlData)
    elif msg_type == 'image':
        return ImageMsg(xmlData)


class Msg(object):
    def __init__(self, xmlData):
        self.ToUserName = xmlData.find('ToUserName').text
        self.FromUserName = xmlData.find('FromUserName').text
        self.CreateTime = xmlData.find('CreateTime').text
        self.MsgType = xmlData.find('MsgType').text
        self.MsgId = xmlData.find('MsgId').text


class TextMsg(Msg):
    def __init__(self, xmlData):
        Msg.__init__(self, xmlData)
        self.Content = xmlData.find('Content').text.encode("utf-8")


class ImageMsg(Msg):
    def __init__(self, xmlData):
        Msg.__init__(self, xmlData)
        self.PicUrl = xmlData.find('PicUrl').text
        self.MediaId = xmlData.find('MediaId').text
回復(fù)消息代碼,保存為reply.py
# -*- coding: utf-8 -*-
# filename: reply.py

import time


class Msg(object):
    def __init__(self):
        pass

    def send(self):
        return "success"


class TextMsg(Msg):
    def __init__(self, toUserName, fromUserName, content):
        self.__dict = dict()
        self.__dict['ToUserName'] = toUserName
        self.__dict['FromUserName'] = fromUserName
        self.__dict['CreateTime'] = int(time.time())
        self.__dict['Content'] = content

    def send(self):
        XmlForm = """
        <xml>
        <ToUserName><![CDATA[{ToUserName}]]></ToUserName>
        <FromUserName><![CDATA[{FromUserName}]]></FromUserName>
        <CreateTime>{CreateTime}</CreateTime>
        <MsgType><![CDATA[text]]></MsgType>
        <Content><![CDATA[{Content}]]></Content>
        </xml>
        """
        return XmlForm.format(**self.__dict)


class ImageMsg(Msg):
    def __init__(self, toUserName, fromUserName, mediaId):
        self.__dict = dict()
        self.__dict['ToUserName'] = toUserName
        self.__dict['FromUserName'] = fromUserName
        self.__dict['CreateTime'] = int(time.time())
        self.__dict['MediaId'] = mediaId

    def send(self):
        XmlForm = """
        <xml>
        <ToUserName><![CDATA[{ToUserName}]]></ToUserName>
        <FromUserName><![CDATA[{FromUserName}]]></FromUserName>
        <CreateTime>{CreateTime}</CreateTime>
        <MsgType><![CDATA[image]]></MsgType>
        <Image>
        <MediaId><![CDATA[{MediaId}]]></MediaId>
        </Image>
        </xml>
        """
        return XmlForm.format(**self.__dict)

上面兩個(gè)文件只用保存就可以,不過細(xì)心的你會(huì)發(fā)現(xiàn),里面除了文字,還有圖片功能,這個(gè)后面再說。

有了接受和回復(fù)文件后,我們就要在handle.py文件中對(duì)Handle類進(jìn)行改寫,如下:

# filename: handle.py

import hashlib
import reply    # 導(dǎo)入回復(fù)文件
import receive  # 導(dǎo)入接收文件
import web


class Handle(object):
    def GET(self):
        try:
            data = web.input()
            if len(data) == 0:
                return "pika pika pikaqu!"
            signature = data.signature
            timestamp = data.timestamp
            nonce = data.nonce
            echostr = data.echostr
            token = 'XXXX'  # 請(qǐng)按照公眾平臺(tái)官網(wǎng)\基本配置中信息填寫

            list = [token, timestamp, nonce]
            list.sort()
            sha1 = hashlib.sha1()
            sha1.update(list[0].encode('utf-8'))
            sha1.update(list[1].encode('utf-8'))
            sha1.update(list[2].encode('utf-8'))
            hashcode = sha1.hexdigest()
            print("handle/GET func: hashcode, signature: ", hashcode, signature)
            if hashcode == signature:
                return echostr
            else:
                return ""
        except Exception as Argument:
            return Argument

    def POST(self):    # 新增加的POST函數(shù)
        try:
            webData = web.data()
            print("Handle Post webdata is ", webData)
            # 后臺(tái)打日志
            recMsg = receive.parse_xml(webData)
            if isinstance(recMsg, receive.Msg) and recMsg.MsgType == 'text':
                toUser = recMsg.FromUserName
                fromUser = recMsg.ToUserName
                content = "test"  # 這里是回復(fù)內(nèi)容
                replyMsg = reply.TextMsg(toUser, fromUser, content)
                return replyMsg.send()
            else:
                print("暫且不處理")
                return "success"
        except Exception as Argment:
            return Argment

現(xiàn)在代碼都寫好了,保存后輸入python(3) main.py 80,服務(wù)器啟動(dòng)。然后就可以進(jìn)行測(cè)試了。

正好在測(cè)試期間有讀者回復(fù),下面是截圖:

小編與一位讀者聊天的后臺(tái)截圖

初步test成功,不過還沒有達(dá)到我們的要求?,F(xiàn)在簡(jiǎn)單的消息回復(fù)功能就實(shí)現(xiàn)了。

下一步預(yù)告

經(jīng)過一番摸索,我們打通了服務(wù)器與微信公眾號(hào),也簡(jiǎn)單實(shí)現(xiàn)了消息回復(fù)功能,盡管還不是那么理想。

另外在測(cè)試中發(fā)現(xiàn),原來設(shè)置的自定義菜單不見了關(guān)注也沒有回復(fù)了,回復(fù)語音達(dá)不到效果。。。

下一步,我們將進(jìn)行如下實(shí)驗(yàn),對(duì)接智能機(jī)器人,讓回復(fù)更有個(gè)性關(guān)注與關(guān)鍵字回復(fù);語音也能很好的回復(fù)自定義菜單又出現(xiàn)了等功能。

本期實(shí)驗(yàn)記錄到此結(jié)束,感謝您的閱讀。如果您喜歡這期文章,請(qǐng)點(diǎn)贊,支持一下。

您可以關(guān)注公眾號(hào):JiawuLab,提前體驗(yàn)更多功能,或者給我留言,說說你遇到的問題,我們一起探討。

文中資源:

1、微信公眾號(hào)官方文檔地址:
https://developers.weixin.qq.com/doc/offiaccount/Getting_Started/Overview.html
2、WeRoBot github地址:
https://github.com/offu/WeRoBot/tree/master/werobot
3、WeRoBot文檔地址:
https://werobot.readthedocs.io/zh_CN/latest/

▼▼▼▼▼▼

長(zhǎng)按掃碼關(guān)注我
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容