package sms import ( "context" "encoding/json" "strings" "testing" openapi "github.com/alibabacloud-go/darabonba-openapi/v2/client" aliyun "github.com/alibabacloud-go/dysmsapi-20170525/v4/client" util "github.com/alibabacloud-go/tea-utils/v2/service" "github.com/alibabacloud-go/tea/tea" tencent "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/sms/v20210111" biz "kra/internal/biz/integration" "kra/internal/integration/runtimeconfig" ) type aliFake struct { calls int request *aliyun.SendSmsRequest code string } func (f *aliFake) SendSmsWithOptions(req *aliyun.SendSmsRequest, opts *util.RuntimeOptions) (*aliyun.SendSmsResponse, error) { f.calls++ f.request = req if tea.BoolValue(opts.Autoretry) { panic("SMS must not retry automatically") } return &aliyun.SendSmsResponse{Body: &aliyun.SendSmsResponseBody{Code: tea.String(f.code), BizId: tea.String("ali-message"), RequestId: tea.String("ali-request")}}, nil } type tcFake struct { calls int request *tencent.SendSmsRequest code string } func (f *tcFake) SendSmsWithContext(_ context.Context, req *tencent.SendSmsRequest) (*tencent.SendSmsResponse, error) { f.calls++ f.request = req return &tencent.SendSmsResponse{Response: &tencent.SendSmsResponseParams{RequestId: tea.String("tc-request"), SendStatusSet: []*tencent.SendStatus{{Code: tea.String(f.code), SerialNo: tea.String("tc-message")}}}}, nil } func testSender(t *testing.T, provider string) *Sender { t.Helper() store := runtimeconfig.NewStore() values := biz.DefaultIntegrationConfig("sms", provider) for k, v := range values { if v == "" { values[k] = "test-" + k } } raw, _ := json.Marshal(values) store.Set(runtimeconfig.Config{Kind: "sms", Provider: provider, Enabled: true, Values: raw}) return NewSender(store).(*Sender) } func TestAliyunSendAndRejection(t *testing.T) { s := testSender(t, "aliyun") f := &aliFake{code: "OK"} s.newAliyun = func(c *openapi.Config) (aliyunClient, error) { if tea.StringValue(c.Endpoint) != "dysmsapi.aliyuncs.com" || tea.StringValue(c.AccessKeySecret) != "test-access_key_secret" { t.Fatal("incorrect client configuration") } return f, nil } m := &biz.SMSMessage{Provider: "aliyun", Phone: "+8613800138000", NamedParams: map[string]string{"code": "123456"}} result, err := s.Send(context.Background(), m) if err != nil || result.MessageID != "ali-message" { t.Fatalf("result=%v error=%v", result, err) } if tea.StringValue(f.request.PhoneNumbers) != "13800138000" || tea.StringValue(f.request.TemplateParam) != `{"code":"123456"}` || tea.StringValue(f.request.TemplateCode) != "test-template_id" { t.Fatal("incorrect Aliyun request") } f.code = "isv.BUSINESS_LIMIT_CONTROL" if _, err = s.Send(context.Background(), m); err == nil || !strings.Contains(err.Error(), f.code) { t.Fatalf("provider rejection not surfaced: %v", err) } if f.calls != 2 { t.Fatal("unexpected retry") } } func TestTencentSendAndRejection(t *testing.T) { s := testSender(t, "tencent") f := &tcFake{code: "Ok"} s.newTencent = func(id, key, region string) (tencentClient, error) { return f, nil } m := &biz.SMSMessage{Provider: "tencent", Phone: "+8613800138000", Params: []string{"123456", "5"}} result, err := s.Send(context.Background(), m) if err != nil || result.MessageID != "tc-message" { t.Fatalf("result=%v error=%v", result, err) } if len(f.request.PhoneNumberSet) != 1 || *f.request.PhoneNumberSet[0] != m.Phone || len(f.request.TemplateParamSet) != 2 || *f.request.TemplateParamSet[1] != "5" || *f.request.SmsSdkAppId != "test-sdk_app_id" { t.Fatal("incorrect Tencent request") } f.code = "FailedOperation.SignatureIncorrectOrUnapproved" if _, err = s.Send(context.Background(), m); err == nil || !strings.Contains(err.Error(), f.code) { t.Fatalf("provider rejection not surfaced: %v", err) } c, _ := s.store.Get("sms", "tencent") c.Enabled = false s.store.Set(c) if _, err = s.Send(context.Background(), m); err == nil { t.Fatal("disabled channel sent SMS") } if f.calls != 2 { t.Fatal("disabled channel reached SDK") } } func TestSDKErrorDoesNotExposeRawMessage(t *testing.T) { err := sdkError(&tea.SDKError{Code: tea.String("InvalidAccessKeyId.NotFound"), Message: tea.String("secret +8613800138000 signed request")}) if strings.Contains(err.Error(), "secret") || strings.Contains(err.Error(), "13800138000") || !strings.Contains(err.Error(), "InvalidAccessKeyId.NotFound") { t.Fatalf("unsafe error: %v", err) } }