gsms

package module
v1.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 16, 2023 License: MIT Imports: 8 Imported by: 0

README

go report card Go.Dev reference Go package MIT License Contributors Forks Stargazers Issues

Gsms :calling:

:calling: 一款满足你的多种发送需求的短信发送组件,此项目参考 easy-sms 实现的 Go 版本

特点

  1. 支持目前市面多家服务商
  2. 一套写法兼容所有平台
  3. 简单配置即可灵活增减服务商
  4. 内置多种服务商轮询策略、支持自定义轮询策略
  5. 统一的返回值格式,便于日志与监控
  6. 自动轮询选择可用的服务商
  7. 更多等你去发现与改进...

平台支持

安装

go get -u github.com/maiqingqiang/gsms

使用

package main

import (
	"github.com/maiqingqiang/gsms"
	"github.com/maiqingqiang/gsms/gateways/aliyun"
	"github.com/maiqingqiang/gsms/gateways/yunpian"
	"github.com/maiqingqiang/gsms/message"
	"log"
)

func main() {
	client := gsms.New(
		[]gsms.Gateway{
			&yunpian.Gateway{
				ApiKey:    "ApiKey",
				Signature: "Signature",
			},
			&aliyun.Gateway{
				AccessKeyId:     "AccessKeyId",
				AccessKeySecret: "AccessKeySecret",
				SignName:        "SignName",
			},
		},
		gsms.WithGateways([]string{
			yunpian.NAME, aliyun.NAME,
		}),
	)

	results, err := client.Send(18888888888, &message.Message{
		Template: "5532044",
		Data: map[string]string{
			"code": "521410",
		},
	})

	if err != nil {
		log.Fatalf("发送失败 %+v", err)
	}

	log.Printf("发送成功 %+v", results)
}

短信内容

由于使用多网关发送,所以一条短信要支持多平台发送,每家的发送方式不一样,但是我们抽象定义了以下公用属性:

  • Content 文字内容,使用在像云片类似的以文字内容发送的平台
  • Template 模板 ID,使用在以模板ID来发送短信的平台
  • Data 模板变量,使用在以模板ID来发送短信的平台

所以,在使用过程中你可以根据所要使用的平台定义发送的内容。

client.Send(18888888888, &core.Message{
    Template: "SMS_00000001",
    Data: map[string]string{
        "code": "521410",
    },
})

client.Send(18888888888, &core.Message{
    Content: "您的验证码为: 6379",
})

闭包方式

client.Send(18888888888, &core.Message{
    Template: func(gateway core.GatewayInterface) string {
        if gateway.Name() == aliyun.NAME {
            return "SMS_271385117"
        }
        return "5532044"
    },
    Data: func(gateway core.GatewayInterface) map[string]string {
        if gateway.Name() == aliyun.NAME {
            return map[string]string{
                "code": "1111",
            }
        }
        return map[string]string{
            "code": "6379",
        }
    },
})

发送网关

client.Send(18888888888, &core.Message{
    Template: "5532044",
    Data: map[string]string{
        "code": "6379",
    },
}, yunpian.NAME, aliyun.NAME)

自定义网关

只需要实现 gsms.Gateway 接口即可,例如:

场景发送


var _ gsms.Message = (*OrderPaidMessage)(nil)

type OrderPaidMessage struct {
    OrderNo string
}

func (o *OrderPaidMessage) Gateways() ([]string, error) {
    return []string{yunpian.NAME}, nil
}

func (o *OrderPaidMessage) Strategy() (gsms.Strategy, error) {
    return nil, nil
}

func (o *OrderPaidMessage) GetContent(gateway gsms.Gateway) (string, error) {
    return fmt.Sprintf("您的订单:%s, 已经完成付款", o.OrderNo), nil
}

func (o *OrderPaidMessage) GetTemplate(gateway gsms.Gateway) (string, error) {
    return "5532044", nil
}

func (o *OrderPaidMessage) GetData(gateway gsms.Gateway) (map[string]string, error) {
    return map[string]string{
    "code": "6379",
    }, nil
}

func (o *OrderPaidMessage) GetType(gateway gsms.Gateway) (string, error) {
    return message.TextMessage, nil
}

client.Send(18888888888, &OrderPaidMessage{OrderNo: "1234"})

各平台配置说明

阿里云

短信内容使用 Template + Data

&aliyun.Gateway{
    AccessKeyId:     "AccessKeyId",
    AccessKeySecret: "AccessKeySecret",
    SignName:        "【默认签名】",
}

云片

短信内容使用 Content

&yunpian.Gateway{
    ApiKey:    "ApiKey",
    Signature: "【默认签名】", // 内容中无签名时使用
}

腾讯云 SMS

短信内容使用 Template + Data

&qcloud.Gateway{
    SdkAppId:  "",
    SecretId:  "",
    SecretKey: "",
    SignName:  "",
}

版权说明

该项目签署了 MIT 授权许可,详情请参阅 LICENSE

鸣谢

Documentation

Index

Constants

View Source
const StatusFailure = "failure"

StatusFailure send message failure.

View Source
const StatusSuccess = "success"

StatusSuccess send message success.

Variables

View Source
var (
	ErrInvalidIDDCode       = errors.New("invalid IDDCode")
	ErrGatewayNotFound      = errors.New("gateway not found")
	ErrMessageTypeError     = errors.New("message type error")
	ErrInvalidPhoneNumber   = errors.New("invalid phone number")
	ErrRequestDataTypeError = errors.New("request data type error")
)

Functions

func WithGateways

func WithGateways(gateways []string) func(*Gsms)

WithGateways set the gateways.

func WithStrategy

func WithStrategy(strategy Strategy) func(*Gsms)

WithStrategy set the strategy.

func WithTimeout

func WithTimeout(timeout time.Duration) func(*Gsms)

WithTimeout set the timeout.

Types

type Config

type Config struct {
	Timeout time.Duration
	Logger  Logger
}

Config gsms config.

type ErrGatewaysFailed

type ErrGatewaysFailed struct {
	Results []*Result
}

func NewErrGatewayFailed

func NewErrGatewayFailed(results []*Result) *ErrGatewaysFailed

func (*ErrGatewaysFailed) Error

func (e *ErrGatewaysFailed) Error() string

type ErrRequestFailed

type ErrRequestFailed struct {
	StatusCode int
	Body       string
	Message    string
}

func (*ErrRequestFailed) Error

func (e *ErrRequestFailed) Error() string

type Gateway

type Gateway interface {
	// Name Get gateway name
	Name() string
	// Send a short message
	Send(to *PhoneNumber, message Message, config *Config) error
}

type Gsms

type Gsms struct {
	// contains filtered or unexported fields
}

func New

func New(gateways []Gateway, options ...Option) *Gsms

New a gsms instance.

func (*Gsms) Debug

func (g *Gsms) Debug() *Gsms

Debug set logger level to info

func (*Gsms) Gateway

func (g *Gsms) Gateway(name string) (Gateway, error)

Gateway Get gateway by name

func (*Gsms) Send

func (g *Gsms) Send(to interface{}, message Message, gateways ...string) ([]*Result, error)

Send a message.

type LogLevel

type LogLevel int

LogLevel log level

const (
	// Silent silent log level
	Silent LogLevel = iota + 1
	// Error error log level
	Error
	// Warn warn log level
	Warn
	// Info info log level
	Info
)

type Logger

type Logger interface {
	LogMode(LogLevel) Logger
	Info(...interface{})
	Infof(string, ...interface{})
	Warn(...interface{})
	Warnf(string, ...interface{})
	Error(...interface{})
	Errorf(string, ...interface{})
}

func NewLogger

func NewLogger(opts ...zap.Option) Logger

type Message

type Message interface {
	// Gateways Supported gateways.
	Gateways() ([]string, error)
	// Strategy Message strategy.
	Strategy() (Strategy, error)
	// GetContent Get message content.
	GetContent(gateway Gateway) (string, error)
	// GetTemplate Get message template.
	GetTemplate(gateway Gateway) (string, error)
	// GetData Get message data.
	GetData(gateway Gateway) (map[string]string, error)
	// GetType Get message type.
	GetType(gateway Gateway) (string, error)
}

Message interface.

type Option

type Option func(*Gsms)

type PhoneNumber

type PhoneNumber struct {
	// contains filtered or unexported fields
}

func NewPhoneNumber

func NewPhoneNumber(numberWithoutIDDCode int, iddCode string) *PhoneNumber

func NewPhoneNumberWithoutIDDCode

func NewPhoneNumberWithoutIDDCode(numberWithoutIDDCode int) *PhoneNumber

func (*PhoneNumber) IDDCode

func (p *PhoneNumber) IDDCode() int

IDDCode e.g. 13800138000.

func (*PhoneNumber) InChineseMainland

func (p *PhoneNumber) InChineseMainland() bool

InChineseMainland Check if the phone number belongs to chinese mainland.

func (*PhoneNumber) Number

func (p *PhoneNumber) Number() int

Number e.g. 86.

func (*PhoneNumber) PrefixedIDDCode

func (p *PhoneNumber) PrefixedIDDCode(prefix string) string

PrefixedIDDCode e.g. + -> +86

func (*PhoneNumber) String

func (p *PhoneNumber) String() string

func (*PhoneNumber) UniversalNumber

func (p *PhoneNumber) UniversalNumber() string

UniversalNumber e.g. +8613800138000.

func (*PhoneNumber) ZeroPrefixedNumber

func (p *PhoneNumber) ZeroPrefixedNumber() string

ZeroPrefixedNumber e.g. 008613800138000.

type Result

type Result struct {
	Gateway  string
	Status   string
	Template string
	Error    error
}

Result Gateway send message result.

func (*Result) String

func (r *Result) String() string

type Strategy

type Strategy interface {
	// Apply the strategy and return result.
	Apply(gateways []string) []string
}

Directories

Path Synopsis
gateways

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL