短信上行 API
通过配置 Webhook,您可以实时接收终端用户发送至您号码的回复内容,即 短信上行 (MO)。本文档详细介绍了如何配置 Webhook URL、解析负载参数,并提供了多种语言的接收处理示例,助您快速实现与用户的双向短信互动。
1. Webhook 配置与说明
Webhook 说明
- 请求方法 (HTTP Method):
GET - Webhook URL:您在 PaaSoo 控制台中预先配置的接收端点(由您提供并维护)。
- 触发时机:当 PaaSoo 接收到来自运营商的短信上行 (MO) 时,系统会立即向您的 Webhook URL 发起
GET请求,推送该条消息详情。 - 重试机制:如果您的服务器未正确返回
HTTP 200 OK,PaaSoo 将在 5 分钟、10 分钟、30 分钟 后分别尝试重新推送。
2. Webhook 请求示例
当上行消息产生后,PaaSoo 平台会以如下形式调用您的 Webhook URL:
GET https://USER_CALLBACK_URL?type=mo&messageid=015bd4-d6dfa7-58w&to=8618912345678&from=1234&text=Hello+World
3. 请求参数
在收到的 GET 请求中,URL Query 包含以下参数:
| 参数 | 类型 | 描述 | 示例 |
|---|---|---|---|
| type | string | 消息类型。短信上行 (MO) 固定为 mo。 | mo |
| messageid | string | 短信 ID,该条上行消息的全局唯一标识符。 | 015bd4-d6dfa7-58w |
| to | string | 上行号码,通常为您在 PaaSoo 平台申请的虚拟号码。 | 10691234 |
| from | string | 终端用户的手机号码。 | 8618912345678 |
| text | string | 短信正文内容。 | Hello World |
4. 接收与处理示例
以下示例展示了如何在服务端接收并处理 Webhook 推送。在实际应用中,请将监听的 URL 修改为您在 PaaSoo 平台配置的 USER_CALLBACK_URL 对应路径,并根据实际业务增加安全校验(如 IP白名单、签名校验等)和入库逻辑。
以下代码假设您的 Webhook URL 为:https://example.com/mo-callback。
- Python
- Node.js
- PHP
- Java
- Go
import requests
# 您的 Webhook URL
url = "https://example.com/mo-callback"
# 模拟接收到的短信上行 (MO) 查询参数
params = {
"type": "mo", # 消息类型,固定为 mo
"messageid": "015bd4-d6dfa7-58w", # 短信 ID (全局唯一)
"to": "10691234", # 上行号码
"from": "8618912345678", # 终端用户的手机号码
"text": "Hello World" # 短信正文内容
}
try:
# 模拟平台向您的 Webhook 发送 HTTP GET 请求
response = requests.get(url, params=params)
response.raise_for_status()
print(f"Webhook 模拟成功。服务器响应状态码: {response.status_code}")
print(f"响应体: {response.text}")
except requests.exceptions.RequestException as e:
print(f"模拟失败: {e}")
const axios = require('axios'); // 运行: npm install axios
// 您的 Webhook URL
const url = 'https://example.com/mo-callback';
// 模拟接收到的短信上行 (MO) 查询参数
const params = {
type: 'mo', // 消息类型,固定为 mo
messageid: '015bd4-d6dfa7-58w', // 短信 ID (全局唯一)
to: '10691234', // 上行号码
from: '8618912345678', // 终端用户的手机号码
text: 'Hello World', // 短信正文内容
};
// 模拟平台向您的 Webhook 发送 HTTP GET 请求
axios.get(url, { params })
.then((response) => {
console.log(`Webhook 模拟成功。服务器响应状态码: ${response.status}`);
console.log(`响应体: ${response.data}`);
})
.catch((error) => {
console.error('模拟失败:', error.message || error);
});
<?php
// 您的 Webhook URL
$url = "https://example.com/mo-callback";
// 模拟接收到的短信上行 (MO) 查询参数
$params = [
"type" => "mo", // 消息类型,固定为 mo
"messageid" => "015bd4-d6dfa7-58w", // 短信 ID (全局唯一)
"to" => "10691234", // 上行号码
"from" => "8618912345678", // 终端用户的手机号码
"text" => "Hello World" // 短信正文内容
];
// 构建查询字符串并附加到 URL
$queryString = http_build_query($params);
$requestUrl = $url . '?' . $queryString;
// 初始化 cURL 会话以模拟 Webhook 请求
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $requestUrl);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
// 执行请求
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if($e = curl_error($ch)) {
echo "模拟失败: " . $e;
} else {
echo "Webhook 模拟成功。服务器响应状态码: " . $httpCode . "\n";
echo "响应体: " . $response . "\n";
}
// 关闭 cURL 会话
curl_close($ch);
?>
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.HttpUrl;
import java.io.IOException;
// 确保在您的 pom.xml 或 build.gradle 中添加了 OkHttp 依赖
public class MoWebhookSimulation {
public static void main(String[] args) {
OkHttpClient client = new OkHttpClient();
// 构建带有查询参数的 Webhook URL
HttpUrl.Builder urlBuilder = HttpUrl.parse("https://example.com/mo-callback").newBuilder();
urlBuilder.addQueryParameter("type", "mo"); // 消息类型,固定为 mo
urlBuilder.addQueryParameter("messageid", "015bd4-d6dfa7-58w"); // 短信 ID (全局唯一)
urlBuilder.addQueryParameter("to", "10691234"); // 上行号码
urlBuilder.addQueryParameter("from", "8618912345678"); // 终端用户的手机号码
urlBuilder.addQueryParameter("text", "Hello World"); // 短信正文内容
String url = urlBuilder.build().toString();
// 构建请求
Request request = new Request.Builder()
.url(url)
.get()
.build();
// 执行请求以模拟平台 Webhook
try (Response response = client.newCall(request).execute()) {
System.out.println("服务器响应状态码: " + response.code());
if (response.body() != null) {
System.out.println("响应体: " + response.body().string());
}
} catch (IOException e) {
System.err.println("模拟失败: " + e.getMessage());
}
}
}
package main
import (
"fmt"
"io/ioutil"
"net/http"
"net/url"
)
func main() {
// 您的 Webhook URL
baseURL, err := url.Parse("https://example.com/mo-callback")
if err != nil {
fmt.Println("解析 URL 出错:", err)
return
}
// 添加模拟接收到的短信上行 (MO) 查询参数
params := url.Values{}
params.Add("type", "mo") // 消息类型,固定为 mo
params.Add("messageid", "015bd4-d6dfa7-58w") // 短信 ID (全局唯一)
params.Add("to", "10691234") // 上行号码
params.Add("from", "8618912345678") // 终端用户的手机号码
params.Add("text", "Hello World") // 短信正文内容
// 编码参数并附加到 URL
baseURL.RawQuery = params.Encode()
// 模拟平台向您的 Webhook 发送 HTTP GET 请求
resp, err := http.Get(baseURL.String())
if err != nil {
fmt.Println("模拟失败:", err)
return
}
defer resp.Body.Close()
// 读取响应体
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
fmt.Println("读取响应出错:", err)
return
}
fmt.Printf("Webhook 模拟成功。服务器响应状态码: %d\n", resp.StatusCode)
fmt.Printf("响应体: %s\n", string(body))
}
5. 响应要求与重试策略
- 成功响应:您的服务器在成功接收并处理请求后,必须返回
HTTP 200 OK或类似的 2xx 成功状态码,以向 PaaSoo 确认该条回调已被正确接收。 - 重试机制:如果 PaaSoo 未接收到有效的 2xx 响应(如服务器超时或返回 4xx/5xx),系统会在 5 分钟、10 分钟、30 分钟间隔时各重试推送一次。若仍未收到
HTTP 200,系统将放弃后续重试。
6. 安全与最佳实践
- 数据传输安全:
- 强烈建议您的 Webhook URL 采用 HTTPS 协议进行加密,以保障短信内容在传输过程中的安全性。
- 访问控制:
- 建议在您的服务器或网关配置 IP白名单,仅放行来自 PaaSoo 官方服务器 IP 段的请求,防止恶意探测与伪造调用。
- 幂等性设计:
- 由于网络抖动或重试机制的存在,您的服务器可能会多次接收到同一条短信上行 (MO)。请务必使用
messageid(短信 ID)作为唯一标识符实现数据库插入或业务逻辑的去重处理(幂等性)。
- 由于网络抖动或重试机制的存在,您的服务器可能会多次接收到同一条短信上行 (MO)。请务必使用
技术支持
如在 API 对接过程中遇到任何技术问题或业务疑问,欢迎随时联系我们的开发者支持团队:support@paasoo.com。我们将竭诚为您提供技术协助。