template-monorepo/internal/model/notification/provider/sms/mitake_sender.go

89 lines
2.1 KiB
Go
Raw Permalink Normal View History

package sms
import (
"context"
"fmt"
"net/http"
"github.com/minchao/go-mitake"
)
// MitakeSettings configures 三竹 Mitake SMS (ported from app-cloudep-notification-service).
type MitakeSettings struct {
Sort int
User string
Password string
}
// MitakeSender delivers SMS via Mitake SmExpress API.
type MitakeSender struct {
name string
sort int
client *mitake.Client
}
// NewMitakeSender builds a Mitake provider.
func NewMitakeSender(cfg MitakeSettings, httpClient *http.Client) (*MitakeSender, error) {
if cfg.User == "" || cfg.Password == "" {
return nil, fmt.Errorf("sms mitake: user and password are required")
}
return &MitakeSender{
name: "mitake",
sort: cfg.Sort,
client: mitake.NewClient(cfg.User, cfg.Password, httpClient),
}, nil
}
func (m *MitakeSender) Name() string { return m.name }
func (m *MitakeSender) Sort() int { return m.sort }
func (m *MitakeSender) Send(ctx context.Context, msg *Message) (string, error) {
if err := ctx.Err(); err != nil {
return "", err
}
if msg == nil || msg.PhoneNumber == "" {
return "", fmt.Errorf("sms mitake: phone number is required")
}
if msg.Body == "" {
return "", fmt.Errorf("sms mitake: body is required")
}
// SDK has no context support; check before the HTTP call.
if err := ctx.Err(); err != nil {
return "", err
}
resp, err := m.client.Send(mitake.Message{
Dstaddr: msg.PhoneNumber,
Destname: msg.RecipientName,
Smbody: msg.Body,
})
if err != nil {
return "", fmt.Errorf("sms mitake: %w", err)
}
if resp == nil || len(resp.Results) == 0 {
return "", fmt.Errorf("sms mitake: empty response")
}
r := resp.Results[0]
if err := mitakeStatusError(r.Statuscode); err != nil {
return "", err
}
if r.Msgid == "" {
return "", fmt.Errorf("sms mitake: empty msgid")
}
return r.Msgid, nil
}
func mitakeStatusError(code string) error {
switch mitake.StatusCode(code) {
case mitake.StatusReservationForDelivery,
mitake.StatusCarrierAccepted,
mitake.StatusCarrierAccepted2,
mitake.StatusCarrierAccepted3,
mitake.StatusDelivered:
return nil
default:
return fmt.Errorf("sms mitake: status %s (%s)", code, mitake.StatusCode(code).String())
}
}