package kyc import ( "crypto/md5" "encoding/base64" "encoding/hex" "encoding/json" "errors" "fmt" "nixcn-cms/internal/cryptography" "unicode/utf8" alicloudauth20190307 "github.com/alibabacloud-go/cloudauth-20190307/v4/client" aliopenapi "github.com/alibabacloud-go/darabonba-openapi/v2/client" aliutil "github.com/alibabacloud-go/tea-utils/v2/service" alitea "github.com/alibabacloud-go/tea/tea" alicredential "github.com/aliyun/credentials-go/credentials" "github.com/spf13/viper" ) func DecodeB64Json(b64Json string) (*KycInfo, error) { rawJson, err := base64.StdEncoding.DecodeString(b64Json) if err != nil { return nil, errors.New("invalid base64 json") } var kyc KycInfo if err := json.Unmarshal(rawJson, &kyc); err != nil { return nil, errors.New("invalid json structure") } return &kyc, nil } func EncodeAES(kyc *KycInfo) (*string, error) { plainJson, err := json.Marshal(kyc) if err != nil { return nil, err } aesKey := viper.GetString("secrets.kyc_info_key") encrypted, err := cryptography.AESCBCEncrypt(plainJson, []byte(aesKey)) if err != nil { return nil, err } return &encrypted, nil } func DecodeAES(cipherStr string) (*KycInfo, error) { aesKey := viper.GetString("secrets.kyc_info_key") plainBytes, err := cryptography.AESCBCDecrypt(cipherStr, []byte(aesKey)) if err != nil { return nil, err } var kyc KycInfo if err := json.Unmarshal(plainBytes, &kyc); err != nil { return nil, errors.New("invalid decrypted json") } return &kyc, nil } func MD5AliEnc(kyc *KycInfo) (*KycAli, error) { if kyc.Type != "Chinese" { return nil, nil } // MD5 Legal Name rule: First Chinese char md5enc, remaining plain, at least 2 Chinese chars if len(kyc.LegalName) < 2 || utf8.RuneCountInString(kyc.LegalName) < 2 { return nil, fmt.Errorf("input string must have at least 2 Chinese characters") } lnFirstRune, size := utf8.DecodeRuneInString(kyc.LegalName) if lnFirstRune == utf8.RuneError { return nil, fmt.Errorf("invalid first character") } lnHash := md5.New() lnHash.Write([]byte(string(lnFirstRune))) lnFirstHash := hex.EncodeToString(lnHash.Sum(nil)) lnRemaining := kyc.LegalName[size:] ln := lnFirstHash + lnRemaining // MD5 Resident Id rule: First 6 char plain, middle birthdate md5enc, last 4 char plain, at least 18 chars if len(kyc.ResidentId) < 18 { return nil, fmt.Errorf("input string must have at least 18 characters") } ridPrefix := kyc.ResidentId[:6] ridSuffix := kyc.ResidentId[len(kyc.ResidentId)-4:] ridMiddle := kyc.ResidentId[6 : len(kyc.ResidentId)-4] ridHash := md5.New() ridHash.Write([]byte(ridMiddle)) ridMiddleHash := hex.EncodeToString(ridHash.Sum(nil)) rid := ridPrefix + ridMiddleHash + ridSuffix // Aliyun Id2MetaVerify API Params var kycAli KycAli kycAli.ParamType = "md5" kycAli.UserName = ln kycAli.IdentifyNum = rid return &kycAli, nil } func AliId2MetaVerify(kycAli *KycAli) (*string, error) { // Create aliyun openapi credential credentialConfig := new(alicredential.Config). SetType("access_key"). SetAccessKeyId(viper.GetString("kyc.ali_access_key_id")). SetAccessKeySecret(viper.GetString("kyc.ali_access_key_secret")) credential, err := alicredential.NewCredential(credentialConfig) if err != nil { return nil, err } // Create aliyun cloudauth client config := &aliopenapi.Config{ Credential: credential, } config.Endpoint = alitea.String("cloudauth.aliyuncs.com") client := &alicloudauth20190307.Client{} client, err = alicloudauth20190307.NewClient(config) if err != nil { return nil, err } // Create Id2MetaVerify request id2MetaVerifyRequest := &alicloudauth20190307.Id2MetaVerifyRequest{ ParamType: &kycAli.ParamType, UserName: &kycAli.UserName, IdentifyNum: &kycAli.IdentifyNum, } // Create client runtime request runtime := &aliutil.RuntimeOptions{} resp, tryErr := func() (*alicloudauth20190307.Id2MetaVerifyResponse, error) { defer func() { if r := alitea.Recover(recover()); r != nil { err = r } }() resp, err := client.Id2MetaVerifyWithOptions(id2MetaVerifyRequest, runtime) if err != nil { return nil, err } return resp, nil }() // Try error handler ??? from ali generated sdk if tryErr != nil { var error = &alitea.SDKError{} if t, ok := tryErr.(*alitea.SDKError); ok { error = t } else { error.Message = alitea.String(tryErr.Error()) } return nil, error } return resp.Body.ResultObject.BizCode, err }