需求:公司需要开发微信公众号,并且和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_exempt
def 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 responsereturn 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 parseString
def weixin_deal_xml(nodes,key):try:node_data = nodes.getElementsByTagName(key)if node_data:return node_data[0].childNodes[0].dataelse:return []except Exception, e:ajaxLogger.error( "解析XML错误 : %s"%str(e) )return []def what_you_want_do(request):#先要验证request,方法和上面get一样,咱也要知道request是否来自微信xml_result = request.bodytry:nodes = parseString(xml_result).documentElementexcept 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 time
def 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 urlexcept 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 Image
import qrcode
from io import StringIO, BytesIO
def 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微信公众号生成专属二维码--你再也不用去求人了相关推荐

  1. 怎么实现微信公众号生成专属二维码推广来源统计

    为了实现微信公众号生成专属二维码推广来源统计功能,第三方平台微号帮提供了渠道二维码生成功能实现,可以给微信公众号在线生成专属推广二维码,统计公众号各个渠道来源的粉丝,一个渠道对应一个推广二维码,可以生 ...

  2. 微信公众号生成临时二维码

    微信公众号生成临时二维码 微信公众平台生成带参数的二维码官方文档 分为三个部分: 获取access_token.通过ticket换取二维码.生成带参数的二维码 特别注意:需要有生成二维码的权限. 整个 ...

  3. 【黄啊码】PHP配合微信公众号生成推广二维码

    前言 为了满足用户渠道推广分析和用户帐号绑定等场景的需要,公众平台提供了生成带参数二维码的接口.使用该接口可以获得多个带不同场景值的二维码,用户扫描后,公众号可以接收到事件推送. 1.目前有2种类型的 ...

  4. java_微信公众号扫码绑定个人信息(微信公众号场景值二维码的使用)

    看了一下网上关于公众号场景值二维码这方面的教程,基本上是微信官方开发文档的复制,没有具体实例.这里给出实例,并附加二维码url转文件流的方法. 思路: 1.后台传入个人信息保存,以个人信息的" ...

  5. 微信公众号带参数二维码的几个使用场景

    微信公众号官方开放了 "带参数二维码" 的功能,根据官网文档的描述,有如下的特点: 为了满足用户渠道推广分析和用户帐号绑定等场景的需要,公众平台提供了生成带参数二维码的接口. 通过 ...

  6. Yii实现微信公众号的场景二维码

    在Yii中实现场景二维码这里我使用的是easywechat插件,安装easywechat插件 composer require jianyan74/yii2-easy-wechat github地址: ...

  7. laravel生成微信公众号带参数二维码并响应扫描带参数二维码

    微信公众号后台ip白名单.网页接口域名之类的配置就不多说了,这里主要配置的是开发->基本配置->服务器配置(注:一旦启用改配置,公众号自动回复就会失效): 1.服务器地址(URL):这里要 ...

  8. 微信公众号带参二维码的生成以及后台Java的处理

    1.生成带参二维码 有两种方式,一是通过微信公众平台来生成,二是通过java代码生成 一:微信平台生成 首先进入公众平台,找到接口权限进入 进入后找到获取access_tocken接口,获取acces ...

  9. JAVA微信公众号开发之二维码的创建与获取

    微信文档说明 两种二维码: 1.临时二维码,是有过期时间的,最长可以设置为在二维码生成后的30天(即2592000秒)后过期,但能够生成较多数量.临时二维码主要用于帐号绑定等不要求二维码永久保存的业务 ...

  10. python之MyQR库生成专属二维码

    目录 普通的二维码 带图片的二维码 动态的二维码 自动化生成脚本 MyQR是Python的一个第三方库,专门用来制作个性二维码,可以静态可以动态,简直潮流啊.在Python调用MyQR之前需要先安装M ...

最新文章

  1. php完美实现下载远程图片保存到本地(保存微信头像)
  2. 动态绑定与继承:不得不去想细节
  3. IIS7 设置读取、脚本和可执行文件的执行权限的步骤
  4. azure webjob java_Executing Java Web Jobs on Azure
  5. xcode 5 使用 XCTest 做单元测试
  6. .NET 开源免费图表组件库,Winform,WPF 通用
  7. java unsafe park_Java魔法类——Unsafe应用解析
  8. 【读书札记】《怦然心动——情感化交互设计指南》
  9. php同学录网站设计_基于PHP的校友录系统的设计与实现
  10. 兰州大学c语言课程作业答案,2016兰州大学C语言程序设计课程作业1附答案.doc
  11. FreeSwitch的Canvas功能
  12. 将对象转换为JSON字符串
  13. @RequestBody注解的简单用法
  14. excel表格打印每页都有表头_Excel打印时如何实现每一页纸上都有表头?
  15. 新版悟能口罩预约小程序源码V1.1.1
  16. 突变!微软将结束对Office Android应用的支持
  17. 【硬件基础】舵机基础知识
  18. 用计算机弹音乐之声,弹响第一个音符
  19. 无向图的Depth-first search和Breadth-first Search
  20. 计算机与音乐制作专业就业前景,计算机音乐制作专业就业形势不错

热门文章

  1. 改变iOS searchBar中textField的背景颜色
  2. wii手柄_Wii时代的隐藏宝石
  3. std::string一个极其隐晦得问题
  4. qq空间日志总显示服务器升级,QQ空间里加不上日志是怎么回事?
  5. 苹果手机上网很慢_手机的信号满格,为什么上网速度却很慢?一招教你解除限制...
  6. 动手学习深度学习(Pytorch版)Task 2:文本预处理
  7. 最受IT公司欢迎的30款开源软件
  8. 有人痴狂,有人跑路,开源软件新一年的冰火两重天
  9. idea工具的内存优化
  10. Word中页眉文字下横线如何变化粗细线型,页脚文字上方如何添加横