更新2.1.2版本,优化部门、角色权限,增加上下级关系;增加登录、系统、短信日志;优化省市区编码

This commit is contained in:
孟帅
2023-01-25 11:49:21 +08:00
parent 11fad0132d
commit 93e0fe7250
190 changed files with 35896 additions and 7208 deletions

View File

@@ -11,34 +11,53 @@ import (
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/text/gstr"
"github.com/mojocn/base64Captcha"
"image/color"
)
// GetVerifyImgString 生成验证码
func GetVerifyImgString(ctx context.Context) (idKeyC string, base64stringC string) {
driver := &base64Captcha.DriverString{
Height: 80,
Width: 240,
//NoiseCount: 50,
//ShowLineOptions: 20,
Length: 4,
Source: "abcdefghjkmnpqrstuvwxyz23456789",
Fonts: []string{"chromohv.ttf"},
// Generate 生成验证码
func Generate(ctx context.Context) (id string, base64 string) {
// 字符
//driver := &base64Captcha.DriverString{
// Height: 42,
// Width: 100,
// //NoiseCount: 50,
// //ShowLineOptions: 20,
// Length: 4,
// BgColor: &color.RGBA{
// R: 255,
// G: 250,
// B: 250,
// A: 250,
// },
// Source: "0123456789", // abcdefghjkmnpqrstuvwxyz23456789
// Fonts: []string{"chromohv.ttf"},
//}
// 计算
driver := &base64Captcha.DriverMath{
Height: 42,
Width: 100,
NoiseCount: 0,
ShowLineOptions: 0,
BgColor: &color.RGBA{
R: 255,
G: 250,
B: 250,
A: 250,
},
Fonts: []string{"chromohv.ttf"},
}
driver = driver.ConvertFonts()
store := base64Captcha.DefaultMemStore
c := base64Captcha.NewCaptcha(driver, store)
idKeyC, base64stringC, err := c.Generate()
c := base64Captcha.NewCaptcha(driver.ConvertFonts(), base64Captcha.DefaultMemStore)
id, base64, err := c.Generate()
if err != nil {
g.Log().Error(ctx, err)
g.Log().Errorf(ctx, "captcha.Generate err:%+v", err)
}
return
}
// VerifyString 验证输入的验证码是否正确
func VerifyString(id, answer string) bool {
driver := new(base64Captcha.DriverString)
store := base64Captcha.DefaultMemStore
c := base64Captcha.NewCaptcha(driver, store)
answer = gstr.ToLower(answer)
return c.Verify(id, answer, true)
// Verify 验证输入的验证码是否正确
func Verify(id, answer string) bool {
c := base64Captcha.NewCaptcha(new(base64Captcha.DriverString), base64Captcha.DefaultMemStore)
return c.Verify(id, gstr.ToLower(answer), true)
}

View File

@@ -35,7 +35,7 @@ func SetUser(ctx context.Context, user *model.Identity) {
Get(ctx).User = user
}
// SetResponse 设置组件响应 用于全局日志使用
// SetResponse 设置组件响应 用于访问日志使用
func SetResponse(ctx context.Context, response *model.Response) {
Get(ctx).Response = response
}

View File

@@ -8,10 +8,53 @@ package views
import (
"context"
"fmt"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/text/gstr"
)
func (l *gCurd) webIndexTplData(ctx context.Context, in *CurdPreviewInput) (data g.Map, err error) {
data = make(g.Map)
return
const (
IndexApiImport = " import {%v } from '@/api/%s';"
IndexIconsImport = " import {%v } from '@vicons/antd';"
)
func (l *gCurd) webIndexTplData(ctx context.Context, in *CurdPreviewInput) (g.Map, error) {
var (
data = make(g.Map)
apiImport = []string{" List"}
iconsImport []string
)
// 添加
if in.options.Step.HasAdd {
iconsImport = append(iconsImport, " PlusOutlined")
}
// 编辑
if in.options.Step.HasEdit {
}
// 导出
if in.options.Step.HasExport {
iconsImport = append(iconsImport, " ExportOutlined")
apiImport = append(apiImport, " Export")
}
// 删除
if in.options.Step.HasDel || in.options.Step.HasBatchDel {
iconsImport = append(iconsImport, " DeleteOutlined")
apiImport = append(apiImport, " Delete")
}
// 导出
if in.options.Step.HasStatus {
apiImport = append(apiImport, " Status")
}
data["apiImport"] = fmt.Sprintf(IndexApiImport, gstr.Implode(",", apiImport), gstr.LcFirst(in.In.VarName))
if len(iconsImport) > 0 {
data["iconsImport"] = fmt.Sprintf(IndexIconsImport, gstr.Implode(",", iconsImport))
}
return data, nil
}

View File

@@ -259,10 +259,10 @@ func (l *gCurd) generateWebModelColumnsEach(buffer *bytes.Buffer, in *CurdPrevie
component = fmt.Sprintf(" {\n title: '%s',\n key: '%s',\n render(row) {\n if (isNullObject(row.%s) || !isArray(row.%s)) {\n return ``;\n }\n return row.%s.map((tagKey) => {\n return h(\n NTag,\n {\n style: {\n marginRight: '6px',\n },\n type: getOptionTag(options.value.%s, tagKey),\n bordered: false,\n },\n {\n default: () => getOptionLabel(options.value.%s, tagKey),\n }\n );\n });\n },\n },\n", field.Dc, field.TsName, field.TsName, field.TsName, field.TsName, in.options.dictMap[field.TsName], in.options.dictMap[field.TsName])
case FormModeUploadImage:
component = fmt.Sprintf(" {\n title: '%s',\n key: '%s',\n render(row) {\n return h(%s, {\n width: 32,\n height: 32,\n src: row.%s,\n style: {\n width: '32px',\n height: '32px',\n 'max-width': '100%%',\n 'max-height': '100%%',\n },\n });\n },\n },\n", field.Dc, field.TsName, "NImage", field.TsName)
component = fmt.Sprintf(" {\n title: '%s',\n key: '%s',\n render(row) {\n return h(%s, {\n width: 32,\n height: 32,\n src: row.%s,\n onError: errorImg,\n style: {\n width: '32px',\n height: '32px',\n 'max-width': '100%%',\n 'max-height': '100%%',\n },\n });\n },\n },\n", field.Dc, field.TsName, "NImage", field.TsName)
case FormModeUploadImages:
component = fmt.Sprintf(" {\n title: '%s',\n key: '%s',\n render(row) {\n if (isNullObject(row.%s)) {\n return ``;\n }\n return row.%s.map((image) => {\n return h(%s, {\n width: 32,\n height: 32,\n src: image,\n style: {\n width: '32px',\n height: '32px',\n 'max-width': '100%%',\n 'max-height': '100%%',\n 'margin-left': '2px',\n },\n });\n });\n },\n },\n", field.Dc, field.TsName, field.TsName, field.TsName, "NImage")
component = fmt.Sprintf(" {\n title: '%s',\n key: '%s',\n render(row) {\n if (isNullObject(row.%s)) {\n return ``;\n }\n return row.%s.map((image) => {\n return h(%s, {\n width: 32,\n height: 32,\n src: image,\n onError: errorImg,\n style: {\n width: '32px',\n height: '32px',\n 'max-width': '100%%',\n 'max-height': '100%%',\n 'margin-left': '2px',\n },\n });\n });\n },\n },\n", field.Dc, field.TsName, field.TsName, field.TsName, "NImage")
case FormModeUploadFile:
component = fmt.Sprintf(" {\n title: '%s',\n key: '%s',\n render(row) {\n if (row.%s === '') {\n return ``;\n }\n return h(\n %s,\n {\n size: 'small',\n },\n {\n default: () => getFileExt(row.%s),\n }\n );\n },\n },\n", field.Dc, field.TsName, field.TsName, "NAvatar", field.TsName)

View File

@@ -208,7 +208,7 @@ func IsUnique(ctx context.Context, dao interface{}, where g.Map, message string,
// GenSubTree 生成下级关系树
func GenSubTree(ctx context.Context, dao interface{}, oldPid int64) (newPid int64, newLevel int, subTree string, err error) {
// 顶级树
if oldPid == 0 {
if oldPid <= 0 {
return 0, 1, "", nil
}
@@ -221,7 +221,7 @@ func GenSubTree(ctx context.Context, dao interface{}, oldPid int64) (newPid int6
return 0, 0, "", err
}
models, err := d.Ctx(ctx).WhereNot(field, oldPid).One()
models, err := d.Ctx(ctx).Where(field, oldPid).One()
if err != nil {
return 0, 0, "", err
}

View File

@@ -15,6 +15,7 @@ import (
"hotgo/internal/consts"
"hotgo/internal/library/contexts"
"hotgo/internal/model/entity"
"hotgo/utility/tree"
)
// HandlerFilterAuth 过滤数据权限
@@ -23,7 +24,7 @@ func HandlerFilterAuth(m *gdb.Model) *gdb.Model {
var (
needAuth bool
filterField string
roleModel *entity.AdminRole
role *entity.AdminRole
ctx = m.GetCtx()
fields = escapeFieldsToSlice(m.GetFieldsStr())
co = contexts.Get(ctx)
@@ -48,34 +49,35 @@ func HandlerFilterAuth(m *gdb.Model) *gdb.Model {
return m
}
err := g.Model("admin_role").Where("id", co.User.RoleId).Scan(&roleModel)
err := g.Model("admin_role").Where("id", co.User.RoleId).Scan(&role)
if err != nil {
panic(fmt.Sprintf("HandlerFilterAuth Failed to role information err:%+v", err))
panic(fmt.Sprintf("failed to role information err:%+v", err))
}
if roleModel == nil {
panic(fmt.Sprintf("HandlerFilterAuth Failed to role information err2:%+v", err))
if role == nil {
panic("failed to role information roleModel == nil")
}
// TODO 当前不是完整功能,预计在下个版本中完善
switch roleModel.DataScope {
sq := g.Model("admin_member").Fields("id")
switch role.DataScope {
case consts.RoleDataAll: // 全部权限
// ...
case consts.RoleDataNowDept: // 当前部门
m = m.Where(filterField, co.User.DeptId)
m = m.WhereIn(filterField, sq.Where("dept_id", co.User.DeptId))
case consts.RoleDataDeptAndSub: // 当前部门及以下部门
//m = m.Where(filterField, 1)
m = m.WhereIn(filterField, sq.WhereIn("dept_id", GetDeptAndSub(co.User.DeptId)))
case consts.RoleDataDeptCustom: // 自定义部门
m = m.WhereIn(filterField, roleModel.CustomDept.Var().Ints())
m = m.WhereIn(filterField, sq.WhereIn("dept_id", role.CustomDept.Var().Ints()))
case consts.RoleDataSelf: // 仅自己
m = m.Where(filterField, co.User.Id)
case consts.RoleDataSelfAndSub: // 自己和直属下级
//m = m.Where(filterField, 1)
m = m.WhereIn(filterField, GetSelfAndSub(co.User.Id))
case consts.RoleDataSelfAndAllSub: // 自己和全部下级
//m = m.Where(filterField, 1)
m = m.WhereIn(filterField, GetSelfAndAllSub(co.User.Id))
default:
panic("HandlerFilterAuth dataScope is not registered")
panic("dataScope is not registered")
}
return m
@@ -90,3 +92,57 @@ func HandlerForceCache(m *gdb.Model) *gdb.Model {
func escapeFieldsToSlice(s string) []string {
return gstr.Explode(",", gstr.Replace(gstr.Replace(s, "`,`", ","), "`", ""))
}
// GetDeptAndSub 获取指定部门的所有下级,含本部门
func GetDeptAndSub(deptId int64) (ids []int64) {
array, err := g.Model("admin_dept").
WhereLike("tree", "%"+tree.GetIdLabel(deptId)+"%").
Fields("id").
Array()
if err != nil {
return
}
for _, v := range array {
ids = append(ids, v.Int64())
}
ids = append(ids, deptId)
return
}
// GetSelfAndSub 获取直属下级,包含自己
func GetSelfAndSub(memberId int64) (ids []int64) {
array, err := g.Model("admin_member").
Where("pid", memberId).
Fields("id").
Array()
if err != nil {
return
}
for _, v := range array {
ids = append(ids, v.Int64())
}
ids = append(ids, memberId)
return
}
// GetSelfAndAllSub 获取全部下级,包含自己
func GetSelfAndAllSub(memberId int64) (ids []int64) {
array, err := g.Model("admin_member").
WhereLike("tree", "%"+tree.GetIdLabel(memberId)+"%").
Fields("id").
Array()
if err != nil {
return
}
for _, v := range array {
ids = append(ids, v.Int64())
}
ids = append(ids, memberId)
return
}

View File

@@ -23,7 +23,7 @@ import (
)
// GenerateLoginToken 为指定用户生成token
func GenerateLoginToken(ctx context.Context, user *model.Identity, isRefresh bool) (interface{}, error) {
func GenerateLoginToken(ctx context.Context, user *model.Identity, isRefresh bool) (string, error) {
var (
jwtVersion = g.Cfg().MustGet(ctx, "jwt.version", "1.0")
jwtSign = g.Cfg().MustGet(ctx, "jwt.sign", "hotGo")
@@ -51,7 +51,7 @@ func GenerateLoginToken(ctx context.Context, user *model.Identity, isRefresh boo
tokenString, err := token.SignedString(jwtSign.Bytes())
if err != nil {
return nil, gerror.New(err.Error())
return "", err
}
var (
@@ -65,12 +65,12 @@ func GenerateLoginToken(ctx context.Context, user *model.Identity, isRefresh boo
err = c.Set(ctx, key, tokenString, expires)
if err != nil {
return nil, gerror.New(err.Error())
return "", err
}
err = c.Set(ctx, consts.RedisJwtUserBind+user.App+":"+gconv.String(user.Id), key, expires)
if err != nil {
return nil, gerror.New(err.Error())
return "", err
}
return tokenString, err
}

View File

@@ -144,6 +144,11 @@ func GetPublicIP(ctx context.Context) (ip string, err error) {
g.Log().Warningf(ctx, "GetPublicIP alternatives are being tried err:%+v", err)
return GetPublicIP2()
}
if data == nil {
g.Log().Warningf(ctx, "publicIP address Parsing failure, check the network and firewall blocking.")
return "0.0.0.0", nil
}
return data.Ip, nil
}
@@ -190,5 +195,10 @@ func GetClientIp(r *ghttp.Request) string {
if ip == "" {
ip = r.GetClientIp()
}
// 如果存在多个,默认取第一个
if gstr.Contains(ip, ",") {
ip = gstr.TrimStr(ip, ",", -1)
}
return ip
}

View File

@@ -93,7 +93,7 @@ func InstanceProducer() (mqClient MqProducer, err error) {
return NewProducer(config.GroupName)
}
// NewProducer 新建一个生产者实例
// NewProducer 初始化生产者实例
func NewProducer(groupName string) (mqClient MqProducer, err error) {
if item, ok := mqProducerInstanceMap[groupName]; ok {
return item, nil
@@ -143,7 +143,7 @@ func NewProducer(groupName string) (mqClient MqProducer, err error) {
return mqClient, nil
}
// NewConsumer 新建一个消费者实例
// NewConsumer 初始化消费者实例
func NewConsumer(groupName string) (mqClient MqConsumer, err error) {
randTag := string(charset.RandomCreateBytes(6))

View File

@@ -87,30 +87,28 @@ func (r *KafkaMq) ListenReceiveMsgDo(topic string, receiveDo func(mqMsg MqMsg))
}
ctx, cancel := context.WithCancel(context.Background())
go func() {
go func(ctx context.Context) {
for {
if err := r.consumerIns.Consume(ctx, []string{topic}, &consumer); err != nil {
FatalLog(ctx, "kafka Error from consumer", err)
g.Log().Fatalf(ctx, "kafka Error from consumer, err%+v", err)
}
if ctx.Err() != nil {
Log(ctx, fmt.Sprintf("kafka consoumer stop : %v", ctx.Err()))
g.Log().Debugf(ctx, fmt.Sprintf("kafka consoumer stop : %v", ctx.Err()))
return
}
consumer.ready = make(chan bool)
}
}()
}(ctx)
<-consumer.ready // Await till the consumer has been set up
Log(ctx, "kafka consumer up and running!...")
g.Log().Debug(ctx, "kafka consumer up and running!...")
signal.AppDefer(func() {
Log(ctx, "kafka consumer close...")
g.Log().Debug(ctx, "kafka consumer close...")
cancel()
if err = r.consumerIns.Close(); err != nil {
FatalLog(ctx, "kafka Error closing client", err)
g.Log().Fatalf(ctx, "kafka Error closing client, err:%+v", err)
}
})
@@ -193,7 +191,7 @@ func RegisterKafkaProducer(connOpt KafkaConfig, mqIns *KafkaMq) {
}
signal.AppDefer(func() {
Log(ctx, "kafka producer AsyncClose...")
g.Log().Debug(ctx, "kafka producer AsyncClose...")
mqIns.producerIns.AsyncClose()
})
}

View File

@@ -10,33 +10,28 @@ import (
"context"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/util/gconv"
"hotgo/internal/consts"
"hotgo/utility/charset"
)
const (
ConsumerLogErrFormat = "消费 [%s] 失败, mqMsgId:%+v, mqMsgData:%+v, err:%+v, stack:%+v"
ProducerLogErrFormat = "生产 [%s] 失败, data:%+v, err:%+v, stack:%+v"
)
// ConsumerLog 消费日志
func ConsumerLog(ctx context.Context, topic string, mqMsg MqMsg, err error) {
if err != nil {
g.Log(consts.QueueLogPath).Error(ctx, "消费 ["+topic+"] 失败", mqMsg, err)
g.Log().Printf(ctx, ConsumerLogErrFormat, topic, mqMsg.MsgId, mqMsg.BodyString(), err, charset.ParseErrStack(err))
} else {
g.Log(consts.QueueLogPath).Debug(ctx, "消费 ["+topic+"] 成功", mqMsg.MsgId)
g.Log().Print(ctx, "消费 ["+topic+"] 成功", mqMsg.MsgId)
}
}
// ProducerLog 生产日志
func ProducerLog(ctx context.Context, topic string, data interface{}, err error) {
if err != nil {
g.Log(consts.QueueLogPath).Error(ctx, "生产 ["+topic+"] 失败", gconv.String(data))
g.Log().Printf(ctx, ProducerLogErrFormat, topic, gconv.String(data), err, charset.ParseErrStack(err))
} else {
g.Log(consts.QueueLogPath).Debug(ctx, "生产 ["+topic+"] 成功", gconv.String(data))
g.Log().Print(ctx, "生产 ["+topic+"] 成功", gconv.String(data))
}
}
// FatalLog 致命日志
func FatalLog(ctx context.Context, text string, err error) {
g.Log(consts.QueueLogPath).Fatal(ctx, text+":", err)
}
// Log 通用日志
func Log(ctx context.Context, text string) {
g.Log(consts.QueueLogPath).Debug(ctx, text)
}

View File

@@ -0,0 +1,18 @@
package queue
import (
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/util/gconv"
)
// Push 推送队列
func Push(topic string, data interface{}) (err error) {
q, err := InstanceProducer()
if err != nil {
g.Log().Fatalf(ctx, "queue.InstanceProducer err:%+v", err)
return err
}
mqMsg, err := q.SendMsg(topic, gconv.String(data))
ProducerLog(ctx, topic, mqMsg.MsgId, err)
return err
}

View File

@@ -7,7 +7,6 @@ import (
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/frame/g"
"github.com/gomodule/redigo/redis"
"hotgo/internal/consts"
"hotgo/utility/encrypt"
"math/rand"
"time"
@@ -113,7 +112,7 @@ func (r *RedisMq) ListenReceiveMsgDo(topic string, receiveDo func(mqMsg MqMsg))
// 生成队列名称
func (r *RedisMq) genQueueName(groupName string, topic string) string {
return fmt.Sprintf(consts.QueueName+"%s_%s", groupName, topic)
return fmt.Sprintf("queue:%s_%s", groupName, topic)
}
func (r *RedisMq) loopReadQueue(queueName string) (mqMsgList []MqMsg) {

View File

@@ -26,8 +26,8 @@ type RocketMq struct {
// rewriteLog 重写日志
func rewriteLog() {
level := g.Cfg().MustGet(ctx, "queue.rocketmq.logLevel", "debug")
rlog.SetLogger(&RocketMqLogger{Flag: "[rocket_mq]", LevelLog: level.String()})
level := g.Cfg().MustGet(ctx, "queue.rocketmq.logLevel", "debug").String()
rlog.SetLogger(&RocketMqLogger{Flag: "[rocket_mq]", LevelLog: level})
}
// RegisterRocketProducerMust 注册并启动生产者接口实现

View File

@@ -7,7 +7,7 @@
package queue
import (
"fmt"
"github.com/gogf/gf/v2/frame/g"
)
type RocketMqLogger struct {
@@ -24,16 +24,16 @@ func (l *RocketMqLogger) Debug(msg string, fields map[string]interface{}) {
}
if l.LevelLog == "debug" || l.LevelLog == "all" {
Log(ctx, fmt.Sprint(l.Flag, " [debug] ", msg))
g.Log().Debug(ctx, msg)
}
}
func (l *RocketMqLogger) Level(level string) {
Log(ctx, fmt.Sprint(l.Flag, " [level] ", level))
g.Log().Info(ctx, level)
}
func (l *RocketMqLogger) OutputPath(path string) (err error) {
Log(ctx, fmt.Sprint(l.Flag, " [path] ", path))
g.Log().Info(ctx, path)
return nil
}
@@ -46,7 +46,7 @@ func (l *RocketMqLogger) Info(msg string, fields map[string]interface{}) {
}
if l.LevelLog == "info" || l.LevelLog == "all" {
Log(ctx, fmt.Sprint(l.Flag, " [info] ", msg))
g.Log().Info(ctx, msg)
}
}
@@ -59,7 +59,7 @@ func (l *RocketMqLogger) Warning(msg string, fields map[string]interface{}) {
}
if l.LevelLog == "warn" || l.LevelLog == "all" {
Log(ctx, fmt.Sprint(l.Flag, " [warn] ", msg))
g.Log().Warning(ctx, msg)
}
}
@@ -71,7 +71,7 @@ func (l *RocketMqLogger) Error(msg string, fields map[string]interface{}) {
return
}
if l.LevelLog == "error" || l.LevelLog == "all" {
Log(ctx, fmt.Sprint(l.Flag, " [error] ", msg))
g.Log().Error(ctx, msg)
}
}
@@ -84,6 +84,6 @@ func (l *RocketMqLogger) Fatal(msg string, fields map[string]interface{}) {
}
if l.LevelLog == "fatal" || l.LevelLog == "all" {
Log(ctx, fmt.Sprint(l.Flag, " [fatal] ", msg))
g.Log().Fatal(ctx, msg)
}
}

View File

@@ -0,0 +1,112 @@
package aliyun
import (
"context"
"fmt"
openapi "github.com/alibabacloud-go/darabonba-openapi/v2/client"
dysmsapi20170525 "github.com/alibabacloud-go/dysmsapi-20170525/v3/client"
util "github.com/alibabacloud-go/tea-utils/v2/service"
"github.com/alibabacloud-go/tea/tea"
"hotgo/internal/model"
"hotgo/internal/model/input/sysin"
"hotgo/internal/service"
)
// SendCode 发送验证码
func SendCode(ctx context.Context, in sysin.SendCodeInp, config *model.SmsConfig) (err error) {
if config == nil {
config, err = service.SysConfig().GetSms(ctx)
if err != nil {
return err
}
}
client, err := CreateClient(tea.String(config.SmsAliyunAccessKeyID), tea.String(config.SmsAliyunAccessKeySecret))
if err != nil {
return err
}
sendSmsRequest := &dysmsapi20170525.SendSmsRequest{
PhoneNumbers: tea.String(in.Mobile),
SignName: tea.String(config.SmsAliyunSign),
TemplateCode: tea.String(in.Template),
TemplateParam: tea.String(fmt.Sprintf("{\"code\":\"%v\"}", in.Code)),
}
tryErr := func() (_e error) {
defer func() {
if r := tea.Recover(recover()); r != nil {
_e = r
}
}()
// 复制代码运行请自行打印 API 的返回值
_, err = client.SendSmsWithOptions(sendSmsRequest, &util.RuntimeOptions{})
if err != nil {
return err
}
return nil
}()
return tryErr
}
// CreateClient 使用AK&SK初始化账号Client
func CreateClient(accessKeyId *string, accessKeySecret *string) (_result *dysmsapi20170525.Client, _err error) {
config := &openapi.Config{
// 必填,您的 AccessKey ID
AccessKeyId: accessKeyId,
// 必填,您的 AccessKey Secret
AccessKeySecret: accessKeySecret,
}
// 访问的域名
config.Endpoint = tea.String("dysmsapi.aliyuncs.com")
_result = &dysmsapi20170525.Client{}
_result, _err = dysmsapi20170525.NewClient(config)
return _result, _err
}
func Send(accessKeyId string, accessKeySecret string) (_err error) {
// 工程代码泄露可能会导致AccessKey泄露并威胁账号下所有资源的安全性。以下代码示例仅供参考建议使用更安全的 STS 方式更多鉴权访问方式请参见https://help.aliyun.com/document_detail/378661.html
client, _err := CreateClient(tea.String(accessKeyId), tea.String(accessKeySecret))
if _err != nil {
return _err
}
sendSmsRequest := &dysmsapi20170525.SendSmsRequest{
PhoneNumbers: tea.String("15303830571"),
SignName: tea.String("布帆云"),
TemplateCode: tea.String("SMS_198921686"),
TemplateParam: tea.String("{\"code\":\"1234\"}"),
}
runtime := &util.RuntimeOptions{}
tryErr := func() (_e error) {
defer func() {
if r := tea.Recover(recover()); r != nil {
_e = r
}
}()
// 复制代码运行请自行打印 API 的返回值
_, _err = client.SendSmsWithOptions(sendSmsRequest, runtime)
if _err != nil {
return _err
}
return nil
}()
if tryErr != nil {
var err = &tea.SDKError{}
if _t, ok := tryErr.(*tea.SDKError); ok {
err = _t
} else {
err.Message = tea.String(tryErr.Error())
}
// 如有需要,请打印 error
_, _err = util.AssertAsString(err.Message)
if _err != nil {
return _err
}
}
return _err
}

View File

@@ -0,0 +1 @@
package aliyun

View File

@@ -0,0 +1 @@
package aliyun

View File

@@ -0,0 +1,2 @@
package sms