{"componentChunkName":"component---src-templates-blog-detail-tsx","path":"/blog/2020-04-23-serverless-wechat-cos","result":{"data":{"currentBlog":{"id":"e0959654-d44e-59c0-8201-19822e61b38d","frontmatter":{"thumbnail":"https://img.serverlesscloud.cn/2020523/1590204021386-16200.jpg","authors":["乂乂又又"],"categories":["user-stories"],"date":"2020-04-23T00:00:00.000Z","title":"万物皆可 Serverless 之使用云函数 SCF+COS 免费运营微信公众号","description":"是的，你没听错，这一次我来带大家直接上手运营微信公众号","authorslink":["https://cloud.tencent.com/developer/article/1612816"],"translators":null,"translatorslink":null,"tags":["云函数","对象存储"],"keywords":"Serverless,Serverless微信,Serverless应用","outdated":null},"wordCount":{"words":271,"sentences":67,"paragraphs":67},"fileAbsolutePath":"/opt/build/repo/content/blog/2020-04-23-serverless-wechat-cos.md","fields":{"slug":"/blog/2020-04-23-serverless-wechat-cos/","keywords":["java","python","serverless","腾讯云无服务器云函数","无服务器","无服务器云函数","云函数","reply","requestParameters","微信","timestamp","nonce","signature"]},"html":"<p>是的，你没听错，这一次我来带大家直接上手运营微信公众号。</p>\n<p><del>震惊，Awesome</del>，哼，我才不信捏，所谓无图无真相 ~</p>\n<h2 id=\"效果展示\"><a href=\"#%E6%95%88%E6%9E%9C%E5%B1%95%E7%A4%BA\" aria-label=\"效果展示 permalink\" class=\"anchor\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>效果展示</h2>\n<p><img src=\"https://img.serverlesscloud.cn/2020523/1590204021016-16200.jpg\" alt=\"最终效果1\"></p>\n<p><img src=\"https://img.serverlesscloud.cn/2020523/1590204021410-16200.jpg\" alt=\"最终效果2\"></p>\n<p>更多的体验，可以关注我的微信公众号： 乂乂又又 （仅供测试，不要乱搞哈~）</p>\n<p>嗯，这次我信了，快点教一下我吧，嘤嘤嘤~</p>\n<h2 id=\"操作步骤\"><a href=\"#%E6%93%8D%E4%BD%9C%E6%AD%A5%E9%AA%A4\" aria-label=\"操作步骤 permalink\" class=\"anchor\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>操作步骤</h2>\n<p>在上一篇<a href=\"https://serverlesscloud.cn/blog/2020-04-23-serverless-scf-cos/\">《万物皆可Serverless之使用SCF+COS快速开发全栈应用》</a>教程中，</p>\n<p>我们用腾讯云无服务器云函数 SCF 和<a href=\"https://cloud.tencent.com/product/cos?from=10680\">对象存储</a>实现了一个后端云函数，这个云函数可以根据我们的请求返回对应的结果。</p>\n<p>现在我们将尝试在这个云函数的基础上解析微信 XML 消息，实现公众号消息的自动回复，关键词回复，文字菜单等功能。</p>\n<h3 id=\"第一步：添加相关依赖\"><a href=\"#%E7%AC%AC%E4%B8%80%E6%AD%A5%EF%BC%9A%E6%B7%BB%E5%8A%A0%E7%9B%B8%E5%85%B3%E4%BE%9D%E8%B5%96\" aria-label=\"第一步：添加相关依赖 permalink\" class=\"anchor\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>第一步：添加相关依赖</h3>\n<p>为了快速完成开发，这里我们选择 python 第三方开源库 wechatpy 来接入微信公众平台。</p>\n<p><img src=\"https://img.serverlesscloud.cn/2020523/1590204020969-16200.jpg\" alt=\"wechatpy\"></p>\n<p>wechatpy 支持以下功能</p>\n<ol>\n<li>普通公众平台被动响应和主动调用 API</li>\n<li>企业微信 API</li>\n<li>微信支付 API</li>\n<li>第三方平台代公众号调用接口 API</li>\n<li>小程序<a href=\"https://cloud.tencent.com/product/tcb?from=10680\">云开发</a> API</li>\n</ol>\n<p>可见功能是十分完整的，不仅支持普通公众平台主被动调用，企业微信和微信支付，甚至还支持第三方平台代公众号调用接口，拿来运营微信公众号是十分绰绰有余的~</p>\n<p><img src=\"https://img.serverlesscloud.cn/2020523/1590204020958-16200.jpg\" alt=\"完整项目依赖\"></p>\n<p>由于腾讯云函数的运行环境中缺少第三方库，需要我们自己手动上传添加依赖，这里我们需要添加的第三方依赖有：<code class=\"language-text\">wechatpy</code>、<code class=\"language-text\">otionaldict</code>、<code class=\"language-text\">xmltodict</code> 以及 <code class=\"language-text\">timeout\\_decorator</code></p>\n<p>其中 <code class=\"language-text\">wechatpy</code> 需要依赖 <code class=\"language-text\">otionaldict</code>、<code class=\"language-text\">xmltodict</code>，<code class=\"language-text\">timeout\\_decorator</code> 是用来限制函数运行时长的，具体的依赖文件可以自行 pip 安装后 copy 到云函数项目根目录，如上图。</p>\n<h3 id=\"第二步：接入微信公众号\"><a href=\"#%E7%AC%AC%E4%BA%8C%E6%AD%A5%EF%BC%9A%E6%8E%A5%E5%85%A5%E5%BE%AE%E4%BF%A1%E5%85%AC%E4%BC%97%E5%8F%B7\" aria-label=\"第二步：接入微信公众号 permalink\" class=\"anchor\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>第二步：接入微信公众号</h3>\n<p><img src=\"https://img.serverlesscloud.cn/2020523/1590204020978-16200.jpg\" alt=\"微信公众号开发者后台\"></p>\n<p>这里需要记下自己的 AppID、Token 和 EncodingAESKey，消息加密方式建议选为安全模式。这个页面先不要关，一会儿上线发布好云函数还需要过来再次修改配置。</p>\n<h3 id=\"第三步：编写云函数解析并回复微信公众号消息\"><a href=\"#%E7%AC%AC%E4%B8%89%E6%AD%A5%EF%BC%9A%E7%BC%96%E5%86%99%E4%BA%91%E5%87%BD%E6%95%B0%E8%A7%A3%E6%9E%90%E5%B9%B6%E5%9B%9E%E5%A4%8D%E5%BE%AE%E4%BF%A1%E5%85%AC%E4%BC%97%E5%8F%B7%E6%B6%88%E6%81%AF\" aria-label=\"第三步：编写云函数解析并回复微信公众号消息 permalink\" class=\"anchor\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>第三步：编写云函数解析并回复微信公众号消息</h3>\n<p>这一步可以直接参考 wechatpy 的<a href=\"http://docs.wechatpy.org/zh_CN/master/quickstart.html#id2\">官方文档</a></p>\n<p><img src=\"https://img.serverlesscloud.cn/2020523/1590204021001-16200.jpg\" alt=\"wechat文档\"></p>\n<p>Life is short, show me the code.</p>\n<p>这里我就直接上代码了（原始业务代码已略去，可以按照自己的需求开发）</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"78488859731572160000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"代码复制成功\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`import json\nimport timeout_decorator\nfrom wechatpy.replies import ArticlesReply\nfrom wechatpy.utils import check_signature\nfrom wechatpy.crypto import WeChatCrypto\nfrom wechatpy import parse_message, create_reply\nfrom wechatpy.exceptions import InvalidSignatureException, InvalidAppIdException\n\n# 是否开启本地debug模式\ndebug = False\n\n# 腾讯云对象存储依赖\nif debug:\n    from qcloud_cos import CosConfig\n    from qcloud_cos import CosS3Client\n    from qcloud_cos import CosServiceError\n    from qcloud_cos import CosClientError\nelse:\n    from qcloud_cos_v5 import CosConfig\n    from qcloud_cos_v5 import CosS3Client\n    from qcloud_cos_v5 import CosServiceError\n    from qcloud_cos_v5 import CosClientError\n\n# 配置存储桶\nappid = '66666666666'\nsecret_id = u'xxxxxxxxxxxxxxx'\nsecret_key = u'xxxxxxxxxxxxxxx'\nregion = u'ap-chongqing'\nbucket = 'name'+'-'+appid\n\n# 对象存储实例\nconfig = CosConfig(Secret_id=secret_id, Secret_key=secret_key, Region=region)\nclient = CosS3Client(config)\n\n# cos 文件读写\ndef cosRead(key):\n    try:\n        response = client.get_object(Bucket=bucket, Key=key)\n        txtBytes = response['Body'].get_raw_stream()\n        return txtBytes.read().decode()\n    except CosServiceError as e:\n        return &quot;&quot;\n\ndef cosWrite(key, txt):\n    try:\n        response = client.put_object(\n            Bucket=bucket,\n            Body=txt.encode(encoding=&quot;utf-8&quot;),\n            Key=key,\n        )\n        return True\n    except CosServiceError as e:\n        return False\n\ndef getReplys():\n    replyMap = {}\n    replyTxt = cosRead('Replys.txt')  # 读取数据\n    if len(replyTxt) > 0:\n        replyMap = json.loads(replyTxt)\n    return replyMap\n\ndef addReplys(reply):\n    replyMap = getReplys()\n    if len(replyMap) > 0:\n        replyMap[reply]='我是黑名单'\n    return cosWrite('Replys.txt', json.dumps(replyMap, ensure_ascii=False)) if len(replyMap) > 0 else False\n\n\ndef delReplys(reply):\n    replyMap = getReplys()\n    if len(replyMap) > 0:\n        replyMap.pop(reply)\n    return cosWrite('Replys.txt', json.dumps(replyMap, ensure_ascii=False)) if len(replyMap) > 0 else False\n\n\n# 微信公众号对接\nwecaht_id = 'xxxxxxxxxxxxxxx'\nWECHAT_TOKEN = 'xxxxxxxxxxxxxxxxxxx'\nencoding_aes_key = 'xxxxxxxxxxxxxxxxxxxxxx'\n\ncrypto = WeChatCrypto(WECHAT_TOKEN, encoding_aes_key, wecaht_id)\n\n# api网关响应集成\ndef apiReply(reply, txt=False, content_type='application/json', code=200):\n    return {\n        &quot;isBase64Encoded&quot;: False,\n        &quot;statusCode&quot;: code,\n        &quot;headers&quot;: {'Content-Type': content_type},\n        &quot;body&quot;: json.dumps(reply, ensure_ascii=False) if not txt else str(reply)\n    }\n\ndef replyMessage(msg):\n    txt = msg.content\n    ip = msg.source\n    print('请求信息--->'+ip+'%'+txt)  # 用来在腾讯云控制台打印请求日志\n    replysTxtMap = getReplys() # 获取回复关键词\n    if '@' in txt:\n        keys = txt.split('@')\n        if keys[0] == '电影': #do something\n            return\n        if keys[0] == '音乐': #do something\n            return\n        if keys[0] == '下架': #do something\n            return\n        if keys[0] == '上架': #do something\n            return\n        if keys[0] == '回复': #do something\n            return\n        if keys[0] == '删除': #do something\n            return\n    elif txt in replysTxtMap.keys(): # 如果消息在回复关键词内则自动回复\n        return create_reply(replysTxtMap[txt], msg)\n    return create_reply(&quot;喵呜 ฅ'ω'ฅ&quot;, msg)\n\ndef wechat(httpMethod, requestParameters, body=''):\n    if httpMethod == 'GET':\n        signature = requestParameters['signature']\n        timestamp = requestParameters['timestamp']\n        nonce = requestParameters['nonce']\n        echo_str = requestParameters['echostr']\n        try:\n            check_signature(WECHAT_TOKEN, signature, timestamp, nonce)\n        except InvalidSignatureException:\n            echo_str = 'error'\n        return apiReply(echo_str, txt=True, content_type=&quot;text/plain&quot;)\n    elif httpMethod == 'POST':\n        msg_signature = requestParameters['msg_signature']\n        timestamp = requestParameters['timestamp']\n        nonce = requestParameters['nonce']\n        try:\n            decrypted_xml = crypto.decrypt_message(\n                body,\n                msg_signature,\n                timestamp,\n                nonce\n            )\n        except (InvalidAppIdException, InvalidSignatureException):\n            return\n        msg = parse_message(decrypted_xml)\n        if msg.type == 'text':\n            reply = replyMessage(msg)\n        elif msg.type == 'image':\n            reply = create_reply('哈◔ ‸◔？\\n好端端的，给我发图片干啥~', msg)\n        elif msg.type == 'voice':\n            reply = create_reply('哈◔ ‸◔？\\n好端端的，给我发语音干啥~', msg)\n        else:\n            reply = create_reply('哈◔ ‸◔？\\n搞不明白你给我发了啥~', msg)\n        reply = reply.render()\n        print('返回结果--->'+str(reply))  # 用来在腾讯云控制台打印请求日志\n        reply = crypto.encrypt_message(reply, nonce, timestamp)\n        return apiReply(reply, txt=True, content_type=&quot;application/xml&quot;)\n    else:\n        msg = parse_message(body)\n        reply = create_reply(&quot;喵呜 ฅ'ω'ฅ&quot;, msg)\n        reply = reply.render()\n        print('返回结果--->'+str(reply))  # 用来在腾讯云控制台打印请求日志\n        reply = crypto.encrypt_message(reply, nonce, timestamp)\n        return apiReply(reply, txt=True, content_type=&quot;application/xml&quot;)\n\n\n@timeout_decorator.timeout(4, timeout_exception=StopIteration)\ndef myMain(httpMethod, requestParameters, body=''):\n    return wechat(httpMethod, requestParameters, body=body)\n\n\ndef timeOutReply(httpMethod, requestParameters, body=''):\n    msg_signature = requestParameters['msg_signature']\n    timestamp = requestParameters['timestamp']\n    nonce = requestParameters['nonce']\n    try:\n        decrypted_xml = crypto.decrypt_message(\n            body,\n            msg_signature,\n            timestamp,\n            nonce\n        )\n    except (InvalidAppIdException, InvalidSignatureException):\n        return\n    msg = parse_message(decrypted_xml)\n    reply = create_reply(&quot;出了点小问题，请稍后再试&quot;, msg).render()\n    print('返回结果--->'+str(reply))  # 用来在腾讯云控制台打印请求日志\n    reply = crypto.encrypt_message(reply, nonce, timestamp)\n    return apiReply(reply, txt=True, content_type=&quot;application/xml&quot;)\n\n\ndef main_handler(event, context):\n    body = ''\n    httpMethod = event[&quot;httpMethod&quot;]\n    requestParameters = event['queryString']\n    if 'body' in event.keys():\n        body = event['body']\n    try:\n        response = myMain(httpMethod, requestParameters, body=body)\n    except:\n        response = timeOutReply(httpMethod, requestParameters, body=body)\n    return response`, `78488859731572160000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                复制代码<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">import</span> json\n<span class=\"token keyword\">import</span> timeout_decorator\n<span class=\"token keyword\">from</span> wechatpy<span class=\"token punctuation\">.</span>replies <span class=\"token keyword\">import</span> ArticlesReply\n<span class=\"token keyword\">from</span> wechatpy<span class=\"token punctuation\">.</span>utils <span class=\"token keyword\">import</span> check_signature\n<span class=\"token keyword\">from</span> wechatpy<span class=\"token punctuation\">.</span>crypto <span class=\"token keyword\">import</span> WeChatCrypto\n<span class=\"token keyword\">from</span> wechatpy <span class=\"token keyword\">import</span> parse_message<span class=\"token punctuation\">,</span> create_reply\n<span class=\"token keyword\">from</span> wechatpy<span class=\"token punctuation\">.</span>exceptions <span class=\"token keyword\">import</span> InvalidSignatureException<span class=\"token punctuation\">,</span> InvalidAppIdException\n\n# 是否开启本地debug模式\ndebug <span class=\"token operator\">=</span> False\n\n# 腾讯云对象存储依赖\n<span class=\"token keyword\">if</span> debug<span class=\"token punctuation\">:</span>\n    <span class=\"token keyword\">from</span> qcloud_cos <span class=\"token keyword\">import</span> CosConfig\n    <span class=\"token keyword\">from</span> qcloud_cos <span class=\"token keyword\">import</span> CosS3Client\n    <span class=\"token keyword\">from</span> qcloud_cos <span class=\"token keyword\">import</span> CosServiceError\n    <span class=\"token keyword\">from</span> qcloud_cos <span class=\"token keyword\">import</span> CosClientError\n<span class=\"token keyword\">else</span><span class=\"token punctuation\">:</span>\n    <span class=\"token keyword\">from</span> qcloud_cos_v5 <span class=\"token keyword\">import</span> CosConfig\n    <span class=\"token keyword\">from</span> qcloud_cos_v5 <span class=\"token keyword\">import</span> CosS3Client\n    <span class=\"token keyword\">from</span> qcloud_cos_v5 <span class=\"token keyword\">import</span> CosServiceError\n    <span class=\"token keyword\">from</span> qcloud_cos_v5 <span class=\"token keyword\">import</span> CosClientError\n\n# 配置存储桶\nappid <span class=\"token operator\">=</span> <span class=\"token string\">'66666666666'</span>\nsecret_id <span class=\"token operator\">=</span> u<span class=\"token string\">'xxxxxxxxxxxxxxx'</span>\nsecret_key <span class=\"token operator\">=</span> u<span class=\"token string\">'xxxxxxxxxxxxxxx'</span>\nregion <span class=\"token operator\">=</span> u<span class=\"token string\">'ap-chongqing'</span>\nbucket <span class=\"token operator\">=</span> <span class=\"token string\">'name'</span><span class=\"token operator\">+</span><span class=\"token string\">'-'</span><span class=\"token operator\">+</span>appid\n\n# 对象存储实例\nconfig <span class=\"token operator\">=</span> <span class=\"token function\">CosConfig</span><span class=\"token punctuation\">(</span>Secret_id<span class=\"token operator\">=</span>secret_id<span class=\"token punctuation\">,</span> Secret_key<span class=\"token operator\">=</span>secret_key<span class=\"token punctuation\">,</span> Region<span class=\"token operator\">=</span>region<span class=\"token punctuation\">)</span>\nclient <span class=\"token operator\">=</span> <span class=\"token function\">CosS3Client</span><span class=\"token punctuation\">(</span>config<span class=\"token punctuation\">)</span>\n\n# cos 文件读写\ndef <span class=\"token function\">cosRead</span><span class=\"token punctuation\">(</span>key<span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span>\n    <span class=\"token keyword\">try</span><span class=\"token punctuation\">:</span>\n        response <span class=\"token operator\">=</span> client<span class=\"token punctuation\">.</span><span class=\"token function\">get_object</span><span class=\"token punctuation\">(</span>Bucket<span class=\"token operator\">=</span>bucket<span class=\"token punctuation\">,</span> Key<span class=\"token operator\">=</span>key<span class=\"token punctuation\">)</span>\n        txtBytes <span class=\"token operator\">=</span> response<span class=\"token punctuation\">[</span><span class=\"token string\">'Body'</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">.</span><span class=\"token function\">get_raw_stream</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n        <span class=\"token keyword\">return</span> txtBytes<span class=\"token punctuation\">.</span><span class=\"token function\">read</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">decode</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n    except CosServiceError <span class=\"token keyword\">as</span> e<span class=\"token punctuation\">:</span>\n        <span class=\"token keyword\">return</span> <span class=\"token string\">\"\"</span>\n\ndef <span class=\"token function\">cosWrite</span><span class=\"token punctuation\">(</span>key<span class=\"token punctuation\">,</span> txt<span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span>\n    <span class=\"token keyword\">try</span><span class=\"token punctuation\">:</span>\n        response <span class=\"token operator\">=</span> client<span class=\"token punctuation\">.</span><span class=\"token function\">put_object</span><span class=\"token punctuation\">(</span>\n            Bucket<span class=\"token operator\">=</span>bucket<span class=\"token punctuation\">,</span>\n            Body<span class=\"token operator\">=</span>txt<span class=\"token punctuation\">.</span><span class=\"token function\">encode</span><span class=\"token punctuation\">(</span>encoding<span class=\"token operator\">=</span><span class=\"token string\">\"utf-8\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n            Key<span class=\"token operator\">=</span>key<span class=\"token punctuation\">,</span>\n        <span class=\"token punctuation\">)</span>\n        <span class=\"token keyword\">return</span> True\n    except CosServiceError <span class=\"token keyword\">as</span> e<span class=\"token punctuation\">:</span>\n        <span class=\"token keyword\">return</span> False\n\ndef <span class=\"token function\">getReplys</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span>\n    replyMap <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span><span class=\"token punctuation\">}</span>\n    replyTxt <span class=\"token operator\">=</span> <span class=\"token function\">cosRead</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Replys.txt'</span><span class=\"token punctuation\">)</span>  # 读取数据\n    <span class=\"token keyword\">if</span> <span class=\"token function\">len</span><span class=\"token punctuation\">(</span>replyTxt<span class=\"token punctuation\">)</span> <span class=\"token operator\">></span> <span class=\"token number\">0</span><span class=\"token punctuation\">:</span>\n        replyMap <span class=\"token operator\">=</span> json<span class=\"token punctuation\">.</span><span class=\"token function\">loads</span><span class=\"token punctuation\">(</span>replyTxt<span class=\"token punctuation\">)</span>\n    <span class=\"token keyword\">return</span> replyMap\n\ndef <span class=\"token function\">addReplys</span><span class=\"token punctuation\">(</span>reply<span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span>\n    replyMap <span class=\"token operator\">=</span> <span class=\"token function\">getReplys</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n    <span class=\"token keyword\">if</span> <span class=\"token function\">len</span><span class=\"token punctuation\">(</span>replyMap<span class=\"token punctuation\">)</span> <span class=\"token operator\">></span> <span class=\"token number\">0</span><span class=\"token punctuation\">:</span>\n        replyMap<span class=\"token punctuation\">[</span>reply<span class=\"token punctuation\">]</span><span class=\"token operator\">=</span><span class=\"token string\">'我是黑名单'</span>\n    <span class=\"token keyword\">return</span> <span class=\"token function\">cosWrite</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Replys.txt'</span><span class=\"token punctuation\">,</span> json<span class=\"token punctuation\">.</span><span class=\"token function\">dumps</span><span class=\"token punctuation\">(</span>replyMap<span class=\"token punctuation\">,</span> ensure_ascii<span class=\"token operator\">=</span>False<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token keyword\">if</span> <span class=\"token function\">len</span><span class=\"token punctuation\">(</span>replyMap<span class=\"token punctuation\">)</span> <span class=\"token operator\">></span> <span class=\"token number\">0</span> <span class=\"token keyword\">else</span> False\n\n\ndef <span class=\"token function\">delReplys</span><span class=\"token punctuation\">(</span>reply<span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span>\n    replyMap <span class=\"token operator\">=</span> <span class=\"token function\">getReplys</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n    <span class=\"token keyword\">if</span> <span class=\"token function\">len</span><span class=\"token punctuation\">(</span>replyMap<span class=\"token punctuation\">)</span> <span class=\"token operator\">></span> <span class=\"token number\">0</span><span class=\"token punctuation\">:</span>\n        replyMap<span class=\"token punctuation\">.</span><span class=\"token function\">pop</span><span class=\"token punctuation\">(</span>reply<span class=\"token punctuation\">)</span>\n    <span class=\"token keyword\">return</span> <span class=\"token function\">cosWrite</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Replys.txt'</span><span class=\"token punctuation\">,</span> json<span class=\"token punctuation\">.</span><span class=\"token function\">dumps</span><span class=\"token punctuation\">(</span>replyMap<span class=\"token punctuation\">,</span> ensure_ascii<span class=\"token operator\">=</span>False<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token keyword\">if</span> <span class=\"token function\">len</span><span class=\"token punctuation\">(</span>replyMap<span class=\"token punctuation\">)</span> <span class=\"token operator\">></span> <span class=\"token number\">0</span> <span class=\"token keyword\">else</span> False\n\n\n# 微信公众号对接\nwecaht_id <span class=\"token operator\">=</span> <span class=\"token string\">'xxxxxxxxxxxxxxx'</span>\n<span class=\"token constant\">WECHAT_TOKEN</span> <span class=\"token operator\">=</span> <span class=\"token string\">'xxxxxxxxxxxxxxxxxxx'</span>\nencoding_aes_key <span class=\"token operator\">=</span> <span class=\"token string\">'xxxxxxxxxxxxxxxxxxxxxx'</span>\n\ncrypto <span class=\"token operator\">=</span> <span class=\"token function\">WeChatCrypto</span><span class=\"token punctuation\">(</span><span class=\"token constant\">WECHAT_TOKEN</span><span class=\"token punctuation\">,</span> encoding_aes_key<span class=\"token punctuation\">,</span> wecaht_id<span class=\"token punctuation\">)</span>\n\n# api网关响应集成\ndef <span class=\"token function\">apiReply</span><span class=\"token punctuation\">(</span>reply<span class=\"token punctuation\">,</span> txt<span class=\"token operator\">=</span>False<span class=\"token punctuation\">,</span> content_type<span class=\"token operator\">=</span><span class=\"token string\">'application/json'</span><span class=\"token punctuation\">,</span> code<span class=\"token operator\">=</span><span class=\"token number\">200</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span>\n    <span class=\"token keyword\">return</span> <span class=\"token punctuation\">{</span>\n        <span class=\"token string\">\"isBase64Encoded\"</span><span class=\"token punctuation\">:</span> False<span class=\"token punctuation\">,</span>\n        <span class=\"token string\">\"statusCode\"</span><span class=\"token punctuation\">:</span> code<span class=\"token punctuation\">,</span>\n        <span class=\"token string\">\"headers\"</span><span class=\"token punctuation\">:</span> <span class=\"token punctuation\">{</span><span class=\"token string\">'Content-Type'</span><span class=\"token punctuation\">:</span> content_type<span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n        <span class=\"token string\">\"body\"</span><span class=\"token punctuation\">:</span> json<span class=\"token punctuation\">.</span><span class=\"token function\">dumps</span><span class=\"token punctuation\">(</span>reply<span class=\"token punctuation\">,</span> ensure_ascii<span class=\"token operator\">=</span>False<span class=\"token punctuation\">)</span> <span class=\"token keyword\">if</span> not txt <span class=\"token keyword\">else</span> <span class=\"token function\">str</span><span class=\"token punctuation\">(</span>reply<span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">}</span>\n\ndef <span class=\"token function\">replyMessage</span><span class=\"token punctuation\">(</span>msg<span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span>\n    txt <span class=\"token operator\">=</span> msg<span class=\"token punctuation\">.</span>content\n    ip <span class=\"token operator\">=</span> msg<span class=\"token punctuation\">.</span>source\n    <span class=\"token function\">print</span><span class=\"token punctuation\">(</span><span class=\"token string\">'请求信息--->'</span><span class=\"token operator\">+</span>ip<span class=\"token operator\">+</span><span class=\"token string\">'%'</span><span class=\"token operator\">+</span>txt<span class=\"token punctuation\">)</span>  # 用来在腾讯云控制台打印请求日志\n    replysTxtMap <span class=\"token operator\">=</span> <span class=\"token function\">getReplys</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> # 获取回复关键词\n    <span class=\"token keyword\">if</span> <span class=\"token string\">'@'</span> <span class=\"token keyword\">in</span> txt<span class=\"token punctuation\">:</span>\n        keys <span class=\"token operator\">=</span> txt<span class=\"token punctuation\">.</span><span class=\"token function\">split</span><span class=\"token punctuation\">(</span><span class=\"token string\">'@'</span><span class=\"token punctuation\">)</span>\n        <span class=\"token keyword\">if</span> keys<span class=\"token punctuation\">[</span><span class=\"token number\">0</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">==</span> <span class=\"token string\">'电影'</span><span class=\"token punctuation\">:</span> #<span class=\"token keyword\">do</span> something\n            <span class=\"token keyword\">return</span>\n        <span class=\"token keyword\">if</span> keys<span class=\"token punctuation\">[</span><span class=\"token number\">0</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">==</span> <span class=\"token string\">'音乐'</span><span class=\"token punctuation\">:</span> #<span class=\"token keyword\">do</span> something\n            <span class=\"token keyword\">return</span>\n        <span class=\"token keyword\">if</span> keys<span class=\"token punctuation\">[</span><span class=\"token number\">0</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">==</span> <span class=\"token string\">'下架'</span><span class=\"token punctuation\">:</span> #<span class=\"token keyword\">do</span> something\n            <span class=\"token keyword\">return</span>\n        <span class=\"token keyword\">if</span> keys<span class=\"token punctuation\">[</span><span class=\"token number\">0</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">==</span> <span class=\"token string\">'上架'</span><span class=\"token punctuation\">:</span> #<span class=\"token keyword\">do</span> something\n            <span class=\"token keyword\">return</span>\n        <span class=\"token keyword\">if</span> keys<span class=\"token punctuation\">[</span><span class=\"token number\">0</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">==</span> <span class=\"token string\">'回复'</span><span class=\"token punctuation\">:</span> #<span class=\"token keyword\">do</span> something\n            <span class=\"token keyword\">return</span>\n        <span class=\"token keyword\">if</span> keys<span class=\"token punctuation\">[</span><span class=\"token number\">0</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">==</span> <span class=\"token string\">'删除'</span><span class=\"token punctuation\">:</span> #<span class=\"token keyword\">do</span> something\n            <span class=\"token keyword\">return</span>\n    elif txt <span class=\"token keyword\">in</span> replysTxtMap<span class=\"token punctuation\">.</span><span class=\"token function\">keys</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span> # 如果消息在回复关键词内则自动回复\n        <span class=\"token keyword\">return</span> <span class=\"token function\">create_reply</span><span class=\"token punctuation\">(</span>replysTxtMap<span class=\"token punctuation\">[</span>txt<span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span> msg<span class=\"token punctuation\">)</span>\n    <span class=\"token keyword\">return</span> <span class=\"token function\">create_reply</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"喵呜 ฅ'ω'ฅ\"</span><span class=\"token punctuation\">,</span> msg<span class=\"token punctuation\">)</span>\n\ndef <span class=\"token function\">wechat</span><span class=\"token punctuation\">(</span>httpMethod<span class=\"token punctuation\">,</span> requestParameters<span class=\"token punctuation\">,</span> body<span class=\"token operator\">=</span><span class=\"token string\">''</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span>\n    <span class=\"token keyword\">if</span> httpMethod <span class=\"token operator\">==</span> <span class=\"token string\">'GET'</span><span class=\"token punctuation\">:</span>\n        signature <span class=\"token operator\">=</span> requestParameters<span class=\"token punctuation\">[</span><span class=\"token string\">'signature'</span><span class=\"token punctuation\">]</span>\n        timestamp <span class=\"token operator\">=</span> requestParameters<span class=\"token punctuation\">[</span><span class=\"token string\">'timestamp'</span><span class=\"token punctuation\">]</span>\n        nonce <span class=\"token operator\">=</span> requestParameters<span class=\"token punctuation\">[</span><span class=\"token string\">'nonce'</span><span class=\"token punctuation\">]</span>\n        echo_str <span class=\"token operator\">=</span> requestParameters<span class=\"token punctuation\">[</span><span class=\"token string\">'echostr'</span><span class=\"token punctuation\">]</span>\n        <span class=\"token keyword\">try</span><span class=\"token punctuation\">:</span>\n            <span class=\"token function\">check_signature</span><span class=\"token punctuation\">(</span><span class=\"token constant\">WECHAT_TOKEN</span><span class=\"token punctuation\">,</span> signature<span class=\"token punctuation\">,</span> timestamp<span class=\"token punctuation\">,</span> nonce<span class=\"token punctuation\">)</span>\n        except InvalidSignatureException<span class=\"token punctuation\">:</span>\n            echo_str <span class=\"token operator\">=</span> <span class=\"token string\">'error'</span>\n        <span class=\"token keyword\">return</span> <span class=\"token function\">apiReply</span><span class=\"token punctuation\">(</span>echo_str<span class=\"token punctuation\">,</span> txt<span class=\"token operator\">=</span>True<span class=\"token punctuation\">,</span> content_type<span class=\"token operator\">=</span><span class=\"token string\">\"text/plain\"</span><span class=\"token punctuation\">)</span>\n    elif httpMethod <span class=\"token operator\">==</span> <span class=\"token string\">'POST'</span><span class=\"token punctuation\">:</span>\n        msg_signature <span class=\"token operator\">=</span> requestParameters<span class=\"token punctuation\">[</span><span class=\"token string\">'msg_signature'</span><span class=\"token punctuation\">]</span>\n        timestamp <span class=\"token operator\">=</span> requestParameters<span class=\"token punctuation\">[</span><span class=\"token string\">'timestamp'</span><span class=\"token punctuation\">]</span>\n        nonce <span class=\"token operator\">=</span> requestParameters<span class=\"token punctuation\">[</span><span class=\"token string\">'nonce'</span><span class=\"token punctuation\">]</span>\n        <span class=\"token keyword\">try</span><span class=\"token punctuation\">:</span>\n            decrypted_xml <span class=\"token operator\">=</span> crypto<span class=\"token punctuation\">.</span><span class=\"token function\">decrypt_message</span><span class=\"token punctuation\">(</span>\n                body<span class=\"token punctuation\">,</span>\n                msg_signature<span class=\"token punctuation\">,</span>\n                timestamp<span class=\"token punctuation\">,</span>\n                nonce\n            <span class=\"token punctuation\">)</span>\n        <span class=\"token function\">except</span> <span class=\"token punctuation\">(</span>InvalidAppIdException<span class=\"token punctuation\">,</span> InvalidSignatureException<span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span>\n            <span class=\"token keyword\">return</span>\n        msg <span class=\"token operator\">=</span> <span class=\"token function\">parse_message</span><span class=\"token punctuation\">(</span>decrypted_xml<span class=\"token punctuation\">)</span>\n        <span class=\"token keyword\">if</span> msg<span class=\"token punctuation\">.</span>type <span class=\"token operator\">==</span> <span class=\"token string\">'text'</span><span class=\"token punctuation\">:</span>\n            reply <span class=\"token operator\">=</span> <span class=\"token function\">replyMessage</span><span class=\"token punctuation\">(</span>msg<span class=\"token punctuation\">)</span>\n        elif msg<span class=\"token punctuation\">.</span>type <span class=\"token operator\">==</span> <span class=\"token string\">'image'</span><span class=\"token punctuation\">:</span>\n            reply <span class=\"token operator\">=</span> <span class=\"token function\">create_reply</span><span class=\"token punctuation\">(</span><span class=\"token string\">'哈◔ ‸◔？\\n好端端的，给我发图片干啥~'</span><span class=\"token punctuation\">,</span> msg<span class=\"token punctuation\">)</span>\n        elif msg<span class=\"token punctuation\">.</span>type <span class=\"token operator\">==</span> <span class=\"token string\">'voice'</span><span class=\"token punctuation\">:</span>\n            reply <span class=\"token operator\">=</span> <span class=\"token function\">create_reply</span><span class=\"token punctuation\">(</span><span class=\"token string\">'哈◔ ‸◔？\\n好端端的，给我发语音干啥~'</span><span class=\"token punctuation\">,</span> msg<span class=\"token punctuation\">)</span>\n        <span class=\"token keyword\">else</span><span class=\"token punctuation\">:</span>\n            reply <span class=\"token operator\">=</span> <span class=\"token function\">create_reply</span><span class=\"token punctuation\">(</span><span class=\"token string\">'哈◔ ‸◔？\\n搞不明白你给我发了啥~'</span><span class=\"token punctuation\">,</span> msg<span class=\"token punctuation\">)</span>\n        reply <span class=\"token operator\">=</span> reply<span class=\"token punctuation\">.</span><span class=\"token function\">render</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n        <span class=\"token function\">print</span><span class=\"token punctuation\">(</span><span class=\"token string\">'返回结果--->'</span><span class=\"token operator\">+</span><span class=\"token function\">str</span><span class=\"token punctuation\">(</span>reply<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>  # 用来在腾讯云控制台打印请求日志\n        reply <span class=\"token operator\">=</span> crypto<span class=\"token punctuation\">.</span><span class=\"token function\">encrypt_message</span><span class=\"token punctuation\">(</span>reply<span class=\"token punctuation\">,</span> nonce<span class=\"token punctuation\">,</span> timestamp<span class=\"token punctuation\">)</span>\n        <span class=\"token keyword\">return</span> <span class=\"token function\">apiReply</span><span class=\"token punctuation\">(</span>reply<span class=\"token punctuation\">,</span> txt<span class=\"token operator\">=</span>True<span class=\"token punctuation\">,</span> content_type<span class=\"token operator\">=</span><span class=\"token string\">\"application/xml\"</span><span class=\"token punctuation\">)</span>\n    <span class=\"token keyword\">else</span><span class=\"token punctuation\">:</span>\n        msg <span class=\"token operator\">=</span> <span class=\"token function\">parse_message</span><span class=\"token punctuation\">(</span>body<span class=\"token punctuation\">)</span>\n        reply <span class=\"token operator\">=</span> <span class=\"token function\">create_reply</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"喵呜 ฅ'ω'ฅ\"</span><span class=\"token punctuation\">,</span> msg<span class=\"token punctuation\">)</span>\n        reply <span class=\"token operator\">=</span> reply<span class=\"token punctuation\">.</span><span class=\"token function\">render</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n        <span class=\"token function\">print</span><span class=\"token punctuation\">(</span><span class=\"token string\">'返回结果--->'</span><span class=\"token operator\">+</span><span class=\"token function\">str</span><span class=\"token punctuation\">(</span>reply<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>  # 用来在腾讯云控制台打印请求日志\n        reply <span class=\"token operator\">=</span> crypto<span class=\"token punctuation\">.</span><span class=\"token function\">encrypt_message</span><span class=\"token punctuation\">(</span>reply<span class=\"token punctuation\">,</span> nonce<span class=\"token punctuation\">,</span> timestamp<span class=\"token punctuation\">)</span>\n        <span class=\"token keyword\">return</span> <span class=\"token function\">apiReply</span><span class=\"token punctuation\">(</span>reply<span class=\"token punctuation\">,</span> txt<span class=\"token operator\">=</span>True<span class=\"token punctuation\">,</span> content_type<span class=\"token operator\">=</span><span class=\"token string\">\"application/xml\"</span><span class=\"token punctuation\">)</span>\n\n\n@timeout_decorator<span class=\"token punctuation\">.</span><span class=\"token function\">timeout</span><span class=\"token punctuation\">(</span><span class=\"token number\">4</span><span class=\"token punctuation\">,</span> timeout_exception<span class=\"token operator\">=</span>StopIteration<span class=\"token punctuation\">)</span>\ndef <span class=\"token function\">myMain</span><span class=\"token punctuation\">(</span>httpMethod<span class=\"token punctuation\">,</span> requestParameters<span class=\"token punctuation\">,</span> body<span class=\"token operator\">=</span><span class=\"token string\">''</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span>\n    <span class=\"token keyword\">return</span> <span class=\"token function\">wechat</span><span class=\"token punctuation\">(</span>httpMethod<span class=\"token punctuation\">,</span> requestParameters<span class=\"token punctuation\">,</span> body<span class=\"token operator\">=</span>body<span class=\"token punctuation\">)</span>\n\n\ndef <span class=\"token function\">timeOutReply</span><span class=\"token punctuation\">(</span>httpMethod<span class=\"token punctuation\">,</span> requestParameters<span class=\"token punctuation\">,</span> body<span class=\"token operator\">=</span><span class=\"token string\">''</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span>\n    msg_signature <span class=\"token operator\">=</span> requestParameters<span class=\"token punctuation\">[</span><span class=\"token string\">'msg_signature'</span><span class=\"token punctuation\">]</span>\n    timestamp <span class=\"token operator\">=</span> requestParameters<span class=\"token punctuation\">[</span><span class=\"token string\">'timestamp'</span><span class=\"token punctuation\">]</span>\n    nonce <span class=\"token operator\">=</span> requestParameters<span class=\"token punctuation\">[</span><span class=\"token string\">'nonce'</span><span class=\"token punctuation\">]</span>\n    <span class=\"token keyword\">try</span><span class=\"token punctuation\">:</span>\n        decrypted_xml <span class=\"token operator\">=</span> crypto<span class=\"token punctuation\">.</span><span class=\"token function\">decrypt_message</span><span class=\"token punctuation\">(</span>\n            body<span class=\"token punctuation\">,</span>\n            msg_signature<span class=\"token punctuation\">,</span>\n            timestamp<span class=\"token punctuation\">,</span>\n            nonce\n        <span class=\"token punctuation\">)</span>\n    <span class=\"token function\">except</span> <span class=\"token punctuation\">(</span>InvalidAppIdException<span class=\"token punctuation\">,</span> InvalidSignatureException<span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span>\n        <span class=\"token keyword\">return</span>\n    msg <span class=\"token operator\">=</span> <span class=\"token function\">parse_message</span><span class=\"token punctuation\">(</span>decrypted_xml<span class=\"token punctuation\">)</span>\n    reply <span class=\"token operator\">=</span> <span class=\"token function\">create_reply</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"出了点小问题，请稍后再试\"</span><span class=\"token punctuation\">,</span> msg<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">render</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n    <span class=\"token function\">print</span><span class=\"token punctuation\">(</span><span class=\"token string\">'返回结果--->'</span><span class=\"token operator\">+</span><span class=\"token function\">str</span><span class=\"token punctuation\">(</span>reply<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>  # 用来在腾讯云控制台打印请求日志\n    reply <span class=\"token operator\">=</span> crypto<span class=\"token punctuation\">.</span><span class=\"token function\">encrypt_message</span><span class=\"token punctuation\">(</span>reply<span class=\"token punctuation\">,</span> nonce<span class=\"token punctuation\">,</span> timestamp<span class=\"token punctuation\">)</span>\n    <span class=\"token keyword\">return</span> <span class=\"token function\">apiReply</span><span class=\"token punctuation\">(</span>reply<span class=\"token punctuation\">,</span> txt<span class=\"token operator\">=</span>True<span class=\"token punctuation\">,</span> content_type<span class=\"token operator\">=</span><span class=\"token string\">\"application/xml\"</span><span class=\"token punctuation\">)</span>\n\n\ndef <span class=\"token function\">main_handler</span><span class=\"token punctuation\">(</span>event<span class=\"token punctuation\">,</span> context<span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span>\n    body <span class=\"token operator\">=</span> <span class=\"token string\">''</span>\n    httpMethod <span class=\"token operator\">=</span> event<span class=\"token punctuation\">[</span><span class=\"token string\">\"httpMethod\"</span><span class=\"token punctuation\">]</span>\n    requestParameters <span class=\"token operator\">=</span> event<span class=\"token punctuation\">[</span><span class=\"token string\">'queryString'</span><span class=\"token punctuation\">]</span>\n    <span class=\"token keyword\">if</span> <span class=\"token string\">'body'</span> <span class=\"token keyword\">in</span> event<span class=\"token punctuation\">.</span><span class=\"token function\">keys</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span>\n        body <span class=\"token operator\">=</span> event<span class=\"token punctuation\">[</span><span class=\"token string\">'body'</span><span class=\"token punctuation\">]</span>\n    <span class=\"token keyword\">try</span><span class=\"token punctuation\">:</span>\n        response <span class=\"token operator\">=</span> <span class=\"token function\">myMain</span><span class=\"token punctuation\">(</span>httpMethod<span class=\"token punctuation\">,</span> requestParameters<span class=\"token punctuation\">,</span> body<span class=\"token operator\">=</span>body<span class=\"token punctuation\">)</span>\n    except<span class=\"token punctuation\">:</span>\n        response <span class=\"token operator\">=</span> <span class=\"token function\">timeOutReply</span><span class=\"token punctuation\">(</span>httpMethod<span class=\"token punctuation\">,</span> requestParameters<span class=\"token punctuation\">,</span> body<span class=\"token operator\">=</span>body<span class=\"token punctuation\">)</span>\n    <span class=\"token keyword\">return</span> response</code></pre></div>\n<p>请求参数解析和<a href=\"https://cloud.tencent.com/product/cos?from=10680\">COS</a>读写部分可参考上一篇<a href=\"https://serverlesscloud.cn/blog/2020-04-23-serverless-scf-cos/\">《万物皆可 Serverless 之使用 SCF+COS 快速开发全栈应用》</a>教程</p>\n<p>下面我来捋一下整个云函数的思路</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"48925047609410120000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"代码复制成功\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`def main_handler(event, context):\n    body = ''\n    httpMethod = event[&quot;httpMethod&quot;]\n    requestParameters = event['queryString']\n    if 'body' in event.keys():\n        body = event['body']\n    try:\n        response = myMain(httpMethod, requestParameters, body=body)\n    except:\n        response = timeOutReply(httpMethod, requestParameters, body=body)\n    return response`, `48925047609410120000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                复制代码<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\">def <span class=\"token function\">main_handler</span><span class=\"token punctuation\">(</span>event<span class=\"token punctuation\">,</span> context<span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span>\n    body <span class=\"token operator\">=</span> <span class=\"token string\">''</span>\n    httpMethod <span class=\"token operator\">=</span> event<span class=\"token punctuation\">[</span><span class=\"token string\">\"httpMethod\"</span><span class=\"token punctuation\">]</span>\n    requestParameters <span class=\"token operator\">=</span> event<span class=\"token punctuation\">[</span><span class=\"token string\">'queryString'</span><span class=\"token punctuation\">]</span>\n    <span class=\"token keyword\">if</span> <span class=\"token string\">'body'</span> <span class=\"token keyword\">in</span> event<span class=\"token punctuation\">.</span><span class=\"token function\">keys</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span>\n        body <span class=\"token operator\">=</span> event<span class=\"token punctuation\">[</span><span class=\"token string\">'body'</span><span class=\"token punctuation\">]</span>\n    <span class=\"token keyword\">try</span><span class=\"token punctuation\">:</span>\n        response <span class=\"token operator\">=</span> <span class=\"token function\">myMain</span><span class=\"token punctuation\">(</span>httpMethod<span class=\"token punctuation\">,</span> requestParameters<span class=\"token punctuation\">,</span> body<span class=\"token operator\">=</span>body<span class=\"token punctuation\">)</span>\n    except<span class=\"token punctuation\">:</span>\n        response <span class=\"token operator\">=</span> <span class=\"token function\">timeOutReply</span><span class=\"token punctuation\">(</span>httpMethod<span class=\"token punctuation\">,</span> requestParameters<span class=\"token punctuation\">,</span> body<span class=\"token operator\">=</span>body<span class=\"token punctuation\">)</span>\n    <span class=\"token keyword\">return</span> response</code></pre></div>\n<p>我们先从 <code class=\"language-text\">main\\_handler</code> 入手，</p>\n<p>这里我们通过 API 网关触发云函数在 event 里拿到了微信公众号请求的方法、头部和请求体，然后传给 myMain 函数做处理，需要注意的是 myMain 是通过 <code class=\"language-text\">timeout\\_decorator</code> 包装的限时运行函数。</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"30367319750038570000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"代码复制成功\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`@timeout_decorator.timeout(4, timeout_exception=StopIteration)\ndef myMain(httpMethod, requestParameters, body=''):\n    return wechat(httpMethod, requestParameters, body=body)`, `30367319750038570000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                复制代码<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\">@timeout_decorator<span class=\"token punctuation\">.</span><span class=\"token function\">timeout</span><span class=\"token punctuation\">(</span><span class=\"token number\">4</span><span class=\"token punctuation\">,</span> timeout_exception<span class=\"token operator\">=</span>StopIteration<span class=\"token punctuation\">)</span>\ndef <span class=\"token function\">myMain</span><span class=\"token punctuation\">(</span>httpMethod<span class=\"token punctuation\">,</span> requestParameters<span class=\"token punctuation\">,</span> body<span class=\"token operator\">=</span><span class=\"token string\">''</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span>\n    <span class=\"token keyword\">return</span> <span class=\"token function\">wechat</span><span class=\"token punctuation\">(</span>httpMethod<span class=\"token punctuation\">,</span> requestParameters<span class=\"token punctuation\">,</span> body<span class=\"token operator\">=</span>body<span class=\"token punctuation\">)</span></code></pre></div>\n<p>当 myMain 函数运行市场超过设定的 4 秒后，就会抛出异常，</p>\n<p>然后我们可以通过设置一个 <code class=\"language-text\">timeOutReply</code> 函数来处理超时后的微信公众号消息回复，可是为什么要这么做呢？</p>\n<p><img src=\"https://img.serverlesscloud.cn/2020523/1590204021016-16200.jpg\" alt=\"函数运行超时后\"></p>\n<p>可以看到，当云函数运行超时后，微信这边就会显示「该公众号提供的服务器出现故障，请稍后再试」</p>\n<p>这对用户体验是极不友好的，所以我们需要一个函数超时后的回复来兜底。</p>\n<p><img src=\"https://img.serverlesscloud.cn/2020523/1590204021394-16200.jpg\" alt=\"微信消息请求频次\"></p>\n<p>那么对于一次微信公众号后台消息请求多长时间算是超时呢？答案是 5 秒左右，从云函数后台的调用日志我们可以得到这个结果。</p>\n<p>不过需要注意的是对于用户的一次消息请求，微信可能会每隔 1 秒左右重拨一次请求，直到收到服务器第一次响应。另外，超过 3 次应该就不会再重拨了，并且在 5 秒超时后即使云函数调用成功并返回了数据，用户也不会再接收到消息了~</p>\n<p>所以我们就很有必要将自己的云函数的运行时长限制在 5 秒之内了！</p>\n<p>当然只通过配置云函数超时时长得方式来处理是不正确的，因为这样做云函数超时后就被系统停掉了，并不会向微信返回消息。所以从一开始我就导入了 <code class=\"language-text\">timeout\\_decorator</code> 库来限制主函数的运行时长，并用一个超时后回复函数来兜底。</p>\n<p>另外值得一提的是，在我原始的业务代码中是有一些爬虫，这些爬虫本来我是单线程顺序执行的，考虑到超时问题，我在微信云函数版这里全部改成了多线程运行来压缩时间，所以如果你也有一些比较耗时的小任务话，也可以尝试通过多线程的方式来压缩云函数的运行时长。</p>\n<p>我们接着向下看：</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"60105980582244520000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"代码复制成功\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`def wechat(httpMethod, requestParameters, body=''):\n    if httpMethod == 'GET':\n        signature = requestParameters['signature']\n        timestamp = requestParameters['timestamp']\n        nonce = requestParameters['nonce']\n        echo_str = requestParameters['echostr']\n        try:\n            check_signature(WECHAT_TOKEN, signature, timestamp, nonce)\n        except InvalidSignatureException:\n            echo_str = 'error'\n        return apiReply(echo_str, txt=True, content_type=&quot;text/plain&quot;)\n    elif httpMethod == 'POST':\n        msg_signature = requestParameters['msg_signature']\n        timestamp = requestParameters['timestamp']\n        nonce = requestParameters['nonce']\n        try:\n            decrypted_xml = crypto.decrypt_message(\n                body,\n                msg_signature,\n                timestamp,\n                nonce\n            )\n        except (InvalidAppIdException, InvalidSignatureException):\n            return\n        msg = parse_message(decrypted_xml)\n        if msg.type == 'text':\n            reply = replyMessage(msg)\n        elif msg.type == 'image':\n            reply = create_reply('哈◔ ‸◔？\\n好端端的，给我发图片干啥~', msg)\n        elif msg.type == 'voice':\n            reply = create_reply('哈◔ ‸◔？\\n好端端的，给我发语音干啥~', msg)\n        else:\n            reply = create_reply('哈◔ ‸◔？\\n搞不明白你给我发了啥~', msg)\n        reply = reply.render()\n        print('返回结果--->'+str(reply))  # 用来在腾讯云控制台打印请求日志\n        reply = crypto.encrypt_message(reply, nonce, timestamp)\n        return apiReply(reply, txt=True, content_type=&quot;application/xml&quot;)\n    else:\n        msg = parse_message(body)\n        reply = create_reply(&quot;喵呜 ฅ'ω'ฅ&quot;, msg)\n        reply = reply.render()\n        print('返回结果--->'+str(reply))  # 用来在腾讯云控制台打印请求日志\n        reply = crypto.encrypt_message(reply, nonce, timestamp)\n        return apiReply(reply, txt=True, content_type=&quot;application/xml&quot;)`, `60105980582244520000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                复制代码<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\">def <span class=\"token function\">wechat</span><span class=\"token punctuation\">(</span>httpMethod<span class=\"token punctuation\">,</span> requestParameters<span class=\"token punctuation\">,</span> body<span class=\"token operator\">=</span><span class=\"token string\">''</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span>\n    <span class=\"token keyword\">if</span> httpMethod <span class=\"token operator\">==</span> <span class=\"token string\">'GET'</span><span class=\"token punctuation\">:</span>\n        signature <span class=\"token operator\">=</span> requestParameters<span class=\"token punctuation\">[</span><span class=\"token string\">'signature'</span><span class=\"token punctuation\">]</span>\n        timestamp <span class=\"token operator\">=</span> requestParameters<span class=\"token punctuation\">[</span><span class=\"token string\">'timestamp'</span><span class=\"token punctuation\">]</span>\n        nonce <span class=\"token operator\">=</span> requestParameters<span class=\"token punctuation\">[</span><span class=\"token string\">'nonce'</span><span class=\"token punctuation\">]</span>\n        echo_str <span class=\"token operator\">=</span> requestParameters<span class=\"token punctuation\">[</span><span class=\"token string\">'echostr'</span><span class=\"token punctuation\">]</span>\n        <span class=\"token keyword\">try</span><span class=\"token punctuation\">:</span>\n            <span class=\"token function\">check_signature</span><span class=\"token punctuation\">(</span><span class=\"token constant\">WECHAT_TOKEN</span><span class=\"token punctuation\">,</span> signature<span class=\"token punctuation\">,</span> timestamp<span class=\"token punctuation\">,</span> nonce<span class=\"token punctuation\">)</span>\n        except InvalidSignatureException<span class=\"token punctuation\">:</span>\n            echo_str <span class=\"token operator\">=</span> <span class=\"token string\">'error'</span>\n        <span class=\"token keyword\">return</span> <span class=\"token function\">apiReply</span><span class=\"token punctuation\">(</span>echo_str<span class=\"token punctuation\">,</span> txt<span class=\"token operator\">=</span>True<span class=\"token punctuation\">,</span> content_type<span class=\"token operator\">=</span><span class=\"token string\">\"text/plain\"</span><span class=\"token punctuation\">)</span>\n    elif httpMethod <span class=\"token operator\">==</span> <span class=\"token string\">'POST'</span><span class=\"token punctuation\">:</span>\n        msg_signature <span class=\"token operator\">=</span> requestParameters<span class=\"token punctuation\">[</span><span class=\"token string\">'msg_signature'</span><span class=\"token punctuation\">]</span>\n        timestamp <span class=\"token operator\">=</span> requestParameters<span class=\"token punctuation\">[</span><span class=\"token string\">'timestamp'</span><span class=\"token punctuation\">]</span>\n        nonce <span class=\"token operator\">=</span> requestParameters<span class=\"token punctuation\">[</span><span class=\"token string\">'nonce'</span><span class=\"token punctuation\">]</span>\n        <span class=\"token keyword\">try</span><span class=\"token punctuation\">:</span>\n            decrypted_xml <span class=\"token operator\">=</span> crypto<span class=\"token punctuation\">.</span><span class=\"token function\">decrypt_message</span><span class=\"token punctuation\">(</span>\n                body<span class=\"token punctuation\">,</span>\n                msg_signature<span class=\"token punctuation\">,</span>\n                timestamp<span class=\"token punctuation\">,</span>\n                nonce\n            <span class=\"token punctuation\">)</span>\n        <span class=\"token function\">except</span> <span class=\"token punctuation\">(</span>InvalidAppIdException<span class=\"token punctuation\">,</span> InvalidSignatureException<span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span>\n            <span class=\"token keyword\">return</span>\n        msg <span class=\"token operator\">=</span> <span class=\"token function\">parse_message</span><span class=\"token punctuation\">(</span>decrypted_xml<span class=\"token punctuation\">)</span>\n        <span class=\"token keyword\">if</span> msg<span class=\"token punctuation\">.</span>type <span class=\"token operator\">==</span> <span class=\"token string\">'text'</span><span class=\"token punctuation\">:</span>\n            reply <span class=\"token operator\">=</span> <span class=\"token function\">replyMessage</span><span class=\"token punctuation\">(</span>msg<span class=\"token punctuation\">)</span>\n        elif msg<span class=\"token punctuation\">.</span>type <span class=\"token operator\">==</span> <span class=\"token string\">'image'</span><span class=\"token punctuation\">:</span>\n            reply <span class=\"token operator\">=</span> <span class=\"token function\">create_reply</span><span class=\"token punctuation\">(</span><span class=\"token string\">'哈◔ ‸◔？\\n好端端的，给我发图片干啥~'</span><span class=\"token punctuation\">,</span> msg<span class=\"token punctuation\">)</span>\n        elif msg<span class=\"token punctuation\">.</span>type <span class=\"token operator\">==</span> <span class=\"token string\">'voice'</span><span class=\"token punctuation\">:</span>\n            reply <span class=\"token operator\">=</span> <span class=\"token function\">create_reply</span><span class=\"token punctuation\">(</span><span class=\"token string\">'哈◔ ‸◔？\\n好端端的，给我发语音干啥~'</span><span class=\"token punctuation\">,</span> msg<span class=\"token punctuation\">)</span>\n        <span class=\"token keyword\">else</span><span class=\"token punctuation\">:</span>\n            reply <span class=\"token operator\">=</span> <span class=\"token function\">create_reply</span><span class=\"token punctuation\">(</span><span class=\"token string\">'哈◔ ‸◔？\\n搞不明白你给我发了啥~'</span><span class=\"token punctuation\">,</span> msg<span class=\"token punctuation\">)</span>\n        reply <span class=\"token operator\">=</span> reply<span class=\"token punctuation\">.</span><span class=\"token function\">render</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n        <span class=\"token function\">print</span><span class=\"token punctuation\">(</span><span class=\"token string\">'返回结果--->'</span><span class=\"token operator\">+</span><span class=\"token function\">str</span><span class=\"token punctuation\">(</span>reply<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>  # 用来在腾讯云控制台打印请求日志\n        reply <span class=\"token operator\">=</span> crypto<span class=\"token punctuation\">.</span><span class=\"token function\">encrypt_message</span><span class=\"token punctuation\">(</span>reply<span class=\"token punctuation\">,</span> nonce<span class=\"token punctuation\">,</span> timestamp<span class=\"token punctuation\">)</span>\n        <span class=\"token keyword\">return</span> <span class=\"token function\">apiReply</span><span class=\"token punctuation\">(</span>reply<span class=\"token punctuation\">,</span> txt<span class=\"token operator\">=</span>True<span class=\"token punctuation\">,</span> content_type<span class=\"token operator\">=</span><span class=\"token string\">\"application/xml\"</span><span class=\"token punctuation\">)</span>\n    <span class=\"token keyword\">else</span><span class=\"token punctuation\">:</span>\n        msg <span class=\"token operator\">=</span> <span class=\"token function\">parse_message</span><span class=\"token punctuation\">(</span>body<span class=\"token punctuation\">)</span>\n        reply <span class=\"token operator\">=</span> <span class=\"token function\">create_reply</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"喵呜 ฅ'ω'ฅ\"</span><span class=\"token punctuation\">,</span> msg<span class=\"token punctuation\">)</span>\n        reply <span class=\"token operator\">=</span> reply<span class=\"token punctuation\">.</span><span class=\"token function\">render</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n        <span class=\"token function\">print</span><span class=\"token punctuation\">(</span><span class=\"token string\">'返回结果--->'</span><span class=\"token operator\">+</span><span class=\"token function\">str</span><span class=\"token punctuation\">(</span>reply<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>  # 用来在腾讯云控制台打印请求日志\n        reply <span class=\"token operator\">=</span> crypto<span class=\"token punctuation\">.</span><span class=\"token function\">encrypt_message</span><span class=\"token punctuation\">(</span>reply<span class=\"token punctuation\">,</span> nonce<span class=\"token punctuation\">,</span> timestamp<span class=\"token punctuation\">)</span>\n        <span class=\"token keyword\">return</span> <span class=\"token function\">apiReply</span><span class=\"token punctuation\">(</span>reply<span class=\"token punctuation\">,</span> txt<span class=\"token operator\">=</span>True<span class=\"token punctuation\">,</span> content_type<span class=\"token operator\">=</span><span class=\"token string\">\"application/xml\"</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>这里的 wechat 函数就是整个微信消息的解析过程，首先判断请求方法是 GET 还是 POST，GET 方法只在第一次绑定微信后台时会用到，这时我们会从微信服务器推送的请求参数中拿到 <code class=\"language-text\">signature</code>, <code class=\"language-text\">timestamp</code>, <code class=\"language-text\">echostr</code> 和 <code class=\"language-text\">nonce</code> 参数，</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"16257796993183037000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"代码复制成功\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`check_signature(WECHAT_TOKEN, signature, timestamp, nonce)`, `16257796993183037000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                复制代码<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token function\">check_signature</span><span class=\"token punctuation\">(</span><span class=\"token constant\">WECHAT_TOKEN</span><span class=\"token punctuation\">,</span> signature<span class=\"token punctuation\">,</span> timestamp<span class=\"token punctuation\">,</span> nonce<span class=\"token punctuation\">)</span></code></pre></div>\n<p>我们只需根据自己的公众号 token 和来生成签名与微信服务器传过来的 signature 对比看是否一致，若一致就说明我们的消息加解密验证是OK的，然后再将 echostr 原样返回即可接入微信公众号后台。</p>\n<p>接入好微信公众号后，如果有用户在后台给我们发送消息，这里云函数收到的就是 POST 方法，</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"39671147880150180000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"代码复制成功\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`elif httpMethod == 'POST':\n        msg_signature = requestParameters['msg_signature']\n        timestamp = requestParameters['timestamp']\n        nonce = requestParameters['nonce']\n        try:\n            decrypted_xml = crypto.decrypt_message(\n                body,\n                msg_signature,\n                timestamp,\n                nonce\n            )\n        except (InvalidAppIdException, InvalidSignatureException):\n            return\n        msg = parse_message(decrypted_xml)\n        if msg.type == 'text':\n            reply = replyMessage(msg)\n        elif msg.type == 'image':\n            reply = create_reply('哈◔ ‸◔？\\n好端端的，给我发图片干啥~', msg)\n        elif msg.type == 'voice':\n            reply = create_reply('哈◔ ‸◔？\\n好端端的，给我发语音干啥~', msg)\n        else:\n            reply = create_reply('哈◔ ‸◔？\\n搞不明白你给我发了啥~', msg)\n        reply = reply.render()\n        print('返回结果--->'+str(reply))  # 用来在腾讯云控制台打印请求日志\n        reply = crypto.encrypt_message(reply, nonce, timestamp)\n        return apiReply(reply, txt=True, content_type=&quot;application/xml&quot;)`, `39671147880150180000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                复制代码<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\">elif httpMethod <span class=\"token operator\">==</span> <span class=\"token string\">'POST'</span><span class=\"token punctuation\">:</span>\n        msg_signature <span class=\"token operator\">=</span> requestParameters<span class=\"token punctuation\">[</span><span class=\"token string\">'msg_signature'</span><span class=\"token punctuation\">]</span>\n        timestamp <span class=\"token operator\">=</span> requestParameters<span class=\"token punctuation\">[</span><span class=\"token string\">'timestamp'</span><span class=\"token punctuation\">]</span>\n        nonce <span class=\"token operator\">=</span> requestParameters<span class=\"token punctuation\">[</span><span class=\"token string\">'nonce'</span><span class=\"token punctuation\">]</span>\n        <span class=\"token keyword\">try</span><span class=\"token punctuation\">:</span>\n            decrypted_xml <span class=\"token operator\">=</span> crypto<span class=\"token punctuation\">.</span><span class=\"token function\">decrypt_message</span><span class=\"token punctuation\">(</span>\n                body<span class=\"token punctuation\">,</span>\n                msg_signature<span class=\"token punctuation\">,</span>\n                timestamp<span class=\"token punctuation\">,</span>\n                nonce\n            <span class=\"token punctuation\">)</span>\n        <span class=\"token function\">except</span> <span class=\"token punctuation\">(</span>InvalidAppIdException<span class=\"token punctuation\">,</span> InvalidSignatureException<span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span>\n            <span class=\"token keyword\">return</span>\n        msg <span class=\"token operator\">=</span> <span class=\"token function\">parse_message</span><span class=\"token punctuation\">(</span>decrypted_xml<span class=\"token punctuation\">)</span>\n        <span class=\"token keyword\">if</span> msg<span class=\"token punctuation\">.</span>type <span class=\"token operator\">==</span> <span class=\"token string\">'text'</span><span class=\"token punctuation\">:</span>\n            reply <span class=\"token operator\">=</span> <span class=\"token function\">replyMessage</span><span class=\"token punctuation\">(</span>msg<span class=\"token punctuation\">)</span>\n        elif msg<span class=\"token punctuation\">.</span>type <span class=\"token operator\">==</span> <span class=\"token string\">'image'</span><span class=\"token punctuation\">:</span>\n            reply <span class=\"token operator\">=</span> <span class=\"token function\">create_reply</span><span class=\"token punctuation\">(</span><span class=\"token string\">'哈◔ ‸◔？\\n好端端的，给我发图片干啥~'</span><span class=\"token punctuation\">,</span> msg<span class=\"token punctuation\">)</span>\n        elif msg<span class=\"token punctuation\">.</span>type <span class=\"token operator\">==</span> <span class=\"token string\">'voice'</span><span class=\"token punctuation\">:</span>\n            reply <span class=\"token operator\">=</span> <span class=\"token function\">create_reply</span><span class=\"token punctuation\">(</span><span class=\"token string\">'哈◔ ‸◔？\\n好端端的，给我发语音干啥~'</span><span class=\"token punctuation\">,</span> msg<span class=\"token punctuation\">)</span>\n        <span class=\"token keyword\">else</span><span class=\"token punctuation\">:</span>\n            reply <span class=\"token operator\">=</span> <span class=\"token function\">create_reply</span><span class=\"token punctuation\">(</span><span class=\"token string\">'哈◔ ‸◔？\\n搞不明白你给我发了啥~'</span><span class=\"token punctuation\">,</span> msg<span class=\"token punctuation\">)</span>\n        reply <span class=\"token operator\">=</span> reply<span class=\"token punctuation\">.</span><span class=\"token function\">render</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n        <span class=\"token function\">print</span><span class=\"token punctuation\">(</span><span class=\"token string\">'返回结果--->'</span><span class=\"token operator\">+</span><span class=\"token function\">str</span><span class=\"token punctuation\">(</span>reply<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>  # 用来在腾讯云控制台打印请求日志\n        reply <span class=\"token operator\">=</span> crypto<span class=\"token punctuation\">.</span><span class=\"token function\">encrypt_message</span><span class=\"token punctuation\">(</span>reply<span class=\"token punctuation\">,</span> nonce<span class=\"token punctuation\">,</span> timestamp<span class=\"token punctuation\">)</span>\n        <span class=\"token keyword\">return</span> <span class=\"token function\">apiReply</span><span class=\"token punctuation\">(</span>reply<span class=\"token punctuation\">,</span> txt<span class=\"token operator\">=</span>True<span class=\"token punctuation\">,</span> content_type<span class=\"token operator\">=</span><span class=\"token string\">\"application/xml\"</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>然后我们根据前面在微信公众号后台拿到的 id，token 和 aes 加密 key 来初始化消息加解密实例并解密还原用户发送的消息</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"1145077024241691900\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"代码复制成功\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`# 微信公众号对接\nwecaht_id = 'xxxxxxxxxxxxxxx'\nWECHAT_TOKEN = 'xxxxxxxxxxxxxxxxxxx'\nencoding_aes_key = 'xxxxxxxxxxxxxxxxxxxxxx'\n\ncrypto = WeChatCrypto(WECHAT_TOKEN, encoding_aes_key, wecaht_id)`, `1145077024241691900`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                复制代码<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"># 微信公众号对接\nwecaht_id <span class=\"token operator\">=</span> <span class=\"token string\">'xxxxxxxxxxxxxxx'</span>\n<span class=\"token constant\">WECHAT_TOKEN</span> <span class=\"token operator\">=</span> <span class=\"token string\">'xxxxxxxxxxxxxxxxxxx'</span>\nencoding_aes_key <span class=\"token operator\">=</span> <span class=\"token string\">'xxxxxxxxxxxxxxxxxxxxxx'</span>\n\ncrypto <span class=\"token operator\">=</span> <span class=\"token function\">WeChatCrypto</span><span class=\"token punctuation\">(</span><span class=\"token constant\">WECHAT_TOKEN</span><span class=\"token punctuation\">,</span> encoding_aes_key<span class=\"token punctuation\">,</span> wecaht_id<span class=\"token punctuation\">)</span></code></pre></div>\n<p>接着判断一下消息类型，不同类型的消息可自行处理</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"23001106157465203000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"代码复制成功\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`        msg = parse_message(decrypted_xml)\n        if msg.type == 'text':\n            reply = replyMessage(msg)\n        elif msg.type == 'image':\n            reply = create_reply('哈◔ ‸◔？ 好端端的，给我发图片干啥~', msg)\n        elif msg.type == 'voice':\n            reply = create_reply('哈◔ ‸◔？ 好端端的，给我发语音干啥~', msg)\n        else:\n            reply = create_reply('哈◔ ‸◔？ 搞不明白你给我发了啥~', msg)`, `23001106157465203000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                复制代码<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\">        msg <span class=\"token operator\">=</span> <span class=\"token function\">parse_message</span><span class=\"token punctuation\">(</span>decrypted_xml<span class=\"token punctuation\">)</span>\n        <span class=\"token keyword\">if</span> msg<span class=\"token punctuation\">.</span>type <span class=\"token operator\">==</span> <span class=\"token string\">'text'</span><span class=\"token punctuation\">:</span>\n            reply <span class=\"token operator\">=</span> <span class=\"token function\">replyMessage</span><span class=\"token punctuation\">(</span>msg<span class=\"token punctuation\">)</span>\n        elif msg<span class=\"token punctuation\">.</span>type <span class=\"token operator\">==</span> <span class=\"token string\">'image'</span><span class=\"token punctuation\">:</span>\n            reply <span class=\"token operator\">=</span> <span class=\"token function\">create_reply</span><span class=\"token punctuation\">(</span><span class=\"token string\">'哈◔ ‸◔？ 好端端的，给我发图片干啥~'</span><span class=\"token punctuation\">,</span> msg<span class=\"token punctuation\">)</span>\n        elif msg<span class=\"token punctuation\">.</span>type <span class=\"token operator\">==</span> <span class=\"token string\">'voice'</span><span class=\"token punctuation\">:</span>\n            reply <span class=\"token operator\">=</span> <span class=\"token function\">create_reply</span><span class=\"token punctuation\">(</span><span class=\"token string\">'哈◔ ‸◔？ 好端端的，给我发语音干啥~'</span><span class=\"token punctuation\">,</span> msg<span class=\"token punctuation\">)</span>\n        <span class=\"token keyword\">else</span><span class=\"token punctuation\">:</span>\n            reply <span class=\"token operator\">=</span> <span class=\"token function\">create_reply</span><span class=\"token punctuation\">(</span><span class=\"token string\">'哈◔ ‸◔？ 搞不明白你给我发了啥~'</span><span class=\"token punctuation\">,</span> msg<span class=\"token punctuation\">)</span></code></pre></div>\n<p>需要注意的是当一个用户新关注自己的公众号时，我们收到的是一个其他类型的消息，也就是上面的最后一个判断项，这里你可以自己设置新关注用户的欢迎语</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"32539694174242185000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"代码复制成功\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`        reply = create_reply('哈◔ ‸◔？\\n搞不明白你给我发了啥~', msg)\n        reply = reply.render()\n        print('返回结果--->'+str(reply))  # 用来在腾讯云控制台打印请求日志\n        reply = crypto.encrypt_message(reply, nonce, timestamp)\n        return apiReply(reply, txt=True, content_type=&quot;application/xml&quot;)`, `32539694174242185000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                复制代码<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\">        reply <span class=\"token operator\">=</span> <span class=\"token function\">create_reply</span><span class=\"token punctuation\">(</span><span class=\"token string\">'哈◔ ‸◔？\\n搞不明白你给我发了啥~'</span><span class=\"token punctuation\">,</span> msg<span class=\"token punctuation\">)</span>\n        reply <span class=\"token operator\">=</span> reply<span class=\"token punctuation\">.</span><span class=\"token function\">render</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n        <span class=\"token function\">print</span><span class=\"token punctuation\">(</span><span class=\"token string\">'返回结果--->'</span><span class=\"token operator\">+</span><span class=\"token function\">str</span><span class=\"token punctuation\">(</span>reply<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>  # 用来在腾讯云控制台打印请求日志\n        reply <span class=\"token operator\">=</span> crypto<span class=\"token punctuation\">.</span><span class=\"token function\">encrypt_message</span><span class=\"token punctuation\">(</span>reply<span class=\"token punctuation\">,</span> nonce<span class=\"token punctuation\">,</span> timestamp<span class=\"token punctuation\">)</span>\n        <span class=\"token keyword\">return</span> <span class=\"token function\">apiReply</span><span class=\"token punctuation\">(</span>reply<span class=\"token punctuation\">,</span> txt<span class=\"token operator\">=</span>True<span class=\"token punctuation\">,</span> content_type<span class=\"token operator\">=</span><span class=\"token string\">\"application/xml\"</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>之后我们通过 <code class=\"language-text\">create\\_reply</code> 来快速创建一个文本回复，并通过 render() 来生成 xml 回复消息文本。因为我之前在后台设置的是安全模式，所以还需要把 xml 重新通过 <code class=\"language-text\">crypto.encrypt\\_message</code> 方法加密，然后才能把加密后的回复消息返回给微信服务器。</p>\n<p>上一篇文章我有提到我们不能直接返回消息，需要按照特定的格式返回数据（API 网关需要开启响应集成）</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"87912965145352010000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"代码复制成功\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`# api网关响应集成\ndef apiReply(reply, txt=False, content_type='application/json', code=200):\n    return {\n        &quot;isBase64Encoded&quot;: False,\n        &quot;statusCode&quot;: code,\n        &quot;headers&quot;: {'Content-Type': content_type},\n        &quot;body&quot;: json.dumps(reply, ensure_ascii=False) if not txt else str(reply)\n    }`, `87912965145352010000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                复制代码<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"># api网关响应集成\ndef <span class=\"token function\">apiReply</span><span class=\"token punctuation\">(</span>reply<span class=\"token punctuation\">,</span> txt<span class=\"token operator\">=</span>False<span class=\"token punctuation\">,</span> content_type<span class=\"token operator\">=</span><span class=\"token string\">'application/json'</span><span class=\"token punctuation\">,</span> code<span class=\"token operator\">=</span><span class=\"token number\">200</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span>\n    <span class=\"token keyword\">return</span> <span class=\"token punctuation\">{</span>\n        <span class=\"token string\">\"isBase64Encoded\"</span><span class=\"token punctuation\">:</span> False<span class=\"token punctuation\">,</span>\n        <span class=\"token string\">\"statusCode\"</span><span class=\"token punctuation\">:</span> code<span class=\"token punctuation\">,</span>\n        <span class=\"token string\">\"headers\"</span><span class=\"token punctuation\">:</span> <span class=\"token punctuation\">{</span><span class=\"token string\">'Content-Type'</span><span class=\"token punctuation\">:</span> content_type<span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n        <span class=\"token string\">\"body\"</span><span class=\"token punctuation\">:</span> json<span class=\"token punctuation\">.</span><span class=\"token function\">dumps</span><span class=\"token punctuation\">(</span>reply<span class=\"token punctuation\">,</span> ensure_ascii<span class=\"token operator\">=</span>False<span class=\"token punctuation\">)</span> <span class=\"token keyword\">if</span> not txt <span class=\"token keyword\">else</span> <span class=\"token function\">str</span><span class=\"token punctuation\">(</span>reply<span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">}</span></code></pre></div>\n<h3 id=\"第四步：上线发布云函数、添加-api-网关触发器、启用响应集成\"><a href=\"#%E7%AC%AC%E5%9B%9B%E6%AD%A5%EF%BC%9A%E4%B8%8A%E7%BA%BF%E5%8F%91%E5%B8%83%E4%BA%91%E5%87%BD%E6%95%B0%E3%80%81%E6%B7%BB%E5%8A%A0-api-%E7%BD%91%E5%85%B3%E8%A7%A6%E5%8F%91%E5%99%A8%E3%80%81%E5%90%AF%E7%94%A8%E5%93%8D%E5%BA%94%E9%9B%86%E6%88%90\" aria-label=\"第四步：上线发布云函数、添加 api 网关触发器、启用响应集成 permalink\" class=\"anchor\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>第四步：上线发布云函数、添加 API 网关触发器、启用响应集成</h3>\n<p>参考上一篇教程 <a href=\"https://serverlesscloud.cn/blog/2020-04-23-serverless-scf-cos/\">《万物皆可 Serverless 之使用 SCF+COS 快速开发全栈应用》</a></p>\n<h3 id=\"第五步：修改微信公众号后台服务器配置\"><a href=\"#%E7%AC%AC%E4%BA%94%E6%AD%A5%EF%BC%9A%E4%BF%AE%E6%94%B9%E5%BE%AE%E4%BF%A1%E5%85%AC%E4%BC%97%E5%8F%B7%E5%90%8E%E5%8F%B0%E6%9C%8D%E5%8A%A1%E5%99%A8%E9%85%8D%E7%BD%AE\" aria-label=\"第五步：修改微信公众号后台服务器配置 permalink\" class=\"anchor\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>第五步：修改微信公众号后台服务器配置</h3>\n<p>终于到最后一步了，如果你已经上线发布了好自己的云函数，那么快去微信公众号后台绑定一下自己的后台服务器配置吧~</p>\n<p><img src=\"https://img.serverlesscloud.cn/2020523/1590204020978-16200.jpg\" alt=\"后台服务器配置\"></p>\n<p>呼~  大功告成</p>\n<hr>\n<div id='scf-deploy-iframe-or-md'></div>\n<hr>\n<blockquote>\n<p><strong>传送门：</strong></p>\n<ul>\n<li>GitHub: <a href=\"https://github.com/serverless/serverless/blob/master/README_CN.md\">github.com/serverless</a></li>\n<li>官网：<a href=\"https://serverless.com/\">serverless.com</a></li>\n</ul>\n</blockquote>\n<p>欢迎访问：<a href=\"https://serverlesscloud.cn/\">Serverless 中文网</a>，您可以在 <a href=\"https://serverlesscloud.cn/best-practice\">最佳实践</a> 里体验更多关于 Serverless 应用的开发！</p>","tableOfContents":"<ul>\n<li><a href=\"/blog/2020-04-23-serverless-wechat-cos/#%E6%95%88%E6%9E%9C%E5%B1%95%E7%A4%BA\">效果展示</a></li>\n<li>\n<p><a href=\"/blog/2020-04-23-serverless-wechat-cos/#%E6%93%8D%E4%BD%9C%E6%AD%A5%E9%AA%A4\">操作步骤</a></p>\n<ul>\n<li><a href=\"/blog/2020-04-23-serverless-wechat-cos/#%E7%AC%AC%E4%B8%80%E6%AD%A5%EF%BC%9A%E6%B7%BB%E5%8A%A0%E7%9B%B8%E5%85%B3%E4%BE%9D%E8%B5%96\">第一步：添加相关依赖</a></li>\n<li><a href=\"/blog/2020-04-23-serverless-wechat-cos/#%E7%AC%AC%E4%BA%8C%E6%AD%A5%EF%BC%9A%E6%8E%A5%E5%85%A5%E5%BE%AE%E4%BF%A1%E5%85%AC%E4%BC%97%E5%8F%B7\">第二步：接入微信公众号</a></li>\n<li><a href=\"/blog/2020-04-23-serverless-wechat-cos/#%E7%AC%AC%E4%B8%89%E6%AD%A5%EF%BC%9A%E7%BC%96%E5%86%99%E4%BA%91%E5%87%BD%E6%95%B0%E8%A7%A3%E6%9E%90%E5%B9%B6%E5%9B%9E%E5%A4%8D%E5%BE%AE%E4%BF%A1%E5%85%AC%E4%BC%97%E5%8F%B7%E6%B6%88%E6%81%AF\">第三步：编写云函数解析并回复微信公众号消息</a></li>\n<li><a href=\"/blog/2020-04-23-serverless-wechat-cos/#%E7%AC%AC%E5%9B%9B%E6%AD%A5%EF%BC%9A%E4%B8%8A%E7%BA%BF%E5%8F%91%E5%B8%83%E4%BA%91%E5%87%BD%E6%95%B0%E3%80%81%E6%B7%BB%E5%8A%A0-api-%E7%BD%91%E5%85%B3%E8%A7%A6%E5%8F%91%E5%99%A8%E3%80%81%E5%90%AF%E7%94%A8%E5%93%8D%E5%BA%94%E9%9B%86%E6%88%90\">第四步：上线发布云函数、添加 API 网关触发器、启用响应集成</a></li>\n<li><a href=\"/blog/2020-04-23-serverless-wechat-cos/#%E7%AC%AC%E4%BA%94%E6%AD%A5%EF%BC%9A%E4%BF%AE%E6%94%B9%E5%BE%AE%E4%BF%A1%E5%85%AC%E4%BC%97%E5%8F%B7%E5%90%8E%E5%8F%B0%E6%9C%8D%E5%8A%A1%E5%99%A8%E9%85%8D%E7%BD%AE\">第五步：修改微信公众号后台服务器配置</a></li>\n</ul>\n</li>\n</ul>"},"previousBlog":{"id":"5e61ae27-a6be-5a1e-a7bd-06ddaaab5c3d","frontmatter":{"thumbnail":"https://img.serverlesscloud.cn/2020523/1590208707614-16201.jpg","authors":["乂乂又又"],"categories":["user-stories"],"date":"2020-04-23T00:00:00.000Z","title":"万物皆可 Serverless 之使用云函数 SCF 快速部署验证码识别接口","description":"验证码识别是搞爬虫实现自动化脚本避不开的一个问题，通常验证码识别程序要么部署在本地，要么部署在服务器端，如果部署在服务器端就需要自己去搭建配置网络环境并编写调用接口，这是一个极其繁琐耗时的过程。但是现在我们通过无服务器云函数 SCF，就可以快速将本地的验证码识别程序发布上线，极大地提高了开发效率。","authorslink":["https://cloud.tencent.com/developer/article/1615839"],"translators":null,"translatorslink":null,"tags":["爬虫","云函数"],"keywords":"Serverless,Serverless SCF,Serverless应用","outdated":null},"wordCount":{"words":131,"sentences":42,"paragraphs":42},"fileAbsolutePath":"/opt/build/repo/content/blog/2020-04-23-serverless-scf-api.md","fields":{"slug":"/blog/2020-04-23-serverless-scf-api/","keywords":["java","python","serverless","无服务器","无服务器云函数","云函数","验证码","putpixel","range","识别"]}},"nextBlog":{"id":"bdf645bd-3599-55a2-9a1b-bcf94ce9be6b","frontmatter":{"thumbnail":"https://img.serverlesscloud.cn/2020421/1587478396860-bannner.jpg","authors":["腾讯云"],"categories":["news"],"date":"2020-04-22T00:00:00.000Z","title":"腾讯云正式发布 Serverless Framework","description":"该版中发布了全新的组件（Component）机制、云引擎部署支持、实时日志和调试等能力，这些新功能为 Serverless 应用程序开发提供了顶级的顺畅体验！","authorslink":["https://serverlesscloud.cn"],"translators":null,"translatorslink":null,"tags":["Serverless","全栈应用"],"keywords":"Serverless,Serverless Framework,全栈解决方案","outdated":null},"wordCount":{"words":204,"sentences":22,"paragraphs":22},"fileAbsolutePath":"/opt/build/repo/content/blog/2020-04-22-serverless-framework.md","fields":{"slug":"/blog/2020-04-22-serverless-framework/","keywords":["go","serverless","Serverless","serverless","Framework","serverlesscloud","部署","腾讯"]}},"recommendBlogs":{"edges":[{"node":{"id":"4300b21c-7209-5256-86ff-0d38e3daec9b","frontmatter":{"thumbnail":"https://main.qcloudimg.com/raw/14f1c8eed372e76c1b139703b2f6d0fa.jpg","authors":["KieranMcCarthy"],"categories":["user-stories","engineering-culture"],"date":"2018-01-09T00:00:00.000Z","title":"我是如何在四年时间里，从厨师转行为 Serverless 应用开发者","description":"我是厨师出身，现在成为了一名 Serverless 应用开发者。","authorslink":["https://serverless.com/author/kieranmccarthy/"],"translators":["Aceyclee"],"translatorslink":["https://www.zhihu.com/people/Aceyclee"],"tags":["应用开发","Serverless"],"keywords":"Serverless 应用开发,Serverless 管理,厨师转行为 Serverless 应用开发者","outdated":null},"wordCount":{"words":285,"sentences":38,"paragraphs":36},"fileAbsolutePath":"/opt/build/repo/content/blog/2018-01-09-from-chef-to-serverless-developer-in-4-years.md","fields":{"slug":"/blog/2018-01-09-from-chef-to-serverless-developer-in-4-years/","keywords":["无服务器","无服务器开发","云函数","学习","Serverless","构建","Framework","开发者","服务器","应用","学位","简历"]}}},{"node":{"id":"713a0563-4bf9-5721-bacb-3b4ef609fe4a","frontmatter":{"thumbnail":"https://s3-us-west-2.amazonaws.com/assets.blog.serverless.com/camp-fire/camp-fire-housing-thumb.jpg","authors":["EricWyne"],"categories":["guides-and-tutorials","user-stories"],"date":"2018-12-05T00:00:00.000Z","title":"Serverless Twitter 机器人帮助为坎普山火受灾者安置住房","description":"加利福尼亚州的坎普山火致使数千人流离失所，为此，我构建了一个简单的 Serverless Twitter 机器人来帮助将受灾者安置在临时住房！","authorslink":["https://serverless.com/author/ericwyne/"],"translators":["Aceyclee"],"translatorslink":["zhihu.com/people/Aceyclee"],"tags":null,"keywords":null,"outdated":null},"wordCount":{"words":157,"sentences":26,"paragraphs":26},"fileAbsolutePath":"/opt/build/repo/content/blog/2018-12-05-serverless-twitter-camp-fire.md","fields":{"slug":"/blog/2018-12-05-serverless-twitter-camp-fire/","keywords":["serverless","无服务器","云函数","Serverless","org","住房","Twitter","函数","受灾","机器人","山火"]}}},{"node":{"id":"98602143-b837-5f50-a24f-3b1ec76044d7","frontmatter":{"thumbnail":"https://s3-us-west-2.amazonaws.com/assets.blog.serverless.com/sqquid/sqquid-serverless-thumb.jpg","authors":["RonPeled"],"categories":["user-stories"],"date":"2018-12-17T00:00:00.000Z","title":"SQQUID：100% 无服务器初创公司","description":"SQQUID 将 AWS Lambda 和无服务器框架用于其核心产品和营销网站。我们来看看一个完全无服务器的初创公司是怎样的。","authorslink":null,"translators":null,"translatorslink":null,"tags":null,"keywords":null,"outdated":null},"wordCount":{"words":266,"sentences":42,"paragraphs":42},"fileAbsolutePath":"/opt/build/repo/content/blog/2018-12-17-sqquid-one-hundred-percent-serverless.md","fields":{"slug":"/blog/2018-12-17-sqquid-one-hundred-percent-serverless/","keywords":["go","serverless","无服务器","无服务器架构","服务器","架构","Lambda","集成","FaaS","串行","系统"]}}},{"node":{"id":"29dc2e58-d2ba-56f9-aee1-d21b0bc62e0e","frontmatter":{"thumbnail":"https://s3-us-west-2.amazonaws.com/assets.blog.serverless.com/ao-com-story/ao-serverless-thumbnail.png","authors":["NickGottlieb"],"categories":["user-stories"],"date":"2019-04-24T00:00:00.000Z","title":"AO.com：逐渐转向无服务器优先","description":"AO.com 的 SCV 团队率先尝试无服务器服务。折服于无服务器框架的快速周转时间和低维护成本，整个团队逐渐转向无服务器优先。","authorslink":null,"translators":null,"translatorslink":null,"tags":null,"keywords":null,"outdated":null},"wordCount":{"words":236,"sentences":42,"paragraphs":35},"fileAbsolutePath":"/opt/build/repo/content/blog/2019-04-24-ao-serverless-first.md","fields":{"slug":"/blog/2019-04-24-ao-serverless-first/","keywords":["serverless","无服务器","服务器","团队","Lambda","功能","构建"]}}},{"node":{"id":"752d08d1-387a-5bde-acf3-98141baab294","frontmatter":{"thumbnail":"https://img.serverlesscloud.cn/2020414/1586871710979-%E5%85%AC%E5%85%B1%E7%94%A8.png","authors":["Anycodes"],"categories":["user-stories"],"date":"2019-06-20T00:00:00.000Z","title":"如何用 Serverless 为 Python 云函数打包依赖","description":"在使用无服务器云函数SCF时通常会遇到导入第三方库的问题，很多小伙伴比较头疼是：应该如何打包进去？这里，推荐几个不错的方法。","authorslink":["https://zhuanlan.zhihu.com/ServerlessGo"],"translators":null,"translatorslink":null,"tags":["云函数","Serverless"],"keywords":"Serverless,Serverless应用,无服务器云函数","outdated":null},"wordCount":{"words":81,"sentences":43,"paragraphs":43},"fileAbsolutePath":"/opt/build/repo/content/blog/2019-06-20-for-python-cloud-functions.md","fields":{"slug":"/blog/2019-06-20-for-python-cloud-functions/","keywords":["java","serverless","无服务器","无服务器云函数","云函数","serverlesscloud","安装","serverless","pillowtest"]}}},{"node":{"id":"2dc78814-9d77-555b-a1bb-ad202c8ec2d1","frontmatter":{"thumbnail":"https://s3-us-west-2.amazonaws.com/assets.blog.serverless.com/cloudforecast/thumbnail.png","authors":["FrancoisLagier"],"categories":["user-stories"],"date":"2019-08-07T00:00:00.000Z","title":"Serverless：初创企业的理想选择？（CloudForecast 案例分析）","description":"CloudForecast 是 2018 年成立的一家独立初创企业，本文将介绍他们决定选择 Serverless 的原因。","authorslink":["https://serverless.com/author/francoislagier/"],"translators":["Aceyclee"],"translatorslink":["zhihu.com/people/Aceyclee"],"tags":null,"keywords":null,"outdated":null},"wordCount":{"words":211,"sentences":29,"paragraphs":29},"fileAbsolutePath":"/opt/build/repo/content/blog/2019-08-07-serverless-for-startups.md","fields":{"slug":"/blog/2019-08-07-serverless-for-startups/","keywords":["serverless","云函数","serverless","函数","Serverless","utm","Framework","blog","CloudForecast","cloudforecast"]}}},{"node":{"id":"97450b07-658b-5207-8216-1c7b9b51b115","frontmatter":{"thumbnail":"https://img.serverlesscloud.cn/2020114/1578988490344-v2-8b2cd2c5275aa2c5a3c5083a148a7a9f_1200x500.jpg","authors":["Anycodes"],"categories":["user-stories"],"date":"2019-09-01T00:00:00.000Z","title":"如何通过 Serverless 与自然语言处理，让搜索引擎「看」到你的博客","description":"Serverless 与自然语言处理结合的一个小应用","authorslink":["https://www.zhihu.com/people/liuyu-43-97"],"translators":null,"translatorslink":null,"tags":["个人博客","serverless"],"keywords":"Serverless 自然语言处理","outdated":null},"wordCount":{"words":106,"sentences":34,"paragraphs":34},"fileAbsolutePath":"/opt/build/repo/content/blog/2019-09-01-search-engine-blog.md","fields":{"slug":"/blog/2019-09-01-search-engine-blog/","keywords":["serverless","云函数","keywords","serverlesscloud","summary"]}}},{"node":{"id":"ae4fd2f8-515c-5aec-b584-38427ef33f7e","frontmatter":{"thumbnail":"https://img.serverlesscloud.cn/2020114/1578989800047-part-00492-780.jpg","authors":["Anycodes"],"categories":["guides-and-tutorials","user-stories"],"date":"2019-09-16T00:00:00.000Z","title":"突破传统 OJ 瓶颈，「判题姬」接入云函数","description":"通过 Serverless 实现在线编程","authorslink":["https://www.zhihu.com/people/liuyu-43-97"],"translators":null,"translatorslink":null,"tags":["在线编程","云函数"],"keywords":"Serverless 在线编程,Serverless OJ","outdated":null},"wordCount":{"words":169,"sentences":30,"paragraphs":30},"fileAbsolutePath":"/opt/build/repo/content/blog/2019-09-16-online-Judge.md","fields":{"slug":"/blog/2019-09-16-online-Judge/","keywords":["python","serverless","云函数","代码","函数","serverless"]}}}],"totalCount":64}},"pageContext":{"isCreatedByStatefulCreatePages":false,"blogId":"e0959654-d44e-59c0-8201-19822e61b38d","previousBlogId":"5e61ae27-a6be-5a1e-a7bd-06ddaaab5c3d","nextBlogId":"bdf645bd-3599-55a2-9a1b-bcf94ce9be6b","categories":["user-stories"]}}}