89 lines
2.1 KiB
Go
89 lines
2.1 KiB
Go
|
|
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())
|
||
|
|
}
|
||
|
|
}
|