零、前言
由于整体weibo的认证流程周期会比较长,建议提前7个工作日申请相关讯息。主要是weibo的接口文档比较迷,需要自己打开console设置属性后某些网站才能正确打开。还是整理一下避免日后在查。
一、接入流程
以下流程完全可以由上面的链接获取,作当前版本记录
https://open.weibo.com/wiki/%E5%BE%AE%E5%8D%9AAPI
(0)认证讯息
没有这一步,下面甚么
回调地址
与appkey
都是扯淡。
①进入这个网站 身份信息 - 开发者信息 - 新浪微博开放平台 (weibo.com)
②点击右上角头像,点击下拉框中的开发者信息
③填写基本信息 & 身份认证
④等待身份认证通过
(1)平台接入流程
①注册企业开发者
② 创建粉丝服务类应用
③配置粉服
④提交上线
(2)服务平台开发模式接入流程
①申请消息接口
② 验证URL有效性
③获取accessToken
二、配置开发者模式
其实这个流程可谓是通用做法,无论是对接甚么平台这个模式都是逃不掉的
0、预设讯息
①预设回调地址:https://api.coffeeandice.cn/weibo
②预设回调其他参数:
appsercret:demo
timestamp:1639017506000
nonce:57155157
echostr:(随机字符串)KeyDMwtf672
1、填写回调地址与自定义appkey
回调地址:对应的就是你精确到端点的接口地址
appkey:自行约定的密钥
2、验证回调地址可用性(Get)
校验参数字段 | 字段类型 | 字段说明 |
---|---|---|
signature | string | 微博加密签名,signature结合了开发者的appsecret、和请求中的timestamp参数,nonce参数 |
timestamp | string | 时间戳 |
nonce | string | 随机数 |
echostr | string | 随机字符串(首次建立时存在) |
懒狗标配:sha1在线解密 在线加密 (ttmd5.com)
sha1签名:(引用预设讯息)
开发者的appsecret,timestamp参数,nonce 排序
拼接:timestamp + nonce + appsecret
=> 1639017506000 + 57155157 + demo
sha1加密: 233dae8d74f45a1ad1f5671a974c485ccd1ac3c5
校验URL:
https://api.coffeeandice.cn/weibo?nonce=57155157×tamp=1639017506000&echostr=KeyDMwtf672&signature=233dae8d74f45a1ad1f5671a974c485ccd1ac3c5
①若想直接测试,不校验可以直接接口返回echostr即可通过验证
直接返回 KeyDMwtf672 即可
@Controller
public class EndpointController {
private final String weibo_appkey = "demo";
@GetMapping("weibo")
public String weiboCheck(HttpServletRequest request,
HttpServletResponse response) throws IOException {
String nonce = request.getParameter("nonce");
String echoStr = request.getParameter("echostr");
String timestamp = request.getParameter("timestamp");
String signature = request.getParameter("signature");
return echoStr;
}
}
②校验式验证
@Controller
public class EndpointController {
@GetMapping("weibo")
public String weiboCheck(HttpServletRequest request,
HttpServletResponse response) throws IOException {
String nonce = request.getParameter("nonce");
String echoStr = request.getParameter("echostr");
String timestamp = request.getParameter("timestamp");
String signature = request.getParameter("signature");
//验证签名
boolean isValid = ValidateSHA(signature, nonce, timestamp);
if(isValid){
return echoStr;
}
}
}
/* cv 微博示例方法 */
/**
* 验证sha1签名,验证通过返回true,否则返回false
*
* @param signature
* @param nonce
* @param timestamp
* @return
*/
private boolean ValidateSHA(String signature, String nonce,
String timestamp) {
if (signature == null || nonce == null || timestamp == null) {
return false;
}
String sign = sha1(getSignContent(nonce, timestamp, weibo_appkey));
if (!signature.equals(sign)) {
return false;
}
return true;
}
/**
* 生产sha1签名
*
* @param strSrc
* @return
*/
private static String sha1(String strSrc) {
MessageDigest md = null;
String strDes = null;
byte[] bt = strSrc.getBytes();
try {
md = MessageDigest.getInstance("SHA-1");
md.update(bt);
strDes = bytes2Hex(md.digest()); // to HexString
} catch (NoSuchAlgorithmException e) {
//TODO
e.printStackTrace();
}
return strDes;
}
private static String bytes2Hex(byte[] bts) {
String des = "";
String tmp = null;
for (int i = 0; i < bts.length; i++) {
tmp = (Integer.toHexString(bts[i] & 0xFF));
if (tmp.length() == 1) {
des += "0";
}
des += tmp;
}
return des;
}
3、验证成功,保存access_token
三、正式回调方法(POST)
@Controller
public class EndpointController {
@PostMapping("weibo")
public String weiboCheck(HttpServletRequest request,
HttpServletResponse response) throws IOException {
String nonce = request.getParameter("nonce");
String timestamp = request.getParameter("timestamp");
String signature = request.getParameter("signature");
//验证签名
boolean isValid = ValidateSHA(signature, nonce, timestamp);
if(isValid){
if(StringUtils.isNotBlank(echoStr)){
//存在echoStr,是首次配置时验证url可达性。
returnContent = echoStr; //返回内容为echoStr的内容
}else{
//回调消息处理
//正常推送消息时不会存在echoStr参数。
//接收post过来的消息数据
//ps: 官方是这样获取的,等待验证,是否需要我们转换格式
StringBuilder sb = new StringBuilder();
BufferedReader in = request.getReader();
String line;
while ((line = in.readLine()) != null) {
sb.append(line);
}
}
}
}
}
(1)消息接受处理
①纯文本私信(text)
paramter | type | description |
---|---|---|
type | string | text |
receiver_id | int64 | 消息的接收者 |
sender_id | int64 | 消息的发送者 |
created_at | string | 消息创建时间 |
text | string | 私信内容 |
data | string | 消息内容,纯文本私信或留言为空 |
{
"type": "text",
"receiver_id": 1902538057,
"sender_id": 2489518277,
"created_at": "Mon Jul 16 18:09:20 +0800 2012",
"text": "私信或留言内容",
"data": {}
}
②位置信息私信(position)
paramter | type | description |
---|---|---|
type | string | position |
receiver_id | int64 | 消息的接收者 |
sender_id | int64 | 消息的发送者 |
created_at | string | 消息创建时间 |
text | string | 原位置私信文本,没有时用默认文案“发送了一个位置” |
data | string | 消息内容 |
data:longitude | string | 经度 |
data:latitude | string | 纬度 |
{
"type": "position",
"receiver_id": 1902538057,
"sender_id": 2489518277,
"created_at": "Mon Jul 16 18:09:20 +0800 2012",
"text": "我在这里: http://t.cn/zQgLLYO",
"data": {
"longitude": "116.308586",
"latitude": "39.982525"
}
}
③语音类型私信(voice)
paramter | type | description |
---|---|---|
type | string | voice |
receiver_id | int64 | 消息的接收者 |
sender_id | int64 | 消息的发送者 |
created_at | string | 消息创建时间 |
text | string | 私信内容 |
data | string | 消息内容,纯文本私信或留言为空 |
data:vfid | string | 语音文件ID,发送者通过此ID读取语音 |
data:tovfid | string | 语音文件ID,接收者通过此ID读取语音 |
{
"type": "voice",
"receiver_id": 1902538057,
"sender_id": 2489518277,
"created_at": "Mon Jul 16 18:09:20 +0800 2012",
"text": "发了一个语音消息",
"data": {
"vfid": 821804459, // 发送者用此ID查看语音
"tovfid": 821804469 // 接收者用此ID查看语音
}
}
查看语音方法:
https://upload.api.weibo.com/2/mss/msget?access_token=RECIPIENT_ACCESS_TOKEN&fid=TOVFID
1.“RECIPIENT_ACCESS_TOKEN”:返回结果中接收者(recipient_id)通过OAuth2授权返回的access_token;
2.“TOVFID”:返回结果data字段中的tovfid。
④图片类型私信(image)
paramter | type | description |
---|---|---|
type | string | image |
receiver_id | int64 | 消息的接收者 |
sender_id | int64 | 消息的发送者 |
created_at | string | 消息创建时间 |
text | string | 私信内容 |
data | string | 消息内容,纯文本私信或留言为空 |
data:vfid | string | 图片ID,发送者通过此ID读取图片 |
data:tovfid | string | 图片ID,接收者通过此ID读取图片 |
{
"type": "image",
"receiver_id": 1902538057,
"sender_id": 2489518277,
"created_at": "Mon Jul 16 18:09:20 +0800 2012",
"text": "发了一张图片",
"data": {
"vfid": 821804459, // 发送者用此ID查看图片
"tovfid": 821804469 // 接收者用此ID查看图片
}
}
查看图片方法:
https://upload.api.weibo.com/2/mss/msget?access_token=RECIPIENT_ACCESS_TOKEN&fid=TOVFID
1,“RECIPIENT_ACCESS_TOKEN”:返回结果中接收者(receiver_id)通过OAuth2授权返回的access_token;
2,“TOVFID”:返回结果data字段中的tovfid。
(2)被动响应处理(被动回复)
①纯文本响应(text)(URLEncode)
paramter | type | require | description |
---|---|---|---|
text | string | true | 要回复的私信文本内容。文本大小必须小于300个汉字。 |
{
"result": true,
"receiver_id":456,
"sender_id":123,
"type": "text",
"data":"{"text": "中文消息"}"
}
//合格内容格式,需要URLEncode编码,但是我实际中并没有这个操作也可以。
{
"result":true,
"sender_id":"123",
"receiver_id":"456",
"type":"text",
"data":"%7B%22text%22%3A%22%E4%B8%AD%E6%96%87%E6%B6%88%E6%81%AF%22%7D"
}
②图文响应(articles)(8个)
paramter | type | require | description |
---|---|---|---|
articles:display_name | string | true | 图文的显示名称标题 |
articles:summary | string | true | 图文的文字描述,大于等于2个图文时,仅显示第一个图文的描述 |
articles:image | string | true | 图文的缩略显示图片,需为JPG、PNG格式,单图及多图第一张推荐使用280155,多图非第一张推荐使用6464 |
articles:url | string | true | 图文的URL地址,点击后跳转(注:该url必须为完整的url,例如, http://weibo.com/xxx ,如果省略掉”http:// “,则无法发送图文消息) |
{
"result": true,
"receiver_id":456,
"sender_id":123,
"type": "articles",
"data": {
"articles": [
{
"display_name": "两个故事",
"summary": "今天讲两个故事,分享给你。谁是公司?谁又是中国人?",
"image": "http://storage.mcp.weibo.cn/0JlIv.jpg",
"url": "http://e.weibo.com/mediaprofile/article/detail?uid=1722052204&aid=983319"
},
... //最多支持8个图文,建议为1或3个
]
}
}
//返回样例
{
"result": true,
"sender_id":"123",
"receiver_id":"456",
"type": "articles",
"data":"%7B%22articles%22%3A%5B%7B%22display_name%22%3A%22%E4%B8%A4%E4%B8%AA%E6%95%85%E4%BA%
8B%22%2C%22summary%22%3A%22%E4%BB%8A%E5%A4%A9%E8%AE%B2%E4%B8%A4%E4%B8%AA%E6%95%85%E4%BA%8B%EF%BC%8C%E5%88%86%E4%BA%AB%E7%BB%99%E4%BD%A0%E3%80%82%E8%B0%81%E6%98%AF%E5%85%AC%E5%8F%B8%EF%BC%9F%E8%B0%81%E5%8F%88%E6%98%AF%E4%B8%AD%E5%9B%BD%E4%BA%BA%EF%BC%9F%E2%80%8B%22%2C%22image%22%3A%22http%3A%2F%2Fstorage.mcp.weibo.cn%2F0JlIv.jpg%22%2C%22url%22%3A%22http%3A%2F%2Fe.weibo.com%2Fmediaprofile%2Farticle%2Fdetail%3Fuid%3D1722052204%26aid%3D983319%22%7D%5D%7D"
}
③位置信息响应(position)
paramter | type | require | description |
---|---|---|---|
longitude | string | true | 经度 |
latitude | string | true | 纬度 |
{
"result": true,
"receiver_id":456,
"sender_id":123,
"type": "position",
"data": {
"longitude": "344.3344",
"latitude": "232.343434"
}
}
//返回样例
{
"result":true,
"sender_id":"123",
"receiver_id":"456",
"type":"position",
"data":"%7B%22longitude%22%3A%22344.3344%22%2C%22latitude%22%3A%22232.343434%22%7D"
}
(3)事件响应处理(接受事件推送)
①关注/取消关注事件
paramter | type | description |
---|---|---|
type | string | event |
receiver_id | int64 | 消息的接收者 |
sender_id | int64 | 消息的发送者 |
created_at | string | 消息创建时间 |
text | string | 默认文案。subtype为follow或unfollow时分别为“关注事件消息”、“取消关注事件消息”; |
data | string | 消息内容 |
data:subtype | string | follow:关注事件,unfollow取消关注事件。 |
{
"type": "event",
"receiver_id": 1902538057,
"sender_id": 2489518277,
"created_at": "Mon Jul 16 18:09:20 +0800 2012",
"text": "关注事件消息",
"data": {
"subtype": "follow"
}
}
②订阅/取消订阅事件
paramter | type | description |
---|---|---|
type | string | event |
receiver_id | int64 | 消息的接收者 |
sender_id | int64 | 消息的发送者 |
created_at | string | 消息创建时间 |
text | string | 默认文案。为subscribe或unsubscribe时为触发订阅的私信关键词(如“dy”),非私信触发时(点击订阅按钮)为“订阅事件消息”、“取消订阅事件消息”; |
data | string | 消息内容 |
data:subtype | string | subscribe订阅事件,unsubscribe订阅事件。 |
{
"type": "event",
"receiver_id": 1902538057,
"sender_id": 2489518277,
"created_at": "Mon Jul 16 18:09:20 +0800 2012",
"text": "订阅事件消息",
"data": {
"subtype": "subscribe"
}
}
③扫描带参数二维码事件
paramter | type | description |
---|---|---|
type | string | event |
receiver_id | int64 | 消息的接收者 |
sender_id | int64 | 消息的发送者 |
created_at | string | 消息创建时间 |
text | string | 默认文案。subtype为scan或scan_follow时为“扫描二维码”; |
data | string | 消息内容 |
data:subtype | string | scan和scan_follow为二维码扫描事件。 |
data:key | string | 事件KEY值,格式为action_name_scene_id,也就是说以action_name为前缀,后面为二维码的scene_id; |
data:ticket | string | 二维码的ticket,可用来换取二维码图片。 |
{
"type": "event",
"receiver_id": 1902538057,
"sender_id": 2489518277,
"created_at": "Mon Jul 16 18:09:20 +0800 2012",
"text": "扫描二维码",
"data": {
"subtype": "scan_follow",
"key": "action_name_scene_id",
"ticket": "TICKET",
}
}
④被@消息 (需申请)
指定的认证用户需被授予接收“被@消息”权限,此接口才返回“被@消息”,申请可邮件 jingyi7@staff.weibo.com
paramter | type | description |
---|---|---|
type | string | mention |
receiver_id | int64 | 消息的接收者 |
sender_id | int64 | 消息的发送者 |
created_at | string | 消息创建时间 |
text | string | 被@的微博或评论文本信息 |
data | string | 消息内容 |
data:subtype | string | status:@的微博,comment:@的评论 |
data:key | string | 当subtype为status时为微博ID,为comment时为评论ID |
{
"type": "mention",
"receiver_id": 1902538057,
"sender_id": 2489518277,
"created_at": "Mon Jul 16 18:09:20 +0800 2012",
"text": "被@的微博或评论文本信息",
"data": {
"subtype": "MENTION_TYPE",
"key": "MENTION_KEY"
}
}
// 默认仅返回可信用户的@,如需返回所有用户@,认证用户可访问此链接设置:http://account.weibo.com/set/message
⑤点击菜单拉取消息时的事件推送(记录)
paramter | type | description |
---|---|---|
type | string | event |
receiver_id | int64 | 消息的接收者 |
sender_id | int64 | 消息的发送者 |
created_at | string | 消息创建时间 |
text | string | 默认文案,subtype为click时为 “自定义菜单点击事件消息”; |
data | string | 消息内容 |
data:subtype | string | click, 自定义菜单点击事件 |
data:key | string | 被点击的自定义菜单的key值 |
{
"type": "event",
"receiver_id": 1902538057,
"sender_id": 2489518277,
"created_at": "Mon Jul 16 18:09:20 +0800 2012",
"text": "自定义菜单点击事件消息",
"data": {
"subtype": "click",
"key": "EVENT_KEY"
}
}
⑥点击菜单跳转链接时的事件推送(记录)
paramter | type | description |
---|---|---|
type | string | event |
receiver_id | int64 | 消息的接收者 |
sender_id | int64 | 消息的发送者 |
created_at | string | 消息创建时间 |
text | string | 默认文案,subtype为view时为 “自定义菜单跳转链接事件消息”; |
data | string | 消息内容 |
data:subtype | string | view, 自定义菜单跳转链接事件消息 |
data:key | string | 该按钮设置的url |
{
"type": "event",
"receiver_id": 1902538057,
"sender_id": 2489518277,
"created_at": "Mon Jul 16 18:09:20 +0800 2012",
"text": "自定义菜单跳转链接事件消息",
"data": {
"subtype": "view",
"key": "url"
}
}