Skip to content

私信接口

类说明

Message 类提供私信消息功能,包括发送消息、获取会话列表、查看聊天记录、拉黑管理等。

功能特点:

  • 支持发送和接收私信
  • 会话列表按最后消息时间排序
  • 自动标记已读
  • 首条消息限制(对方未回复前只能发一条)
  • 频率限制(1分钟最多5条)
  • 黑名单功能
  • CSRF保护(状态变更接口)

安全机制:

  • 不能给自己发消息
  • 不能给拉黑的人发消息
  • 被拉黑后无法发送消息
  • 所有状态变更接口需要CSRF验证

发送私信

Method : POST

URL : /wp-json/vtheme/v1/messages/send

Auth required : True

Headers :

  • Authorization: Bearer
  • Content-Type: application/json

Body :

json
{
  "receiver_id": 5,
  "content": "你好,这是一条测试消息"
}

参数说明:

  • receiver_id : [integer] 接收者用户ID
  • content : [string] 消息内容

Success Response

Code : 200 OK

Content example :

json
{
  "success": true,
  "message": "发送成功",
  "id": 123,
  "sender_id": 1,
  "receiver_id": 5,
  "content": "你好,这是一条测试消息",
  "created_at": "2023-01-01 12:00:00"
}

Error Response

Code : 400 Bad Request

Content examples :

json
{
  "error": "参数不完整"
}
json
{
  "error": "不能给自己发消息"
}

Code : 401 Unauthorized

Content example :

json
{
  "error": "401"
}

Code : 403 Forbidden

Content examples :

json
{
  "error": "您已被对方拉黑,无法发送消息"
}
json
{
  "error": "您已拉黑该用户,请先取消拉黑"
}
json
{
  "error": "对方尚未回复,您只能发送一条消息"
}

Code : 404 Not Found

Content example :

json
{
  "error": "用户不存在"
}

Code : 429 Too Many Requests

Content example :

json
{
  "error": "发送过于频繁,请稍后再试"
}

Code : 500 Internal Server Error

Content example :

json
{
  "error": "发送失败"
}

获取会话列表

Method : GET

URL : /wp-json/vtheme/v1/messages/conversations

Auth required : True

Headers :

  • Authorization: Bearer

Query Parameters :

  • page : [integer] 页码,默认1
  • per_page : [integer] 每页数量,默认20(范围1-100)

Success Response

Code : 200 OK

Content example :

json
[
  {
    "conversation_id": "1_5",
    "unread_count": 3,
    "other_user": {
      "id": 5,
      "display_name": "张三",
      "avatar_url": "http://example.com/avatar.jpg"
    },
    "last_message": {
      "id": 123,
      "content": "最近怎么样?",
      "sender_id": 5,
      "created_at": "2023-01-01 12:00:00",
      "is_read": 0
    }
  },
  {
    "conversation_id": "1_8",
    "unread_count": 0,
    "other_user": {
      "id": 8,
      "display_name": "李四",
      "avatar_url": "http://example.com/avatar2.jpg"
    },
    "last_message": {
      "id": 120,
      "content": "好的,谢谢",
      "sender_id": 1,
      "created_at": "2023-01-01 11:00:00",
      "is_read": 1
    }
  }
]

返回字段说明:

  • conversation_id : 会话ID(格式:小ID_大ID)
  • unread_count : 未读消息数
  • other_user : 对话的另一方用户信息
  • last_message : 最后一条消息

获取会话详情(聊天记录)

Method : GET

URL : /wp-json/vtheme/v1/messages/conversation/{user_id}

Auth required : True

URL Parameters :

  • user_id : [integer] 对话用户ID

Headers :

  • Authorization: Bearer

Query Parameters :

  • page : [integer] 页码,默认1
  • per_page : [integer] 每页数量,默认50(范围1-100)

Success Response

Code : 200 OK

Content example :

json
{
  "messages": [
    {
      "id": 1,
      "sender_id": 1,
      "receiver_id": 5,
      "content": "你好",
      "is_read": 1,
      "created_at": "2023-01-01 10:00:00"
    },
    {
      "id": 2,
      "sender_id": 5,
      "receiver_id": 1,
      "content": "你好啊",
      "is_read": 1,
      "created_at": "2023-01-01 10:05:00"
    }
  ],
  "pagination": {
    "current_page": 1,
    "total_pages": 2,
    "total_count": 75
  }
}

注意:

  • 消息按时间升序排列(旧到新)
  • 访问时会自动标记该会话中接收的消息为已读

获取未读消息总数

Method : GET

URL : /wp-json/vtheme/v1/messages/unread-count

Auth required : True

Headers :

  • Authorization: Bearer

Success Response

Code : 200 OK

Content example :

json
{
  "unread_count": 5
}

拉黑用户

Method : POST

URL : /wp-json/vtheme/v1/messages/block

Auth required : True

Headers :

  • Authorization: Bearer
  • X-WP-Nonce:
  • Content-Type: application/json

Body :

json
{
  "user_id": 5
}

参数说明:

  • user_id : [integer] 要拉黑的用户ID

Success Response

Code : 200 OK

Content example :

json
{
  "success": true,
  "message": "已拉黑该用户"
}

注意: 此接口具有幂等性,重复拉黑同一用户不会报错

Error Response

Code : 400 Bad Request

Content examples :

json
{
  "error": "用户ID无效"
}
json
{
  "error": "不能拉黑自己"
}

Code : 401 Unauthorized

Content example :

json
{
  "error": "401"
}

Code : 403 Forbidden (CSRF验证失败)

Content example :

json
{
  "code": "invalid_nonce",
  "message": "CSRF verification failed",
  "data": {
    "status": 403
  }
}

Code : 500 Internal Server Error

Content example :

json
{
  "error": "操作失败"
}

取消拉黑

Method : DELETE

URL : /wp-json/vtheme/v1/messages/block/{user_id}

Auth required : True

URL Parameters :

  • user_id : [integer] 要取消拉黑的用户ID

Headers :

  • Authorization: Bearer

Success Response

Code : 200 OK

Content example :

json
{
  "success": true,
  "message": "已取消拉黑"
}

Error Response

Code : 400 Bad Request

Content example :

json
{
  "error": "用户ID无效"
}

Code : 401 Unauthorized

Content example :

json
{
  "error": "401"
}

Code : 500 Internal Server Error

Content example :

json
{
  "error": "操作失败"
}

获取黑名单列表

Method : GET

URL : /wp-json/vtheme/v1/messages/blocks

Auth required : True

Headers :

  • Authorization: Bearer

Query Parameters :

  • page : [integer] 页码,默认1
  • per_page : [integer] 每页数量,默认20(范围1-100)

Success Response

Code : 200 OK

Content example :

json
[
  {
    "id": 1,
    "created_at": "2023-01-01 12:00:00",
    "blocked_user": {
      "id": 5,
      "display_name": "张三",
      "avatar_url": "http://example.com/avatar.jpg"
    }
  },
  {
    "id": 2,
    "created_at": "2023-01-02 12:00:00",
    "blocked_user": {
      "id": 8,
      "display_name": "李四",
      "avatar_url": "http://example.com/avatar2.jpg"
    }
  }
]

使用示例

发送消息

javascript
// 发送消息
function sendMessage(receiverId, content) {
  fetch('/wp-json/vtheme/v1/messages/send', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'Authorization': 'Bearer ' + ajax_object.wp_rest_nonce
    },
    body: JSON.stringify({
      receiver_id: receiverId,
      content: content
    })
  })
  .then(response => response.json())
  .then(data => {
    if (data.success) {
      console.log('发送成功');
      // 将消息添加到聊天界面
      appendMessage(data);
      // 清空输入框
      document.getElementById('message-input').value = '';
    }
  })
  .catch(error => {
    console.error('发送失败:', error);
    alert('发送失败,请稍后重试');
  });
}

// 绑定发送按钮
document.getElementById('send-btn').addEventListener('click', () => {
  const content = document.getElementById('message-input').value.trim();
  const receiverId = document.getElementById('chat-container').dataset.userId;
  
  if (content) {
    sendMessage(receiverId, content);
  }
});

// 支持回车发送
document.getElementById('message-input').addEventListener('keypress', (e) => {
  if (e.key === 'Enter' && !e.shiftKey) {
    e.preventDefault();
    document.getElementById('send-btn').click();
  }
});

获取会话列表

javascript
// 获取会话列表
function getConversations(page = 1) {
  fetch(`/wp-json/vtheme/v1/messages/conversations?page=${page}&per_page=20`, {
    headers: {
      'Authorization': 'Bearer ' + ajax_object.wp_rest_nonce
    }
  })
  .then(response => response.json())
  .then(data => {
    // 渲染会话列表
    renderConversationList(data);
  });
}

// 渲染会话列表
function renderConversationList(conversations) {
  const container = document.getElementById('conversation-list');
  container.innerHTML = conversations.map(conv => `
    <div class="conversation-item" data-user-id="${conv.other_user.id}">
      <img src="${conv.other_user.avatar_url}" alt="${conv.other_user.display_name}">
      <div class="conversation-info">
        <div class="conversation-name">${conv.other_user.display_name}</div>
        <div class="last-message">${conv.last_message.content}</div>
      </div>
      ${conv.unread_count > 0 ? `<span class="unread-badge">${conv.unread_count}</span>` : ''}
    </div>
  `).join('');
}

获取聊天记录

javascript
// 获取聊天记录
function getConversation(userId, page = 1) {
  fetch(`/wp-json/vtheme/v1/messages/conversation/${userId}?page=${page}&per_page=50`, {
    headers: {
      'Authorization': 'Bearer ' + ajax_object.wp_rest_nonce
    }
  })
  .then(response => response.json())
  .then(data => {
    // 渲染消息列表
    renderMessages(data.messages);
    
    // 如果有更多,可以加载
    if (data.pagination.current_page < data.pagination.total_pages) {
      console.log('还有更多消息');
    }
  });
}

// 渲染消息
function renderMessages(messages) {
  const container = document.getElementById('message-list');
  const currentUserId = ajax_object.current_user_id;
  
  container.innerHTML = messages.map(msg => `
    <div class="message ${msg.sender_id == currentUserId ? 'sent' : 'received'}">
      <div class="message-content">${msg.content}</div>
      <div class="message-time">${formatTime(msg.created_at)}</div>
    </div>
  `).join('');
  
  // 滚动到底部
  container.scrollTop = container.scrollHeight;
}

实时更新未读数

javascript
// 定时获取未读消息数
function updateUnreadCount() {
  fetch('/wp-json/vtheme/v1/messages/unread-count', {
    headers: {
      'Authorization': 'Bearer ' + ajax_object.wp_rest_nonce
    }
  })
  .then(response => response.json())
  .then(data => {
    const badge = document.getElementById('unread-badge');
    if (data.unread_count > 0) {
      badge.textContent = data.unread_count;
      badge.style.display = 'block';
    } else {
      badge.style.display = 'none';
    }
  });
}

// 每30秒更新一次
setInterval(updateUnreadCount, 30000);

拉黑/取消拉黑

javascript
// 拉黑用户
function blockUser(userId) {
  if (!confirm('确定要拉黑该用户吗?拉黑后将无法收到对方的消息。')) {
    return;
  }
  
  fetch('/wp-json/vtheme/v1/messages/block', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'Authorization': 'Bearer ' + ajax_object.wp_rest_nonce,
      'X-WP-Nonce': ajax_object.wp_rest_nonce
    },
    body: JSON.stringify({
      user_id: userId
    })
  })
  .then(response => response.json())
  .then(data => {
    if (data.success) {
      alert('已拉黑该用户');
      // 刷新黑名单列表
      loadBlocks();
    }
  });
}

// 取消拉黑
function unblockUser(userId) {
  if (!confirm('确定要取消拉黑该用户吗?')) {
    return;
  }
  
  fetch(`/wp-json/vtheme/v1/messages/block/${userId}`, {
    method: 'DELETE',
    headers: {
      'Authorization': 'Bearer ' + ajax_object.wp_rest_nonce
    }
  })
  .then(response => response.json())
  .then(data => {
    if (data.success) {
      alert('已取消拉黑');
      // 从列表中移除
      removeBlockItem(userId);
    }
  });
}

// 获取黑名单列表
function loadBlocks(page = 1) {
  fetch(`/wp-json/vtheme/v1/messages/blocks?page=${page}&per_page=20`, {
    headers: {
      'Authorization': 'Bearer ' + ajax_object.wp_rest_nonce
    }
  })
  .then(response => response.json())
  .then(data => {
    renderBlocksList(data);
  });
}

注意事项

  1. 首条消息限制

    • 如果对方从未回复过,你只能发送一条消息
    • 这是为了防止骚扰
    • 对方回复后可以正常聊天
  2. 频率限制

    • 1分钟内最多发送5条消息
    • 超过限制会返回429错误
    • 建议前端做防抖处理
  3. 黑名单机制

    • 拉黑后双方无法互相发送消息
    • 拉黑操作具有幂等性
    • 取消拉黑后可以恢复正常通信
  4. 已读标记

    • 查看聊天记录时会自动标记为已读
    • 只标记接收的消息,不标记自己发送的
    • 会话列表会显示未读数量
  5. CSRF保护

    • 拉黑操作需要携带 X-WP-Nonce
    • Nonce 从 ajax_object.wp_rest_nonce 获取
    • 其他读取操作不需要Nonce
  6. 会话ID规则

    • 会话ID格式:小ID_大ID
    • 例如用户1和用户5的会话ID是 1_5
    • 确保双方看到的是同一个会话
  7. 消息排序

    • 会话列表按最后消息时间降序
    • 聊天记录按时间升序(旧到新)
    • 新消息应该追加到末尾
  8. 性能优化

    • 聊天记录建议分页加载
    • 可以实现无限滚动
    • 考虑缓存最近的会话