91 lines
2.7 KiB
Go

package sms
import (
"context"
"encoding/json"
"errors"
"fmt"
"strings"
openapi "github.com/alibabacloud-go/darabonba-openapi/v2/client"
dysmsapi20170525 "github.com/alibabacloud-go/dysmsapi-20170525/v3/client"
tea "github.com/alibabacloud-go/tea/tea"
)
// Config holds Aliyun SMS configuration.
type Config struct {
AccessKeyID string
AccessKeySecret string
SignName string
TemplateCode string
Endpoint string // default: dysmsapi.aliyuncs.com
}
type Client struct {
cfg Config
client *dysmsapi20170525.Client
}
// New creates an Aliyun SMS client. Does not send any request.
func New(cfg Config) (*Client, error) {
if strings.TrimSpace(cfg.AccessKeyID) == "" || strings.TrimSpace(cfg.AccessKeySecret) == "" {
return nil, errors.New("sms: access key not configured")
}
if strings.TrimSpace(cfg.SignName) == "" || strings.TrimSpace(cfg.TemplateCode) == "" {
return nil, errors.New("sms: signName/templateCode not configured")
}
if strings.TrimSpace(cfg.Endpoint) == "" {
cfg.Endpoint = "dysmsapi.aliyuncs.com"
}
oc := &openapi.Config{
AccessKeyId: tea.String(cfg.AccessKeyID),
AccessKeySecret: tea.String(cfg.AccessKeySecret),
Endpoint: tea.String(cfg.Endpoint),
}
cli, err := dysmsapi20170525.NewClient(oc)
if err != nil {
return nil, err
}
return &Client{cfg: cfg, client: cli}, nil
}
// TemplateData matches the Java version: time/name/content
type TemplateData struct {
Time string `json:"time"`
Name string `json:"name"`
Content string `json:"content"`
Alert string `json:"alert"`
}
// Send sends the template message to one or more phone numbers.
// name/content/alert/msgTime map to template ${name}, ${content}, ${alert}, ${time}.
func (c *Client) Send(ctx context.Context, name, content, alert, msgTime string, phones []string) error {
if len(phones) == 0 {
return errors.New("sms: empty phone list")
}
payload := TemplateData{Time: msgTime, Name: name, Content: content, Alert: alert}
b, _ := json.Marshal(payload)
param := string(b)
// Aliyun supports multiple comma-separated numbers, but keep batches small if needed.
joined := strings.Join(phones, ",")
req := &dysmsapi20170525.SendSmsRequest{
PhoneNumbers: tea.String(joined),
SignName: tea.String(c.cfg.SignName),
TemplateCode: tea.String(c.cfg.TemplateCode),
TemplateParam: tea.String(param),
}
// Execute request
resp, err := c.client.SendSms(req)
if err != nil {
return err
}
code := tea.StringValue(resp.Body.Code)
if strings.ToUpper(code) != "OK" {
return fmt.Errorf("sms: send failed code=%s message=%s requestId=%s", code, tea.StringValue(resp.Body.Message), tea.StringValue(resp.Body.RequestId))
}
return nil
}