zhayujie / chatgpt-on-wechat

基于大模型搭建的聊天机器人,同时支持 微信公众号、企业微信应用、飞书、钉钉 等接入,可选择GPT3.5/GPT-4o/GPT4.0/ Claude/文心一言/讯飞星火/通义千问/ Gemini/GLM-4/Claude/Kimi/LinkAI,能处理文本、语音和图片,访问操作系统和互联网,支持基于自有知识库进行定制企业智能客服。
https://docs.link-ai.tech/cow
MIT License
28.06k stars 7.47k forks source link

希望功能新增:添加将公众号信息转发到另外的服务, #2025

Open Lands-1203 opened 1 month ago

Lands-1203 commented 1 month ago

⚠️ 搜索是否存在类似issue

总结

我使用服务号搭建了AI的自动回复,但是菜单会失效。我使用了python代码在服务端创建了菜单,但是菜单类型有很多种:‘打开小程序’、‘打开链接’、‘自动回复’。其中自动回复("type": "click",)是通过触发KEY然后自动触发回复,这个在没有接入开发者的时候微信自带支持,但是接入服务器后,就需要服务器自己支持,由于我们cow,服务的信息接受已经被cow占用了,但是cow并没处理"type": "click",消息类型,我希望在配置里面可以添加一个转发到其他服务的功能,我使用其他服务给与微信回复。 以下是我创建菜单,和创建接收服务的整个过程 当我点击联系我们时,请求日志会答应下面的日志 但不会处理 image

menu.json

{
    "button": [
        {
            "name": "合作方",
            "sub_button": [
                {
                    "type": "view",
                    "name": "入围电催&调解方",
                    "url": "https://xxxxx"
                },
                {
                    "type": "view",
                    "name": "入围律师事务所",
                    "url": "https://xxxxxx"
                },
                {
                    "type": "click",
                    "name": "联系我们",
                    "key": "CONTACT_US"
                }
            ]
        },
        {
            "type": "view",
            "name": "联系客服",
            "url": "https://work.weixin.qq.com/xxxxx"
        }
    ]
}

config.py


WECHAT_APPID = 'xxxx'
WECHAT_SECRET = 'xxxx'
TOKEN = 'xxxx'

responses.py

# responses.py
RESPONSES = {
    "CONTACT_US": "咨询电话:xxx\n邮箱:xxx@xxx.com"
}

wechat_menu.py

import requests
import json
from config import WECHAT_APPID, WECHAT_SECRET

# 获取 access token

def get_access_token(appid, secret):
    url = f"https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={appid}&secret={secret}"
    print("发出请求获取 access token")
    response = requests.get(url)
    if response.status_code == 200:
        data = response.json()
        return data.get('access_token')
    else:
        print(f"获取 access token 失败: {response.text}")
        return None

# 创建菜单

def create_menu(access_token, menu_data):
    print("进入create_menu")

    url = f"https://api.weixin.qq.com/cgi-bin/menu/create?access_token={access_token}"
    response = requests.post(url, data=menu_data.encode('utf-8'))
    if response.status_code == 200:
        data = response.json()
        if data.get('errcode') == 0:
            print("菜单创建成功")
        else:
            print(f"菜单创建失败: {data}")
    else:
        print(f"请求失败: {response.text}")

print("开始")
access_token = get_access_token(WECHAT_APPID, WECHAT_SECRET)
print(f"access_token: {access_token}")
if access_token:
    with open('menu.json', 'r', encoding='utf-8') as file:
        menu_data = file.read()
    create_menu(access_token, menu_data)

wechat_server.py

from flask import Flask, request, make_response
import hashlib
import xml.etree.ElementTree as ET
import time
import argparse
from config import TOKEN
from responses import RESPONSES

app = Flask(__name__)

def verify_signature(signature, timestamp, nonce, token):
    tmp_list = [token, timestamp, nonce]
    tmp_list.sort()
    tmp_str = ''.join(tmp_list)
    hash_str = hashlib.sha1(tmp_str.encode('utf-8')).hexdigest()
    return hash_str == signature

def create_text_response(from_user, to_user, content):
    response = f"""
        <xml>
        <ToUserName><![CDATA[{from_user}]]></ToUserName>
        <FromUserName><![CDATA[{to_user}]]></FromUserName>
        <CreateTime>{int(time.time())}</CreateTime>
        <MsgType><![CDATA[text]]></MsgType>
        <Content><![CDATA[{content}]]></Content>
        </xml>
    """
    return response

@app.route('/wechat', methods=['GET', 'POST'])
def wechat():
    if request.method == 'GET':
        signature = request.args.get('signature')
        timestamp = request.args.get('timestamp')
        nonce = request.args.get('nonce')
        echostr = request.args.get('echostr')

        if verify_signature(signature, timestamp, nonce, TOKEN):
            return echostr
        else:
            return "Signature verification failed"

    elif request.method == 'POST':
        xml_data = request.data
        xml_tree = ET.fromstring(xml_data)
        msg_type = xml_tree.find('MsgType').text
        from_user = xml_tree.find('FromUserName').text
        to_user = xml_tree.find('ToUserName').text

        if msg_type == 'event':
            event = xml_tree.find('Event').text
            if event == 'CLICK':
                event_key = xml_tree.find('EventKey').text
                response_content = RESPONSES.get(event_key, "未找到相应的自动回复内容")
                response = create_text_response(from_user, to_user, response_content)
                response = make_response(response)
                response.content_type = 'application/xml'
                return response

        elif msg_type == 'text':
            content = xml_tree.find('Content').text
            response_content = f"您发送的是: {content}"
            response = create_text_response(from_user, to_user, response_content)
            response = make_response(response)
            response.content_type = 'application/xml'
            return response

        return "success"

if __name__ == '__main__':
    parser = argparse.ArgumentParser(description='WeChat Server')
    parser.add_argument('--port', type=int, default=80, help='Port to run the server on')
    args = parser.parse_args()

    app.run(host='0.0.0.0', port=args.port)
## 安装资源
`pip install -r requirements.txt`
## 创建菜单
`python3 wechat_menu.py`
## 启动关键字触发服务
`python wechat_server.py --port 8888`

举例

No response

动机

No response