# POST消息发送接口说明
通过消息发送接口,可以接入消息平台的消息发送能力,目前支持消息的发送方式有6种:手机短信(SMS),电子邮件(MAIL),微信(WECHAT),钉钉(DINGTALK),系统消息(WEBSITE),超级app(公司手机端产品)(SUPERAPP)
# api 调用权限说明
要调用此API,需要申请开放平台的能力,并且获取token;获取token后在接口请求时,header中添加 Authorization 值为token
# 请求方法
请求方式-POST
报文样例
POST /apis/messagecenter/v1/poaMessage/messageSend
Host: poa地址(例如:https://poa.dev2.supwisdom.com)
Authorization:String
Content-Type:application/json
{
"appId": "string",
"sendId": "string",
"sendTime": "string",
"messageTypeCode": "string",
"toPersons": "string",
"toDepts": "string",
"toGroups": "string",
"toEmails": "string",
"toPhones": "string",
"excludeUser": "string",
"signOff": "string",
"sendType": [
"string"
],
"promise": true,
"importantIdentity": true,
"data": {
"title": "string",
"handleKey": "string",
"coverImageUrl": "string",
"filesUrl": "string",
"mobileUrl": "string",
"url": "string",
"paramValueJson": {
"property1": {},
"property2": {}
}
}
}
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
34
35
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
34
35
# Header参数
名称 | 类型 | 是否必填 | 描述 |
---|---|---|---|
Authorization | String | 是 | 调用该接口的访问凭证 |
# Body参数
参数 | 描述 | 类型 | 必填 | 默认值 |
---|---|---|---|---|
appId | 应用ID | string | 是 | - |
sendId | 消息任务序列识别号,唯一【值为空时,消息服务生成唯一sendId,并返回】 | string | 否 | - |
sendTime | 定时发送时间【yyyy-MM-dd HH:mm:ss】,不填时及时发送 | string | 否 | - |
sendType | 根据消息类型配置发送方式:【SMS(手机短信)、MAIL(邮件)、WECHAT(微信)、DINGTALK(钉钉)、SUPERAPP(APP)、WEBSITE(系统消息) 】【不填写,则默认按照平台这边控制的发送渠道来发送】 | string[] | 否 | - |
messageTypeCode | 消息类型编码【消息类型编码由应用申请消息类型产生,消息类型定义模板】 | string | 是 | - |
promise | 消息送达承诺【如果true,校验比较严格】 | boolean | 否 | false |
importantIdentity | 重要消息的标识 | boolean | 否 | false |
toPersons | 接收人账号,多个用英文逗号分隔【5种接收方式,至少有一不为空】 | string | 否 | - |
toDepts | 接收部门id,多个用英文逗号分隔【5种接收方式,至少有一不为空】 | string | 否 | - |
toGroups | 接收用户组id,多个用英文逗号分隔【5种接收方式,至少有一不为空】 | string | 否 | - |
toPhones | 接收手机号,多个用英文逗号分隔【只能发送短信】 | string | 否 | - |
toEmails | 接收邮箱,多个用英文逗号分隔【只能发送邮件】 | string | 否 | - |
signOff | 落款 | string | 否 | - |
data.title | 消息标题 | string | 是 | - |
data.coverImageUrl | 封面图url | string | 否 | - |
data.filesUrl | 消息附件url,多个用英文逗号分隔【此处调用消息中台服务文件上传功能】 | string | 否 | - |
data.mobileUrl | 移动端跳转链接 | string | 否 | - |
data.url | pc端跳转链接 | string | 否 | - |
data.handleKey | 处理字段;包含APP跳转预设的KEY或者是接收方要处理的URL地址等【如果为空,默认设置该消息任务的账号唯一key】 | string | 否 | - |
data.paramValueJson | 消息类型模板设置的变量,如果没有配置模板参数,就传递json空对象 | JSONObject | 是 | - |
注意:
- appId在消息中台应用管理申请完成后获得;
- sendType 字段,如果没有特殊要求可以传空,这样可以由平台这边控制具体的发送渠道
- WEBSITE发送方式,在平台的PC网页端和APP端内,同步显示消息,后续消息已读状态也会在两端保持一致
- SUPERAPP发送方式,表示手机的通知栏消息,并非APP站内消息
# 接口调用成功返回
接口返回code值0为成功返回
data.sendId 返回消息任务发送的序列号;根据sendId 可以查询发送任务的情况;
{
"timestamp": 1693813788317,
"code": 0,
"message": "已发送",
"data": {
"sendId": "9e244a204af711ee56c3af7e72cbc051",
"errorList": null
}
}
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
# 接口调用失败返回
data.errorList 返回有异常的发送情况数组: receiverKey 接收对象【可以是账号、手机号、邮箱地址】 exceptionMessage 该接收对象具体的异常问题
{
"timestamp": 1693820106246,
"code": 500,
"message": "发送方式 [SUPERAPP1, WEBSITE1] ,未在应用的消息类型中定义;请重新指定消息发送方式!",
"data": null
}
1
2
3
4
5
6
2
3
4
5
6
# postman 发送方式demo
{
"appId": "a0f758601c7511ee57aac4d032aa123b",
"sendId": "",
"sendType": [
"SUPERAPP",
"WEBSITE"
],
"messageTypeCode": "MT1692869455123",
"promise": false,
"importantIdentity": false,
"toPersons": "学工号",
"toDepts": "",
"toGroups": "",
"toPhones": "",
"toEmails": "",
"data": {
"handleKey": "",
"coverImageUrl": "",
"signOff": "",
"mobileUrl": "",
"title": "要发送的消息title",
"paramValueJson": {},
"filesUrl": "",
"url": ""
}
}
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
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
# 消息发送时模板设定说明
# 模板示例
假如有一个应用有消息发送的需求,消息的文字模板如下:
您好,{{name}}转阅了{{ffname}}流程事项给您。
1
其中定义了两个模板变量 | name-用户名称; ffname-应用名称
那么就需要在发送消息时,提供上面两个模板变量的值,下面用postman演示变量的传递过程。
需要在提供的json类型的参数中 data.paramValueJson值中提供 模板变量的值 "name":"张三"
, "ffname":"留学生出国申请"
截图如下:
# 单模板&多模板发送
# 单模板
模板如下:
验证码{{code}},您正在进行身份验证,打死不要告诉别人哦!
1
入参demo:
{
"data": {
"paramValueJson": {
"code": "000212"
},
"title": "验证码"
},
"messageTypeCode": "MTxxx",
"appId": "xxxxx",
"sendType": [
"SMS","MAIL","WEBSITE","SUPERAPP"
],
"toPersons": "smartadmin",
"toPhones": "153****2458"
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 多模板
SMS模板为
验证码{{code}},您正在进行身份验证,打死不要告诉别人哦!
1
WEBSITE模板为
您正在进行身份验证,验证码为{{code}},有效时间为{{num}}分钟
1
入参demo:
{
"data": {
"paramValueJson": {
"SMS":"{code": "000212"},
"WEBSITE":"{code": "000212","num":"30"}
},
"title": "验证码"
},
"messageTypeCode": "MTxxx",
"appId": "xxxx",
"sendType": [
"SMS","WEBSITE"
],
"toPersons": "smartadmin",
"toPhones": "153****2458"
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
demo
点击查看JAVA DEMO
package util;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import org.apache.commons.httpclient.NameValuePair;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.http.HttpResponse;
import org.springframework.stereotype.Service;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import net.jodah.expiringmap.ExpirationPolicy;
import net.jodah.expiringmap.ExpiringMap;
@Service
public class MessageUtil {
private static final String oauth2_tokenurl ="https://poa.xxxxx.com/oauth2/token";
private static final String MESSAGE_SEND = "https://poa.xxxx.com/apis/messagecenter/v1/poaMessage/messageSend";
private static final String APPID ="a132c4c0c52a11ec5fa415e4485f32e0";
private static final String MESSAGETYPECODE ="MT1650954853000";
private static final String client_id ="xcfvGIgSgAu5yo85-xNYAXJi72k=";
private static final String client_secret ="laRffpmQ9Dp6wr6_pYVq5gV9zSB5OdXl-wmR7Sv0kt8=";
private static final String scope ="ttc:v1:writeTransaction,ttc:v1:writeTtc,messagecenter:v1:sendMessage";
private static final ExpiringMap<String, String> expireToken = ExpiringMap.builder()
.maxSize(110)
.variableExpiration().expirationPolicy(ExpirationPolicy.CREATED).build();
private String getContactsAccessToken() {
String contactsAccessToken = "";
if(expireToken!=null && expireToken.get("access_token")!=null) {
contactsAccessToken = expireToken.get("access_token").toString();
}else {
//获取到poa token
JSONObject resultJsonObject = getAccessTokenObject();
contactsAccessToken = resultJsonObject.getString("access_token");
int expires_in = resultJsonObject.getInteger("expires_in")-100;
expireToken.put("access_token", contactsAccessToken,expires_in, TimeUnit.SECONDS);
}
System.out.println("token:"+contactsAccessToken);
return contactsAccessToken;
}
public static void main(String[] args) {
MessageUtil MessageUtil=new MessageUtil();
MessageUtil.sendMessage();
}
/**
* 发送短信
*
* @param code
* @return
*/
public boolean sendMessage()
{
Map<String, Object> headers = new HashMap<String, Object>();
JSONObject parameters = new JSONObject();
parameters.put("appId", APPID); //消息服务对接的应用ID (应用ID(必填))
parameters.put("messageTypeCode", MESSAGETYPECODE); //消息服务对接的应用内的消息类型编码, (消息类型编码((必填))【消息类型编码由应用申请消息类型产生,消息类型定义模板】)
parameters.put("sendId", ""); // string (消息任务发送序列号,唯一【为空,消息服务生成唯一sendId,并返回】)
parameters.put("toPhones", "13083008175"); // string (接收手机号,多个英文逗号分隔)
//parameters.put("sendTime", "xxxx"); //string (定时发送时间【yyyy-MM-dd HH:mm:ss】)
//parameters.put("toPersons", "xxxx"); //string (接收人账号,多个英文逗号分隔)
//parameters.put("toDepts", "xxxx"); //string (接收部门id,多个英文逗号分隔)
//parameters.put("toGroups", "xxxx"); // string (接收用户组id,多个英文逗号分隔)
//parameters.put("toEmails", "xxxx"); //string (接收邮箱,多个英文逗号分隔)
//parameters.put("excludeUser", "xxxx"); // string (排除接收人学工号,多个用英文逗号分割)
//parameters.put("signOff", "hzysign"); // string (落款)
JSONArray sendType = new JSONArray(); // Array of strings (发送方式) 如果发送方式不传,则以后台配置的消息类型默认发送方式来发送
sendType.add("SMS");
parameters.put("sendType", sendType);
parameters.put("promise", true); // (消息送达承诺【如果是,校验比较严格】)
parameters.put("importantIdentity", true); //boolean (是否重要消息标识)
JSONObject data = new JSONObject();
data.put("title", "测试hzy"); //string (消息标题(必填))
//data.put("handleKey", "xxx"); //string (处理字段;APP跳转预设的KEY或者是接收方要处理的地址等【如果为空,默认设置该消息任务的账号唯一key】)
//data.put("coverImageUrl", "xxx"); // string (封面图URL)
//data.put("filesUrl", "xxx"); //string (附件url,多附件英文逗号分隔【后续提供文件服务,暂不支持】)
//data.put("mobileUrl", "xxx"); //string (移动端跳转链接)
//data.put("url", "xxx"); //string (pc端跳转链接)
JSONObject paramValueJson = new JSONObject(); // object (消息类型模板定义的变量&值)
paramValueJson.put("name", "hzy");
paramValueJson.put("tname", "thzy");
data.put("paramValueJson", paramValueJson);
parameters.put("data", data);
String entity = parameters.toJSONString();
JSONObject resultJsonObject = null;
String contactsAccessToken = getContactsAccessToken();
headers.put("Authorization", contactsAccessToken);
HttpResponse httpResponse = null;
try {
httpResponse = HttpUtil.execute(MESSAGE_SEND, "POST", null, null, parameters, headers, entity);
resultJsonObject = parseJSONObject(httpResponse);
if (resultJsonObject != null) {
if (resultJsonObject.getIntValue("code")==0) {
String rsdata = resultJsonObject.getString("data");
System.out.println("-----创建成功返回taskIds:-------"+data);
return true;
} else if( resultJsonObject.getIntValue("code")==-1) {
System.out.print("-----error-------"+resultJsonObject.getString("message"));
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
HttpUtil.close(httpResponse);
}
return false;
}
private static JSONObject getAccessTokenObject() {
String tokenUrl = oauth2_tokenurl;
String grantType = "client_credentials";
NameValuePair[] data = {
new NameValuePair("grant_type", grantType),
new NameValuePair("client_id", client_id),
new NameValuePair("client_secret", client_secret),
new NameValuePair("scope", scope)
};
String httpResponse = null;
JSONObject resultJsonObject = null;
try {
httpResponse = postx(tokenUrl, data);
//。。超时等重发略写
resultJsonObject = JSONObject.parseObject(httpResponse);
} catch (Exception e) {
e.printStackTrace();
//todo you need
}
return resultJsonObject;
}
private static JSONObject parseJSONObject(HttpResponse httpResponse) {
try {
if (httpResponse != null) {
StringBuilder entityStringBuilder = new StringBuilder();
BufferedReader b = new BufferedReader(new InputStreamReader(httpResponse.getEntity().getContent(), "UTF-8"), 8*1024);
String line=null;
while ((line=b.readLine())!=null) {
entityStringBuilder.append(line);
}
JSONObject resultJsonObject = JSONObject.parseObject(entityStringBuilder.toString());
return resultJsonObject;
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (UnsupportedOperationException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
// 发送x-www-form-urlencoded格式数据
public static String postx(String url ,NameValuePair[] data) {
try {
PostMethod postMethod = null;
postMethod = new PostMethod(url) ;
postMethod.setRequestHeader("Content-Type", "application/x-www-form-urlencoded;charset=utf-8") ;
//参数设置,需要注意的就是里边不能传NULL,要传空字符串
postMethod.setRequestBody(data);
org.apache.commons.httpclient.HttpClient httpClient = new org.apache.commons.httpclient.HttpClient();
int response = httpClient.executeMethod(postMethod); // 执行POST方法
String result = postMethod.getResponseBodyAsString() ;
System.out.println("--------"+response);
System.out.println("===="+result);
return result;
} catch (Exception e) {
throw new RuntimeException(e.getMessage());
}
}
}
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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
← 接入教程(使用POA) 发送方式查询 →