乐趣区

关于golang:一看便会微信后台服务器开发

微信后盾服务器开发

就要上班了,兵长关上手机,看到弹出的某微信聊天机器人广告便点了进去,于是有了如下故事 …

最近兵长在看微信的时候突发奇想的去玩了一下某微信机器人,可能像智能语音助手一下和本人聊天

兵长就在想,这机器人是咋做的,咱们是做服务器开发的,咱用 go 语言疾速实现一下给本人玩玩,实现一个定制化的聊天机器人可好

胖 sir 听到兵长喃喃自语的不明所以,便走上前说,咋开始玩起聊天了,不来峡谷游了吗?

上次带你原本是想带你成为 winer 的,没想到,每一把都是 loser,我打算最近收收手,管制一下情绪,找机器人安慰一下我手上的心灵

你是说微信聊天机器人吗?哪些不都是千篇一律的嘛

那么你能弄个定制化的嘛?把我情绪弄好了,我带你来大乱斗吧

~~(偷笑),小伙子,还好我留了一手,我先给你说说微信后盾服务器如何初步开发一个简略的你问我答性能吧,授人以渔,不如授人以鱼 是不

开发一个微信后盾服务器作为 被动回复机器人,大抵分为如下几步:

  • 开明公众号,注册微信公众号开发平台,这里能够是注册 订阅号,具体的前面给你说
  • 配置权限,配置微信后盾开发者权限
  • 流程介绍
  • 接入微信后盾
  • 性能实现
  • 兵长乱斗带胖 sir 飞

开明公众号

注册微信公众号开发平台,这里能够是注册 订阅号,依照提醒进行注册输出信息即可,置信你一看就会

注册地址:https://mp.weixin.qq.com/cgi-bin/registermidpage?action=index&lang=zh_CN&token=

我整顿了一个表格来介绍一下订阅号和服务器号的区别,你也能够先初步理解一下区别,前面能够缓缓推敲

订阅号 服务号
用处 次要目标 为大家流传征询;相似报纸,杂志,集体输入 偏差企业或组织的交互,如银行,商场,餐厅等;自助服务的服务号,用于企业
群发次数 一天能够发送一次;所有的订阅号推送音讯,会被对立收纳到订阅号栏目中 一个月发送 4 条群发音讯
展现地位 全副收录在 订阅号的 信息栏中 展现在好友音讯列表之中;关注一个服务号,即相当与加了一个敌人
微信领取 不可开明领取性能 认证后 能够开明微信领取性能
自定义菜单 绝对简略 绝对高级,微信有接口,能够自行开发

配置权限

配置微信后盾开发者权限

  • 进入公众号治理页面,下拉右边侧,进入根本配置

  1. URL:填写本人的外网服务器URL,如果没有能够买一个云服务器,当初买云服务器还是很便宜的
  2. Token:自定义Token,用于制作签名,这个十分重要,须要窃密
  3. EncodingAESKey:随机生成即可
  4. 音讯加解密形式:为了演示不便,咱们这里应用明文模式
  • 微信公众号后盾接口权限

普通用户只有是接管音讯和主动回复音讯的权限

流程介绍

开发被动回复音讯流程介绍,简略来说,能够是这样的

性能实现必备知识点

  • http 服务 进行通信
  • Token 机制
  • 微信后盾开发 xml 的数据序列化

http 服务

做上述被动回复音讯的性能,此处仅须要后盾服务器实现 get 办法和 post 办法即可

  • get 办法

    次要是用于,咱们在微信后盾设置 token 的时候,微信后盾会向咱们的服务器发送 get 申请,判断咱们服务是否有正确的数据

  • post 办法

    次要是用于,粉丝在咱们的微信后盾发送音讯的时候,是以 post 的形式发送给咱们的后盾服务器的

Token 机制

参数 形容
signature 微信加密签名,signature 联合了开发者填写的 token 参数和申请中的 timestamp 参数、nonce 参数。
timestamp 工夫戳
nonce 随机数
echostr 随机字符串

开发者通过测验 signature 对申请进行校验(上面有校验形式)。若确认此次 GET 申请来自微信服务器,请原样返回 echostr 参数内容,则接入失效,成为开发者胜利,否则接入失败。加密 / 校验流程如下:

1)将 token、timestamp、nonce 三个参数进行 字典序 排序

2)将三个参数字符串拼接成一个字符串进行 sha1 加密

3)开发者取得加密后的字符串可与 signature 比照,标识该申请来源于微信

token 算法流程图

验证办法(get)

  • 1. 服务器端获取 token、nonce、timestamp 组成列表
  • 2. 列表排成字典序
  • 3. 排序后的元素进行摘要
  • 4. 摘要比对 signature
  • 5. 响应echostr

参考微信后盾开发文档连贯:https://developers.weixin.qq.com/doc/offiaccount/Getting_Started/Getting_Started_Guide.html

xml 数据解析

兵长,不晓得你有没有用过 xml 来做数据的序列化,此处你必定会问,为什么用 xml,而不必 json,不必 protobuf

来我给你简略介绍一下 xml:

XML 是可扩大标记语言,其中标记指的是计算机中所能了解的信息符号,通过标记计算机之间能够解决蕴含各种信息的资源,咱们能够通过通用的标记语言来进行标记

用人话来说就是,xml 是数据序列化的其中一种形式,微信定下来应用该形式来对数据进行序列化,咱们须要对此进行开发,因而也须要遵循微信的规定

例如 微信后盾的 text 音讯类型 申请 xml 格局如下

文本音讯,微信公众平台申请微信后盾服务器会带的字段有:FromUserNameToUserNameCreateTime,MsgTypeContentMsgId

咱们开发的微信后盾服务器,须要依照如下数据格式做回复:xml 带上如下字段ToUserNameFromUserNameCreateTime,MsgTypeContent

兵长,再给你回顾一下,实现微信后盾服务器被动回复音讯的服务,须要用到上述说到的 3 点,http 服务、token 机制、xml 解析,记住咯,我要开始撸代码了

具体实现

main.go

  • 启动 http 服务器,开始监听 80 端口
package main

import (
   "fmt"
   "github.com/wonderivan/logger"
   "net/http"
   "time"
)

const (
   port     = 80 // 后盾服务器端口号 80,本人的公网服务器 须要设置防火墙,关上 80 端口
   token    = "XXXXXXX"
)

// 须要本人批改 token,以适应本人公众号的 token
func main() {logger.SetLogger("./log.json")
   logger.Info("------------ start  main ------------")

   server := http.Server{Addr:           fmt.Sprintf(":%d", port), // 设置监听地址,ip:port
      Handler:        &httpHandler{},           // 具体应用哪个 handler 来解决
      ReadTimeout:    5 * time.Second,          // 读写超时 微信给进去 5 秒
      WriteTimeout:   5 * time.Second,
      MaxHeaderBytes: 0,
   }

   logger.Info(fmt.Sprintf("Listen: %d", port))
   logger.Fatal(server.ListenAndServe())
}

route.go

  • 路由性能,具体实现 get 和 post 办法
  • 定义 Handler 以及 ServeHTTP 接口的实现
package main

import (
   "fmt"
   "github.com/wonderivan/logger"
   "io"
   "net/http"
   "regexp"
   "time"
   "wechat/wx"
)

type WebController struct {Function func(http.ResponseWriter, *http.Request)
   Method   string
   Pattern  string
}

var mux []WebController // 本人定义的路由
// ^ 匹配输出字符串的开始地位
func init() {mux = append(mux, WebController{post, "POST", "^/"})
   mux = append(mux, WebController{get, "GET", "^/"})
}

type httpHandler struct{} 

//httpHandler 本人实现了 ServeHTTP 接口,能够通过源码看到,创立 httpHandler 对象的时候,理论源码逻辑是会调用 ServeHTTP 进行解决
func (*httpHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {t := time.Now()
   for _, webController := range mux { // 遍历路由
      // 匹配申请的   r.URL.Path  -> webController.Pattern
      if m, _ := regexp.MatchString(webController.Pattern, r.URL.Path); m { // 匹配 URL
         logger.Info("webController.Pattern  ==", webController.Pattern)
         logger.Info("r.URL.Path  ==", r.URL.Path)
         if r.Method == webController.Method { // 匹配办法
            logger.Info("webController.Method  ==", webController.Method)

            webController.Function(w, r) // 调用对应的处理函数

            d := time.Now().Sub(t)

            l := fmt.Sprintf("[ACCESS] | % -10s | % -40s | % -16s", r.Method, r.URL.Path, d.String())

            logger.Info(l)

            return
         }
      }
   }

   d := time.Now().Sub(t)

   l := fmt.Sprintf("[ACCESS] | % -10s | % -40s | % -16s", r.Method, r.URL.Path, d.String())

   logger.Info(l)

   io.WriteString(w, "")
   return
}

// 解决 token 的认证
func get(w http.ResponseWriter, r *http.Request) {client, err := wx.NewClient(r, w, token)

   if err != nil {logger.Info(err)
      w.WriteHeader(403) // 校验失败
      return
   }

   if len(client.Query.Echostr) > 0 {logger.Info("Echostr ==", client.Query.Echostr)
      w.Write([]byte(client.Query.Echostr)) // 校验胜利返回的是 Echostr
      return
   }

   w.WriteHeader(403)
   return
}

// 微信平台过去音讯,解决,而后返回微信平台
func post(w http.ResponseWriter, r *http.Request) {client, err := wx.NewClient(r, w, token)

   if err != nil {logger.Info(err)
      w.WriteHeader(403)
      return
   }
   // 到这一步签名曾经验证通过了
   client.Run()
   return
}

具体代码实现还有 1 个定义构造文件和外围实现文件:

  • structs.go

    xml 序列化音讯对应的构造体的定义,蕴含根本音讯字段,FromUserNameToUserNameMsgTypeCreateTime, 以及文本音讯,图片音讯,录音音讯,音乐音讯,地理位置音讯,视频音讯等须要哪一些字段,都能够参考微信后盾给出的规定

  • wx.go

    token + 随机数 + 工夫戳 排成字典序,并应用 sha1 加密后生成 signature

    NewClient 的具体实现

    文本音讯,图片音讯等的音讯解决以及被动回复性能

上述 2 个外围文件若是感兴趣,本人有想法并且冀望本人实现的小伙伴,能够增加我的微信,能够给大家共享一下

当然,微信后盾开发波及的性能还很多,明天给大家分享到的还只是冰山一角,沿途的风光还是须要大家一步一个脚印去感触,能够在微信的开发文档中纵情实战,如下图,感兴趣的能够多多交换。

技术是凋谢的,咱们共享技术,心态也应是凋谢的,咱们拥抱变动,你违心一直摸索后退,你必将播种你冀望的货色。

以上是本期全部内容,保持原创,实际本人的想法,咱们下期见

作者:小魔童哪吒

退出移动版