Files

207 lines
5.8 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# iotlcm-sms
独立短信 HTTP/gRPC 服务,支持阿里云和腾讯云短信。
## 启动
```bash
go mod tidy
go run .
```
默认监听 `:8080`,可通过 `HTTP_ADDR` 修改:
```bash
HTTP_ADDR=:9090 go run .
```
gRPC 默认监听 `:11200`,可通过 `GRPC_ADDR` 修改。HTTP 与 gRPC 使用同一套短信发送实现。
## 默认供应商配置
短信服务自身持有全局凭证与签名,调用方只需传模板 ID 和短信内容。默认配置按下面的顺序合并:
```text
config.yaml 默认值 → SMS_* 环境变量覆盖 → 调用方请求中显式提供的字段优先
```
配置文件查找顺序:`SMS_CONFIG_FILE` 指定路径 → `./config.yaml` → `./config/config.yaml` → `/app/config/config.yaml`。
```yaml
# config.yaml(真实凭证只放服务器,不要提交 Git)
serviceType: "1" # 1=阿里云,2=腾讯云
regionId: cn-hangzhou
accessKeyId: ""
accessKeySecret: ""
signName: "示例企业"
```
可用环境变量覆盖:`SMS_SERVICE_TYPE`、`SMS_REGION_ID`、`SMS_ACCESS_KEY_ID`、
`SMS_ACCESS_KEY_SECRET`、`SMS_SDK_APP_ID`、`SMS_SIGN_NAME`、`SMS_TEMPLATE_ID`。
仓库内提供 `config.example.yaml` 作为模板;`.gitignore` 已排除真实 `config.yaml`。
启动日志会打印实际加载的配置来源(`file=... env=...`),便于排查。
## 场景模板配置库(可选)
除全局凭证外,还支持按业务场景(scene)从数据库回填模板与签名:调用方只传 `scene`
和内容参数,无需关心具体模板 ID。连接参数与凭证同放 `config.yaml`:
```yaml
# 场景模板配置库(表 t_sms_template_config);DSN 留空或省略 = 关闭该能力
sceneDbDsn: "user:pass@tcp(127.0.0.1:3306)/db_iotlcm?charset=utf8mb4&parseTime=true&loc=Local"
sceneDbCacheTtl: 60s # 场景配置内存缓存时长,"改库即生效"的最长延迟
```
可用环境变量覆盖:`SMS_DB_DSN`、`SMS_DB_CONFIG_CACHE_TTL`。DSN 未配置时,
带 `scene` 的请求返回 400(`短信场景未配置或已停用`)。
生产环境使用 `deploy/docker-compose.yml` 容器化部署,HTTP 端口为 `11190`,
gRPC 端口为 `11200`。
```bash
docker build --platform linux/amd64 -f build/Dockerfile \
-t <your-registry>/iotlcm-sms:latest .
docker push <your-registry>/iotlcm-sms:latest
cd deploy
# 先在服务器放置真实 config.yaml(不入库)
docker compose pull
docker compose up -d
```
生产部署建议通过 `IOTLCM_SMS_IMAGE` 指定不可变版本标签:
```bash
IOTLCM_SMS_IMAGE=<your-registry>/iotlcm-sms:<commit> docker compose up -d
```
健康检查:
```bash
curl http://127.0.0.1:8080/healthz
```
## 发送短信
接口:`POST /api/v1/sms/send`
阿里云请求示例:
```bash
curl -X POST http://127.0.0.1:8080/api/v1/sms/send \
-H 'Content-Type: application/json' \
-d '{
"config": {
"serviceType": "1",
"regionId": "cn-hangzhou",
"accessKeyId": "your-access-key-id",
"accessKeySecret": "your-access-key-secret",
"signName": "your-sign-name",
"templateId": "SMS_000000001"
},
"params": {
"phoneNumber": "13800008000",
"msgContent": "{\"code\":\"123456\"}"
}
}'
```
腾讯云请求示例:
```bash
curl -X POST http://127.0.0.1:8080/api/v1/sms/send \
-H 'Content-Type: application/json' \
-d '{
"config": {
"serviceType": "2",
"sdkAppId": "1400000000",
"accessKeyId": "your-secret-id",
"accessKeySecret": "your-secret-key",
"signName": "your-sign-name",
"templateId": "000000"
},
"params": {
"phoneNumber": "+8613800138000",
"msgContent": "123456|5"
}
}'
```
`serviceType` 为 `1` 时使用阿里云,`msgContent` 应为模板参数 JSON。`serviceType` 为 `2` 时使用腾讯云,多个模板参数继续沿用原项目的 `|` 分隔格式。多个手机号使用英文逗号分隔,腾讯云号码应使用 E.164 格式。
成功响应:
```json
{
"code": 0,
"message": "发送成功",
"data": {
"provider": "aliyun",
"requestId": "provider-request-id"
}
}
```
参数错误返回 HTTP 400,上游短信平台调用失败返回 HTTP 502。响应体中的 `code` 同步表示业务结果。
## 测试实例
运行不访问真实短信平台的 HTTP 接口测试:
```bash
go test ./...
```
运行示例客户端(先启动服务并替换示例中的测试凭证):
```bash
go run ./examples/http_client
```
也可以传入其他服务地址:
```bash
go run ./examples/http_client http://127.0.0.1:9090/api/v1/sms/send
```
## gRPC 接口
迁移后的接口保持原服务 protobuf 兼容:
```text
PbNotice.Notice/Send
```
请求中的 `config` 和 `params` 是 JSON 编码的 bytes,字段内容与 HTTP 接口一致。
响应结果放在 `head.code` 和 `head.message` 中;`routerId`、`traceId` 会原样返回。
protobuf 源文件位于 `proto`,生成的客户端和服务端代码位于 `api/pb`。
使用 Go 示例客户端发送请求:
```bash
go run ./examples/grpc_client examples/requests/aliyun.local.json
go run ./examples/grpc_client examples/requests/tencent.local.json 127.0.0.1:11200
```
服务注册了 gRPC reflection,可查看线上接口:
```bash
grpcurl -plaintext 127.0.0.1:11200 list
grpcurl -plaintext 127.0.0.1:11200 describe PbNotice.Notice
```
已保存的 HTTP 请求示例位于 `examples/requests`。其中 `aliyun.json` 和
`tencent.json` 使用环境变量占位符,可用于文档和版本管理;同目录的
`*.local.json` 是包含本机测试凭证的可直接重放请求,已被 `.gitignore` 排除。
```bash
curl -X POST http://127.0.0.1:8080/api/v1/sms/send \
-H 'Content-Type: application/json' \
--data-binary @examples/requests/aliyun.local.json
curl -X POST http://127.0.0.1:8080/api/v1/sms/send \
-H 'Content-Type: application/json' \
--data-binary @examples/requests/tencent.local.json
```