# 开发者对接

关于第三方系统,如何接入消息API,获取消息能力的操作指导

# 名词解释

# 消息任务

调用一次消息中心的消息发送接口为一个消息任务,成功调用的消息任务返回一个唯一sendId。

# 消息记录

一个消息任务可发送给多个人,对应到个人的记录为一个消息记录。

# 发送方式

消息发送,支持多种发送方式:系统消息、手机短信、电子邮件、钉钉、微信、app消息推送。

# 消息网关

消息网关为消息发送方式对应的对接方式,例如:手机短信方式已对接阿里云短信、天瑞和、飞鸽传书、一信通、即信等网关。

发送方式 消息网关
系统消息 站内信、智慧校园系统消息通用网关
手机短信 阿里云短信、天瑞和、飞鸽传书、一信通、即信
电子邮件 网易、腾讯、通用
钉钉 钉钉工作消息网关
微信 微信企业网关、瑞雷森企业微信网关
app消息推送 个推推送网关

# 消息应用

应用发送消息需要在消息平台注册应用,根据应用分配的 appId 进行接口调用。

# 消息类型

消息应用下可以创建多个消息类型,方便消息的分类管理;例如流程应用, 创建了流程代办提醒、流程办结提醒、流程转办提醒等消息类型。 同时,消息类型需要配置对应的发送方式,每个发送方式可以选择一个对应消息发送网关。

# 消息模板

消息类型都需要设置模板,模板便于管理消息发送,消息模板有单模板和多模板;单模板表示所有的发送方式使用同种模板,而多模板表示每个发送方式可以设置不同的模板。

# 消息对接

# 应用注册

第三方业务系统,如果需要对接消息接口,需要先在消息平台注册应用

# 消息类型

参数 描述 举例
所属消息类别 目前有通知、提醒、其他(单选) 通知
消息类型名称 名称需贴合该类型的使用场景 流程代办提醒
消息类型编号 编号,不可重复(messageTypeCode) flow_asdasada_asdasd
消息的发送方式 目前有 SMS(手机短信)、MAIL(邮件)、WECHAT(微信)、DINGTALK(钉钉)、SUPERAPP(APP消息推送)、WEBSITE(系统消息) (可多选,具体参考项目实际情况) SMS(手机短信)、WEBSITE(系统消息网关)、SUPERAPP(个推网关)
是否通用模板 是:多个发送方式共用一个模板; 否:每个发送方式可自定义不同模板

# 消息模板

模板 变量
您好,转阅了流程事项给您。 name-用户名称; ffname-应用名称
于申请下载主题数据目录:的数据,请及时处理 username-学工号;time-时间;dataListName-数据目录名称
您正在激活帐号,须验证身份,验证码,有效期5分钟,请尽快完成验证。 code-验证码

# 消息类型

# 描述

接入应用后,需要新建消息类型,消息类型是消息发送的场景。

# 操作

  • 通过应用管理-消息类型管理,进入【消息类型管理】功能;

    图片

  • 点击【添加消息类型】,创建1个消息类型;

    图片

  • 消息类型编号,用于区分不同的消息类型,对接消息接口时使用;

    图片

  • 消息类别,选择一个消息类别,简单理解为给消息类型分类即可,在消息类别管理中可以添加新的消息类别;

    图片

  • 发送方式,如果1个消息类型,需要同时通过多个渠道给接收者发送消息,可以选择多个发送方式;

  • 勾选发送方式后,需要选择当前发送方式发消息的网关,默认选中1个,就是我们在消息网关管理中设置的默认网关;

    图片

  • 模板类型:添加消息类型后,需要编辑消息模板,消息模板的编辑方式分2种,叫做模板类型。一种是单模板,只要编辑1套模板,多个发送方式都使用这1套模板;另一种是多模板,每一个发送方式都分别定义一套模板;

    图片

# 消息模板

# 描述

添加了消息类型后,需要编辑消息模板,发送消息时,从消息模板中获取内容作为消息正文发送。

# 操作

  • 在应用管理-消息类型管理中,点击【模板管理】,可以进入模板管理功能;

    图片

  • 消息模板类型:

    • 消息模板类型包括:单模板和多模板;

    • 单模板:编辑1套模板,多个发送方式共用;

    • 多模板:每个发送方式分别定义1套模板;

      图片

      图片

  • 模板消息支持插入变量:

    • 变量类型包括内置变量和自定义变量;

    • 美元符号+双中括号的是内置变量,双花括号的是自定义变量;

    • 内置变量由消息服务系统提供,自定义变量由开发者自行传值;

    • 添加自定义变量需要按照格式添加,不然系统无法识别;

    • 自定义变量添加后,鼠标光标移出编辑框后,自动识别自定义变量,并在下方出现变量设置,需要填写变量标题;

      图片

  • 短信模板,短信发送方式有2种,一种是选择模板,一种是自定义:

    • 在设置-短信编辑方式中可以切换;

    • 具体选择哪种发送方式,需要根据短信网关运营商的政策定,如阿里云短信要求必须要提前申请短信模板,通过短信模板发送短信,飞鸽传书短信支持自定义短信;

    • 选择短信模板发送的短信编辑方式,消息类型中,短信发送方式的消息模板,必须从网关支持的短信模板中选择,带入到消息模板中,不可以自定义编辑;

      图片

      图片

      图片

  • 示例:

    • 如果希望消息内容保持一致,可以选择单模板类型;

    • 如果希望每个发送方式各自定义1套模板,可以选择多模板类型;

    • 如果希望消息内容自定义,可以选择单模板类型,在模板中插入自定义变量,即可实现消息内容自定义;

      图片

# access token

请参照项目实际域名操作

# poa能力申请

  • 注册应用 已注册过的应用,不用重复注册,直接申请发送信息scope即可。 curl -i -s -X POST -H 'Content-Type: application/json' -d '{"clientName": "应用名称"}' 'http://poa-sa.xxx.edu.cn/v1/clients' 响应结果如下: {"code":0,"message":null,"data":{"clientId":"*************","clientSecret":"*************"}}

  • 应用申请发送消息 scope curl -i -s -X POST -H 'Content-Type: application/json' -d '{"scopes": ["messagecenter:v1:sendMessage"]}' 'http://poa-sa.xxx.edu.cn/v1/clients/应用clientId/scopes'

  • 查询已注册应用 curl -i -s -X GET 'http://poa-sa.xxx.edu.cn/v1/clients?pageNo=1&pageSize=20'

# 获取access token

请求:

POST /oauth2/token HTTP/1.1
Host: poa.xxx.edu.cn
Content-Type: application/x-www-form-urlencoded

grant_type=client_credentials&client_id=<your_client_id>&client_secret=
<your_client_secret>&scope=<your_scopes>

参数说明:

参数 说明
grant_type 值必须是client_credentials。
client_id 申请的 Client ID。
client_secret 申请的 Client Secret。
scope 所请求的权限,多个用逗号分割。

响应:

200 OK
Content-Type: application/json

{
  "access_token": "AYjcyMzY3ZDhiNmJkNTY",
  "token_type": "bearer",
  "expires_in": 3600
}

更多poa相关操作请看poa相关文档

# 接口能力

  • 发送消息接口文档

    发送接口文档地址: https://poa-docs.xxx.edu.cn/messagecenter/v1/latest/#operation/messageSend (域名地址参考实际项目地址)

    图片

  • access token

    access token获取方式参考上方poa获取access token

  • 入参说明

参数 描述 类型 必填 默认值
appId 应用ID string
sendId 消息任务序列识别号,不重复【为空,消息服务生成唯一sendId,并返回】 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 消息类型模板设置的变量【模板设置了变量就必填】 JSONObject

其中 appId是由消息平台应用申请完成后分配;

  • 发送demo

    以上方流程表单消息模板为例 您好,${name}转阅了${ffname}流程事项给您。| name-用户名称; ffname-应用名称 Postman截图如下:

    图片 图片

发送成功

code 为 0 表示发送成功
data.sendId 返回消息任务发送的序列号;根据sendId 可以查询发送任务的情况;

发送失败

code !=  0

若是入参  promise 设置为false

message 给出错误信息;

若是入参  promise 设置为true 

message 给出错误信息;

data.errorList 返回有异常的发送情况数组:
        receiverKey 接收对象【可以是账号、手机号、邮箱地址】
        exceptionMessage 该接收对象具体的异常问题

# 获取消息类别分页列表

# 获取消息类别分页列表

文档地址: https://poa-docs.xxx.edu.cn/messagecenter/v1/latest/#operation/getMessageTypePageList (域名地址参考实际项目地址)

# access token

获取方式参考上方poa获取access token

# 入参说明

参数 描述 类型 必填 默认值
name 消息类别名称 string
pageIndex 分页-页码 integer 0
pageSize 分页-每页记录数 integer 10

# 响应结果

查询成功

{
  "timestamp": 时间戳,
  "code": 0, //code 为 0表示查询成功
  "message": "查询成功",
  "data": {
    "totalCount": 记录总数,
    "pageSize": 每页记录数,
    "totalPages": 分页总数,
    "pageIndex": 当前页码,
    "items": [
      {
        "name": "消息类别名称",
        "description": "消息类别描述",
        "editTime": "消息类别编辑时间",
        "id": "消息类别主键",
        "code": "消息类别编码"
      },...
    ]
  }
}

查询失败

{
  "code": , //code 不为 0表示查询失败
  "message": "错误信息",
  "timestamp": 时间戳
}

# 获取应用列表

# 获取应用列表

文档地址: https://poa-docs.xxx.edu.cn/messagecenter/v1/latest/#operation/listApp (域名地址参考实际项目地址)

# access token

获取方式参考上方poa获取access token

# 入参说明

# 响应结果

查询成功

{
  "timestamp": 时间戳,
  "code": 0, //code 为 0表示查询成功
  "message": "查询成功",
  "data": [
    {
      "name": "应用名称",
      "description": 描述,
      "systemName": 所属系统,
      "enabled": 是否启用【1表示启用,0表示未启用】,
      "appId": "应用appId"
    },...
  ]
}  

查询失败

{
  "code": , //code 不为 0表示查询失败
  "message": "错误信息",
  "timestamp": 时间戳
}

# 根据消息类别查询消息类型分页列表

# 根据消息类别查询消息类型分页列表

文档地址: https://poa-docs.xxx.edu.cn/messagecenter/v1/latest/#operation/getMessageTypeByCategory (域名地址参考实际项目地址)

# access token

获取方式参考上方poa获取access token

# 入参说明

参数 描述 类型 必填 默认值
messageCategoryName 消息类别名称 string
messageCategoryCode 消息类别编码 string
pageIndex 分页-页码 integer 0
pageSize 分页-每页记录数 integer 10

# 响应结果

查询成功

{
  "timestamp": 时间戳,
  "code": 0, //code 为 0表示查询成功
  "message": "查询成功",
  "data": {
    "totalCount": 记录总数,
    "pageSize": 每页记录数,
    "totalPages": 分页总数,
    "pageIndex": 当前页码,
    "items": [
      {
        "messageCategoryName": "消息类别名称",
        "messageTypeCode": "消息类型编码",
        "whetherUniversal": 是否通用模板【1表示是,0表示不是】,
        "messageTypeId": "消息类型ID",
        "appId": "应用appId",
        "messageCategoryCode": "消息类别编码",
        "description": "描述",
        "messageTypeName": "消息类型名称",
        "enabled": 是否启用【1表示启用,0表示未启用】
      },...
    ]
  }
}

查询失败

{
  "code": , //code 不为 0表示查询失败
  "message": "错误信息",
  "timestamp": 时间戳
}

# 个人消息记录分页查询

# 个人消息记录分页查询

文档地址: https://poa-docs.xxx.edu.cn/messagecenter/v1/latest/#operation/listMessageRecord (域名地址参考实际项目地址)

# access token

获取方式参考上方poa获取access token

# 入参说明

参数 描述 类型 必填 默认值
accountName 用户名(学工号) string
appKey 应用appId string
messageCategoryCode 分页-页码 integer 0
messageTypeId 消息类型Id string 0
messageTypeCode 消息类型CODE string 0
notReceiveCategorys 不接收消息类别(类别代码),多个用英文逗号隔开 string 0
notReceiveTypes 不接收消息类型(ID),多个用英文逗号隔开 string 0
title 消息标题 string 0
important 是否重要消息 boolean 0
star 是否标星信息【0 表示 正常状态 1 表示标星】 integer 0
readed 是否已读 boolean 0
readerStatus 接收人标记消息状态【0 表示 正常状态 1 表示回收站】 integer 0
pageIndex 分页-页码 integer 0
pageSize 分页-每页记录数 integer 10

# 响应结果

查询成功

{
  "timestamp": 时间戳,
  "code": 0, //code 为 0表示查询成功
  "message": "查询成功",
  "data": {
    "totalCount": 记录总数,
    "pageSize": 每页记录数,
    "totalPages": 分页总数,
    "pageIndex": 当前页码,
    "items": [
      {
        "recordId": "消息记录ID",
        "title": "消息记录标题",
        "coverImageUrl": "封面图地址",
        "content": "消息记录内容",
        "mobileUrl": "移动端跳转链接",
        "signOff": "落款",
        "url": "pc端跳转链接",
        "sendType": "发送方式",
        "accountName": "消息接收人账号",
        "sendTime": "发送时间",
        "appId": "应用appId",
        "appName": "应用名称",
        "messageCategoryCode": "消息类别编码",
        "messageTypeName": "消息类型名称",
        "readed": "是否已读【1表示已读,0表示未读】",
        "star": "是否标星【1表示标星,0表示未标星】",
        "readerStatus": "接收人标记消息状态【0表示正常,1表示回收站,2表示删除】",
        "deptId": "落款部门",
        "sendTaskPersonKey": "消息任务唯一键",
        "receiverKey": "接收号码",
        "messageCategoryName": "消息类别名称",
        "messageTypeCode": "消息类别编码",
        "important": "是否重要消息【1表示重要,0表示不重要】",
        "deleteTime": "删除时间",
        "files": "附件"
      },...
    ]
  }
}

查询失败

{
  "code": , //code 不为 0表示查询失败
  "message": "错误信息",
  "timestamp": 时间戳
}

# 根据消息类型编码查询对应发送方式

# 根据消息类型编码查询对应发送方式

文档地址: https://poa-docs.xxx.edu.cn/messagecenter/v1/latest/#operation/getSendTypeByMessageTypeCode (域名地址参考实际项目地址)

# access token

获取方式参考上方poa获取access token

# 入参说明

参数 描述 类型 必填 默认值
code 消息类型编码 string

# 响应结果

查询成功

{
  "timestamp": 时间戳,
  "code": 0, //code 为 0表示查询成功
  "message": "查询成功",
  "data": [
    {
      "发送方式": "发送方式名称",
      ...
    },...
  ]
}  

查询失败

{
  "code": , //code 不为 0表示查询失败
  "message": "错误信息",
  "timestamp": 时间戳
}

# 根据学工号获取安全手机号(手机号脱敏)

# 根据学工号获取安全手机号(手机号脱敏)

文档地址: https://poa-docs.xxx.edu.cn/messagecenter/v1/latest/#operation/getVerificationPhoneNum (域名地址参考实际项目地址)

# access token

获取方式参考上方poa获取access token

# 入参说明

参数 描述 类型 必填 默认值
accountNames 学工号,多个学工号英文逗号分隔 string

# 响应结果

查询成功

{
  "timestamp": 时间戳,
  "code": 0, //code 为 0表示查询成功
  "message": "查询成功",
  "data": [
    {
      "accountName": "账号",
      "securePhone":"手机号(脱敏)"
    },...
  ]
}  

查询失败

{
  "code": , //code 不为 0表示查询失败
  "message": "错误信息",
  "timestamp": 时间戳
}

# app消息推送接口

# app消息批量推送接口;全体推送以及批量推送;【该接口,无消息记录】

文档地址: https://poa-docs.xxx.edu.cn/messagecenter/v1/latest/#operation/appBatchMessageSend (域名地址参考实际项目地址)

# access token

获取方式参考上方poa获取access token

# 入参说明

参数 描述 类型 必填 默认值
appId 应用appId string
sendId 消息任务序列识别号,不重复【为空,消息服务生成唯一sendId,并返回】 string
messageTypeCode 消息类型的编码 string
all 是否全体推送【设置全量推送,clientIds,tags设置无效】 boolean false
clientIds 设备clientId,多个英文逗号分隔【clientIds,tags 二选一】 string false
tags 标签,多个英文逗号分隔【app登录用户打上标签,通过标签可以分组批量推送】【clientIds,tags 二选一】 string
promise 消息送达承诺【如果true,校验比较严格】 boolean false
importantIdentity 是否重要消息的标识 boolean false
data.title 消息标题 string
data.extraParams 额外参数 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 消息类型模板设置的变量【模板设置了变量就必填】 JSONObject

其中 appId是由消息平台应用申请完成后获得;

# 响应结果

发送成功

code 为 0 表示发送成功

发送失败


  "code": , //code 不为 0表示查询失败
  "message": "错误信息",
  "timestamp": 时间戳
}

# 消息任务结果统计

# 消息任务结果统计

文档地址: https://poa-docs.xxx.edu.cn/messagecenter/v1/latest/#operation/getSendTaskCount (域名地址参考实际项目地址)

# access token

获取方式参考上方poa获取access token

# 入参说明

参数 描述 类型 必填 默认值
sendId 消息任务发送序列号 string

# 响应结果

查询成功

{
  "timestamp": 时间戳,
  "code": 0, //code 为 0表示查询成功
  "message": "查询成功",
  "data": [
    {
      "count": "消息任务下消息记录总数",
      "sendId":"发送序列号",
      "type": "发送方式",
      "error":"消息记录失败数",
      "success": "消息记录成功数"
    },...
  ]
}  

查询失败

{
  "code": , //code 不为 0表示查询失败
  "message": "错误信息",
  "timestamp": 时间戳
}

# 根根据应用appId查询消息类型列表

# 根根据应用appId查询消息类型列表

文档地址: https://poa-docs.xxx.edu.cn/messagecenter/v1/latest/#operation/listMessageType (域名地址参考实际项目地址)

# access token

获取方式参考上方poa获取access token

# 入参说明

参数 描述 类型 必填 默认值
appKey 应用appId string
messageTypeId 消息类型ID string

# 响应结果

查询成功

{
  "timestamp": 时间戳,
  "code": 0, //code 为 0表示查询成功
  "message": "查询成功",
  "data": [
    {
      "code": "消息类型编码",
      "addTime":"消息类型创建时间",
      "appName": "应用名称",
      "appId":"应用appId",
      "id": "消息类型ID",
      "type": "发送方式",
      "messageTypeName":"消息类型名称",
      "enabled": "是否启用【1表示启用,0表示未启用】",
    },...
  ]
}  

查询失败

{
  "code": , //code 不为 0表示查询失败
  "message": "错误信息",
  "timestamp": 时间戳
}

# 对接demo

# java

maven依赖

<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>3.13.1</version>
</dependency>
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import okhttp3.*;


OkHttpClient client = new OkHttpClient().newBuilder().build();
MediaType mediaType = MediaType.parse("application/x-www-form-urlencoded");
//注意修改body里边的client_id,client_secret,scope等值
RequestBody body = RequestBody.create(mediaType, "grant_type=client_credentials&client_id=CPZrUASAj_6XdMZ_wuWB2e8GXmM=&scope=user:v1:readUser,user:v1:readOrganization,user:v1:readGroup,user:v1:readLabel,user:v1:readUserSecret,user:v1:readPost,authz:v1:readRole,messagecenter:v1:sendMessage,messagecenter:v1:writeMessage,messagecenter:v1:readMessage&client_secret=Sgl4DbaFP93Yyh28uEvTqICb_WyyV-iiWAUVJds4HlE=");
//获取token(xxx是泛指,url需根据项目实际地址修改)
Request request = new Request.Builder()
        .url("https://poa.xxx.cn/oauth2/token")
        .method("POST", body)
        .addHeader("Content-Type", "application/x-www-form-urlencoded")
        .build();
Response response = client.newCall(request).execute();
Object token= null;
if(response.isSuccessful()){
    ResponseBody responseBody = response.body();
    String responseStr = responseBody.string();
    JSONObject jsonObject = JSON.parseObject(responseStr);
    if(null != jsonObject){
         token = jsonObject.get("access_token");
    }
}
if(null != token){
    MediaType sendMediaType = MediaType.parse("application/json");
    RequestBody sendBody = RequestBody.create(sendMediaType, "{\"accountName\":\"发送人学工号\",\"appId\":\"应用appId\",\"data\":{\"coverImageUrl\":\"封面图链接\",\"filesUrl\":\"附件链接\",\"paramValueJson\":{\"模板参数名\":\"参数填充值\"},\"title\":\"消息标题\"},\"messageTypeCode\":\"消息类型CODE\",\"sendType\":[\"WEBSITE\",\"发送方式\"],\"toDepts\":\"部门\",\"toEmails\":\"邮件\",\"toGroups\":\"用户组\",\"toPersons\":\"用户学工号\",\"toPhones\":\"手机号\"}\r\n");
    //消息发送(xxx是泛指,url需根据项目实际地址修改)
    Request sendRequest = new Request.Builder()
            .url("http://poa.xxx.edu.cn/apis/messagecenter/v1/poaMessage/messageSend")
            .method("POST", sendBody)
            .addHeader("Authorization", "Bearer " + token.toString())
            .addHeader("Content-Type", "application/json")
            .build();
    Response sendResponse = client.newCall(sendRequest).execute();
}

# PHP

//获取token(xxx是泛指,url需根据项目实际地址修改)
<?php

$curl = curl_init();

curl_setopt_array($curl, array(
  CURLOPT_URL => 'https://poa.xxx.edu.cn/oauth2/token',
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_ENCODING => '',
  CURLOPT_MAXREDIRS => 10,
  CURLOPT_TIMEOUT => 0,
  CURLOPT_FOLLOWLOCATION => true,
  CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
  CURLOPT_CUSTOMREQUEST => 'POST',
  CURLOPT_POSTFIELDS => 'grant_type=client_credentials&client_id=CPZrUASAj_6XdMZ_wuWB2e8GXmM%3D&scope=user%3Av1%3AreadUser%2Cuser%3Av1%3AreadOrganization%2Cuser%3Av1%3AreadGroup%2Cuser%3Av1%3AreadLabel%2Cuser%3Av1%3AreadUserSecret%2Cuser%3Av1%3AreadPost%2Cauthz%3Av1%3AreadRole%2Cmessagecenter%3Av1%3AsendMessage%2Cmessagecenter%3Av1%3AwriteMessage%2Cmessagecenter%3Av1%3AreadMessage&client_secret=Sgl4DbaFP93Yyh28uEvTqICb_WyyV-iiWAUVJds4HlE%3D',
  CURLOPT_HTTPHEADER => array(
    'Content-Type: application/x-www-form-urlencoded'
  ),
));

$response = curl_exec($curl);

curl_close($curl);
echo $response;
//消息发送(xxx是泛指,url需根据项目实际地址修改)
<?php

$curl = curl_init();

curl_setopt_array($curl, array(
  CURLOPT_URL => 'http://poa.xxx.edu.cn/apis/messagecenter/v1/poaMessage/messageSend',
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_ENCODING => '',
  CURLOPT_MAXREDIRS => 10,
  CURLOPT_TIMEOUT => 0,
  CURLOPT_FOLLOWLOCATION => true,
  CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
  CURLOPT_CUSTOMREQUEST => 'POST',
  CURLOPT_POSTFIELDS =>'{"accountName":"发送人学工号","appId":"应用appId","data":{"coverImageUrl":"封面图链接","filesUrl":"附件链接","paramValueJson":{"模板参数名":"参数填充值"},"title":"消息标题"},"messageTypeCode":"消息类型CODE","sendType":["WEBSITE","发送方式"],"toDepts":"部门","toEmails":"邮件","toGroups":"用户组","toPersons":"用户学工号","toPhones":"手机号"}
',
  CURLOPT_HTTPHEADER => array(
  //把上一步得到的token替换到 token
    'Authorization: Bearer token',
    'Content-Type: application/json'
  ),
));

$response = curl_exec($curl);

curl_close($curl);
echo $response;

# Python

import http.client
import json

//获取token(xxx是泛指,url需根据项目实际地址修改)
conn = http.client.HTTPSConnection("poa.xxx.edu.cn")
payload = 'grant_type=client_credentials&client_id=CPZrUASAj_6XdMZ_wuWB2e8GXmM%3D&scope=user%3Av1%3AreadUser%2Cuser%3Av1%3AreadOrganization%2Cuser%3Av1%3AreadGroup%2Cuser%3Av1%3AreadLabel%2Cuser%3Av1%3AreadUserSecret%2Cuser%3Av1%3AreadPost%2Cauthz%3Av1%3AreadRole%2Cmessagecenter%3Av1%3AsendMessage%2Cmessagecenter%3Av1%3AwriteMessage%2Cmessagecenter%3Av1%3AreadMessage&client_secret=Sgl4DbaFP93Yyh28uEvTqICb_WyyV-iiWAUVJds4HlE%3D'
headers = {
  'Content-Type': 'application/x-www-form-urlencoded'
}
conn.request("POST", "/oauth2/token", payload, headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))

//消息发送(xxx是泛指,url需根据项目实际地址修改)
conn = http.client.HTTPSConnection("poa.xxx.edu.cn")
payload = json.dumps({
  "accountName": "发送人学工号",
  "appId": "应用appId",
  "data": {
    "coverImageUrl": "封面图链接",
    "filesUrl": "附件链接",
    "paramValueJson": {
      "模板参数名": "参数填充值"
    },
    "title": "消息标题"
  },
  "messageTypeCode": "消息类型CODE",
  "sendType": [
    "WEBSITE",
    "发送方式"
  ],
  "toDepts": "部门",
  "toEmails": "邮件",
  "toGroups": "用户组",
  "toPersons": "用户学工号",
  "toPhones": "手机号"
})
headers = {
//把上一步得到的token替换到 token
  'Authorization': 'Bearer token',
  'Content-Type': 'application/json'
}
conn.request("POST", "/apis/messagecenter/v1/poaMessage/messageSend", payload, headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))