verifycode.go 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. package verifycode
  2. import (
  3. "fmt"
  4. "strings"
  5. "sync"
  6. "github.com/runningwater/gohub/pkg/app"
  7. "github.com/runningwater/gohub/pkg/config"
  8. "github.com/runningwater/gohub/pkg/helpers"
  9. "github.com/runningwater/gohub/pkg/logger"
  10. "github.com/runningwater/gohub/pkg/mail"
  11. "github.com/runningwater/gohub/pkg/sms"
  12. // "github.com/runningwater/gohub/pkg/sms"
  13. )
  14. type VerifyCode struct {
  15. Store Store
  16. }
  17. var once sync.Once
  18. var internalVerifyCode *VerifyCode
  19. func NewVerifyCode() *VerifyCode {
  20. once.Do(func() {
  21. internalVerifyCode = &VerifyCode{
  22. Store: NewRedisStore(),
  23. }
  24. })
  25. return internalVerifyCode
  26. }
  27. // SendSMS 发送验证码
  28. // 发送验证码到手机, 调用示例
  29. //
  30. // verifycode.NewVerifyCode().SendSMS(request.Phone)
  31. func (v *VerifyCode) SendSMS(phone string) bool {
  32. // 生成验证码
  33. code := v.generateVerifyCode(phone)
  34. // 方便本地和 测试环境调试
  35. if !app.IsProduction() &&
  36. strings.HasPrefix(phone, config.GetString("verifycode.debug_phone_prefix")) {
  37. // 测试环境,直接返回成功
  38. return true
  39. }
  40. logger.DebugJSON("验证码", "发送验证码", map[string]string{phone: code})
  41. // return true
  42. // 发送验证码
  43. return sms.NewSMS().Send(phone, sms.Message{
  44. Template: config.GetString("sms.aliyun.template_code"),
  45. Data: map[string]string{"code": code},
  46. })
  47. }
  48. // SendEmail 发送验证码
  49. // 发送验证码到邮箱, 调用示例
  50. //
  51. // verifycode.NewVerifyCode().SendEmail(request.Email)
  52. func (v *VerifyCode) SendEmail(email string) error {
  53. // 生成验证码
  54. code := v.generateVerifyCode(email)
  55. // 方便本地和 测试环境调试
  56. if !app.IsProduction() &&
  57. strings.HasSuffix(email, config.GetString("verifycode.debug_email_suffix")) {
  58. return nil
  59. }
  60. content := fmt.Sprintf("<p>您的验证码是:%v</p>", code)
  61. // 发送邮件
  62. mail.NewMailer().Send(mail.Email{
  63. From: mail.From{
  64. Address: config.GetString("mail.from.address"),
  65. Name: config.GetString("mail.from.name"),
  66. },
  67. To: []string{email},
  68. Subject: "Email 验证码",
  69. HTML: []byte(content),
  70. })
  71. return nil
  72. }
  73. // CheckAnswer 检查验证码是否正确
  74. // key: 手机号 或 Email
  75. func (v *VerifyCode) CheckAnswer(key, answer string) bool {
  76. logger.DebugJSON("验证码", "检查验证码是否正确", map[string]string{key: answer})
  77. // 方便本地和 测试环境调试
  78. if !app.IsProduction() &&
  79. (strings.HasPrefix(key, config.GetString("verifycode.debug_phone_prefix")) || strings.HasPrefix(key, config.GetString("verifycode.debug_email_prefix"))) {
  80. return true
  81. }
  82. return v.Store.Verify(key, answer, false)
  83. }
  84. // 生成验证码, 并放置于 Redis 中
  85. func (v *VerifyCode) generateVerifyCode(key string) string {
  86. // 生成随机码
  87. code := helpers.RandomNumber(config.GetInt("verifycode.code_length"))
  88. if app.IsLocal() {
  89. code = config.GetString("verifycode.debug_code")
  90. }
  91. logger.DebugJSON("验证码", "生成验证码", map[string]string{key: code})
  92. // 存储验证码到 Redis
  93. v.Store.Set(key, code)
  94. return code
  95. }