package service import ( "context" "errors" "sync" "time" "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" "laic-backend/service/smsrpc" ) const ( smsRequestTimeout = time.Second smsLoginTemplateID = "SMS_73670083" smsRegisterTemplate = "SMS_73670081" ) type smsTemplate struct { verifyType int32 id string } var smsTemplates = map[string]smsTemplate{ "login": {verifyType: 1, id: smsLoginTemplateID}, "register": {verifyType: 2, id: smsRegisterTemplate}, "reset": {verifyType: 1, id: smsLoginTemplateID}, } type smsRPCClient struct { mu sync.Mutex url string conn *grpc.ClientConn close func() error } var defaultSMSRPCClient smsRPCClient func sendSMS(url, scene, phone, code string) error { template, ok := smsTemplates[scene] if !ok || url == "" { return errors.New("短信服务配置错误") } client, err := defaultSMSRPCClient.client(url) if err != nil { return err } ctx, cancel := context.WithTimeout(context.Background(), smsRequestTimeout) defer cancel() result, err := client.SendSms(ctx, &message.SmsRequest{ VerifyCode: code, VerifyType: template.verifyType, SmsId: template.id, Phone: phone, }) if err != nil || result == nil || !result.Value { return errors.New("短信发送失败") } return nil } func (c *smsRPCClient) client(url string) (message.SmsClient, error) { c.mu.Lock() defer c.mu.Unlock() if c.conn != nil && c.url == url { return message.NewSmsClient(c.conn), nil } if c.close != nil { _ = c.close() } conn, err := grpc.NewClient(url, grpc.WithTransportCredentials(insecure.NewCredentials())) if err != nil { return nil, err } c.url = url c.conn = conn c.close = conn.Close return message.NewSmsClient(conn), nil }