一般动作
登录
Wiki: BROPEN ▼: Document Index
»
Space: FAQ ▼: Document Index
»
Page: 如何开发短信接口
搜索
zh
页面动作
导出 ▼: 以PDF格式导出 以RTF格式导出 以HTML格式导出
更多动作 ▼: 打印预览 察看源码
欢迎进入Wiki » FAQ » 如何开发短信接口?

# 如何开发短信接口?

在2015-08-08 15:24上被李小翔修改
评论 (0) · 附件 (2) · 记录 · 信息

供稿人：刘少林

现在的越来越多的项目都有发送短信的需求，FWK 中内置有短信发送的功能模块，开发中需要根据短信提供商的接口或短信网关接口，实现相应的短信服务即可。

首先，在应用中新建一个新的 ShortMessageService 服务类，并继承 bropen.framework.plugins.message.ShortMessageService，模板如下：

import bropen.framework.plugins.message.ShortMessage
import bropen.framework.plugins.message.MessageStatus
/**
* XXX 短信服务
*/
class ShortMessageService extends bropen.framework.plugins.message.ShortMessageService {
static aliasOverridingOrder = bropen.framework.plugins.message.ShortMessageService.aliasOverridingOrder + 1
static bootStrapInit() {
// 一些初始化配置可以放到这里
}
@java.lang.Override
protected MessageStatus send(ShortMessage sms) {
// 调用短信接口，发送短信，并且返回状态
...
return MessageStatus.SENT
}
@java.lang.Override
protected ShortMessage bind(Map msg) {
// 将一个 Map 转换为 ShortMessage 对象
}
}

上面的模板中，bootStrapInit 方法用于初始化一些系统参数，如系统参数：

- bropen.framework.plugins.message.sms.enabled：是否启用短信，默认为否
- bropen.framework.plugins.message.sms.http.url：第三方短信服务的地址
- bropen.framework.plugins.message.sms.attempt.max：短信发送失败的最大重试次数，默认为 5
- bropen.framework.plugins.message.sms.attempt.interval：短信发送失败的重试间隔，默认为 5 分钟

此外，还可以根据第三方短信服务的接口，自定义其他系统参数，如下例所示：

static bootStrapInit() {
if ( !settingService.exists("bropen.framework.plugins.message.sms.http.sn") ) {
// 短信服务地址
settingService.createOrUpdate("bropen.framework.plugins.message.sms.http.url",
"http://www.jianzhou.sh.cn/JianzhouSMSWSServer/services/BusinessService", "string").save()
// 短信服务帐号
settingService.createOrUpdate("bropen.framework.plugins.message.sms.http.sn",
"sdk_foobar", "string").save()
// 短信服务密码
settingService.createOrUpdate("bropen.framework.plugins.message.sms.http.pwd",
"1234567890", "passwd").save()
// 短信服务开关
settingService.createOrUpdate("bropen.framework.plugins.message.sms.enabled",
"false", "boolean").save()
// 短信服务帐号
settingService.createOrUpdate("bropen.framework.plugins.message.sms.http.sig",
"【Foobar】", "string").save()
}
}

接口方法 send 是最重要的部分，该方法中，需要调用实际的第三方接口，将短信发送出去，如下例所示：

/**
* 接口方法：通过短信网关发送短信，并返回状态。如果短信发送被禁用，则应直接返回 null。
*/
@java.lang.Override
protected MessageStatus send(ShortMessage sms) {
if ( !isEnabled() ) return null // 如果没有启用短信服务，则直接返回null
String url = settingService.get("bropen.framework.plugins.message.sms.http.url") // 服务地址
String account = settingService.get("bropen.framework.plugins.message.sms.http.sn") // 企业账户
String pwd = settingService.get("bropen.framework.plugins.message.sms.http.pwd") // 密码
String sig = settingService.get("bropen.framework.plugins.message.sms.http.sig") ?: "" // 短信后缀
// 收件人
List<String> phones = []
for ( String to in sms.to ) {
if ( to.indexOf("<") )
phones += to.replaceAll("^[^<]*<", "").replaceAll(">.*\$", "")
}
// 拼消息实体：接收人、短信内容
String phone = phones.join(";")
String message = sms.text + (sms.signature ? ("\n"+ sms.signature) : "")
message += sig
// 发送 (开发和测试环境不发短信)
String resp = null
if ( grails.util.Environment.current == grails.util.Environment.PRODUCTION ) {
Client c = new Client(url,account, pwd)
resp = c.sendBatchMessage(phone, message)
log.debug("sms.id=" + sms.id + ", resp=" + resp)
resp = resp.replaceAll(/,.+/, "")
} else {
resp = '999999999'
log.debug("sms.id=" + sms.id + ", resp=" + resp + ", phone=" + phone + ", message=" + message)
}
// 检查返回值（服务反馈的状态码），并设置 sms 对象的 statusCode、statusMessage，以便审计和查找发送失败原因
sms.statusCode = resp
switch ( sms.statusCode ) {
case "-1" : sms.statusMessage="余额不足"; break
case "-2" : sms.statusMessage="帐号或密码错误"; break
...
case "-19" : sms.statusMessage="必须为POST提交"; break
case "-20" : sms.statusMessage="超速提交(一般为每秒一次提交)"; break
default: sms.statusMessage = sms.statusCode
}
// 返回状态
return sms.statusCode.toLong() > 0 ? MessageStatus.SENT : MessageStatus.ERROR
}
/**
* 从第三方接口的 demo 代码中拷贝出来的短信客户端
*/
public static class Client {
....
}

上面的例子中，注意：

- 第一行判断是否启用了短信，否则直接返回 null
- 调用短信客户端类发送完成后，可以设置 sms 对象的 statusCode、statusMessage 属性，以便审计和查找发送失败原因

此外，上面的例子中有一个内部类 Client，一般可以从短信服务商提供的 java 例子中找到，简单修改即可，如：

public static class Client {
// webservice服务器定义
private String serviceURL = null; // 入口地址：http://www.jianzhou.sh.cn/JianzhouSMSWSServer/http/sendBatchMessage
private String account = null; // 账户
private String pwd = null; // 密码
/*
* 构造函数
*/
public Client(String url, String account, String pwd) throws UnsupportedEncodingException {
this.serviceURL = url;
this.account = account;
this.pwd = pwd;
}
/*
* 方法名称：sendBatchMessage
* 功 能：发送个性短信
* 参 数：mobile,content(手机号，内容)
* 返 回 值：唯一标识，如果不填写rrid将返回系统生成的
*/
public String sendBatchMessage(String mobile, String content) {
....
}
}

接口方法 bind 用来将 Map 对象转换成一个 ShortMessage 对象，默认情况下，Map 中包含下列数据（其中 from、to、text 不能为空）：

- from：发送人名称/员工或用户对象
- to：逗号或分号分隔的手机号、或手机号列表、员工列表
- text：消息正文
- signature：签名
- sentDateSche：计划发送时间，空则立即发送

如有其他需求，可以覆盖 bind 方法实现自己的转换逻辑。

最后，接口开发完成后，可以调用 ShortMessageService 的 sendMessage 方法发送短信，如：

ctx.shortMessageService.flush = true // 如果在 console 中执行，必须加上这句；否则不需要
// 发送一条新的短信
ctx.shortMessageService.sendMessage( [from:"abc", to:"13312345678", text:"test text"] )
// 重试一条老的短信
def sms = bropen.framework.plugins.message.ShortMessage.get(xxxx)
ctx.shortMessageService.sendMessage( sms )

如上例所示，sendMessage 方法有两个版本，一个版本的参数是 Map、一个版本的参数是 ShortMessage 对象，通常情况下我们使用 Map 来传递参数（新建一条短信并发送），而 Map 中的数据规范参见上文中 bind 方法的默认情况。

此外，启用短信配置、并实现短信接口后，用管理员登录到后台，可以查看短信发送情况，并进行重发、或直接发送短信。

标签： BroFramework
在2015-08-08 15:22上被李小翔创建

- 评论 （0）
- 附件 （2）
- 记录
- 信息

# 快速链接

- 首页
- 新闻动态
- FAQ

Copyright © 2013 北京博瑞开源软件有限公司
京ICP备12048974号