python微信公众号生成专属二维码--你再也不用去求人了
来源:互联网 发布:决战武神弓进阶数据 编辑:程序博客网 时间:2024/04/29 21:30
需求:公司需要开发微信公众号,并且和h5无缝对接。由于以前都是运营人员直接在微信公众平台进行编辑的,就从没考虑如何做。前几天运营人员有个需求,也就是我们平日在别人公众号里点击生成专属二维码,现在要求统计谁生成的二维码,谁通过此二维码进行的扫码关注。
小公司,开发2人,原本想直接在网上找一个python的模块,import即可,想到今后要扩展功能会不会很麻烦。就自己干了。(既然微信开发的api,如果很复杂的话,公众号就不会这么火了。)
思路:微信平台就类似中间件, 我们的服务器,以及用户之间进行三角恋的变态关系。
1:和微信平台建立信赖关系。就是配置咱们的服务器和微信的连接。
2:微信事件推送,咱们服务器收到后,进行反馈。(微信有5秒等待时间)
3:调用微信二维码生成接口。(参数二维码)
4:利用python qrcode生成参数二维码,用PIL 将二维码图片和漂亮的背景图片进行合并,paste到设计的指定位置。
4:将图片上传至微信素材
5:将消息发给用户。
整个流程没有任何难点,难点就是特么文档接口之间毫无联系,查起来效率老低了。不知为何市场上却那么多以此谋生的企业???(你只需要最多一天的时间基本搞定所有这些东西)
废话不设了,
1:https://mp.weixin.qq.com/wiki 在文档中点击 接入指南。
token自己输入一个你喜欢并且保密的字符串。
当配置号url,token,EncodingAESKey 我们需要做的就是用我们的服务器在此url链接下返回微信想要的数据。(目的告诉微信相信我哦),这一步通过后,才能进行下面的步骤。
所以按照文档要求:
1)将token、timestamp、nonce三个参数进行字典序排序
2)将三个参数字符串拼接成一个字符串进行sha1加密
3)开发者获得加密后的字符串可与signature对比,标识该请求来源于微信
ajaxLogger = logging.getLogger('ajax')@csrf_exemptdef wechat_message_views(request): result = {} result["title"] = "微信消息" if request.method == 'GET': if request.GET.has_key("signature"): signature = request.GET["signature"] timestamp = request.GET["timestamp"] nonce = request.GET["nonce"] echostr = request.GET["echostr"] token = "你的touken" data_list = [token, timestamp, nonce] data_list.sort() weixin_sha1 = hashlib.sha1() weixin_sha1.update("".join(data_list)) weixin_sha1 = weixin_sha1.hexdigest() if weixin_sha1 == signature: response = HttpResponse(echostr) ajaxLogger.info("成功") else: response = HttpResponse("403") ajaxLogger.info("非法") else: ajaxLogger.info(request.get_host()) response = HttpResponse("ok") return response return what_you_want_do(request)
其中,@csrf_exempt很重要,不然就403了。
接入成功。
2:接收微信事件推送。
(1)关注和取关事件推送
(2)扫描带参数二维码事件
就他两个了,最简单暴力的方法就是直接分析微信发送的xml格式。根据xml内容进行函数执行。(这里你可以用高级的python语法就执行)
在我们的服务器url 接口函数那里,我们的 what_you_want_do函数需要进行事件判读,然后分发。你可以用策略模式等高级方法去完善。咱们直接if else…………(记得有仁熊说过,有的人写了一辈子代码,永远的if else)
from xml.dom.minidom import parseStringdef weixin_deal_xml(nodes,key): try: node_data = nodes.getElementsByTagName(key) if node_data: return node_data[0].childNodes[0].data else: return [] except Exception, e: ajaxLogger.error( "解析XML错误 : %s"%str(e) ) return []def what_you_want_do(request): #先要验证request,方法和上面get一样,咱也要知道request是否来自微信 xml_result = request.body try: nodes = parseString(xml_result).documentElement except Exception, e: ajaxLogger.error("报错啦,sb %s" %str(e)) return HttpResponse("403") #研究发现微信的返回参数都有的,就这么干了,最好是封装成函数,说不定今后有变化 msg_type = weixin_deal_xml(nodes, "MsgType") user_open_id = weixin_deal_xml(nodes, "FromUserName") wechat_pub_id = weixin_deal_xml(nodes, "ToUserName") create_time = weixin_deal_xml(nodes, "CreateTime") if not msg_type: return HttpResponse("") if not user_open_id: return HttpResponse("") #此处开始处理 事件推送,根据事件推送类型,去处理 if msg_type == "event": event = weixin_deal_xml(nodes, "Event") eventkey = weixin_deal_xml(nodes, "EventKey") return deal_wechat_event(event, eventkey, user_open_id, wechat_pub_id, create_time) else: pass
收到不同微信服务器的事件推送,理论我们都应该就行xml的回复。如果是
VIEW : 视图跳转,咱们可以不返回,有需要后台存储一下用户的点击行为
CLICK :(这里参数二维码生成一定要是CLICK事件)。即在生成menu(https://api.weixin.qq.com/cgi-bin/menu/create?access_token={ACCESS_TOKEN})时,一定要将生成专属二维码设置成click。类似 {
“type”:”click”,
“name”:u”邀请好友”,
“key”:”V1001_你的_CODE_KEY”
}
此时,咱们做接收click事件,并通过key来判断是哪一个,然后返回相应的函数。
由于咱们处理生成二维码,还要进行和微信服务器素材的交互行为,但事件推送等待时间有限。咱们采用异步处理模式(gearman处理),先发一个消息提示用户,让用户等待一下,正在生成中。如:
即what_you_want_do函数,不论收到来自微信的任何消息,都应该返回一个xml消息。这里我们先返回一段话给用户。
根据微信的消息格式,这里一定要注意,微信没有在文档中进行说明,消息必须回复。真是坑爹,一定要回他哦。
import timedef response_to_wechat(touser, fromuser, text_content): data = "<xml><ToUserName><![CDATA[%s]]></ToUserName>\ <FromUserName><![CDATA[%s]]></FromUserName>\ <CreateTime>%s</CreateTime>\ <MsgType><![CDATA[%s]]></MsgType>\ <Content><![CDATA[%s]]></Content>\ </xml>"%(touser, fromuser, int(time.time()), "text", text_content ) return HttpResponse(data, content_type="application/xml")
调用response_to_wechat 发送一段等待的话给他,在这个之前调用异步生成参数二维码接口。
def deal_wechat_event(event, eventkey, user_open_id, wechat_pub_id, create_time): # 点击菜单事件 if event == "CLICK": if eventkey == "V1001_你的_CODE_KEY": params = { "user_open_id":user_open_id, "eventkey":eventkey, "wechat_pub_id":wechat_pub_id, "create_time":create_time } call_command('gearman_submit_job','worker_name', json.dumps(params),foreground=False) text_content = "协力正为您生成邀请二维码,等待5秒左右即可收到。" return response_to_wechat(user_open_id, wechat_pub_id, text_content)
(上面的if ,else 都可以通过python技巧,以及设计模式进行更好的代码维护。自己进行吧。)
异步的worker,我们在里面定义处理函数。
函数一:生成参数二维码,需求里我们要存储生成二维码的用户的信息。(此用户信息即为参数key。当其他人通过扫描生成的二维码时,我们要从推送的信息中查询微信返回的key是哪个用户。)
文档
我们使用临时二维码,临时素材。(因为永久的生成的个数太少了)
def create_scene_qrcode(user_open_id): scene_id = 100000000 #(每个用户不一样,你自己需要进行改变,如自增) # 获取参数二维码 url。自己进行二维码图片生成 url = wechat_qr_imge_url(scene_id) image_data = create_wechat_qrcode(url) media_id = post_picture_to_weixin(image_data) create_time = int(time.time()) send_user_message(user_open_id, media_id)
#带参数二维码def wechat_qr_imge_url(final_scene_id): ACCESS_TOKEN = get_accesstoken() url = "https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token={ACCESS_TOKEN}".format(ACCESS_TOKEN=ACCESS_TOKEN) data = { "expire_seconds": 1000, "action_name": "QR_SCENE", "action_info": {"scene": {"scene_id": final_scene_id} } } data = json.dumps(data) try: data_result = requests.post(url,data.encode('utf8')) result = data_result.json() ajaxLogger.info(str(result)) if result.has_key("ticket"): ticket = result["ticket"] url = result["url"] return url except Exception, e: ajaxLogger.error("生成专属参数二维码 {error}".format(error=str(e)))# 获取二维码ticket后,开发者可用ticket换取二维码图片,也可以将返回的url自行处理,咱们自此处理#{"ticket":"gQH47joAAAAAAAAAASxodHRwOi8vd2VpeGluLnFxLmNvbS9xL2taZ2Z3TVRtNzJXV1Brb3ZhYmJJAAIEZ23sUwMEmm# 换取二维码图片# https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=TICKET
get_accesstoken方法,实现了使用redis存储token,因为token微信每天获取次数有限制,并且有过期时间。所以咱们使用reids expire。将过期时间和 token过期一致即可。非常简单
create_wechat_qrcode 生成合并图片。
此函数目的就是1:生成二维码,2:将二维码和美丽的背景图片进行合并。
from PIL import Imageimport qrcodefrom io import StringIO, BytesIOdef create_wechat_qrcode(params): #参数可自行调整 qr = qrcode.QRCode( version=2, error_correction=qrcode.constants.ERROR_CORRECT_H, box_size=10, border=1 ) #二维码填充内容 qr.add_data(params) qr.make(fit=True) img = qr.make_image() img = img.convert("RGBA") #打开背景图片 icon = Image.open("你的背景图片地址.png") #根据设计将二维码填充到制定位置 icon.paste(img, ("位置坐标", "位置坐标"), img) buf = BytesIO() #生成二进制文件,直接发给微信 icon.save(buf,format="PNG") file_content = buf.getvalue() return file_content
此函数将图片上传至微信的临时素材
post_picture_to_weixin
# 上传图消息素材def post_picture_to_weixin(rawimg): ACCESS_TOKEN = get_accesstoken() url = "https://api.weixin.qq.com/cgi-bin/media/upload?access_token={ACCESS_TOKEN}&type={TYPE}".format(ACCESS_TOKEN=ACCESS_TOKEN, TYPE="image") file_name = str(time.time()).split(".")[0] + 'tmp.png' #微信文档有文件上传时的要求 files = { 'media' : (file_name, rawimg,'image/png')} res = requests.post(url, files=files) result_data = res.json() #media_id 通过media_id给微信用户发送图片消息 if result_data.has_key("media_id"): media_id = result_data["media_id"] return media_id
最后哦,send_user_message给用户主动发消息。(由于我们异步处理,xml格式的回复已经发给用户,现在就得主动发消息给用户。)
def send_user_message(OPENID, MEDIA_ID, msgtype="image"): ACCESS_TOKEN = get_accesstoken() url = "https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token={ACCESS_TOKEN}".format(ACCESS_TOKEN=ACCESS_TOKEN) data = { "touser":OPENID, "msgtype":msgtype, "image": { "media_id":MEDIA_ID } } if msgtype == "text": data["text"] = { "content":"Hello World" } request_weixin(url, data)def request_weixin(url, data): # 有些中文,以及json格式中的,必须使用ensure_ascii=False,不然有时会报错 data = json.dumps(data, ensure_ascii=False) try: data_result = requests.post(url,data.encode('utf8')) result = data_result.json() print result # ajaxLogger.info(str(result)) except Exception, e: print e # ajaxLogger.error("设置客服失败 {error}".format(error=str(e)))
哈哈没有美工,就拿logo放在中间啦,结果logo和二维码,太丑陋了。
至此我们就完成了,生成专属二维码的整个流程和代码。
第一次在这里发博客,如果有错误欢迎大家指出来。如果帮助了大家,希望大家给个赞。
- python微信公众号生成专属二维码--你再也不用去求人了
- 生成微信公众号关注二维码
- 爱迈分享 海量淘宝天猫优惠券网站微信公众号自主搜索 再也不用加入烦人的QQ微信群了
- 公众号生成带参数二维码,php开发微信公众号生成推广二维码
- 微信支付放大招 再也不用担心限额了!
- 生成公众号永久二维码,php开发微信公众号永久二维码
- 微信公众号 订阅号 生成带参数二维码
- 微信生成公众号带参数二维码(一)
- 微信公众号开发---生成带参二维码
- 微信公众号开发---生成带参二维码
- 微信公众号生成带参数的二维码
- 微信公众平台生成场景二维码
- 微信公众号二维码
- 是时候给你的微信公众号请一位专属客服了
- JDK自带工具一览表。妈妈再也不用担心你到处去下载小软件了~~
- 微信官方提供的生成二维码接口得到的是当前公众号的二维码。
- 微信官方提供的生成二维码接口得到的是当前公众号的二维码
- 微信公众平台自带的生成公众号二维码的连接
- hdu 3038 日了狗的并查集
- SSL JudgeOnline 1069——比赛安排
- c# 使用Sharpcap进行网络数据包监听
- 新人掌握的五大Linux终端命令的技巧
- iOS 卡顿总结优化
- python微信公众号生成专属二维码--你再也不用去求人了
- Qt测算程序运行时间
- Python基础学习笔记
- Android特效专辑(十一)——仿水波纹流量球进度条控制器,实现高端大气的主流特效
- Javascript--父子数据层次结构和平行结构的转换
- Spring Boot 多数据源
- Async和Await如何简化异步编程,几个实例让你彻底明白!
- oracle打补丁
- 回调函数的作用机制