|
| 1 | +package tencent |
| 2 | + |
| 3 | +import ( |
| 4 | + "context" |
| 5 | + "errors" |
| 6 | + "strconv" |
| 7 | + |
| 8 | + "github.com/cloudwego/hertz/pkg/common/json" |
| 9 | + "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common" |
| 10 | + tencenterrors "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/errors" |
| 11 | + "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/profile" |
| 12 | + tencentsms "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/sms/v20210111" |
| 13 | + "github.com/xh-polaris/synapse/biz/conf" |
| 14 | + "github.com/xh-polaris/synapse/biz/infra/contract/cache" |
| 15 | + "github.com/xh-polaris/synapse/biz/infra/contract/sms" |
| 16 | + "github.com/xh-polaris/synapse/biz/pkg/logs" |
| 17 | +) |
| 18 | + |
| 19 | +type tencentSMS struct { |
| 20 | + cache *sms.Cache |
| 21 | + client *tencentsms.Client |
| 22 | +} |
| 23 | + |
| 24 | +func New(ctx context.Context, cache *sms.Cache, account, token string) (sms.Provider, error) { |
| 25 | + s, err := getTencentSMSProvider(ctx, cache, account, token) |
| 26 | + if err != nil { |
| 27 | + return nil, err |
| 28 | + } |
| 29 | + return s, nil |
| 30 | +} |
| 31 | + |
| 32 | +func getTencentSMSProvider(_ context.Context, cache *sms.Cache, secretId, secretKey string) (sms.Provider, error) { |
| 33 | + credential := common.NewCredential(secretId, secretKey) |
| 34 | + client, err := tencentsms.NewClient(credential, "ap-guangzhou", profile.NewClientProfile()) |
| 35 | + if err != nil { |
| 36 | + return nil, err |
| 37 | + } |
| 38 | + return &tencentSMS{cache: cache, client: client}, nil |
| 39 | +} |
| 40 | + |
| 41 | +func (t *tencentSMS) Send(ctx context.Context, app, cause, phone string, param *sms.SMSParam) (err error) { |
| 42 | + // 发送短信 |
| 43 | + if _, err = t.send(ctx, app, cause, phone, param); err != nil { |
| 44 | + return err |
| 45 | + } |
| 46 | + expire := param.Expire |
| 47 | + |
| 48 | + if err = t.cache.Store(ctx, app, cause, phone, param.Code, expire); err != nil { |
| 49 | + return err |
| 50 | + } |
| 51 | + return nil |
| 52 | +} |
| 53 | + |
| 54 | +func (t *tencentSMS) send(_ context.Context, app, cause, phone string, param *sms.SMSParam) (map[string]any, error) { |
| 55 | + // 参数设置 |
| 56 | + req := tencentsms.NewSendSmsRequest() |
| 57 | + req.SmsSdkAppId = common.StringPtr(conf.GetConfig().SMS.Extra["AppId"]) // 应用ID |
| 58 | + req.SignName = common.StringPtr(conf.GetConfig().SMS.Extra["Sign"]) // 签名内容 |
| 59 | + req.TemplateId = common.StringPtr(conf.GetConfig().SMS.AppConf[app][cause]) //模板ID |
| 60 | + req.TemplateParamSet = common.StringPtrs([]string{param.Code, strconv.Itoa(int(param.Expire.Minutes()))}) |
| 61 | + req.PhoneNumberSet = common.StringPtrs([]string{phone}) |
| 62 | + |
| 63 | + // 发送响应 |
| 64 | + resp, err := t.client.SendSms(req) |
| 65 | + |
| 66 | + // SDK 错误 |
| 67 | + var tencentCloudSDKError *tencenterrors.TencentCloudSDKError |
| 68 | + if errors.As(err, &tencentCloudSDKError) { |
| 69 | + logs.Errorf("An Tencent API error has returned: %s", err) |
| 70 | + } |
| 71 | + if err != nil { |
| 72 | + return nil, err |
| 73 | + } |
| 74 | + // 正常响应 |
| 75 | + r, respStr := map[string]any{}, resp.ToJsonString() |
| 76 | + if err = json.Unmarshal([]byte(respStr), &r); err != nil { |
| 77 | + logs.Infof("Tencent sms return resp %s but unmarsharl failed %s", respStr, err) |
| 78 | + } |
| 79 | + return r, nil |
| 80 | +} |
| 81 | +func (t *tencentSMS) Check(ctx context.Context, app, cause, phone, code string) (bool, error) { |
| 82 | + if code == "xh-polaris" && conf.GetConfig().State == "test" { |
| 83 | + return true, nil |
| 84 | + } |
| 85 | + ori, err := t.cache.Load(ctx, app, cause, phone) |
| 86 | + if errors.Is(err, cache.Nil) { |
| 87 | + return false, nil |
| 88 | + } |
| 89 | + return ori == code, err |
| 90 | +} |
0 commit comments