commit 9ad229dbb7f8a64b7c3a3132e18713be08010d56 Author: Yun <995116474@qq.com> Date: Fri Nov 15 18:55:02 2024 +0800 初始化 diff --git a/aliyun/aliyun.go b/aliyun/aliyun.go new file mode 100644 index 0000000..59f25ae --- /dev/null +++ b/aliyun/aliyun.go @@ -0,0 +1,410 @@ +package aliyun + +import ( + "context" + "encoding/json" + "errors" + "fmt" + "regexp" + + "code.yun.ink/pkg/smsx/entity" + "code.yun.ink/pkg/smsx/interfaces" + openapi "github.com/alibabacloud-go/darabonba-openapi/v2/client" + dysmsapi20170525 "github.com/alibabacloud-go/dysmsapi-20170525/v4/client" + util "github.com/alibabacloud-go/tea-utils/v2/service" + "github.com/alibabacloud-go/tea/tea" + "github.com/yuninks/loggerx" +) + +type Aliyun struct { + interfaces.DefaultSmsx + client *dysmsapi20170525.Client + params entity.SmsConfigData + logger loggerx.LoggerInterface +} + +func (l *Aliyun) InitSmsx(ctx context.Context, params entity.SmsConfigData, logger loggerx.LoggerInterface) (interfaces.Smsx, error) { + l.logger = logger + if params.SysType != entity.Platform3rdTypeAliyun { + return nil, errors.New("not aliyun") + } + + config := &openapi.Config{ + // 必填,请确保代码运行环境设置了环境变量 ALIBABA_CLOUD_ACCESS_KEY_ID。 + AccessKeyId: tea.String(params.Aliyun.AccessKeyId), + // 必填,请确保代码运行环境设置了环境变量 ALIBABA_CLOUD_ACCESS_KEY_SECRET。 + AccessKeySecret: tea.String(params.Aliyun.AccessKeySecret), + } + // Endpoint 请参考 https://api.aliyun.com/product/Dysmsapi + if params.Aliyun.Endpoint == "" { + params.Aliyun.Endpoint = "dysmsapi.aliyuncs.com" + } + + config.Endpoint = tea.String(params.Aliyun.Endpoint) + // _result = &dysmsapi20170525.Client{} + _result, err := dysmsapi20170525.NewClient(config) + if err != nil { + return nil, err + } + + return &Aliyun{ + client: _result, + params: params, + logger: logger, + }, nil +} + +// Send 发送短信 +func (l *Aliyun) Send(ctx context.Context, templateCode string, phone string, params []interfaces.SmsSendParam) error { + if l.client == nil { + return errors.New("not init") + } + + l.logger.Infof(ctx, "Aliyun send templateId:%+v phone:%+v params:%+v", templateCode, phone, params) + + paramMap := map[string]string{} + for _, param := range params { + paramMap[param.Field] = param.Value + } + + b, _ := json.Marshal(paramMap) + + sendSmsRequest := &dysmsapi20170525.SendSmsRequest{ + SignName: tea.String(l.params.Aliyun.SignName), + TemplateCode: tea.String(templateCode), + PhoneNumbers: tea.String(phone), + TemplateParam: tea.String(string(b)), + } + + runtime := &util.RuntimeOptions{} + tryErr := func() (_e error) { + defer func() { + if r := tea.Recover(recover()); r != nil { + _e = r + } + }() + // 复制代码运行请自行打印 API 的返回值 + resp, _err := l.client.SendSmsWithOptions(sendSmsRequest, runtime) + l.logger.Infof(ctx, "Aliyun resp resp:%+v err:%+v", resp, _err) + if _err != nil { + return _err + } + + if resp == nil || resp.Body == nil { + return errors.New("未知响应") + } + + if *resp.Body.Code != "OK" { + return errors.New(tea.StringValue(resp.Body.Message)) + } + + // { + // "headers": { + // "access-control-allow-origin": "*", + // "access-control-expose-headers": "*", + // "connection": "keep-alive", + // "content-length": "133", + // "content-type": "application/json;charset=utf-8", + // "date": "Tue, 27 Aug 2024 10:37:25 GMT", + // "etag": "1YHcV2uF0Hw6v4+PJKSpMwA1", + // "keep-alive": "timeout=25", + // "x-acs-request-id": "B7CCDAD3-AA89-55ED-94F5-4C08D746399B", + // "x-acs-trace-id": "cef86cfb21d73f60869bbb9034794714" + // }, + // "statusCode": 200, + // "body": { + // "Code": "isv.SMS_SIGNATURE_ILLEGAL", + // "Message": "该账号下找不到对应签名", + // "RequestId": "B7CCDAD3-AA89-55ED-94F5-4C08D746399B" + // } + // } + + // { + // "headers": { + // "access-control-allow-origin": "*", + // "access-control-expose-headers": "*", + // "connection": "keep-alive", + // "content-length": "110", + // "content-type": "application/json;charset=utf-8", + // "date": "Tue, 27 Aug 2024 10:39:59 GMT", + // "etag": "19rMwUYhdQd2sDRXr2iLPLg0", + // "keep-alive": "timeout=25", + // "x-acs-request-id": "D8F5E530-57BD-5A6C-AE57-18AD67BDDF70", + // "x-acs-trace-id": "95bdbb6a3f64ca8f7da8d398410c1bfa" + // }, + // "statusCode": 200, + // "body": { + // "BizId": "181408424755199417^0", + // "Code": "OK", + // "Message": "OK", + // "RequestId": "D8F5E530-57BD-5A6C-AE57-18AD67BDDF70" + // } + // } + + return nil + }() + + if tryErr != nil { + + return tryErr + + // var error = &tea.SDKError{} + // if _t, ok := tryErr.(*tea.SDKError); ok { + // error = _t + // } else { + // error.Message = tea.String(tryErr.Error()) + // } + // // 此处仅做打印展示,请谨慎对待异常处理,在工程项目中切勿直接忽略异常。 + // // 错误 message + // fmt.Println(tea.StringValue(error.Message)) + // // 诊断地址 + // var data interface{} + // d := json.NewDecoder(strings.NewReader(tea.StringValue(error.Data))) + // d.Decode(&data) + // if m, ok := data.(map[string]interface{}); ok { + // recommend, _ := m["Recommend"] + // fmt.Println(recommend) + // } + // _, _err := util.AssertAsString(error.Message) + // if _err != nil { + // return _err + // } + } + + return nil +} + +// GetTemp 获取模板 +func (l *Aliyun) GetTemp(ctx context.Context) ([]interfaces.TemplateInfo, error) { + page := 0 + resp := []interfaces.TemplateInfo{} + + l.logger.Infof(ctx, "aliyun getTemp: start") + + for { + page++ + r, err := l.getTemp(ctx, int32(page)) + if err != nil { + l.logger.Errorf(ctx, "aliyun getTemp: err:%+v", err) + return nil, err + } + if len(r) == 0 { + break + } + resp = append(resp, r...) + } + return resp, nil + +} + +func (l *Aliyun) getTemp(ctx context.Context, page int32) ([]interfaces.TemplateInfo, error) { + if l.client == nil { + return nil, errors.New("not init") + } + + querySmsTemplateListRequest := &dysmsapi20170525.QuerySmsTemplateListRequest{ + PageIndex: tea.Int32(page), + PageSize: tea.Int32(20), + } + runtime := &util.RuntimeOptions{} + + resps := []interfaces.TemplateInfo{} + + tryErr := func() (_e error) { + defer func() { + if r := tea.Recover(recover()); r != nil { + l.logger.Errorf(ctx, "aliyun getTemp: err:%+v", r) + _e = r + } + }() + // 复制代码运行请自行打印 API 的返回值 + resp, _err := l.client.QuerySmsTemplateListWithOptions(querySmsTemplateListRequest, runtime) + if _err != nil { + l.logger.Errorf(ctx, "aliyun getTemp: err:%+v", _err) + return _err + } + + l.logger.Infof(ctx, "aliyun getTemp: resp:%+v err:%+v", resp, _err) + + if resp == nil || resp.Body == nil { + return fmt.Errorf("resp is nil") + } + + for _, val := range resp.Body.SmsTemplateList { + s := l.extractParams(tea.StringValue(val.TemplateContent)) + + params := []entity.SmsTemplateParam{} + for _, p := range s { + params = append(params, entity.SmsTemplateParam{ + FieldName: p, + }) + } + + resps = append(resps, interfaces.TemplateInfo{ + TempId: tea.StringValue(val.TemplateCode), + TempName: tea.StringValue(val.TemplateName), + TempType: l.tempTypePlatToLocal(tea.Int32Value(val.OuterTemplateType)), + TempRange: l.tempRangePlatToLocal(tea.Int32Value(val.OuterTemplateType)), + Content: tea.StringValue(val.TemplateContent), + Status: l.auditStatusPlatToLocal(tea.StringValue(val.AuditStatus)), + Params: params, + }) + } + + return nil + }() + + if tryErr != nil { + var error = &tea.SDKError{} + if _t, ok := tryErr.(*tea.SDKError); ok { + error = _t + } else { + error.Message = tea.String(tryErr.Error()) + } + return nil, error + + // 此处仅做打印展示,请谨慎对待异常处理,在工程项目中切勿直接忽略异常。 + // 错误 message + // fmt.Println(tea.StringValue(error.Message)) + // 诊断地址 + // var data interface{} + // d := json.NewDecoder(strings.NewReader(tea.StringValue(error.Data))) + // d.Decode(&data) + // if m, ok := data.(map[string]interface{}); ok { + // recommend, _ := m["Recommend"] + // fmt.Println(recommend) + // } + // _, _err := util.AssertAsString(error.Message) + // if _err != nil { + // return nil, _err + // } + } + + return resps, nil +} + +// TempDel 删除模板 +func (l *Aliyun) TempDel(ctx context.Context, templateId string) error { + if l.client == nil { + return errors.New("not init") + } + + deleteSmsTemplateRequest := &dysmsapi20170525.DeleteSmsTemplateRequest{ + TemplateCode: tea.String(templateId), + } + runtime := &util.RuntimeOptions{} + tryErr := func() (_e error) { + defer func() { + if r := tea.Recover(recover()); r != nil { + _e = r + } + }() + // 复制代码运行请自行打印 API 的返回值 + _, _err := l.client.DeleteSmsTemplateWithOptions(deleteSmsTemplateRequest, runtime) + if _err != nil { + return _err + } + + return nil + }() + + if tryErr != nil { + + return tryErr + + // var error = &tea.SDKError{} + // if _t, ok := tryErr.(*tea.SDKError); ok { + // error = _t + // } else { + // error.Message = tea.String(tryErr.Error()) + // } + // // 此处仅做打印展示,请谨慎对待异常处理,在工程项目中切勿直接忽略异常。 + // // 错误 message + // fmt.Println(tea.StringValue(error.Message)) + // // 诊断地址 + // var data interface{} + // d := json.NewDecoder(strings.NewReader(tea.StringValue(error.Data))) + // d.Decode(&data) + // if m, ok := data.(map[string]interface{}); ok { + // recommend, _ := m["Recommend"] + // fmt.Println(recommend) + // } + // _, _err := util.AssertAsString(error.Message) + // if _err != nil { + // return _err + // } + } + + return nil +} + +// 审核状态转换 短信平台=>本地 +func (l *Aliyun) auditStatusPlatToLocal(status string) entity.SmsTemplateStatus { + + // AUDIT_STATE_INIT:审核中。 + // AUDIT_STATE_PASS:通过审核。 + // AUDIT_STATE_NOT_PASS:未通过审核,请在返回参数 Reason 中查看审核未通过原因。 + // AUDIT_STATE_CANCEL:取消审核。 + // AUDIT_SATE_CANCEL:取消审核。 + + switch status { + case "AUDIT_STATE_INIT": + return entity.SmsTemplateStatusAudit + case "AUDIT_STATE_PASS": + return entity.SmsTemplateStatusPass + case "AUDIT_STATE_NOT_PASS": + return entity.SmsTemplateStatusUnPass + case "AUDIT_STATE_CANCEL": + return entity.SmsTemplateStatusCancel + case "AUDIT_SATE_CANCEL": + return entity.SmsTemplateStatusCancel + default: + return entity.SmsTemplateStatusUnknown + } +} + +func (l *Aliyun) tempTypePlatToLocal(platType int32) entity.SmsTemplateType { + // 0:验证码短信。 + // 1:通知短信。 + // 2:推广短信。 + // 3:国际/港澳台短信。 + // 7:数字短信。 + + switch platType { + case 0: + return entity.SmsTemplateTypeVerifyCode + case 1: + return entity.SmsTemplateTypeNotice + case 2: + return entity.SmsTemplateTypePromotion + case 3: + return entity.SmsTemplateTypeInternational + case 7: + return entity.SmsTemplateTypeDigital + default: + return entity.SmsTemplateTypeUnknown + } +} + +func (l *Aliyun) tempRangePlatToLocal(platType int32) entity.SmsTemplateRange { + // 非国际/港澳台短信。 + if platType == 3 { + return entity.SmsTemplateRangeInternational + } + return entity.SmsTemplateRangeChina +} + +// 提取参数 +func (l *Aliyun) extractParams(str string) []string { + // str := "订单尾号${dingdanhao}超过${shijian}分钟,系统已自动放行。交易完成,请登录查看账户变动。" + + re := regexp.MustCompile(`\$\{(.+?)\}`) + matches := re.FindAllStringSubmatch(str, -1) + + var keys []string + for _, match := range matches { + keys = append(keys, match[1]) + } + + return keys +} diff --git a/aliyun/aliyun_test.go b/aliyun/aliyun_test.go new file mode 100644 index 0000000..4c16669 --- /dev/null +++ b/aliyun/aliyun_test.go @@ -0,0 +1,70 @@ +package aliyun_test + +import ( + "context" + "testing" + + "code.yun.ink/pkg/smsx/aliyun" + "code.yun.ink/pkg/smsx/entity" + "code.yun.ink/pkg/smsx/interfaces" + "github.com/yuninks/loggerx" +) + +func TestSend(t *testing.T) { + ali := &aliyun.Aliyun{} + ctx := context.Background() + + logger := loggerx.NewLogger(ctx) + + params := entity.SmsConfigData{ + SysType: entity.Platform3rdTypeAliyun, + Aliyun: &entity.SmsConfigDataAliyun{ + AccessKeyId: "LTAI5tSgopmbntKXnq8ESrvh", + AccessKeySecret: "BEgEFCOh4eokzhg8EfxeETbSk4B2UJ", + SignName: "深圳展鸣科技", + }, + } + + nAli, err := ali.InitSmsx(ctx, params, logger) + if err != nil { + t.Fatal(err) + } + + err = nAli.Send(ctx, "SMS_465941403", "18819446148", []interfaces.SmsSendParam{ + {Field: "code", Value: "123456"}, + }) + if err != nil { + t.Fatal(err) + } + + t.Log("success") +} + +func TestGetTemp(t *testing.T) { + ali := &aliyun.Aliyun{} + ctx := context.Background() + + logger := loggerx.NewLogger(ctx) + + params := entity.SmsConfigData{ + SysType: entity.Platform3rdTypeAliyun, + Aliyun: &entity.SmsConfigDataAliyun{ + AccessKeyId: "LTAI5tSgopmbntKXnq8ESrvh", + AccessKeySecret: "BEgEFCOh4eokzhg8EfxeETbSk4B2UJ", + SignName: "深圳展鸣科技", + }, + } + + nAli, err := ali.InitSmsx(ctx, params, logger) + if err != nil { + t.Fatal(err) + } + + resp, err := nAli.GetTemp(ctx) + if err != nil { + t.Fatal(err) + } + + t.Log("resp=", resp) + +} diff --git a/entity/consts.go b/entity/consts.go new file mode 100644 index 0000000..becdbdd --- /dev/null +++ b/entity/consts.go @@ -0,0 +1,36 @@ +package entity + +// 第三方平台 +type Platform3rdType string + +func (s Platform3rdType) String() string { + return string(s) +} + +const( + Platform3rdTypeAliyun Platform3rdType = "ali" // 阿里云[短信、邮件] + Platform3rdTypeTencent Platform3rdType = "tencent" // 腾讯云[短信] +) + + +type SmsTemplateType int + +// 模板类型(0.未知类型 1.验证码 2.短信通知 3.推广短信 4.国际消息 5.数字短信 ) +const ( + SmsTemplateTypeUnknown SmsTemplateType = 0 // 未知类型 + SmsTemplateTypeVerifyCode SmsTemplateType = 1 // 验证码 + SmsTemplateTypeNotice SmsTemplateType = 2 // 通知短信 + SmsTemplateTypePromotion SmsTemplateType = 3 // 推广短信 + SmsTemplateTypeInternational SmsTemplateType = 4 // 国际消息 + SmsTemplateTypeDigital SmsTemplateType = 5 // 数字短信 +) + +type SmsTemplateRange int + +const ( + SmsTemplateRangeUnknown SmsTemplateRange = 0 // 未知类型 + SmsTemplateRangeGlobal SmsTemplateRange = 1 // 全球/通用场景 + SmsTemplateRangeChina SmsTemplateRange = 2 // 中国(仅中国大陆) + SmsTemplateRangeInternational SmsTemplateRange = 3 // 国际(除中国大陆外) +) + diff --git a/entity/params.go b/entity/params.go new file mode 100644 index 0000000..dd7b352 --- /dev/null +++ b/entity/params.go @@ -0,0 +1,30 @@ +package entity + +type SmsConfig struct { + SmsType Platform3rdType `json:"sms_type" gorm:"column:sms_type;not null;comment:短信类型(ali.阿里云 tencent.腾讯云 smsbao.短信宝)"` + Name string `json:"name" gorm:"column:name;not null;comment:平台名称"` + ConfigData SmsConfigData `json:"config_data" gorm:"column:config_data;serializer:json;not null;comment:配置数据JSON"` + Status int8 `json:"status" gorm:"column:status;default:1;comment:通道状态(1.开启 -1关闭)"` +} + +type SmsConfigData struct { + SysType Platform3rdType `json:"sys_type"` // 短信平台类型 + Aliyun *SmsConfigDataAliyun `json:"aliyun,omitempty"` // 阿里云短信平台参数 + Tencent *SmsConfigDataTencent `json:"tencent,omitempty"` // 腾讯云短信平台参数 +} + +type SmsConfigDataAliyun struct { + AccessKeyId string `json:"access_key_id"` // 阿里云短信平台access_key_id + AccessKeySecret string `json:"access_key_secret"` // 阿里云短信平台access_key_secret + SignName string `json:"sign_name"` // 阿里云短信平台签名 + Endpoint string `json:"endpoint"` // 选填 阿里云短信平台地址 +} + +type SmsConfigDataTencent struct { + SecretId string `json:"secret_id"` // 腾讯云短信平台secret_id + SecretKey string `json:"secret_key"` // 腾讯讯云短信平台secret_key + SignName string `json:"sign_name"` // 腾讯云短信平台签名 + SmsSdkAppId string `json:"sms_sdk_app_id"` // 腾讯云短信平台sdk_app_id + Endpoint string `json:"endpoint"` // 选填 腾讯云短信平台地址 + Region string `json:"region"` // 选填 腾讯云短信平台region +} diff --git a/entity/template.go b/entity/template.go new file mode 100644 index 0000000..50d22df --- /dev/null +++ b/entity/template.go @@ -0,0 +1,47 @@ +package entity + + +type SmsTemplate struct { + ConfigId int64 `json:"config_id" gorm:"column:config_id;not null;comment:短信配置ID"` + TempId string `json:"temp_id" gorm:"column:temp_id;not null;comment:第三方的模板ID"` + TempName string `json:"temp_name" gorm:"column:temp_name;not null;comment:第三方模版名称"` + TempType SmsTemplateType `json:"temp_type" gorm:"column:temp_type;not null;comment:模板类型(1.验证码 2.短信通知 3.推广短信 4.国际消息)"` + Content string `json:"content" gorm:"column:content;not null;comment:模版发送的值"` + TempStatus SmsTemplateStatus `json:"temp_status" gorm:"column:temp_status;not null;comment:模板的状态(1.通过审核 2.审核中)"` + Params []SmsTemplateParam `json:"params" gorm:"column:params;serializer:json;comment:模板的参数"` // json类型存储 + Remark string `json:"remark" gorm:"column:remark;type:varchar(1000);comment:备注"` // 备注 + ParamsStatus SmsTemplateParamStatus `json:"params_status" gorm:"column:params_status;default:2;comment:参数校验状态(1.正常 2.待校验)"` + DataType SmsTemplateDataType `json:"data_type" gorm:"column:data_type;not null;comment:数据类型(1.自动同步 2.手动加入)"` // 1: 自动同步 2: 手动加入 + TempRange SmsTemplateRange `json:"temp_range" gorm:"column:temp_range;default:0;comment:作用地区(0.未知地区 1.全球 2.仅中国大陆 3.国际及港澳台)"` // 0: 未知地区 1: 全球 2: 仅中国大陆 3: 国际及港��� +} + +type SmsTemplateParam struct { + FieldName string `json:"field_name" binding:"required"` // 第三方平台字段 + // FieldType consts.SmsFieldType `json:"field_type" binding:"required"` // 内部对应对应类型 +} + +type SmsTemplateStatus int8 + +// (0.未知状态 1.通过审核 2.审核中 3.未通过审核 4.取消审核) +const ( + SmsTemplateStatusUnknown SmsTemplateStatus = 0 + SmsTemplateStatusPass SmsTemplateStatus = 1 + SmsTemplateStatusAudit SmsTemplateStatus = 2 + SmsTemplateStatusUnPass SmsTemplateStatus = 3 + SmsTemplateStatusCancel SmsTemplateStatus = 4 +) + +type SmsTemplateParamStatus int8 + +const ( + SmsTemplateParamStatusNormal SmsTemplateParamStatus = 1 + SmsTemplateParamStatusWait SmsTemplateParamStatus = 2 +) + +type SmsTemplateDataType int8 + +const ( + SmsTemplateDataTypeAutoSync SmsTemplateDataType = 1 // 自动同步 + SmsTemplateDataTypeManual SmsTemplateDataType = 2 // 手动加入的模板,需要人工审核和加入到库中 +) + diff --git a/example/main.go b/example/main.go new file mode 100644 index 0000000..643d014 --- /dev/null +++ b/example/main.go @@ -0,0 +1,50 @@ +package main + +import ( + "context" + "fmt" + + "code.yun.ink/pkg/smsx" + "code.yun.ink/pkg/smsx/entity" + "code.yun.ink/pkg/smsx/interfaces" + "github.com/yuninks/loggerx" +) + +func main() { + ctx := context.Background() + + logger := loggerx.NewLogger(ctx) + sms, err := smsx.GetPlatform(ctx, entity.Platform3rdTypeTencent) + if err != nil { + fmt.Println(err) + return + } + + ini, err := sms.InitSmsx(ctx, entity.SmsConfigData{ + SysType: entity.Platform3rdTypeTencent, + Tencent: &entity.SmsConfigDataTencent{ + SecretId: "AKIDb2b8SefT8YjgUBk8N0XtANMSZWFqLiIp", + SecretKey: "QxqstqipqkTzfKqGVdgr3Merx0uvoU3R", + SignName: "深圳宏建源贸易", + SmsSdkAppId: "1400883795", + }, + }, logger) + if err != nil { + fmt.Println(err) + return + } + + err = ini.Send(ctx, "2060882", "+85267369217", []interfaces.SmsSendParam{ + { + Field: "1", + Value: "123456", + }, + }) + if err != nil { + fmt.Println(err) + return + } + + fmt.Println("success") + +} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..2accc21 --- /dev/null +++ b/go.mod @@ -0,0 +1,51 @@ +module code.yun.ink/pkg/smsx + +go 1.22.6 + +require ( + github.com/alibabacloud-go/darabonba-openapi/v2 v2.0.10 + github.com/alibabacloud-go/dysmsapi-20170525/v4 v4.1.0 + github.com/alibabacloud-go/tea v1.2.2 + github.com/alibabacloud-go/tea-utils/v2 v2.0.7 + github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1040 + github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/sms v1.0.1040 + github.com/yuninks/loggerx v1.0.12 +) + +require ( + github.com/alibabacloud-go/alibabacloud-gateway-spi v0.0.5 // indirect + github.com/alibabacloud-go/debug v1.0.1 // indirect + github.com/alibabacloud-go/endpoint-util v1.1.0 // indirect + github.com/alibabacloud-go/openapi-util v0.1.0 // indirect + github.com/alibabacloud-go/tea-utils v1.3.1 // indirect + github.com/alibabacloud-go/tea-xml v1.1.3 // indirect + github.com/aliyun/credentials-go v1.3.10 // indirect + github.com/bytedance/sonic v1.9.1 // indirect + github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect + github.com/clbanning/mxj/v2 v2.5.5 // indirect + github.com/gabriel-vasile/mimetype v1.4.2 // indirect + github.com/gin-contrib/sse v0.1.0 // indirect + github.com/gin-gonic/gin v1.9.1 // indirect + github.com/go-playground/locales v0.14.1 // indirect + github.com/go-playground/universal-translator v0.18.1 // indirect + github.com/go-playground/validator/v10 v10.14.0 // indirect + github.com/goccy/go-json v0.10.2 // indirect + github.com/json-iterator/go v1.1.12 // indirect + github.com/klauspost/cpuid/v2 v2.2.4 // indirect + github.com/leodido/go-urn v1.2.4 // indirect + github.com/mattn/go-isatty v0.0.19 // indirect + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/pelletier/go-toml/v2 v2.0.8 // indirect + github.com/tjfoc/gmsm v1.4.1 // indirect + github.com/twitchyliquid64/golang-asm v0.15.1 // indirect + github.com/ugorji/go/codec v1.2.11 // indirect + golang.org/x/arch v0.3.0 // indirect + golang.org/x/crypto v0.21.0 // indirect + golang.org/x/net v0.23.0 // indirect + golang.org/x/sys v0.18.0 // indirect + golang.org/x/text v0.14.0 // indirect + google.golang.org/protobuf v1.30.0 // indirect + gopkg.in/ini.v1 v1.67.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..9812f4f --- /dev/null +++ b/go.sum @@ -0,0 +1,294 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/alibabacloud-go/alibabacloud-gateway-pop v0.0.6 h1:eIf+iGJxdU4U9ypaUfbtOWCsZSbTb8AUHvyPrxu6mAA= +github.com/alibabacloud-go/alibabacloud-gateway-pop v0.0.6/go.mod h1:4EUIoxs/do24zMOGGqYVWgw0s9NtiylnJglOeEB5UJo= +github.com/alibabacloud-go/alibabacloud-gateway-spi v0.0.4/go.mod h1:sCavSAvdzOjul4cEqeVtvlSaSScfNsTQ+46HwlTL1hc= +github.com/alibabacloud-go/alibabacloud-gateway-spi v0.0.5 h1:zE8vH9C7JiZLNJJQ5OwjU9mSi4T9ef9u3BURT6LCLC8= +github.com/alibabacloud-go/alibabacloud-gateway-spi v0.0.5/go.mod h1:tWnyE9AjF8J8qqLk645oUmVUnFybApTQWklQmi5tY6g= +github.com/alibabacloud-go/darabonba-array v0.1.0 h1:vR8s7b1fWAQIjEjWnuF0JiKsCvclSRTfDzZHTYqfufY= +github.com/alibabacloud-go/darabonba-array v0.1.0/go.mod h1:BLKxr0brnggqOJPqT09DFJ8g3fsDshapUD3C3aOEFaI= +github.com/alibabacloud-go/darabonba-encode-util v0.0.2 h1:1uJGrbsGEVqWcWxrS9MyC2NG0Ax+GpOM5gtupki31XE= +github.com/alibabacloud-go/darabonba-encode-util v0.0.2/go.mod h1:JiW9higWHYXm7F4PKuMgEUETNZasrDM6vqVr/Can7H8= +github.com/alibabacloud-go/darabonba-map v0.0.2 h1:qvPnGB4+dJbJIxOOfawxzF3hzMnIpjmafa0qOTp6udc= +github.com/alibabacloud-go/darabonba-map v0.0.2/go.mod h1:28AJaX8FOE/ym8OUFWga+MtEzBunJwQGceGQlvaPGPc= +github.com/alibabacloud-go/darabonba-openapi/v2 v2.0.10 h1:GEYkMApgpKEVDn6z12DcH1EGYpDYRB8JxsazM4Rywak= +github.com/alibabacloud-go/darabonba-openapi/v2 v2.0.10/go.mod h1:26a14FGhZVELuz2cc2AolvW4RHmIO3/HRwsdHhaIPDE= +github.com/alibabacloud-go/darabonba-signature-util v0.0.7 h1:UzCnKvsjPFzApvODDNEYqBHMFt1w98wC7FOo0InLyxg= +github.com/alibabacloud-go/darabonba-signature-util v0.0.7/go.mod h1:oUzCYV2fcCH797xKdL6BDH8ADIHlzrtKVjeRtunBNTQ= +github.com/alibabacloud-go/darabonba-string v1.0.2 h1:E714wms5ibdzCqGeYJ9JCFywE5nDyvIXIIQbZVFkkqo= +github.com/alibabacloud-go/darabonba-string v1.0.2/go.mod h1:93cTfV3vuPhhEwGGpKKqhVW4jLe7tDpo3LUM0i0g6mA= +github.com/alibabacloud-go/debug v0.0.0-20190504072949-9472017b5c68/go.mod h1:6pb/Qy8c+lqua8cFpEy7g39NRRqOWc3rOwAy8m5Y2BY= +github.com/alibabacloud-go/debug v1.0.0/go.mod h1:8gfgZCCAC3+SCzjWtY053FrOcd4/qlH6IHTI4QyICOc= +github.com/alibabacloud-go/debug v1.0.1 h1:MsW9SmUtbb1Fnt3ieC6NNZi6aEwrXfDksD4QA6GSbPg= +github.com/alibabacloud-go/debug v1.0.1/go.mod h1:8gfgZCCAC3+SCzjWtY053FrOcd4/qlH6IHTI4QyICOc= +github.com/alibabacloud-go/dysmsapi-20170525/v4 v4.1.0 h1:DRd/m0TAVzmVoacUv4+C32HrpoehAPxe7Yi8jBwW5HY= +github.com/alibabacloud-go/dysmsapi-20170525/v4 v4.1.0/go.mod h1:XA0GIZV/FIFTuasWP6WlGolkSfH/t8J5eqxT2dHAFbE= +github.com/alibabacloud-go/endpoint-util v1.1.0 h1:r/4D3VSw888XGaeNpP994zDUaxdgTSHBbVfZlzf6b5Q= +github.com/alibabacloud-go/endpoint-util v1.1.0/go.mod h1:O5FuCALmCKs2Ff7JFJMudHs0I5EBgecXXxZRyswlEjE= +github.com/alibabacloud-go/openapi-util v0.1.0 h1:0z75cIULkDrdEhkLWgi9tnLe+KhAFE/r5Pb3312/eAY= +github.com/alibabacloud-go/openapi-util v0.1.0/go.mod h1:sQuElr4ywwFRlCCberQwKRFhRzIyG4QTP/P4y1CJ6Ws= +github.com/alibabacloud-go/tea v1.1.0/go.mod h1:IkGyUSX4Ba1V+k4pCtJUc6jDpZLFph9QMy2VUPTwukg= +github.com/alibabacloud-go/tea v1.1.7/go.mod h1:/tmnEaQMyb4Ky1/5D+SE1BAsa5zj/KeGOFfwYm3N/p4= +github.com/alibabacloud-go/tea v1.1.8/go.mod h1:/tmnEaQMyb4Ky1/5D+SE1BAsa5zj/KeGOFfwYm3N/p4= +github.com/alibabacloud-go/tea v1.1.11/go.mod h1:/tmnEaQMyb4Ky1/5D+SE1BAsa5zj/KeGOFfwYm3N/p4= +github.com/alibabacloud-go/tea v1.1.17/go.mod h1:nXxjm6CIFkBhwW4FQkNrolwbfon8Svy6cujmKFUq98A= +github.com/alibabacloud-go/tea v1.1.20/go.mod h1:nXxjm6CIFkBhwW4FQkNrolwbfon8Svy6cujmKFUq98A= +github.com/alibabacloud-go/tea v1.2.2 h1:aTsR6Rl3ANWPfqeQugPglfurloyBJY85eFy7Gc1+8oU= +github.com/alibabacloud-go/tea v1.2.2/go.mod h1:CF3vOzEMAG+bR4WOql8gc2G9H3EkH3ZLAQdpmpXMgwk= +github.com/alibabacloud-go/tea-utils v1.3.1 h1:iWQeRzRheqCMuiF3+XkfybB3kTgUXkXX+JMrqfLeB2I= +github.com/alibabacloud-go/tea-utils v1.3.1/go.mod h1:EI/o33aBfj3hETm4RLiAxF/ThQdSngxrpF8rKUDJjPE= +github.com/alibabacloud-go/tea-utils/v2 v2.0.5/go.mod h1:dL6vbUT35E4F4bFTHL845eUloqaerYBYPsdWR2/jhe4= +github.com/alibabacloud-go/tea-utils/v2 v2.0.6/go.mod h1:qxn986l+q33J5VkialKMqT/TTs3E+U9MJpd001iWQ9I= +github.com/alibabacloud-go/tea-utils/v2 v2.0.7 h1:WDx5qW3Xa5ZgJ1c8NfqJkF6w+AU5wB8835UdhPr6Ax0= +github.com/alibabacloud-go/tea-utils/v2 v2.0.7/go.mod h1:qxn986l+q33J5VkialKMqT/TTs3E+U9MJpd001iWQ9I= +github.com/alibabacloud-go/tea-xml v1.1.3 h1:7LYnm+JbOq2B+T/B0fHC4Ies4/FofC4zHzYtqw7dgt0= +github.com/alibabacloud-go/tea-xml v1.1.3/go.mod h1:Rq08vgCcCAjHyRi/M7xlHKUykZCEtyBy9+DPF6GgEu8= +github.com/aliyun/credentials-go v1.1.2/go.mod h1:ozcZaMR5kLM7pwtCMEpVmQ242suV6qTJya2bDq4X1Tw= +github.com/aliyun/credentials-go v1.3.1/go.mod h1:8jKYhQuDawt8x2+fusqa1Y6mPxemTsBEN04dgcAcYz0= +github.com/aliyun/credentials-go v1.3.6/go.mod h1:1LxUuX7L5YrZUWzBrRyk0SwSdH4OmPrib8NVePL3fxM= +github.com/aliyun/credentials-go v1.3.10 h1:45Xxrae/evfzQL9V10zL3xX31eqgLWEaIdCoPipOEQA= +github.com/aliyun/credentials-go v1.3.10/go.mod h1:Jm6d+xIgwJVLVWT561vy67ZRP4lPTQxMbEYRuT2Ti1U= +github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM= +github.com/bytedance/sonic v1.9.1 h1:6iJ6NqdoxCDr6mbY8h18oSO+cShGSMRGCEo7F2h0x8s= +github.com/bytedance/sonic v1.9.1/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY= +github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 h1:qSGYFH7+jGhDF8vLC+iwCD4WpbV1EBDSzWkJODFLams= +github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk= +github.com/clbanning/mxj/v2 v2.5.5 h1:oT81vUeEiQQ/DcHbzSytRngP6Ky9O+L+0Bw0zSJag9E= +github.com/clbanning/mxj/v2 v2.5.5/go.mod h1:hNiWqW14h+kc+MdF9C6/YoRfjEJoR3ou6tn/Qo+ve2s= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU= +github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA= +github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= +github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= +github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg= +github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU= +github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= +github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= +github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= +github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= +github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= +github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= +github.com/go-playground/validator/v10 v10.14.0 h1:vgvQWe3XCz3gIeFDm/HnTIbj6UGmg/+t63MyGU2n5js= +github.com/go-playground/validator/v10 v10.14.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU= +github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= +github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/gopherjs/gopherjs v0.0.0-20200217142428-fce0ec30dd00/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= +github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= +github.com/klauspost/cpuid/v2 v2.2.4 h1:acbojRNwl3o09bUq+yDCtZFc1aiwaAAxtcn8YkZXnvk= +github.com/klauspost/cpuid/v2 v2.2.4/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q= +github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4= +github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= +github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/pelletier/go-toml/v2 v2.0.8 h1:0ctb6s9mE31h0/lhu+J6OPmVeDxJn+kYnJc2jZR9tGQ= +github.com/pelletier/go-toml/v2 v2.0.8/go.mod h1:vuYfssBdrU2XDZ9bYydBu6t+6a6PYNcZljzZR9VXg+4= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= +github.com/smartystreets/assertions v1.1.0/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYlVhC/LOxJk7iOWnoo= +github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY= +github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1040 h1:GPxMtHVIHUCmLQwYDJaD+r5fJDWEK8kLQila3+PgpMU= +github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1040/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0= +github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/sms v1.0.1040 h1:+WnLW3zhWFPSIZgtNRZFdY4nNTkj3/eB8EnDSKudSkI= +github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/sms v1.0.1040/go.mod h1:n3q/N5fA+GQRNzMqybNqYukXpD8REJWx9emEFjFXEUQ= +github.com/tjfoc/gmsm v1.3.2/go.mod h1:HaUcFuY0auTiaHB9MHFGCPx5IaLhTUd2atbCFBQXn9w= +github.com/tjfoc/gmsm v1.4.1 h1:aMe1GlZb+0bLjn+cKTPEvvn9oUEBlJitaZiiBwsbgho= +github.com/tjfoc/gmsm v1.4.1/go.mod h1:j4INPkHWMrhJb38G+J6W4Tw0AbuN8Thu3PbdVYhVcTE= +github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= +github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= +github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU= +github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.30/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +github.com/yuninks/loggerx v1.0.12 h1:5XxhSo5bQZEjLRdJ9FPmj+uS018s1meo/9OhG9y2hUg= +github.com/yuninks/loggerx v1.0.12/go.mod h1:+QFoywQ1ICh4v40zj6OHM8GBZHEqV0yvRbkZjZUe2o4= +golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= +golang.org/x/arch v0.3.0 h1:02VY4/ZcO/gBOH6PUaoiptASxtXU10jazRCP865E97k= +golang.org/x/arch v0.3.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191219195013-becbf705a915/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20201012173705-84dcc777aaee/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= +golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= +golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= +golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= +golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= +golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= +golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= +golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= +golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs= +golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200509044756-6aff5f38e54f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= +golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= +golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= +golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= +golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= +golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20200509030707-2212a7e161a5/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= +google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= +gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/ini.v1 v1.56.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= +gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= diff --git a/interfaces/interfaces.go b/interfaces/interfaces.go new file mode 100644 index 0000000..c2c5ca5 --- /dev/null +++ b/interfaces/interfaces.go @@ -0,0 +1,60 @@ +package interfaces + +import ( + "context" + "errors" + + "code.yun.ink/pkg/smsx/entity" + "github.com/yuninks/loggerx" +) + +type Smsx interface { + InitSmsx(ctx context.Context, params entity.SmsConfigData,logger loggerx.LoggerInterface) (Smsx, error) + // Send 发送短信 + // templateId: 短信模板ID + // phone: 手机号(格式:+86xxx) + // params: 模板参数 + Send(ctx context.Context, templateId string, phone string, params []SmsSendParam) error + + // GetTemp 获取所有短信模板 + GetTemp(ctx context.Context) ([]TemplateInfo, error) + + // TempDel 删除短信模板 + TempDel(ctx context.Context, tempId string) error +} + +type SmsSendParam struct { + Field string `json:"field"` // 字段 + Value string `json:"value"` // 值 +} + +type TemplateInfo struct { + TempId string `json:"temp_id"` // 模板ID + TempName string `json:"temp_name"` // 模板名称 + TempType entity.SmsTemplateType `json:"temp_type"` // 模板类型 + TempRange entity.SmsTemplateRange `json:"temp_range"` // 作用范围 + Content string `json:"content"` // 内容 + Status entity.SmsTemplateStatus `json:"status"` // 状态 (1.通过审核 2.审核中 3.未通过审核 4.取消审核) + Params []entity.SmsTemplateParam `json:"params"` // 模板参数 +} + +// 默认的实现 +type DefaultSmsx struct{} + +func (l *DefaultSmsx) InitSmsx(ctx context.Context, params entity.SmsConfigData,logger loggerx.LoggerInterface) (Smsx, error) { + return &DefaultSmsx{}, nil +} + +func (l *DefaultSmsx) Send(ctx context.Context, templateId string, phone string, params []SmsSendParam) error { + return errors.New("not implemented") +} + +// GetTemp 获取模板 +func (l *DefaultSmsx) GetTemp(ctx context.Context) ([]TemplateInfo, error) { + return nil, errors.New("not implemented") +} + +// TempDel 删除模板 +func (l *DefaultSmsx) TempDel(ctx context.Context, tempId string) error { + return errors.New("not implemented") +} diff --git a/log/2024-11-15_info.log b/log/2024-11-15_info.log new file mode 100644 index 0000000..10cc0c7 --- /dev/null +++ b/log/2024-11-15_info.log @@ -0,0 +1,3 @@ + +[info]{"time":"2024-11-15 18:49:21.806280","file":"/tencent/tencent.go:77","func":"Send","gid":"1","content":["tencent send templateId:2060882 phone:+85267369217 params:[{Field:1 Value:123456}]"]} +[info]{"time":"2024-11-15 18:49:22.071829","file":"/tencent/tencent.go:128","func":"Send","gid":"1","content":["tencent send response:{\"Response\":{\"SendStatusSet\":[{\"SerialNo\":\"f374bd9c-fb31-450a-b9b8-7eca7663f156\",\"PhoneNumber\":\"+85267369217\",\"Fee\":1,\"SessionContext\":\"\",\"Code\":\"Ok\",\"Message\":\"send success\",\"IsoCode\":\"HK\"}],\"RequestId\":\"a0924c44-c5b5-4be8-a08d-a9c620a8abc6\"}} err:\u003cnil\u003e"]} \ No newline at end of file diff --git a/smsx.go b/smsx.go new file mode 100644 index 0000000..00fe8c5 --- /dev/null +++ b/smsx.go @@ -0,0 +1,31 @@ +package smsx + +import ( + "context" + "errors" + + "code.yun.ink/pkg/smsx/aliyun" + "code.yun.ink/pkg/smsx/entity" + "code.yun.ink/pkg/smsx/interfaces" + "code.yun.ink/pkg/smsx/tencent" +) + +var platform map[entity.Platform3rdType]interfaces.Smsx + +// 注册 +func init() { + platform = make(map[entity.Platform3rdType]interfaces.Smsx) + // 阿里 + platform[entity.Platform3rdTypeAliyun] = &aliyun.Aliyun{} + // 腾讯 + platform[entity.Platform3rdTypeTencent] = &tencent.Tencent{} +} + +func GetPlatform(ctx context.Context, plat entity.Platform3rdType) (interfaces.Smsx, error) { + iplat, ok := platform[plat] + if ok { + return iplat, nil + } + + return nil, errors.New("not found" + string(plat)) +} diff --git a/tencent/log/2024-09-30_info.log b/tencent/log/2024-09-30_info.log new file mode 100644 index 0000000..95d2e0e --- /dev/null +++ b/tencent/log/2024-09-30_info.log @@ -0,0 +1,12 @@ + +[info]{"time":"2024-09-30 11:31:10.613596","file":"/tencent.go:269","func":"getTemp","gid":"52","content":["response:{\"Response\":{\"DescribeTemplateStatusSet\":[{\"TemplateId\":2137926,\"International\":3,\"StatusCode\":0,\"ReviewReply\":\"\",\"TemplateName\":\"您有一条新的订单待确认\",\"CreateTime\":1713950524,\"TemplateContent\":\"您有一条新的订单待确认。请在规定时间内确认,逾期未确认订单将自动取消。\"},{\"TemplateId\":2137925,\"International\":3,\"StatusCode\":0,\"ReviewReply\":\"\",\"TemplateName\":\"订单尾号{1}超过{2}分钟,系统已自动放行\",\"CreateTime\":1713950512,\"TemplateContent\":\"订单尾号{1}超过{2}分钟,系统已自动放行。交易完成,请登录查看账户变动。\"},{\"TemplateId\":2137917,\"International\":3,\"StatusCode\":0,\"ReviewReply\":\"\",\"TemplateName\":\"订单短信\",\"CreateTime\":1713950348,\"TemplateContent\":\"订单尾号{1},对方已完成,请及时放行,如果{2}分钟您未放行,订单将会自动放行。\"},{\"TemplateId\":2137916,\"International\":3,\"StatusCode\":0,\"ReviewReply\":\"\",\"TemplateName\":\"短信验证码\",\"CreateTime\":1713950267,\"TemplateContent\":\"您的验证码为{1},{2}分钟内有效,请勿将安全码告知任何人,如非本人操作,请忽略本短信\"},{\"TemplateId\":2096611,\"International\":3,\"StatusCode\":0,\"ReviewReply\":\"\",\"TemplateName\":\"驗證碼\",\"CreateTime\":1710488679,\"TemplateContent\":\"您的验证码为{1},5分钟内有效,请勿将验证码告知任何人,如果本人操作请忽略此短信。\"},{\"TemplateId\":2096608,\"International\":3,\"StatusCode\":0,\"ReviewReply\":\"\",\"TemplateName\":\"訂單更新\",\"CreateTime\":1710488660,\"TemplateContent\":\"{1}您好,您的订单状态已更新,请及时查看交易。\"},{\"TemplateId\":2095696,\"International\":3,\"StatusCode\":0,\"ReviewReply\":\"\",\"TemplateName\":\"订单状态已更新\",\"CreateTime\":1710405997,\"TemplateContent\":\"{1}您的订单状态已更新,如果15分钟您未放行,订单将会自动放行。\"},{\"TemplateId\":2080544,\"International\":3,\"StatusCode\":0,\"ReviewReply\":\"\",\"TemplateName\":\"放行2\",\"CreateTime\":1709022641,\"TemplateContent\":\"订单尾号{1}超过15分钟,系统已自动放行。交易完成,请登录查看账户变动。\"},{\"TemplateId\":2080542,\"International\":3,\"StatusCode\":0,\"ReviewReply\":\"\",\"TemplateName\":\"自動放行\",\"CreateTime\":1709022623,\"TemplateContent\":\"订单尾号{1},对方已完成,请及时放行,如果15分钟您未放行,订单将会自动放行。\"},{\"TemplateId\":2080541,\"International\":3,\"StatusCode\":0,\"ReviewReply\":\"\",\"TemplateName\":\"安全碼有效\",\"CreateTime\":1709022583,\"TemplateContent\":\"您的安全码为{1},10分钟内有效,请勿将安全码告知任何人,如非本人操作,请忽略本短信\"}],\"RequestId\":\"f718abb7-db05-45cb-8b9c-ffc8bf02929c\"}}"]} +[info]{"time":"2024-09-30 11:31:10.806522","file":"/tencent.go:269","func":"getTemp","gid":"52","content":["response:{\"Response\":{\"DescribeTemplateStatusSet\":[{\"TemplateId\":2061198,\"International\":3,\"StatusCode\":0,\"ReviewReply\":\"\",\"TemplateName\":\"您好,您的订单状态已更新,请查看 验证码为:{1}\",\"CreateTime\":1706182051,\"TemplateContent\":\"您好,您的订单状态已更新,请查看 验证码为:{1}\"},{\"TemplateId\":2060882,\"International\":3,\"StatusCode\":0,\"ReviewReply\":\"\",\"TemplateName\":\"验证码为:{1},您好,您的订单状态已更新,请查看\",\"CreateTime\":1706170226,\"TemplateContent\":\"验证码为:{1},您好,您的订单状态已更新,请查看\"},{\"TemplateId\":2053729,\"International\":3,\"StatusCode\":0,\"ReviewReply\":\"\",\"TemplateName\":\"{1}为您的登录验证码,请于{2}分钟内填写\",\"CreateTime\":1705576650,\"TemplateContent\":\"{1}为您的登录验证码,请于{2}分钟内填写,如非本人操作,请忽略本短信。\"},{\"TemplateId\":2052904,\"International\":3,\"StatusCode\":0,\"ReviewReply\":\"\",\"TemplateName\":\"您好,您的订单状态已更新,请查看\",\"CreateTime\":1705548655,\"TemplateContent\":\"您好,您的订单状态已更新,请查看\"},{\"TemplateId\":2050942,\"International\":3,\"StatusCode\":0,\"ReviewReply\":\"\",\"TemplateName\":\"宏建源贸易\",\"CreateTime\":1705393309,\"TemplateContent\":\"您的注册验证码:{1},如非本人操作,请忽略本短信!\"}],\"RequestId\":\"50d4d150-727b-4010-b9b3-6e292b1f4f05\"}}"]} +[info]{"time":"2024-09-30 11:31:11.036941","file":"/tencent.go:269","func":"getTemp","gid":"52","content":["response:{\"Response\":{\"DescribeTemplateStatusSet\":[],\"RequestId\":\"13ce9c3f-a75b-419f-9728-c3f700eefd4b\"}}"]} +[info]{"time":"2024-09-30 11:31:11.036941","file":"/tencent.go:210","func":"GetTemp","gid":"52","content":["ins:[{TempId:2137926 TempName:您有一条新的订单待确认 TempType:0 TempRange:1 Content:您有一条新的订单待确认。请在规定时间内确认,逾期未确认订单将自动取消。 Status:1 Params:[]} {TempId:2137925 TempName:订单尾号{1}超过{2}分钟,系统已自动放行 TempType:0 TempRange:1 Content:订单尾号{1}超过{2}分钟,系统已自动放行。交易完成,请登录查看账户变动。 Status:1 Params:[{FieldName:1 FieldType:} {FieldName:2 FieldType:}]} {TempId:2137917 TempName:订单短信 TempType:0 TempRange:1 Content:订单尾号{1},对方已完成,请及时放行,如果{2}分钟您未放行,订单将会自动放行。 Status:1 Params:[{FieldName:1 FieldType:} {FieldName:2 FieldType:}]} {TempId:2137916 TempName:短信验证码 TempType:0 TempRange:1 Content:您的验证码为{1},{2}分钟内有效,请勿将安全码告知任何人,如非本人操作,请忽略本短信 Status:1 Params:[{FieldName:1 FieldType:} {FieldName:2 FieldType:}]} {TempId:2096611 TempName:驗證碼 TempType:0 TempRange:1 Content:您的验证码为{1},5分钟内有效,请勿将验证码告知任何人,如果本人操作请忽略此短信。 Status:1 Params:[{FieldName:1 FieldType:}]} {TempId:2096608 TempName:訂單更新 TempType:0 TempRange:1 Content:{1}您好,您的订单状态已更新,请及时查看交易。 Status:1 Params:[{FieldName:1 FieldType:}]} {TempId:2095696 TempName:订单状态已更新 TempType:0 TempRange:1 Content:{1}您的订单状态已更新,如果15分钟您未放行,订单将会自动放行。 Status:1 Params:[{FieldName:1 FieldType:}]} {TempId:2080544 TempName:放行2 TempType:0 TempRange:1 Content:订单尾号{1}超过15分钟,系统已自动放行。交易完成,请登录查看账户变动。 Status:1 Params:[{FieldName:1 FieldType:}]} {TempId:2080542 TempName:自動放行 TempType:0 TempRange:1 Content:订单尾号{1},对方已完成,请及时放行,如果15分钟您未放行,订单将会自动放行。 Status:1 Params:[{FieldName:1 FieldType:}]} {TempId:2080541 TempName:安全碼有效 TempType:0 TempRange:1 Content:您的安全码为{1},10分钟内有效,请勿将安全码告知任何人,如非本人操作,请忽略本短信 Status:1 Params:[{FieldName:1 FieldType:}]} {TempId:2061198 TempName:您好,您的订单状态已更新,请查看 验证码为:{1} TempType:0 TempRange:1 Content:您好,您的订单状态已更新,请查看 验证码为:{1} Status:1 Params:[{FieldName:1 FieldType:}]} {TempId:2060882 TempName:验证码为:{1},您好,您的订单状态已更新,请查看 TempType:0 TempRange:1 Content:验证码为:{1},您好,您的订单状态已更新,请查看 Status:1 Params:[{FieldName:1 FieldType:}]} {TempId:2053729 TempName:{1}为您的登录验证码,请于{2}分钟内填写 TempType:0 TempRange:1 Content:{1}为您的登录验证码,请于{2}分钟内填写,如非本人操作,请忽略本短信。 Status:1 Params:[{FieldName:1 FieldType:} {FieldName:2 FieldType:}]} {TempId:2052904 TempName:您好,您的订单状态已更新,请查看 TempType:0 TempRange:1 Content:您好,您的订单状态已更新,请查看 Status:1 Params:[]} {TempId:2050942 TempName:宏建源贸易 TempType:0 TempRange:1 Content:您的注册验证码:{1},如非本人操作,请忽略本短信! Status:1 Params:[{FieldName:1 FieldType:}]}]"]} +[info]{"time":"2024-09-30 11:31:11.242949","file":"/tencent.go:269","func":"getTemp","gid":"52","content":["response:{\"Response\":{\"DescribeTemplateStatusSet\":[{\"TemplateId\":2137926,\"International\":3,\"StatusCode\":0,\"ReviewReply\":\"\",\"TemplateName\":\"您有一条新的订单待确认\",\"CreateTime\":1713950524,\"TemplateContent\":\"您有一条新的订单待确认。请在规定时间内确认,逾期未确认订单将自动取消。\"},{\"TemplateId\":2137925,\"International\":3,\"StatusCode\":0,\"ReviewReply\":\"\",\"TemplateName\":\"订单尾号{1}超过{2}分钟,系统已自动放行\",\"CreateTime\":1713950512,\"TemplateContent\":\"订单尾号{1}超过{2}分钟,系统已自动放行。交易完成,请登录查看账户变动。\"},{\"TemplateId\":2137917,\"International\":3,\"StatusCode\":0,\"ReviewReply\":\"\",\"TemplateName\":\"订单短信\",\"CreateTime\":1713950348,\"TemplateContent\":\"订单尾号{1},对方已完成,请及时放行,如果{2}分钟您未放行,订单将会自动放行。\"},{\"TemplateId\":2137916,\"International\":3,\"StatusCode\":0,\"ReviewReply\":\"\",\"TemplateName\":\"短信验证码\",\"CreateTime\":1713950267,\"TemplateContent\":\"您的验证码为{1},{2}分钟内有效,请勿将安全码告知任何人,如非本人操作,请忽略本短信\"},{\"TemplateId\":2096611,\"International\":3,\"StatusCode\":0,\"ReviewReply\":\"\",\"TemplateName\":\"驗證碼\",\"CreateTime\":1710488679,\"TemplateContent\":\"您的验证码为{1},5分钟内有效,请勿将验证码告知任何人,如果本人操作请忽略此短信。\"},{\"TemplateId\":2096608,\"International\":3,\"StatusCode\":0,\"ReviewReply\":\"\",\"TemplateName\":\"訂單更新\",\"CreateTime\":1710488660,\"TemplateContent\":\"{1}您好,您的订单状态已更新,请及时查看交易。\"},{\"TemplateId\":2096354,\"International\":1,\"StatusCode\":0,\"ReviewReply\":\"\",\"TemplateName\":\"订单状态已更新\",\"CreateTime\":1710477402,\"TemplateContent\":\"{1}您好,您的订单状态已更新,请及时查看交易。\"},{\"TemplateId\":2096351,\"International\":1,\"StatusCode\":0,\"ReviewReply\":\"\",\"TemplateName\":\"验证码\",\"CreateTime\":1710477374,\"TemplateContent\":\"您的验证码为{1},5分钟内有效,请勿将验证码告知任何人,如果本人操作请忽略此短信。\"},{\"TemplateId\":2095696,\"International\":3,\"StatusCode\":0,\"ReviewReply\":\"\",\"TemplateName\":\"订单状态已更新\",\"CreateTime\":1710405997,\"TemplateContent\":\"{1}您的订单状态已更新,如果15分钟您未放行,订单将会自动放行。\"},{\"TemplateId\":2080544,\"International\":3,\"StatusCode\":0,\"ReviewReply\":\"\",\"TemplateName\":\"放行2\",\"CreateTime\":1709022641,\"TemplateContent\":\"订单尾号{1}超过15分钟,系统已自动放行。交易完成,请登录查看账户变动。\"}],\"RequestId\":\"f51811c7-560d-4fb4-92d3-28d44b6d176d\"}}"]} +[info]{"time":"2024-09-30 11:31:11.466534","file":"/tencent.go:269","func":"getTemp","gid":"52","content":["response:{\"Response\":{\"DescribeTemplateStatusSet\":[{\"TemplateId\":2080542,\"International\":3,\"StatusCode\":0,\"ReviewReply\":\"\",\"TemplateName\":\"自動放行\",\"CreateTime\":1709022623,\"TemplateContent\":\"订单尾号{1},对方已完成,请及时放行,如果15分钟您未放行,订单将会自动放行。\"},{\"TemplateId\":2080541,\"International\":3,\"StatusCode\":0,\"ReviewReply\":\"\",\"TemplateName\":\"安全碼有效\",\"CreateTime\":1709022583,\"TemplateContent\":\"您的安全码为{1},10分钟内有效,请勿将安全码告知任何人,如非本人操作,请忽略本短信\"},{\"TemplateId\":2061198,\"International\":3,\"StatusCode\":0,\"ReviewReply\":\"\",\"TemplateName\":\"您好,您的订单状态已更新,请查看 验证码为:{1}\",\"CreateTime\":1706182051,\"TemplateContent\":\"您好,您的订单状态已更新,请查看 验证码为:{1}\"},{\"TemplateId\":2061157,\"International\":1,\"StatusCode\":0,\"ReviewReply\":\"\",\"TemplateName\":\"您好,您的订单状态已更新,请查看 验证码为:{1}\",\"CreateTime\":1706181321,\"TemplateContent\":\"您好,您的订单状态已更新,请查看 验证码为:{1}\"},{\"TemplateId\":2060882,\"International\":3,\"StatusCode\":0,\"ReviewReply\":\"\",\"TemplateName\":\"验证码为:{1},您好,您的订单状态已更新,请查看\",\"CreateTime\":1706170226,\"TemplateContent\":\"验证码为:{1},您好,您的订单状态已更新,请查看\"},{\"TemplateId\":2053729,\"International\":3,\"StatusCode\":0,\"ReviewReply\":\"\",\"TemplateName\":\"{1}为您的登录验证码,请于{2}分钟内填写\",\"CreateTime\":1705576650,\"TemplateContent\":\"{1}为您的登录验证码,请于{2}分钟内填写,如非本人操作,请忽略本短信。\"},{\"TemplateId\":2052904,\"International\":3,\"StatusCode\":0,\"ReviewReply\":\"\",\"TemplateName\":\"您好,您的订单状态已更新,请查看\",\"CreateTime\":1705548655,\"TemplateContent\":\"您好,您的订单状态已更新,请查看\"},{\"TemplateId\":2052816,\"International\":1,\"StatusCode\":0,\"ReviewReply\":\"\",\"TemplateName\":\"验证码\",\"CreateTime\":1705546113,\"TemplateContent\":\"验证码为:{1},您正在登录,若非本人操作,请勿泄露。\"},{\"TemplateId\":2050942,\"International\":3,\"StatusCode\":0,\"ReviewReply\":\"\",\"TemplateName\":\"宏建源贸易\",\"CreateTime\":1705393309,\"TemplateContent\":\"您的注册验证码:{1},如非本人操作,请忽略本短信!\"}],\"RequestId\":\"2c46303c-abce-4a78-975e-7805047f2f95\"}}"]} +[info]{"time":"2024-09-30 11:31:11.668775","file":"/tencent.go:269","func":"getTemp","gid":"52","content":["response:{\"Response\":{\"DescribeTemplateStatusSet\":[],\"RequestId\":\"6fbc5fff-45ff-4d5d-993b-5ec1af2ef448\"}}"]} +[info]{"time":"2024-09-30 11:31:11.668775","file":"/tencent.go:217","func":"GetTemp","gid":"52","content":["outs:[{TempId:2137926 TempName:您有一条新的订单待确认 TempType:0 TempRange:1 Content:您有一条新的订单待确认。请在规定时间内确认,逾期未确认订单将自动取消。 Status:1 Params:[]} {TempId:2137925 TempName:订单尾号{1}超过{2}分钟,系统已自动放行 TempType:0 TempRange:1 Content:订单尾号{1}超过{2}分钟,系统已自动放行。交易完成,请登录查看账户变动。 Status:1 Params:[{FieldName:1 FieldType:} {FieldName:2 FieldType:}]} {TempId:2137917 TempName:订单短信 TempType:0 TempRange:1 Content:订单尾号{1},对方已完成,请及时放行,如果{2}分钟您未放行,订单将会自动放行。 Status:1 Params:[{FieldName:1 FieldType:} {FieldName:2 FieldType:}]} {TempId:2137916 TempName:短信验证码 TempType:0 TempRange:1 Content:您的验证码为{1},{2}分钟内有效,请勿将安全码告知任何人,如非本人操作,请忽略本短信 Status:1 Params:[{FieldName:1 FieldType:} {FieldName:2 FieldType:}]} {TempId:2096611 TempName:驗證碼 TempType:0 TempRange:1 Content:您的验证码为{1},5分钟内有效,请勿将验证码告知任何人,如果本人操作请忽略此短信。 Status:1 Params:[{FieldName:1 FieldType:}]} {TempId:2096608 TempName:訂單更新 TempType:0 TempRange:1 Content:{1}您好,您的订单状态已更新,请及时查看交易。 Status:1 Params:[{FieldName:1 FieldType:}]} {TempId:2096354 TempName:订单状态已更新 TempType:0 TempRange:3 Content:{1}您好,您的订单状态已更新,请及时查看交易。 Status:1 Params:[{FieldName:1 FieldType:}]} {TempId:2096351 TempName:验证码 TempType:0 TempRange:3 Content:您的验证码为{1},5分钟内有效,请勿将验证码告知任何人,如果本人操作请忽略此短信。 Status:1 Params:[{FieldName:1 FieldType:}]} {TempId:2095696 TempName:订单状态已更新 TempType:0 TempRange:1 Content:{1}您的订单状态已更新,如果15分钟您未放行,订单将会自动放行。 Status:1 Params:[{FieldName:1 FieldType:}]} {TempId:2080544 TempName:放行2 TempType:0 TempRange:1 Content:订单尾号{1}超过15分钟,系统已自动放行。交易完成,请登录查看账户变动。 Status:1 Params:[{FieldName:1 FieldType:}]} {TempId:2080542 TempName:自動放行 TempType:0 TempRange:1 Content:订单尾号{1},对方已完成,请及时放行,如果15分钟您未放行,订单将会自动放行。 Status:1 Params:[{FieldName:1 FieldType:}]} {TempId:2080541 TempName:安全碼有效 TempType:0 TempRange:1 Content:您的安全码为{1},10分钟内有效,请勿将安全码告知任何人,如非本人操作,请忽略本短信 Status:1 Params:[{FieldName:1 FieldType:}]} {TempId:2061198 TempName:您好,您的订单状态已更新,请查看 验证码为:{1} TempType:0 TempRange:1 Content:您好,您的订单状态已更新,请查看 验证码为:{1} Status:1 Params:[{FieldName:1 FieldType:}]} {TempId:2061157 TempName:您好,您的订单状态已更新,请查看 验证码为:{1} TempType:0 TempRange:3 Content:您好,您的订单状态已更新,请查看 验证码为:{1} Status:1 Params:[{FieldName:1 FieldType:}]} {TempId:2060882 TempName:验证码为:{1},您好,您的订单状态已更新,请查看 TempType:0 TempRange:1 Content:验证码为:{1},您好,您的订单状态已更新,请查看 Status:1 Params:[{FieldName:1 FieldType:}]} {TempId:2053729 TempName:{1}为您的登录验证码,请于{2}分钟内填写 TempType:0 TempRange:1 Content:{1}为您的登录验证码,请于{2}分钟内填写,如非本人操作,请忽略本短信。 Status:1 Params:[{FieldName:1 FieldType:} {FieldName:2 FieldType:}]} {TempId:2052904 TempName:您好,您的订单状态已更新,请查看 TempType:0 TempRange:1 Content:您好,您的订单状态已更新,请查看 Status:1 Params:[]} {TempId:2052816 TempName:验证码 TempType:0 TempRange:3 Content:验证码为:{1},您正在登录,若非本人操作,请勿泄露。 Status:1 Params:[{FieldName:1 FieldType:}]} {TempId:2050942 TempName:宏建源贸易 TempType:0 TempRange:1 Content:您的注册验证码:{1},如非本人操作,请忽略本短信! Status:1 Params:[{FieldName:1 FieldType:}]}]"]} +[info]{"time":"2024-09-30 11:31:11.668775","file":"/tencent_test.go:53","func":"TestGetTemp","gid":"52","content":["sssss [{\"temp_id\":\"2137926\",\"temp_name\":\"您有一条新的订单待确认\",\"temp_type\":0,\"temp_range\":1,\"content\":\"您有一条新的订单待确认。请在规定时间内确认,逾期未确认订单将自动取消。\",\"status\":1,\"params\":[]},{\"temp_id\":\"2137925\",\"temp_name\":\"订单尾号{1}超过{2}分钟,系统已自动放行\",\"temp_type\":0,\"temp_range\":1,\"content\":\"订单尾号{1}超过{2}分钟,系统已自动放行。交易完成,请登录查看账户变动。\",\"status\":1,\"params\":[{\"field_name\":\"1\",\"field_type\":\"\"},{\"field_name\":\"2\",\"field_type\":\"\"}]},{\"temp_id\":\"2137917\",\"temp_name\":\"订单短信\",\"temp_type\":0,\"temp_range\":1,\"content\":\"订单尾号{1},对方已完成,请及时放行,如果{2}分钟您未放行,订单将会自动放行。\",\"status\":1,\"params\":[{\"field_name\":\"1\",\"field_type\":\"\"},{\"field_name\":\"2\",\"field_type\":\"\"}]},{\"temp_id\":\"2137916\",\"temp_name\":\"短信验证码\",\"temp_type\":0,\"temp_range\":1,\"content\":\"您的验证码为{1},{2}分钟内有效,请勿将安全码告知任何人,如非本人操作,请忽略本短信\",\"status\":1,\"params\":[{\"field_name\":\"1\",\"field_type\":\"\"},{\"field_name\":\"2\",\"field_type\":\"\"}]},{\"temp_id\":\"2096611\",\"temp_name\":\"驗證碼\",\"temp_type\":0,\"temp_range\":1,\"content\":\"您的验证码为{1},5分钟内有效,请勿将验证码告知任何人,如果本人操作请忽略此短信。\",\"status\":1,\"params\":[{\"field_name\":\"1\",\"field_type\":\"\"}]},{\"temp_id\":\"2096608\",\"temp_name\":\"訂單更新\",\"temp_type\":0,\"temp_range\":1,\"content\":\"{1}您好,您的订单状态已更新,请及时查看交易。\",\"status\":1,\"params\":[{\"field_name\":\"1\",\"field_type\":\"\"}]},{\"temp_id\":\"2095696\",\"temp_name\":\"订单状态已更新\",\"temp_type\":0,\"temp_range\":1,\"content\":\"{1}您的订单状态已更新,如果15分钟您未放行,订单将会自动放行。\",\"status\":1,\"params\":[{\"field_name\":\"1\",\"field_type\":\"\"}]},{\"temp_id\":\"2080544\",\"temp_name\":\"放行2\",\"temp_type\":0,\"temp_range\":1,\"content\":\"订单尾号{1}超过15分钟,系统已自动放行。交易完成,请登录查看账户变动。\",\"status\":1,\"params\":[{\"field_name\":\"1\",\"field_type\":\"\"}]},{\"temp_id\":\"2080542\",\"temp_name\":\"自動放行\",\"temp_type\":0,\"temp_range\":1,\"content\":\"订单尾号{1},对方已完成,请及时放行,如果15分钟您未放行,订单将会自动放行。\",\"status\":1,\"params\":[{\"field_name\":\"1\",\"field_type\":\"\"}]},{\"temp_id\":\"2080541\",\"temp_name\":\"安全碼有效\",\"temp_type\":0,\"temp_range\":1,\"content\":\"您的安全码为{1},10分钟内有效,请勿将安全码告知任何人,如非本人操作,请忽略本短信\",\"status\":1,\"params\":[{\"field_name\":\"1\",\"field_type\":\"\"}]},{\"temp_id\":\"2061198\",\"temp_name\":\"您好,您的订单状态已更新,请查看 验证码为:{1}\",\"temp_type\":0,\"temp_range\":1,\"content\":\"您好,您的订单状态已更新,请查看 验证码为:{1}\",\"status\":1,\"params\":[{\"field_name\":\"1\",\"field_type\":\"\"}]},{\"temp_id\":\"2060882\",\"temp_name\":\"验证码为:{1},您好,您的订单状态已更新,请查看\",\"temp_type\":0,\"temp_range\":1,\"content\":\"验证码为:{1},您好,您的订单状态已更新,请查看\",\"status\":1,\"params\":[{\"field_name\":\"1\",\"field_type\":\"\"}]},{\"temp_id\":\"2053729\",\"temp_name\":\"{1}为您的登录验证码,请于{2}分钟内填写\",\"temp_type\":0,\"temp_range\":1,\"content\":\"{1}为您的登录验证码,请于{2}分钟内填写,如非本人操作,请忽略本短信。\",\"status\":1,\"params\":[{\"field_name\":\"1\",\"field_type\":\"\"},{\"field_name\":\"2\",\"field_type\":\"\"}]},{\"temp_id\":\"2052904\",\"temp_name\":\"您好,您的订单状态已更新,请查看\",\"temp_type\":0,\"temp_range\":1,\"content\":\"您好,您的订单状态已更新,请查看\",\"status\":1,\"params\":[]},{\"temp_id\":\"2050942\",\"temp_name\":\"宏建源贸易\",\"temp_type\":0,\"temp_range\":1,\"content\":\"您的注册验证码:{1},如非本人操作,请忽略本短信!\",\"status\":1,\"params\":[{\"field_name\":\"1\",\"field_type\":\"\"}]},{\"temp_id\":\"2137926\",\"temp_name\":\"您有一条新的订单待确认\",\"temp_type\":0,\"temp_range\":1,\"content\":\"您有一条新的订单待确认。请在规定时间内确认,逾期未确认订单将自动取消。\",\"status\":1,\"params\":[]},{\"temp_id\":\"2137925\",\"temp_name\":\"订单尾号{1}超过{2}分钟,系统已自动放行\",\"temp_type\":0,\"temp_range\":1,\"content\":\"订单尾号{1}超过{2}分钟,系统已自动放行。交易完成,请登录查看账户变动。\",\"status\":1,\"params\":[{\"field_name\":\"1\",\"field_type\":\"\"},{\"field_name\":\"2\",\"field_type\":\"\"}]},{\"temp_id\":\"2137917\",\"temp_name\":\"订单短信\",\"temp_type\":0,\"temp_range\":1,\"content\":\"订单尾号{1},对方已完成,请及时放行,如果{2}分钟您未放行,订单将会自动放行。\",\"status\":1,\"params\":[{\"field_name\":\"1\",\"field_type\":\"\"},{\"field_name\":\"2\",\"field_type\":\"\"}]},{\"temp_id\":\"2137916\",\"temp_name\":\"短信验证码\",\"temp_type\":0,\"temp_range\":1,\"content\":\"您的验证码为{1},{2}分钟内有效,请勿将安全码告知任何人,如非本人操作,请忽略本短信\",\"status\":1,\"params\":[{\"field_name\":\"1\",\"field_type\":\"\"},{\"field_name\":\"2\",\"field_type\":\"\"}]},{\"temp_id\":\"2096611\",\"temp_name\":\"驗證碼\",\"temp_type\":0,\"temp_range\":1,\"content\":\"您的验证码为{1},5分钟内有效,请勿将验证码告知任何人,如果本人操作请忽略此短信。\",\"status\":1,\"params\":[{\"field_name\":\"1\",\"field_type\":\"\"}]},{\"temp_id\":\"2096608\",\"temp_name\":\"訂單更新\",\"temp_type\":0,\"temp_range\":1,\"content\":\"{1}您好,您的订单状态已更新,请及时查看交易。\",\"status\":1,\"params\":[{\"field_name\":\"1\",\"field_type\":\"\"}]},{\"temp_id\":\"2096354\",\"temp_name\":\"订单状态已更新\",\"temp_type\":0,\"temp_range\":3,\"content\":\"{1}您好,您的订单状态已更新,请及时查看交易。\",\"status\":1,\"params\":[{\"field_name\":\"1\",\"field_type\":\"\"}]},{\"temp_id\":\"2096351\",\"temp_name\":\"验证码\",\"temp_type\":0,\"temp_range\":3,\"content\":\"您的验证码为{1},5分钟内有效,请勿将验证码告知任何人,如果本人操作请忽略此短信。\",\"status\":1,\"params\":[{\"field_name\":\"1\",\"field_type\":\"\"}]},{\"temp_id\":\"2095696\",\"temp_name\":\"订单状态已更新\",\"temp_type\":0,\"temp_range\":1,\"content\":\"{1}您的订单状态已更新,如果15分钟您未放行,订单将会自动放行。\",\"status\":1,\"params\":[{\"field_name\":\"1\",\"field_type\":\"\"}]},{\"temp_id\":\"2080544\",\"temp_name\":\"放行2\",\"temp_type\":0,\"temp_range\":1,\"content\":\"订单尾号{1}超过15分钟,系统已自动放行。交易完成,请登录查看账户变动。\",\"status\":1,\"params\":[{\"field_name\":\"1\",\"field_type\":\"\"}]},{\"temp_id\":\"2080542\",\"temp_name\":\"自動放行\",\"temp_type\":0,\"temp_range\":1,\"content\":\"订单尾号{1},对方已完成,请及时放行,如果15分钟您未放行,订单将会自动放行。\",\"status\":1,\"params\":[{\"field_name\":\"1\",\"field_type\":\"\"}]},{\"temp_id\":\"2080541\",\"temp_name\":\"安全碼有效\",\"temp_type\":0,\"temp_range\":1,\"content\":\"您的安全码为{1},10分钟内有效,请勿将安全码告知任何人,如非本人操作,请忽略本短信\",\"status\":1,\"params\":[{\"field_name\":\"1\",\"field_type\":\"\"}]},{\"temp_id\":\"2061198\",\"temp_name\":\"您好,您的订单状态已更新,请查看 验证码为:{1}\",\"temp_type\":0,\"temp_range\":1,\"content\":\"您好,您的订单状态已更新,请查看 验证码为:{1}\",\"status\":1,\"params\":[{\"field_name\":\"1\",\"field_type\":\"\"}]},{\"temp_id\":\"2061157\",\"temp_name\":\"您好,您的订单状态已更新,请查看 验证码为:{1}\",\"temp_type\":0,\"temp_range\":3,\"content\":\"您好,您的订单状态已更新,请查看 验证码为:{1}\",\"status\":1,\"params\":[{\"field_name\":\"1\",\"field_type\":\"\"}]},{\"temp_id\":\"2060882\",\"temp_name\":\"验证码为:{1},您好,您的订单状态已更新,请查看\",\"temp_type\":0,\"temp_range\":1,\"content\":\"验证码为:{1},您好,您的订单状态已更新,请查看\",\"status\":1,\"params\":[{\"field_name\":\"1\",\"field_type\":\"\"}]},{\"temp_id\":\"2053729\",\"temp_name\":\"{1}为您的登录验证码,请于{2}分钟内填写\",\"temp_type\":0,\"temp_range\":1,\"content\":\"{1}为您的登录验证码,请于{2}分钟内填写,如非本人操作,请忽略本短信。\",\"status\":1,\"params\":[{\"field_name\":\"1\",\"field_type\":\"\"},{\"field_name\":\"2\",\"field_type\":\"\"}]},{\"temp_id\":\"2052904\",\"temp_name\":\"您好,您的订单状态已更新,请查看\",\"temp_type\":0,\"temp_range\":1,\"content\":\"您好,您的订单状态已更新,请查看\",\"status\":1,\"params\":[]},{\"temp_id\":\"2052816\",\"temp_name\":\"验证码\",\"temp_type\":0,\"temp_range\":3,\"content\":\"验证码为:{1},您正在登录,若非本人操作,请勿泄露。\",\"status\":1,\"params\":[{\"field_name\":\"1\",\"field_type\":\"\"}]},{\"temp_id\":\"2050942\",\"temp_name\":\"宏建源贸易\",\"temp_type\":0,\"temp_range\":1,\"content\":\"您的注册验证码:{1},如非本人操作,请忽略本短信!\",\"status\":1,\"params\":[{\"field_name\":\"1\",\"field_type\":\"\"}]}]"]} +[info]{"time":"2024-09-30 11:31:11.669295","file":"/tencent.go:75","func":"Send","gid":"98","content":["tencent send templateId:2060882 phone:+85267369217 params:[{Field:1 Value:123456}]"]} +[info]{"time":"2024-09-30 11:31:12.125368","file":"/tencent.go:126","func":"Send","gid":"98","content":["tencent send response:{\"Response\":{\"SendStatusSet\":[{\"SerialNo\":\"5feff58c-dda5-4530-b606-4fad8013fc5d\",\"PhoneNumber\":\"+85267369217\",\"Fee\":1,\"SessionContext\":\"\",\"Code\":\"Ok\",\"Message\":\"send success\",\"IsoCode\":\"HK\"}],\"RequestId\":\"f8f29547-82e0-474d-8fdf-3b6379ff0ed0\"}} err:\u003cnil\u003e"]} \ No newline at end of file diff --git a/tencent/tencent.go b/tencent/tencent.go new file mode 100644 index 0000000..9a499e0 --- /dev/null +++ b/tencent/tencent.go @@ -0,0 +1,381 @@ +package tencent + +import ( + "context" + "encoding/json" + "errors" + "fmt" + + "code.yun.ink/pkg/smsx/entity" + "code.yun.ink/pkg/smsx/interfaces" + "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common" + errorsTen "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/errors" + "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/profile" + sms "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/sms/v20210111" // 引入sms + "github.com/yuninks/loggerx" +) + +type Tencent struct { + interfaces.DefaultSmsx + client *sms.Client + params entity.SmsConfigData + logger loggerx.LoggerInterface +} + +func (l *Tencent) InitSmsx(ctx context.Context, params entity.SmsConfigData, logger loggerx.LoggerInterface) (interfaces.Smsx, error) { + l.logger = logger + if params.SysType != entity.Platform3rdTypeTencent || params.Tencent == nil { + return nil, errors.New("not tencent") + } + + if params.Tencent.Endpoint == "" { + params.Tencent.Endpoint = "sms.tencentcloudapi.com" + } + + if params.Tencent.Region == "" { + params.Tencent.Region = "ap-guangzhou" + } + + credential := common.NewCredential( + params.Tencent.SecretId, + params.Tencent.SecretKey, + ) + /* 非必要步骤: + * 实例化一个客户端配置对象,可以指定超时时间等配置 */ + cpf := profile.NewClientProfile() + + /* SDK默认使用POST方法。 + * 如果您一定要使用GET方法,可以在这里设置。GET方法无法处理一些较大的请求 */ + cpf.HttpProfile.ReqMethod = "POST" + cpf.HttpProfile.ReqTimeout = 10 // 请求超时时间,单位为秒(默认60秒) + /* 指定接入地域域名,默认就近地域接入域名为 sms.tencentcloudapi.com ,也支持指定地域域名访问,例如广州地域的域名为 sms.ap-guangzhou.tencentcloudapi.com */ + cpf.HttpProfile.Endpoint = params.Tencent.Endpoint + + /* SDK默认用TC3-HMAC-SHA256进行签名,非必要请不要修改这个字段 */ + cpf.SignMethod = "HmacSHA1" + + /* 实例化要请求产品(以sms为例)的client对象 + * 第二个参数是地域信息,可以直接填写字符串ap-guangzhou,支持的地域列表参考 https://cloud.tencent.com/document/api/382/52071#.E5.9C.B0.E5.9F.9F.E5.88.97.E8.A1.A8 */ + client, err := sms.NewClient(credential, params.Tencent.Region, cpf) + if err != nil { + return nil, err + } + + return &Tencent{ + client: client, + params: params, + logger: logger, + }, nil +} + +// Send 发送短信 +func (l *Tencent) Send(ctx context.Context, templateId string, phone string, params []interfaces.SmsSendParam) error { + if l.client == nil { + return errors.New("not init") + } + + l.logger.Infof(ctx, "tencent send templateId:%+v phone:%+v params:%+v", templateId, phone, params) + + /* 实例化一个请求对象,根据调用的接口和实际情况,可以进一步设置请求参数 + * 您可以直接查询SDK源码确定接口有哪些属性可以设置 + * 属性可能是基本类型,也可能引用了另一个数据结构 + * 推荐使用IDE进行开发,可以方便的跳转查阅各个接口和数据结构的文档说明 */ + request := sms.NewSendSmsRequest() + + /* 基本类型的设置: + * SDK采用的是指针风格指定参数,即使对于基本类型您也需要用指针来对参数赋值。 + * SDK提供对基本类型的指针引用封装函数 + * 帮助链接: + * 短信控制台: https://console.cloud.tencent.com/smsv2 + * 腾讯云短信小助手: https://cloud.tencent.com/document/product/382/3773#.E6.8A.80.E6.9C.AF.E4.BA.A4.E6.B5.81 */ + + /* 短信应用ID: 短信SdkAppId在 [短信控制台] 添加应用后生成的实际SdkAppId,示例如1400006666 */ + // 应用 ID 可前往 [短信控制台](https://console.cloud.tencent.com/smsv2/app-manage) 查看 + request.SmsSdkAppId = common.StringPtr(l.params.Tencent.SmsSdkAppId) + + /* 短信签名内容: 使用 UTF-8 编码,必须填写已审核通过的签名 */ + // 签名信息可前往 [国内短信](https://console.cloud.tencent.com/smsv2/csms-sign) 或 [国际/港澳台短信](https://console.cloud.tencent.com/smsv2/isms-sign) 的签名管理查看 + request.SignName = common.StringPtr(l.params.Tencent.SignName) + + /* 模板 ID: 必须填写已审核通过的模板 ID */ + // 模板 ID 可前往 [国内短信](https://console.cloud.tencent.com/smsv2/csms-template) 或 [国际/港澳台短信](https://console.cloud.tencent.com/smsv2/isms-template) 的正文模板管理查看 + request.TemplateId = common.StringPtr(templateId) + + tempParams := []string{} + for _, val := range params { + tempParams = append(tempParams, val.Value) + } + + /* 模板参数: 模板参数的个数需要与 TemplateId 对应模板的变量个数保持一致,若无模板参数,则设置为空*/ + request.TemplateParamSet = common.StringPtrs(tempParams) + + /* 下发手机号码,采用 E.164 标准,+[国家或地区码][手机号] + * 示例如:+8613711112222, 其中前面有一个+号 ,86为国家码,13711112222为手机号,最多不要超过200个手机号*/ + request.PhoneNumberSet = common.StringPtrs([]string{phone}) + + /* 用户的 session 内容(无需要可忽略): 可以携带用户侧 ID 等上下文信息,server 会原样返回 */ + request.SessionContext = common.StringPtr("") + + /* 短信码号扩展号(无需要可忽略): 默认未开通,如需开通请联系 [腾讯云短信小助手] */ + request.ExtendCode = common.StringPtr("") + + /* 国内短信无需填写该项;国际/港澳台短信已申请独立 SenderId 需要填写该字段,默认使用公共 SenderId,无需填写该字段。注:月度使用量达到指定量级可申请独立 SenderId 使用,详情请联系 [腾讯云短信小助手](https://cloud.tencent.com/document/product/382/3773#.E6.8A.80.E6.9C.AF.E4.BA.A4.E6.B5.81)。 */ + request.SenderId = common.StringPtr("") + + // 通过client对象调用想要访问的接口,需要传入请求对象 + response, err := l.client.SendSms(request) + + l.logger.Infof(ctx, "tencent send response:%+v err:%+v", response.ToJsonString(), err) + + // 处理异常 + if _, ok := err.(*errorsTen.TencentCloudSDKError); ok { + l.logger.Errorf(ctx, "An API error has returned: %s", err) + // return + return err + } + // 非SDK异常,直接失败。实际代码中可以加入其他的处理。 + if err != nil { + // panic(err) + l.logger.Errorf(ctx, "An API error has returned: %s", err) + return err + } + + if response == nil || response.Response == nil { + l.logger.Errorf(ctx, "response is nil") + return errors.New("response is nil") + } + + if response.Response.SendStatusSet == nil || len(response.Response.SendStatusSet) == 0 { + l.logger.Errorf(ctx, "response.Response.SendStatusSet is nil") + return errors.New("response is nil") + } + + if *response.Response.SendStatusSet[0].Code != "Ok" { + b, _ := json.Marshal(response.Response) + l.logger.Errorf(ctx, "val:%+v", string(b)) + return errors.New(*response.Response.SendStatusSet[0].Message) + } + + // { + // "SendStatusSet": [ + // { + // "SerialNo": "", + // "PhoneNumber": "18819446148", + // "Fee": 0, + // "SessionContext": "", + // "Code": "FailedOperation.SignatureIncorrectOrUnapproved", + // "Message": "signature format is incorrect or signature is not approved", + // "IsoCode": "" + // } + // ], + // "RequestId": "33550d74-3654-4317-aabb-0fc50c2f4ab3" + // } + + // { + // "SendStatusSet": [ + // { + // "SerialNo": "4413:108110024517247563857264614", + // "PhoneNumber": "+8618819446148", + // "Fee": 1, + // "SessionContext": "", + // "Code": "Ok", + // "Message": "send success", + // "IsoCode": "CN" + // } + // ], + // "RequestId": "fd30a822-8664-4b85-b9b0-c8c1fa6293f9" + // } + + /* 当出现以下错误码时,快速解决方案参考 + * [FailedOperation.SignatureIncorrectOrUnapproved](https://cloud.tencent.com/document/product/382/9558#.E7.9F.AD.E4.BF.A1.E5.8F.91.E9.80.81.E6.8F.90.E7.A4.BA.EF.BC.9Afailedoperation.signatureincorrectorunapproved-.E5.A6.82.E4.BD.95.E5.A4.84.E7.90.86.EF.BC.9F) + * [FailedOperation.TemplateIncorrectOrUnapproved](https://cloud.tencent.com/document/product/382/9558#.E7.9F.AD.E4.BF.A1.E5.8F.91.E9.80.81.E6.8F.90.E7.A4.BA.EF.BC.9Afailedoperation.templateincorrectorunapproved-.E5.A6.82.E4.BD.95.E5.A4.84.E7.90.86.EF.BC.9F) + * [UnauthorizedOperation.SmsSdkAppIdVerifyFail](https://cloud.tencent.com/document/product/382/9558#.E7.9F.AD.E4.BF.A1.E5.8F.91.E9.80.81.E6.8F.90.E7.A4.BA.EF.BC.9Aunauthorizedoperation.smssdkappidverifyfail-.E5.A6.82.E4.BD.95.E5.A4.84.E7.90.86.EF.BC.9F) + * [UnsupportedOperation.ContainDomesticAndInternationalPhoneNumber](https://cloud.tencent.com/document/product/382/9558#.E7.9F.AD.E4.BF.A1.E5.8F.91.E9.80.81.E6.8F.90.E7.A4.BA.EF.BC.9Aunsupportedoperation.containdomesticandinternationalphonenumber-.E5.A6.82.E4.BD.95.E5.A4.84.E7.90.86.EF.BC.9F) + * 更多错误,可咨询[腾讯云助手](https://tccc.qcloud.com/web/im/index.html#/chat?webAppId=8fa15978f85cb41f7e2ea36920cb3ae1&title=Sms) + */ + + return nil +} + +// GetTemp 获取模板 +func (l *Tencent) GetTemp(ctx context.Context) ([]interfaces.TemplateInfo, error) { + if l.client == nil { + return nil, errors.New("not init") + } + // International 是 Integer 是否国际/港澳台短信: + // 0:表示国内短信。 + // 1:表示国际/港澳台短信。 + // 示例值:0 + + // 国内 + ins, err := l.getTempPages(ctx, 0) + l.logger.Infof(ctx, "ins:%+v", ins) + if err != nil { + return nil, err + } + + // 国外 + outs, err := l.getTempPages(ctx, 1) + l.logger.Infof(ctx, "outs:%+v", outs) + if err != nil { + return nil, err + } + + return append(ins, outs...), nil + +} + +func (l *Tencent) getTempPages(ctx context.Context, internal uint64) ([]interfaces.TemplateInfo, error) { + page := 0 + list := []interfaces.TemplateInfo{} + + for { + page++ + r, err := l.getTemp(ctx, uint64(page), internal) + if err != nil { + return nil, err + } + // break + if len(r) == 0 { + break + } + list = append(list, r...) + } + return list, nil +} + +// 文档 +// https://cloud.tencent.com/document/api/382/52067 +func (l *Tencent) getTemp(ctx context.Context, page uint64, internal uint64) ([]interfaces.TemplateInfo, error) { + + // 实例化一个请求对象,每个接口都会对应一个request对象 + request := sms.NewDescribeSmsTemplateListRequest() + + request.Limit = common.Uint64Ptr(10) + request.Offset = common.Uint64Ptr((page - 1) * 10) + request.International = common.Uint64Ptr(internal) + + // 返回的resp是一个DescribeSmsTemplateListResponse的实例,与请求对象对应 + response, err := l.client.DescribeSmsTemplateList(request) + if _, ok := err.(*errorsTen.TencentCloudSDKError); ok { + l.logger.Errorf(ctx, "An API error has returned: %s", err) + return nil, err + } + if err != nil { + // panic(err) + l.logger.Errorf(ctx, "An API error has returned: %s", err) + return nil, err + } + // 输出json格式的字符串回包 + // fmt.Printf("%s", response.ToJsonString()) + l.logger.Infof(ctx, "response:%+v", response.ToJsonString()) + + if response == nil || response.Response == nil { + l.logger.Errorf(ctx, "response is nil") + return nil, errors.New("response is nil") + } + + resps := []interfaces.TemplateInfo{} + + for _, val := range response.Response.DescribeTemplateStatusSet { + // fmt.Printf("pppppp:%+v\n", val) + info := interfaces.TemplateInfo{} + if val.TemplateId != nil { + info.TempId = fmt.Sprintf("%d", *val.TemplateId) + } + if val.TemplateName != nil { + info.TempName = *val.TemplateName + } + if val.TemplateContent != nil { + info.Content = *val.TemplateContent + + p := []entity.SmsTemplateParam{} + s := l.extractParams(*val.TemplateContent) + for _, v := range s { + p = append(p, entity.SmsTemplateParam{ + FieldName: v, + }) + } + info.Params = p + + } + if val.International != nil { + info.TempType = l.tempTypePlatToLocal(*val.International) + info.TempRange = l.tempRangePlatToLocal(*val.International) + } + if val.StatusCode != nil { + info.Status = l.auditStatusPlatToLocal(*val.StatusCode) + } + + resps = append(resps, info) + } + + // fmt.Printf("resps:%+v\n", resps) + + return resps, nil + +} + +// TempDel 删除模板 +func (l *Tencent) TempDel(ctx context.Context, templateId string) error { + if l.client == nil { + return errors.New("not init") + } + return nil +} + +// 判断作用范围 +func (l *Tencent) tempRangePlatToLocal(plat uint64) entity.SmsTemplateRange { + // 是否国际/港澳台短信,其中0表示国内短信,1表示国际/港澳台短信,3表示该模板既支持国内短信也支持国际/港澳台短信。 + switch plat { + case 0: + return entity.SmsTemplateRangeChina + case 1: + return entity.SmsTemplateRangeInternational + case 3: + return entity.SmsTemplateRangeGlobal + default: + return entity.SmsTemplateRangeChina // 若未找到匹配项,默认为国内短信 + } +} + +// 审核状态转换 +func (l *Tencent) auditStatusPlatToLocal(plat int64) entity.SmsTemplateStatus { + // 申请模板状态,其中0表示审核通过且已生效,1表示审核中,2表示审核通过待生效,-1表示审核未通过或审核失败。注:只有状态值为0时该模板才能使用。 + switch plat { + case 0: + return entity.SmsTemplateStatusPass + case 1: + return entity.SmsTemplateStatusAudit + case 2: + return entity.SmsTemplateStatusAudit + case -1: + return entity.SmsTemplateStatusUnPass + default: + return entity.SmsTemplateStatusUnPass // 若未找到匹配项,默认为审核未通过或审核失败 + } +} + +// 模板类型转换(查询接口没返回) +func (l *Tencent) tempTypePlatToLocal(plat uint64) entity.SmsTemplateType { + // 是否国际/港澳台短信,其中0表示国内短信,1表示国际/港澳台短信,3表示该模板既支持国内短信也支持国际/港澳台短信。 + return entity.SmsTemplateTypeUnknown +} + +// 提取参数 +func (l *Tencent) extractParams(str string) []string { + params := []string{} + for i := 0; i < len(str); i++ { + if str[i] == '{' { + start := i + for j := i + 1; j < len(str); j++ { + if str[j] == '}' { + params = append(params, str[start+1:j]) + i = j + break + } + } + } + } + return params +} diff --git a/tencent/tencent_test.go b/tencent/tencent_test.go new file mode 100644 index 0000000..5bf0fcf --- /dev/null +++ b/tencent/tencent_test.go @@ -0,0 +1,96 @@ +package tencent_test + +import ( + "context" + "encoding/json" + "fmt" + "testing" + + "code.yun.ink/pkg/smsx/entity" + "code.yun.ink/pkg/smsx/interfaces" + "code.yun.ink/pkg/smsx/tencent" + "github.com/yuninks/loggerx" +) + +// SecretId: "AKID73nQvEex74oGVcWCmJeltvpVxBCzvc5L", +// SecretKey: "CB378ye8QdfT2Yt2zmTyFJ9k7MYsKwW2", +// SignName: "破德商贸", +// SmsSdkAppId: "1400932084", + +// SecretId: "AKIDcWYTFrKdoLpBLLDvUtjCWgiaIsJaihOn", +// SecretKey: "gOVa2NZbTFtN7tnUicdffbwq0w1ZEB6e", +// SignName: "永济彭俊网络科技有限公司", +// SmsSdkAppId: "1400908293", + +func TestGetTemp(t *testing.T) { + ctx := context.Background() + + logger := loggerx.NewLogger(ctx) + + ten := tencent.Tencent{} + + ini, err := ten.InitSmsx(ctx, entity.SmsConfigData{ + SysType: entity.Platform3rdTypeTencent, + Tencent: &entity.SmsConfigDataTencent{ + SecretId: "AKIDb2b8SefT8YjgUBk8N0XtANMSZWFqLiIp", + SecretKey: "QxqstqipqkTzfKqGVdgr3Merx0uvoU3R", + SignName: "深圳宏建源贸易", + SmsSdkAppId: "1400883795", + }, + }, logger) + if err != nil { + t.Fatal(err) + } + resp, err := ini.GetTemp(ctx) + if err != nil { + t.Fatal(err) + } + + b, _ := json.Marshal(resp) + + logger.Infof(ctx, "sssss %s", string(b)) + + fmt.Println("sssss", string(b)) + + t.Log(resp) +} + +func TestSend(t *testing.T) { + ctx := context.Background() + + logger := loggerx.NewLogger(ctx) + + ten := tencent.Tencent{} + + // Tencent: &model.SmsConfigDataTencent{ + // SecretId: "AKID73nQvEex74oGVcWCmJeltvpVxBCzvc5L", + // SecretKey: "CB378ye8QdfT2Yt2zmTyFJ9k7MYsKwW2", + // SignName: "破德商贸", + // SmsSdkAppId: "1400932084", + // }, + + ini, err := ten.InitSmsx(ctx, entity.SmsConfigData{ + SysType: entity.Platform3rdTypeTencent, + Tencent: &entity.SmsConfigDataTencent{ + SecretId: "AKIDb2b8SefT8YjgUBk8N0XtANMSZWFqLiIp", + SecretKey: "QxqstqipqkTzfKqGVdgr3Merx0uvoU3R", + SignName: "深圳宏建源贸易", + SmsSdkAppId: "1400883795", + }, + },logger) + if err != nil { + t.Fatal(err) + } + + err = ini.Send(ctx, "2060882", "+85267369217", []interfaces.SmsSendParam{ + { + Field: "1", + Value: "123456", + }, + }) + if err != nil { + t.Fatal(err) + } + t.Log("success") + +}