梦醒何必执着 發表於 2019-5-30 20:14:00

python开发微信公众号

<svg xmlns="http://www.w3.org/2000/svg" style="display: none">
                        <path stroke-linecap="round" d="M5,0 0,2.5 5,5z" id="raphael-marker-block" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0)"></path>
                  </svg>
                  <ol><li> <p><strong>注册个微信公众号, 选择订阅号</strong><br> <img src="https://img-blog.csdnimg.cn/20190530194341976.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3pzeDEzMTRsb3Zlenlm,size_16,color_FFFFFF,t_70" alt="在这里插入图片描述"></p> </li><li> <p><strong>注册完成后你会到首页</strong></p> <p><img src="https://img-blog.csdnimg.cn/20190530194659945.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3pzeDEzMTRsb3Zlenlm,size_16,color_FFFFFF,t_70" alt="在这里插入图片描述"></p> </li><li> <p><strong>我们进入到测试平台</strong><br> <img src="https://img-blog.csdnimg.cn/20190530195208527.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3pzeDEzMTRsb3Zlenlm,size_16,color_FFFFFF,t_70" alt="在这里插入图片描述"></p> </li><li> <p><strong>写python代码</strong></p> <pre><code> # coding:utf-8

from flask import Flask, request, abort, render_template
import hashlib
import xmltodict
import time
# 用它可以访问http请求地址
import urllib2
import json

# 常量
# 微信的token令牌
WECHAT_TOKEN = "刚刚在测试哪里填写的Token值"
# appid
WECHAT_APPID = "填写测试版的APPID"
# appsecret
WECHAT_APPSECRET = "填写测试版的APPSECRET"

app = Flask(__name__)


# 这是微信服务器访问的
@app.route("/wechat8001", methods=["GET", "POST"])
def wechat():
   """对接微信公众号服务器"""
   # 验证服务器地址的有效性
   # 开发者提交信息后,微信服务器将发送GET请求到填写的服务器地址URL上,GET请求携带四个参数:
   # signature:微信加密, signature结合了开发者填写的token参数和请求中的timestamp参数 nonce参数
   # timestamp:时间戳(chuo这是拼音)
   # nonce: 随机数
   # echostr: 随机字符串


   # 接收微信服务器发送参数
   signature = request.args.get("signature")
   timestamp = request.args.get("timestamp")
   nonce = request.args.get("nonce")

   # 校验参数
   # 校验流程:
   # 将token、timestamp、nonce三个参数进行字典序排序
   # 将三个参数字符串拼接成一个字符串进行sha1加密
   # 开发者获得加密后的字符串可与signature对比,标识该请求来源于微信


   if not all():
         # 抛出400错误
         abort(400)

   # 按照微信的流程计算签名
   li =

   # 排序
   li.sort()

   # 拼接字符串
   tmp_str = "".join(li)

   # 进行sha1加密, 得到正确的签名值
   sign = hashlib.sha1(tmp_str).hexdigest()

   # 将自己计算的签名值, 与请求的签名参数进行对比, 如果相同, 则证明请求来自微信
   if signature != sign:
         # 代表请求不是来自微信
         # 弹出报错信息, 身份有问题
         abort(403)
   else:
         # 表示是微信发送的请求
         if request.method == "GET":
             # 表示第一次接入微信服务器的验证
             echostr = request.args.get("echostr")
             # 校验echostr
             if not echostr:
               abort(400)
             return echostr

         elif request.method == "POST":
             # 表示微信服务器转发消息过来
             # 拿去xml的请求数据
             xml_str = request.data

             # 当xml_str为空时
             if not xml_str:
               abort(400)

             # 对xml字符串进行解析成字典
             xml_dict = xmltodict.parse(xml_str)

             xml_dict = xml_dict.get("xml")

             # MsgType是消息类型 这里是提取消息类型
             msg_type = xml_dict.get("MsgType")

             if msg_type == "text":
               # 表示发送文本消息
               # 第一次要么回复你想回复的内容, 不知道回复什么, 微信说了要么回复success, 要么空字符串
               # 够造返回值, 经由微信服务器回复给用户的消息内容
               # 回复消息
               # ToUsername: (必须传) 接收方账号(收到的OpenID)
               # FromUserName: (必须传) 开发者微信号
               # CreateTime: (必须传) 消息创建时间(整形)
               # MsgType: (必须传) 消息类型
               # Content: (必须传) 回复消息的内容(换行:在Content中能够换行, 微信客户端就支持换行显示)

               resp_dict = {
                     "xml":{
                         "ToUserName":xml_dict.get("FromUserName"),
                         "FromUserName":xml_dict.get("ToUserName"),
                         "CreateTime":int(time.time()),
                         "MsgType":"text",
                         "Content":xml_dict.get("Content")
                     }
               }
             else:
               resp_dict = {
                     "xml": {
                         "ToUserName": xml_dict.get("FromUserName"),
                         "FromUserName": xml_dict.get("ToUserName"),
                         "CreateTime": int(time.time()),
                         "MsgType": "text",
                         "Content": "I LOVE YOU"
                     }
               }
             # 将字典转换为xml字符串
             resp_xml_str = xmltodict.unparse(resp_dict)
             # 返回消息数据给微信服务器
             return resp_xml_str


# 这是用户通过微信访问的 这里只能通过域名访问
# www.itcastcpp.cn/wechat8001/index
@app.route("/wechat8001/index")
def index():
   """让用户通过微信访问的网页页面视图"""

   # 用户同意授权,获取code
   # 让用户访问一下链接地址:
   # https: // open.weixin.qq.com / connect / oauth2 / authorize?
   # appid = APPID &amp; redirect_uri = REDIRECT_URI &amp; response_type = code &amp;
   # scope = SCOPE &amp; state = STATE# wechat_redirect

   # 参数      是否必须            说明
   # appid         是            公众号唯一标识
   # redirect_uri是            授权后的回调链接地址, 请使用urlencode对连接进行处理
   # response_type 是            返回类型, 请填写code
   # scope         是            应用授权作用域snsapi_base, (不弹出授权页面直接跳转, 只能获取用户openid)
   #                               snsapi_userinfo(弹出授权页面, 可通过openid拿到昵称, 性别, 所在地,
   #                               并且, 即使在未关注的情况下, 只要用户授权, 也能获取其信息)
   # state         否            从定向后会带上state参数, 开发者可以填写a-zA-Z0-9的参数值, 最多128字节
   # #wechat_redirect是          无论直接打开还是做页面302重定向的时候, 必须带此参数

   # 从微信服务器中拿去用户的资料数据
   # 1. 提取code参数
   code = request.args.get("code")

   # 用户同意授权后
   # 如果用户同意授权,页面将跳转至
   # redirect_uri /?code = CODE &amp; state = STATE。若用户禁止授权,
   # 则重定向后不会带上code参数,仅会带上state参数redirect_uri?state = STATE
   if not code:
         return "Missing code parameters"



   # 2. 向微信服务器发送http请求回去access_token
   # 通过code换取网页授权access_token
   # 请求方法
   # https: // api.weixin.qq.com / sns / oauth2 / access_token?appid = APPID &amp;
   # secret = SECRET &amp; code = CODE &amp; grant_type = authorization_code
   # 参数                  是否必须                说明
   # appid               是                  公众号唯一标识
   # secret                是                  公众号的appsecret
   # code                  是                  填写第一步获取code参数
   # grant_type            是                  填写为authorization_type


   url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=%s&amp;secret=%s&amp;code=%s&amp;grant_type=authorization_code"%(WECHAT_APPID, WECHAT_APPSECRET, code)


   # 使用urllib2.urlopen方法发送请求
   # 如果只传网址的url参数, 则默认使用http的get请求方式, 返回响应对象
   response = urllib2.urlopen(url)

   # 获取相应体数据, 这是微信返回的json数据
   json_str = response.read()
   # 返回值
   # 正确时返回的JSON数据包如下:
   #
   # {
   #   "access_token": "ACCESS_TOKEN",
   #   "expires_in": 7200,
   #   "refresh_token": "REFRESH_TOKEN",
   #   "openid": "OPENID",
   #   "scope": "SCOPE"
   # }

   # 参数                        参数描述
   # access_token               网页授权接口调用凭证, 注意,此access_token与基础支持的access_token不同
   # expires_in               access_token接口调用凭证超时时间, 单位(秒)
   # refresh_token            用户刷新access_token
   # openid                     用户唯一标识, 请注意, 在未关注公众号时, 用户访问公众号的页面, 也会产生一个用户和公众号唯一的openid
   # scope                      用户授权的作用域, 使用逗号(,)分隔

   # 错误时微信会返回JSON数据包如下(示例为Code无效错误):
   #
   # {
   #   "errcode": 40029,
   #   "errmsg": "invalid code"
   # }



   # 把json字符串解析成python里面的字典
   resp_dict = json.loads(json_str)

   # 获取access_token, openid
   if "errcode" in resp_dict:
         return "Failed to get access_token parameter"

   access_token = resp_dict.get("access_token")
   openid = resp_dict.get("openid")




   # 3. 向微信服务器发送http请求, 获取用户的资料数据
   # 拉取用户信息(需scope为snsapi_userinfo)
   # 请求方法
   # https: // api.weixin.qq.com / sns / userinfo?access_token = ACCESS_TOKEN
   # &amp; openid = OPENID &amp; lang = zh_CN
   # 参数                  描述
   # access_token         网页授权接口调用凭证, 注意,此access_token与基础支持的access_token不同
   # openid               用户的唯一标识
   # lang                   返回国家地区预言版本, zh_CN简体, zh_TW繁体, en英语

   url = "https://api.weixin.qq.com/sns/userinfo?access_token=%s&amp;openid=%s&amp;lang=zh_CN"%(access_token, openid)
   response = urllib2.urlopen(url)
   # 读取微信传回的json的响应体数据
   user_json_str = response.read()
   user_dict_data = json.loads(user_json_str)
   # 返回值
   # 正确时返回的JSON数据包如下:
   #
   # {
   #   "openid": " OPENID",
   #   " nickname": NICKNAME,
   #   "sex": "1",
   #   "province": "PROVINCE",
   #   "city":"CITY",
   #   "country":"COUNTRY",
   #   "headimgurl":"http://wx.qlogo.cn/mmopen/g3MonUZtNHkdmzicIlibx6iaFqAc56vxLSUfpb6n5WKSYVY0ChQKkiaJSgQ1dZuTOgvLLrhJbERQQ4eMsv84eavHiaiceqxibJxCfHe/46",
   #   "privilege":[
   #      "PRIVILEGE1",
   #      "PRIVILEGE2"
   #      ],
   #      "unionid": "o6_bmasdasdsad6_2sgVt7hMZOPfL"
   # }

   # 参数                            描述
   # openid                         用户唯一标识
   # nickname                     用户昵称
   # sex                            用户的性别, 值为1时男性, 值为2时女性, 值为0时是未知
   # province                     用户个人资料填写的省份
   # city                           普通用户个人资料填写的城市
   # country                        国家, 如中国为CN
   # headimgurl                     用户头像, 最后一个值代表正方形头像大小(0 ,46, 64, 96,
   #                              132数值可选, 0代表640*640头像), 用户没有头像时该项为空.
   #                              若用户跟换头像,原有头像url将失效.
   # privilege                      用户特权信息, json数组, 如微信沃卡用户为(chinaunicom)
   # unionid                        只有在用户将公众号绑定到微信开放平台账号后, 才会出现该字段.
   #                              详见:获取用户个人信息(UnionID机制)

   # 错误时微信会返回JSON数据包如下:
   #
   # {
   #   "errcode": 40003,
   #   "errmsg": " invalid openid "
   # }


   # 判断微信返回的是不是错误的json
   if "errcode" in user_dict_data:
         return "Failed to obtain user information"

   # 将用户的资料数据填充到页面中
   return render_template("index.html", user=user_dict_data)


if __name__ == '__main__':
   app.run(port=8001, debug=True)
</code></pre> </li><li> <p><strong>将你的代码上传到公网ip的服务器上</strong></p> <pre><code> scp 程序的路径 账号@公网ip:(上传的路径)

scp ./wechat.py 5050@172.168.66.238:~/xiaoge/
</code></pre> </li><li> <p>在公网ip的服务器上运行你的.py文件, 你可以关注你测试的那个公众号, 对你的代码惊醒测试<br> <img src="https://img-blog.csdnimg.cn/20190530200429521.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3pzeDEzMTRsb3Zlenlm,size_16,color_FFFFFF,t_70" alt="在这里插入图片描述"></p> </li><li> <p>没问题的话, 在进行上线版的配置, 就ok了.<br> <img src="https://img-blog.csdnimg.cn/20190530201221635.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3pzeDEzMTRsb3Zlenlm,size_16,color_FFFFFF,t_70" alt="在这里插入图片描述"></p> </li></ol><br><br>
来源:https://www.cnblogs.com/gmllxx/p/14405350.html
頁: [1]
查看完整版本: python开发微信公众号