tencent_captcha_service.go 2.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. package repository
  2. import (
  3. "context"
  4. "fmt"
  5. "github.com/Wei-Shaw/sub2api/internal/service"
  6. captcha "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/captcha/v20190722"
  7. "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common"
  8. "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/profile"
  9. )
  10. type tencentCaptchaAPI interface {
  11. DescribeCaptchaResultWithContext(context.Context, *captcha.DescribeCaptchaResultRequest) (*captcha.DescribeCaptchaResultResponse, error)
  12. }
  13. type tencentCaptchaClientFactory func(secretID, secretKey, endpoint string) (tencentCaptchaAPI, error)
  14. type tencentCaptchaVerifier struct {
  15. newClient tencentCaptchaClientFactory
  16. }
  17. func NewTencentCaptchaVerifier() service.TencentCaptchaVerifier {
  18. return &tencentCaptchaVerifier{newClient: newTencentCaptchaSDKClient}
  19. }
  20. // newTencentCaptchaSDKClient 接入点由调用方按站点下发(中国站 / 国际站)。
  21. // service 层的 tencentCaptchaEndpoint 已保证 endpoint 非空;即便为空,
  22. // 腾讯 SDK 也会回落到服务默认域 captcha.tencentcloudapi.com(即中国站),不会失败。
  23. func newTencentCaptchaSDKClient(secretID, secretKey, endpoint string) (tencentCaptchaAPI, error) {
  24. clientProfile := profile.NewClientProfile()
  25. clientProfile.HttpProfile.Endpoint = endpoint
  26. clientProfile.HttpProfile.ReqMethod = "POST"
  27. clientProfile.HttpProfile.ReqTimeout = 5
  28. return captcha.NewClient(common.NewCredential(secretID, secretKey), "", clientProfile)
  29. }
  30. func (v *tencentCaptchaVerifier) VerifyTicket(ctx context.Context, credentials service.TencentCaptchaCredentials, proof service.TencentCaptchaProof, remoteIP string) (*service.TencentCaptchaVerifyResponse, error) {
  31. client, err := v.newClient(credentials.CloudSecretID, credentials.CloudSecretKey, credentials.Endpoint)
  32. if err != nil {
  33. return nil, fmt.Errorf("create tencent captcha client: %w", err)
  34. }
  35. request := captcha.NewDescribeCaptchaResultRequest()
  36. request.CaptchaType = common.Uint64Ptr(9)
  37. request.Ticket = common.StringPtr(proof.Ticket)
  38. request.UserIp = common.StringPtr(remoteIP)
  39. request.Randstr = common.StringPtr(proof.Randstr)
  40. request.CaptchaAppId = common.Uint64Ptr(credentials.AppID)
  41. request.AppSecretKey = common.StringPtr(credentials.AppSecretKey)
  42. response, err := client.DescribeCaptchaResultWithContext(ctx, request)
  43. if err != nil {
  44. return nil, fmt.Errorf("describe captcha result: %w", err)
  45. }
  46. if response == nil || response.Response == nil {
  47. return nil, fmt.Errorf("describe captcha result: empty response")
  48. }
  49. return &service.TencentCaptchaVerifyResponse{
  50. CaptchaCode: valueOrZero(response.Response.CaptchaCode),
  51. CaptchaMsg: valueOrEmpty(response.Response.CaptchaMsg),
  52. RequestID: valueOrEmpty(response.Response.RequestId),
  53. }, nil
  54. }
  55. func valueOrZero(value *int64) int64 {
  56. if value == nil {
  57. return 0
  58. }
  59. return *value
  60. }
  61. func valueOrEmpty(value *string) string {
  62. if value == nil {
  63. return ""
  64. }
  65. return *value
  66. }