Scala实战-通过微信聊天窗口实现应答式点餐 1:连接微信API

当前代码tag: v0.0.1,https://github.com/yangbajing/wechat-meal/tree/v0.0.1

微信公众号提供了详尽的API文档说明,提供了明文和加密两种接入方式。这里,我们选择加密的接入方式微信公众号接入指南

本此实战的代码部署到了Heroku,读者也可以下载代码尝试部署到Heroku并连接微信公众号。本章末尾讲讲述Heroku的部署及怎样与微信公众号连接。

微信API

现在主要的功能是实现与微信公众号的连接,我们将在微信里实现一个echo功能。就是用户在公众号聊天窗口里输入一段文本,系统原样返回。

连接微信API的代码WeixinCtrl。微信公众号的连接分两个部分:

  1. 验证服务器地址有效性
    这个接口为WeixinCtrl.get方法,用户校验服务器的有效性

  2. 依据接口文档实现业务逻辑
    这个接口为WeixinCtrl.post方法,通过微信公众号聊天窗口发送的各类消息都会发送的这里。

代码WeixinService是所以微信API相关功能实现的入口,现在提供了签名校验、加密消息和解密消息功能。

WeixinCtrl控制器中,我们将收到的微信公众号消息原样返回给用户:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
def post = Action.async(parse.tolerantText) { request =>
def getBody = ......

def responseContent(body: String) = {
val node = scala.xml.XML.loadString(body)
OrdinaryMessage.msgType(node) match {
case MessageTypes.Event => // event
......
case _ => // message
getContent(node)
}
}

for {
body <- getBody
resp <- responseContent(body)
} yield {
Ok(resp).withHeaders("Content-Type" -> "application/xml; charset=UTF-8")
}
}

private def getContent(node: Elem, reply: String = ""): Future[String] = {
val msg = OrdinaryMessage(node)
val newTs = Utils.currentTimeSeconds()
val replyContent =
if (StringUtils.isEmpty(reply)) {
msg.contentOption getOrElse "欢迎关注羊八井花园"
} else {
reply
}
val respStr = OrdinaryTextResponse(msg.fromUserName, msg.toUserName, newTs, replyContent).stringify()
weixinService.encryptMsg(respStr, newTs, Utils.randomString(8))
}

Play 2的依赖注入

Play 2.4开始,官方推荐使用依赖注入的方式定义路由和服务了,Play使用了一个Java标准注入方式的实现:Guice

1
2
3
4
5
6
7
8
9
10
11
12
13
@Singleton
class WeixinCtrl @Inject()(weixinService: WeixinService) extends Controller with BaseController {
def get(signature: String, echostr: String, timestamp: String, nonce: String) = Action.async { request =>
logger.debug(request.rawQueryString)

weixinService.validateSign(timestamp, nonce).map {
case `signature` => Ok(echostr)
case s =>
logger.error(s"$s not match $signature")
BadRequest
}
}
......

@singleton注解表示这个控制器将做为单例存在于整个应用生命周期,默认情况是每次调用时都会重新生成一个。

Play中,注入依赖的方式和Java很不一样,它是在scala类定义的主构造器中注入的,而Java代码中我们一般是在类的私用属性变量上进行注入。@Inject()是一个特殊的语法,用于修饰构造函数,之后的参数实例将由注解框架自动注入。在这里,weixinService这个服务就由系统框架注入了,我们不需要手动管理它的生命周期。

部署代码到Heroku

Heroku官网https://www.heroku.com注册开发者账号。

  • 登陆Heroku的Dashboard,点击屏幕右上方的+号按钮添加新应用。
  • 安装Heroku Toolbelt,支持MacLinuxWindows系统。
  • 有3种部署代码到Heroku的方式:
    • 通过ToolbeltGit方式提交
    • 连接到你的Github代码库
    • 通过Dropbox提交。

这里选择了通过Toolbelt手动提交到Heroku的GIT代码库的方式。

  1. 添加新的或已存的项目到GIT版本库
1
2
3
$ cd wechat-meal/
$ git init
$ heroku git:remote -a wechat-meal
  1. 部署应用
1
2
3
$ git add .
$ git commit -am "make it better"
$ git push heroku master

连接微信公众号

程序使用“加密连接”的方式,示例代码已经整合了微信提供的Java版加密、解密功能。

配置微信接口参数

URL(服务器地址)配置好连接微信API的服务地址,这里注意需要使用http协议(必需为80端口)。设置好Token(令牌)EncodingAESKey(消息加解密密钥),并选择“安全模式”。

当全部配置都设置好后就可以点击“提交”按钮了。若微信API校验成功,这时你从公众号的聊天窗口输入一段文本,公众号应该会回显你的输入内容。

目录

  1. Scala实战-通过微信聊天窗口实现应答式点餐 0
  2. Scala实战-通过微信聊天窗口实现应答式点餐 1:连接微信API
分享到