aliyun_captcha_verifier.go 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. package repository
  2. import (
  3. "context"
  4. "errors"
  5. "fmt"
  6. captcha "github.com/alibabacloud-go/captcha-20230305/client"
  7. openapiutil "github.com/alibabacloud-go/darabonba-openapi/v2/utils"
  8. "github.com/alibabacloud-go/tea/dara"
  9. "github.com/alibabacloud-go/tea/tea"
  10. "github.com/Wei-Shaw/sub2api/internal/service"
  11. )
  12. const aliyunCaptchaTimeoutMillis = 10_000
  13. type aliyunCaptchaVerifier struct {
  14. protocol string // "HTTPS";测试注入 "HTTP" 指向 httptest.Server
  15. timeoutMillis int
  16. }
  17. func NewAliyunCaptchaVerifier() service.AliyunCaptchaVerifier {
  18. return &aliyunCaptchaVerifier{
  19. protocol: "HTTPS",
  20. timeoutMillis: aliyunCaptchaTimeoutMillis,
  21. }
  22. }
  23. // VerifyCaptcha 调用阿里云验证码 2.0 VerifyIntelligentCaptcha。
  24. // AK/SK 是可热更的后台设置,每次调用按当前凭证新建 client。
  25. func (v *aliyunCaptchaVerifier) VerifyCaptcha(ctx context.Context, cred service.AliyunCaptchaCredentials, captchaVerifyParam string) (*service.AliyunCaptchaVerifyResult, error) {
  26. client, err := captcha.NewClient(&openapiutil.Config{
  27. AccessKeyId: dara.String(cred.AccessKeyID),
  28. AccessKeySecret: dara.String(cred.AccessKeySecret),
  29. Endpoint: dara.String(cred.Endpoint),
  30. Protocol: dara.String(v.protocol),
  31. ConnectTimeout: dara.Int(v.timeoutMillis),
  32. ReadTimeout: dara.Int(v.timeoutMillis),
  33. })
  34. if err != nil {
  35. return nil, fmt.Errorf("create aliyun captcha client: %w", err)
  36. }
  37. request := &captcha.VerifyIntelligentCaptchaRequest{
  38. CaptchaVerifyParam: dara.String(captchaVerifyParam),
  39. SceneId: dara.String(cred.SceneID),
  40. }
  41. response, err := client.VerifyIntelligentCaptchaWithContext(ctx, request, &dara.RuntimeOptions{})
  42. if err != nil {
  43. return nil, normalizeAliyunCaptchaError(err)
  44. }
  45. result := &service.AliyunCaptchaVerifyResult{}
  46. if body := response.Body; body != nil && body.Result != nil {
  47. result.VerifyResult = dara.BoolValue(body.Result.VerifyResult)
  48. result.VerifyCode = dara.StringValue(body.Result.VerifyCode)
  49. }
  50. return result, nil
  51. }
  52. // normalizeAliyunCaptchaError 把 SDK 的两种错误类型归一化为 service.AliyunCaptchaAPIError,
  53. // 其余错误(网络/超时等)原样返回。
  54. func normalizeAliyunCaptchaError(err error) error {
  55. var teaErr *tea.SDKError
  56. if errors.As(err, &teaErr) {
  57. return &service.AliyunCaptchaAPIError{
  58. Code: tea.StringValue(teaErr.Code),
  59. Message: tea.StringValue(teaErr.Message),
  60. }
  61. }
  62. var daraErr *dara.SDKError
  63. if errors.As(err, &daraErr) {
  64. return &service.AliyunCaptchaAPIError{
  65. Code: dara.StringValue(daraErr.Code),
  66. Message: dara.StringValue(daraErr.Message),
  67. }
  68. }
  69. return err
  70. }