wechatpy开发微信公众号(实现自定义菜单,翻译)

今天来学习通过wechatpy 来开发微信公众号。
准备工作:
1.申请一个微信公众号
2.pip install wechatpy
如是自己没有服务器,下载ngrok :ngrok 是一个反向代理,通过在公共端点和本地运行的 Web 服务器之间建立一个安全的通道,实现内网主机的服务可以暴露给外网

有兴趣的可以先看WeChatpy的官方文档

1.打开ngrok,复制图中所示代码,点击确认
wechatpy开发微信公众号(实现自定义菜单,翻译)_第1张图片
出现下列结果,将图示网址复制到浏览器打开如图所示:
wechatpy开发微信公众号(实现自定义菜单,翻译)_第2张图片
2 新建一个Django项目,并在里面新建一个名字为wechat的app. 在settings.py 文件里,添加wechat的app,更改host = [’*’],在wechat 的view.py 文件里进行如下先添加如下代码:

from wechatpy.utils import check_signature
from wechatpy.exceptions import InvalidSignatureException
from django.http import HttpResponse
from wechatpy import WeChatClient

# 这里的token 取自微信公众号自己设置的
token = 'fan'

def handle_wx(request):
    # GET 方式用于微信公众平台绑定验证
    if request.method == 'GET':
        signature = request.GET.get('signature', '')
        timestamp = request.GET.get('timestamp', '')
        nonce = request.GET.get('nonce', '')
        echo_str = request.GET.get('echostr', '')
        try:
            check_signature(token, signature, timestamp, nonce)
        except InvalidSignatureException:
            echo_str = '错误的请求'
        response = HttpResponse(echo_str)
        return response

在urls.py 文件里加入路由,并在主文件的urls 文件里include(‘wechat.urls’)
在命令行以80端口启动该文件:python manage.py runserver 80
wechatpy开发微信公众号(实现自定义菜单,翻译)_第3张图片
因为我们还没有在微信公众号设置,所以这里暂时返回的是错误的
wechatpy开发微信公众号(实现自定义菜单,翻译)_第4张图片
配置公众号
进入到公众号页面后,左边的菜单栏有一个基本配置,点击,输入刚才的网址,令牌自己写,我这里是fan,随机生成秘钥,点击确认,如图所示
wechatpy开发微信公众号(实现自定义菜单,翻译)_第5张图片
在左边点击开发者工具, 点击公众平台测试账号
wechatpy开发微信公众号(实现自定义菜单,翻译)_第6张图片
用微信扫码登录后如图所示;
wechatpy开发微信公众号(实现自定义菜单,翻译)_第7张图片

一 自定义菜单

还是上面的网页,接着往下拉,会看到图中所示
wechatpy开发微信公众号(实现自定义菜单,翻译)_第8张图片
点进去之后,可以看到有很多关于菜单的操作,这里只介绍如何创建新菜单
wechatpy开发微信公众号(实现自定义菜单,翻译)_第9张图片
现在切换到Django项目,在wechat的views.py 文件中,接着上面的函数,我们重新定义一个函数,把自定义菜单的创建接口代码复制过去,可以进行改动,如下所示

def create_menu(request):
	# 第一个参数是公众号里面的appID,第二个参数是appsecret
    client = WeChatClient("wxd8adb366cf6afb91", "4c0faa3a007df74b0664da87ad2887b8")
    client.menu.create({
         "button": [
            {
                "type": "click",
                "name": "今日歌曲",
                "key": "V1001_TODAY_MUSIC"
            },
            {
                "type": "click",
                "name": "歌手简介",
                "key": "V1001_TODAY_SINGER"
            },
            {
                "name": "菜单",
                "sub_button": [
                    {
                        "type": "view",
                        "name": "搜索",
                        "url": "http://www.soso.com/"
                    },
                    {
                        "type": "view",
                        "name": "视频",
                        "url": "http://v.qq.com/"
                    },
                    {
                        "type": "click",
                        "name": "赞一下我们",
                        "key": "V1001_GOOD"
                    }
                ]
            }
        ],
        "matchrule": {
            "group_id": "2",
            "sex": "1",
            "country": "中国",
            "province": "广东",
            "city": "广州",
            "client_platform_type": "2"
        }
    })
    return HttpResponse('ok')

书写完毕,把该函数添加到路由,重启服务,打开浏览器,输入:
http://dda0fdf3.ngrok.io/wx/create_menu/, 显示如下图所示,表示成功
(网址每个人都不一样,但是后面的配置是一样的)
wechatpy开发微信公众号(实现自定义菜单,翻译)_第10张图片
扫描并关注测试号二维码,可以看到如下界面,表示已经成功。
wechatpy开发微信公众号(实现自定义菜单,翻译)_第11张图片

二 接入外部的API

上面的菜单可以连接到外部不同的接口,传回不同的数据,这里取免费的腾讯AI平台文本翻译,现在该平台进行相应的注册与登录,创建应用,接入能力,如图所示, 记得保存好自己App_ID 与 App_Key 后面会用到
wechatpy开发微信公众号(实现自定义菜单,翻译)_第12张图片
走到这一步,我们可以先下载源码看看,这样可以省去好多事
wechatpy开发微信公众号(实现自定义菜单,翻译)_第13张图片
解压之后,发现有三个文件夹,一会我们要用到的东西就在这里面
wechatpy开发微信公众号(实现自定义菜单,翻译)_第14张图片
我们在wechat这个app 里新建一个py文件。名为utils ,将如下代码复制进去,

import apiutil
from wechatpy import create_reply

def translate(msg):

    app_id = '2109327500'
    app_key = 'K6oaVJvL7oUmA1co'

    str_text = msg.content
    
    type = 0
    ai_obj = apiutil.AiPlat(app_id, app_key)
    rsp = ai_obj.getNlpTextTrans(str_text, type)
    str_rsp = create_reply(rsp, msg)
    return str_rsp

如果你看了源码的话,你会发现,这个文件就是上面那个文件夹demo 里面的test_npl_texttrans.py文件,只是做了一些改动。
test_npl_texttrans.py 里str_text 的字符串是写死的,因为这里是用作翻译,所以是用一个变量来接受。
一会在view.py 文件中,接受到这个参数。
代码飘红不要紧,
暂时将上面的SDK文件夹中的apiutil.py 文件复制到项目的主目录,因为上面的代码要导入模块就在这个文件里。 这里只是暂时导入,因为这个文件使用Python2 写的,但是我们用的是Python3 ,所以一会要做些许改动,这里暂时先放着。

改动后的apiutil.py 文件:
其中将urlib2 删除,改为用requests,
将暂时不需要的函数删除,因为是做测试用,所以也将一些try: except 的内容进行简略处理。
这个文件最后的一个返回值是翻译过后的值

import hashlib
import urllib
import time
import requests


url_preffix = 'https://api.ai.qq.com/fcgi-bin/'

def setParams(array, key, value):
    array[key] = value


# 这个parser 就是下面传进来的字典
def genSignString(parser):
    uri_str = ''
    for key in sorted(parser.keys()):
        if key == 'app_key':
            continue
        uri_str += "%s=%s&" % (key, urllib.parse.quote(str(parser[key]), safe=''))
    sign_str = uri_str + 'app_key=' + parser['app_key']
    sign_str = sign_str.encode()
    hash_md5 = hashlib.md5(sign_str)
    return hash_md5.hexdigest().upper()


class AiPlat(object):
    def __init__(self, app_id, app_key):
        self.app_id = app_id
        self.app_key = app_key
        # 设置一个字典,把以后的参数都以键值对的形式展现出来
        self.data = {}

    # 这里的params 也是字典
    def invoke(self, params):
        self.url_data = urllib.parse.urlencode(params)
        print(self.url_data)
        # 下来该执行API调用

        try:
            req = requests.get(self.url, self.url_data).json()
            str_rsp = req['data']['trans_text']
            return str_rsp
        except Exception as e:
            dict_error = {}
            if hasattr(e, "code"):
                dict_error = {}
                dict_error['ret'] = -1
                dict_error['httpcode'] = e.code
                dict_error['msg'] = "sdk http post err"
                return dict_error
            if hasattr(e, "reason"):
                dict_error['msg'] = 'sdk http post err'
                dict_error['httpcode'] = -1
                dict_error['ret'] = -1
                return dict_error

    def getNlpTextTrans(self, text, type):
        self.url = url_preffix + 'nlp/nlp_texttrans'
        setParams(self.data, 'app_id', self.app_id)
        setParams(self.data, 'app_key', self.app_key)
        setParams(self.data, 'time_stamp', int(time.time()))
        setParams(self.data, 'nonce_str', int(time.time()))
        setParams(self.data, 'text', text)
        setParams(self.data, 'type', type)
        sign_str = genSignString(self.data)
        # 大键是sigh,后面又是字典嵌套
        setParams(self.data, 'sign', sign_str)
        return self.invoke(self.data)

在views.py 文件的handle_wx 函数补上下面的代码:
因为这次是Post 请求

from wechatpy import parse_message
from .utils import translate

token = 'fan'
def handle_wx(request):
    # GET 方式用于微信公众平台绑定验证
    if request.method == 'GET':
        signature = request.GET.get('signature', '')
       ........
       .......
       ......
        response = HttpResponse(echo_str)
        return response
    else:
        msg = parse_message(request.body)
        if msg.type == 'text':
            reply = translate(msg)
        response = HttpResponse(reply.render(), content_type='application/xml')
        return response

这时,我们扫描这个测试公众号二维码,输入一些汉子,可以看到,它已经返回了相应的英文
wechatpy开发微信公众号(实现自定义菜单,翻译)_第15张图片
至此,所有的问题已经解决。当然在上面的代码中肯定会遇到很多问题,要学会找出问题在哪。
比如,在输入了相应的文字后,没有返回值,我们就要去判断,是哪个环节出了问题,先看后端能接受到这个数据嘛,最简单的方法就是通过print()来打印判断。如果能接受到,再判断能否将数据封装好,传递给腾讯翻译后端,后端再返回数据,能接受到数据吗…这都是一系列问题,要慢慢的去测试,一步步的的判断问题出在哪里。

你可能感兴趣的:(wecaht)