代码不维护,可能已经不好使了,企业微信版的现在域名报错第三方,需要自己研究方法了,别问我,我很久不弄这个了。只能给你们提供逻辑,其他的你们自己悟吧
微信个人聊天版本
网上很多微信机器人版本的,但是原理是网页版微信,很多账号都不能登陆网页版微信,然后还随时面临着24小时封禁的风险,不是很靠谱。
小程序版本
小程序版本,使用uniapp做的小程序,然后上线了一阵,后来被封禁了,就是如下的感觉。
封禁原因是接口被封
想要强制使用的话,就是云服务开个云函数,然后做个接口请求转发,也可以正常用。
公众号版本
小程序弄完了,感觉每次还要下滑找小程序,进小程序,跳转界面什么的,不是很方便,于是我又开始研究公众号版本。
公众号可以接收个人发送的消息,然后通过接口回复消息,这样就可以用AI大模型来就行回复了。
大概效果是这样:
我这个是挂载到阿里云的云函数里面,代码如下:
from flask import Flask,make_response
from flask import request
import xml.etree.ElementTree as ET
import hashlib
import requests
import json
import time
import re
REQUEST_ID_HEADER = 'x-fc-request-id'
app = Flask(__name__)
# openai的key
openaikey = 'sk-s5S5BoVMLTUyVtEVL'
# 微信公众号的appid
appid= "wx518c64",
# 微信公众号的secret
secret= "e68a9550"
@app.route('/robot', methods=['GET','POST'])
def wechat_tuling():
if request.method == 'GET':
print(request)
my_signature = request.args.get(
'signature', '') # 获取携带 signature微信加密签名的参数
my_timestamp = request.args.get('timestamp', '') # 获取携带随机数timestamp的参
my_nonce = request.args.get('nonce', '') # 获取携带时间戳nonce的参数
my_echostr = request.args.get('echostr', '') # 获取携带随机字符串echostr的参数
token = 'xytx'
# 这里输入你要在微信公众号里面填的token,保持一致
data = [token, my_timestamp, my_nonce]
data.sort()
# 进行字典排序
temp = ''.join(data)
# 拼接成字符串
mysignature = hashlib.sha1(temp.encode('utf-8')).hexdigest()
# # 判断请求来源,将三个参数字符串拼接成一个字符串进行sha1加密,记得转换为utf-8格式
if my_signature == mysignature:
# 开发者获得加密后的字符串可与signature对比,标识该请求来源于微信
return make_response(my_echostr)
else:
return ''
if request.method == 'POST':
print(request)
print(request.data)
try:
return ''
finally:
xml = ET.fromstring(request.data)
print('XML',xml)
# 获取用户发送的原始数据
# fromstring()就是解析xml的函数,然后通过标签进行find(),即可得到标记内的内容。
fromUser = xml.find('FromUserName').text
toUser = xml.find('ToUserName').text
msgType = xml.find("MsgType").text
# 获取向服务器发送的消息
createTime = xml.find("CreateTime")
content = xml.find('Content').text
print(content)
xml_sta = '<xml><ToUserName><![CDATA[%s]]></ToUserName><FromUserName><![CDATA[%s]]></FromUserName><CreateTime>%s</CreateTime><MsgType><![CDATA[text]]></MsgType><Content><![CDATA[%s]]></Content></xml>'
# 定义返回的xml数据结构,这里指的是文本消息,更多请参考微信公众号开发者文档
print(xml_sta)
if msgType == 'text':
# 判断消息类型,如果返回的字段是text,则是文字
print('接收到的text')
tuling_reply = reply(fromUser,content)
print('openai begin')
# 调用api回复赋值给xml里面的content,这里定义为tuling_reply
res = make_response(xml_sta % (fromUser, toUser, str(int(time.time())), tuling_reply))
# 微信公众号做出响应,自动回复的格式如上
print(res)
res.content_type = 'application/xml'
# 定义回复的类型为xml
print('res',res)
return res
# 输出自动回复
else:
# 如果输入非文字的则会提示下面这句话
return '我还只会文字,请等我慢慢成长,谢谢!'
def reply(user,info):
print('进入接口')
# 调用api
api = '填写你自己的大模型接口地址'
# 请求api接口的网址
data = {
"prompt": info, "max_tokens": 2048, "model": "text-davinci-003"
}
headers = {
'content-type': 'application/json', 'Authorization': 'Bearer '+openaikey}
# 请求的数据(这里只有对话的,可以添加url或者其他,有问题查看官方文档)
print('合成数据',headers)
jsondata = json.dumps(data)
print('json化字典data',jsondata)
# 根据官方文档,需要把利用json.dumps()方法把字典转化成json格式字符串
try:
response = requests.post(api, data=jsondata, headers=headers,timeout=None)
print('开始请求')
# 发起post请求
robot_res = json.loads(response.content)
print('返回结果',robot_res)
# 把json格式的数据再转化成Python数据输出,注意编码为utf-8 格式
robot_reply = robot_res['choices'][0]['text']
print(robot_reply)
postsend(user,robot_reply)
return robot_reply
except:
return '服务接口缓慢请稍后重试'
def get_token():
"""
获取微信的access_token
:return:返回access_token
"""
url = "https://api.weixin.qq.com/cgi-bin/token"
params = {"grant_type": "client_credential",
"appid":appid,
"secret":secret}
a = requests.get(url=url, params=params).json().get("access_token")
print('aaaaaaaaaaaaaa',a)
return a
def postsend(fromUser,cont):
token=get_token()
params = {
"access_token": token
}
data = {
"touser": fromUser,
"msgtype": "text",
"text": {
"content": cont
}
}
print(data)
kf = requests.post("https://api.weixin.qq.com/cgi-bin/message/custom/send", params=params,data=bytes(json.dumps(data, ensure_ascii=False), encoding='utf-8'), headers = {"Content-type": "application/json", "charset": "UTF-8"})
print(kf.text)
return kf
if __name__ == '__main__':
app.run(host='0.0.0.0',port=9000)
函数代码部署后,在这里有公网访问地址:
拿到的地址,放在微信公众号的配置界面
然后启用就可以了
目前存在的问题就是,有的时候会推送多次,你问一个问题,但是微信公众号的后台会给你接口推送好几次,没空解决这个,举一反三也没啥事,有能力的自己维护改改bug吧。
但是这个微信公众号有的时候,会被订阅号折叠进去,找着使用的也很费劲,所以我又拿企业微信应用下手了
企业微信版本
大概的效果:
企业微信版本和公众号版本差不多,但是操作的东西需要的多一些
逻辑
逻辑就是企业微信接收到消息,然后解析成数据,然后发送给AI模型服务商,然后调用接口返回给企业微信
实现方式
首先阿里云函数部署接收企业微信推送消息的代码,然后再把AI模型接口返回的消息发送到腾讯云云计算服务上,再通过腾讯云计算服务把结果返回到企业微信,企业微信推送到个人微信。
听着是不是就很乱,但是必须要这么乱才能白嫖,如果你有个人服务器,有域名,有固定IP,就不用这么乱了。
因为企业微信应用接口需要一个域名做数据回调,但是腾讯云提供的业务域名会被判定为第三方服务商,不能用,只能用阿里云的函数计算应用的域名。又因为给企业微信推送消息的时候,需要一个固定的公网IP,阿里云的出口IP是收费的,腾讯云的函数计算的出口IP是免费的,所以就两个一起用吧
阿里云上的代码如下,看看就好,估计没人会照着这个部署的
from WXBizJsonMsgCrypt import WXBizJsonMsgCrypt
from WXBizMsgCrypt import WXBizMsgCrypt
import sys
from flask import Flask, request,Response,jsonify
import json
import xml.etree.cElementTree as ET
import requests
from config import config
REQUEST_ID_HEADER = 'x-fc-request-id'
app = Flask(__name__)
sToken = config.sToken
sEncodingAESKey = config.sEncodingAESKey
sCorpID = config.sCorpID
MsgIdglo=''
@app.route('/wx', methods=['GET','POST'])
def wxpush():
print(request)
if request.method == 'GET':
wxcpt = WXBizJsonMsgCrypt(sToken, sEncodingAESKey, sCorpID)
sVerifyMsgSig = request.args.get('msg_signature')
sVerifyTimeStamp = request.args.get('timestamp')
sVerifyNonce = request.args.get('nonce')
sVerifyEchoStr = request.args.get('echostr')
# print(sVerifyMsgSig, sVerifyTimeStamp, sVerifyNonce, sVerifyEchoStr)
ret, sEchoStr = wxcpt.VerifyURL(
sVerifyMsgSig, sVerifyTimeStamp, sVerifyNonce, sVerifyEchoStr)
# print('===============')
# print(ret,sEchoStr)
aa = int(sEchoStr)
# print('===============')
if (ret != 0):
print("ERR: VerifyURL ret: " + str(ret))
else:
print("done VerifyURL")
return jsonify(aa)
if request.method == 'POST':
try:
print('OKOK')
# return Response(status=200)
finally:
# 微信服务器发来的三个get参数
signature = request.args.get("signature")
timestamp = request.args.get("timestamp")
nonce = request.args.get("nonce")
# 加进同一个列表里
list1 = [sToken, timestamp, nonce]
encrypted_bytes = request.data
# print(type(encrypted_bytes))
if encrypted_bytes: # 获取openid参数和msg_signature参数
openid = request.args.get("openid")
msg_signature = request.args.get("msg_signature")
# 用微信官方提供的SDK解密,附带一个错误码和生成明文
keys = WXBizMsgCrypt(sToken, sEncodingAESKey, sCorpID)
# print('-----')
# print(encrypted_bytes, msg_signature, timestamp, nonce)
# encrypted_bytes.encode()
ierror, decrypted_bytes = keys.DecryptMsg(encrypted_bytes, msg_signature, timestamp, nonce)
# 若错误码为0则表示解密成功
print(decrypted_bytes)
if ierror == 0:
# 对XML进行解析
# print('00000')
# dom_data = parseString(decrypted_bytes).documentElement
xml_tree = ET.fromstring(decrypted_bytes)
print(xml_tree)
content = xml_tree.find("Content").text
user = xml_tree.find("FromUserName").text
agentid = xml_tree.find("AgentID").text
touse = xml_tree.find("ToUserName").text
MsgId = xml_tree.find("MsgId").text
creat = xml_tree.find("CreateTime").text
send(user,agentid,content,MsgId)
def send(touser,agen,content,MsgId):
print("开始请求",content)
openaikey = config.openaikey
print(openaikey)
MsgIdglo = MsgId
print(MsgIdglo,MsgId,'开始')
url='你对接的AI大模型的接口地址'
req = requests.post(url, json={"prompt": content, "max_tokens": 2048, "model": "text-davinci-003"}, headers={
'content-type': 'application/json', 'Authorization': 'Bearer '+openaikey})
print(req)
reqdic = json.loads(req.text)
aa = reqdic['choices'][0]['text']
print("aaaaaa",aa)
data = {
'touser':touser,
'agen':agen,
'mess':aa
}
String_textMsg=json.dumps(data)
HEADERS = {"Content-Type": "application/json ;charset=utf-8"}
wechaturl = config.wechaturl
res = requests.post(wechaturl, data=String_textMsg, headers=HEADERS)
return Response(res)
if __name__ == '__main__':
app.run(host='0.0.0.0', port=9000)
配套的还有一个config.py文件:
里面放着相关的秘钥等信息
class config():
#openaikey
openaikey = 'sk-s5S5BoVMLTU3btLsD'
# 企业微信的接口回调token
sToken = "7YWMt8FvunaE2oPJ7c0"
# 企业微信的接口回调AESKEY
sEncodingAESKey = "b72tmVWnptXYwuDI1"
# 企业微信的企业ID
sCorpID = "wweab244f"
# 腾讯云的函数公网访问域名
wechaturl = f'https://servicetencentcs.com/release/'
之后开始部署腾讯云的转发服务
import os
from flask import Flask, jsonify, render_template, request, url_for, send_from_directory
import requests
import json
IS_SERVERLESS = bool(os.environ.get('SERVERLESS'))
print(IS_SERVERLESS)
app = Flask(__name__)
@app.route("/", methods=['GET', 'POST'])
def index():
if request.method == 'POST':
print(request)
touser = request.json.get('touser')
agen = request.json.get('agen')
mess = request.json.get('mess')
corpid = 'wweb244f'
# 应用secret
corpsecret = 'k6b1TZ6I1woUI'
HEADERS = {"Content-Type": "application/json ;charset=utf-8"}
# 获取token
r = requests.get(
f'https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid={corpid}&corpsecret={corpsecret}').text
js = json.loads(r)
token = js['access_token']
# data 中agentid 按应用实际id更换
data = {
"touser": touser,
"msgtype": "text",
"agentid": agen,
"text": {
"content": mess
},
"safe": 0,
"enable_id_trans": 0,
"enable_duplicate_check": 0,
"duplicate_check_interval": 1800
}
String_textMsg = json.dumps(data)
# 企业微信应用地址
wechaturl = f'https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token={token}'
res = requests.post(wechaturl, data=String_textMsg, headers=HEADERS)
print(res.text)
return res.text
# 启动服务,监听 9000 端口,监听地址为 0.0.0.0
app.run(debug=IS_SERVERLESS != True, port=9000, host='0.0.0.0')
代码中的这两个换成你的企业微信的id和ser秘钥
然后就可以了
能教的就这么多了,有基础的经常开发企业应用的大神们可以优化优化