update ivyz5773

This commit is contained in:
liangzai 2025-04-02 18:30:48 +08:00
parent 689faa0739
commit 85dea05704
9 changed files with 287 additions and 59 deletions

View File

@ -3,25 +3,29 @@ Host: 0.0.0.0
Port: 10003 Port: 10003
DataSource: "tianyuanapi:g3h98u0291j@tcp(127.0.0.1:3307)/tianyuanapi?charset=utf8mb4&parseTime=True&loc=Local" DataSource: "tianyuanapi:g3h98u0291j@tcp(127.0.0.1:3307)/tianyuanapi?charset=utf8mb4&parseTime=True&loc=Local"
CacheRedis: CacheRedis:
- Host: "127.0.0.1:6379" - Host: "127.0.0.1:6379"
Pass: "" # Redis 密码,如果未设置则留空 Pass: "" # Redis 密码,如果未设置则留空
Type: "node" # 单节点模式 Type: "node" # 单节点模式
SentinelRpc: SentinelRpc:
Etcd: Etcd:
Hosts: Hosts:
- 127.0.0.1:2379 - 127.0.0.1:2379
Key: sentinel.rpc Key: sentinel.rpc
KqPusherConf: KqPusherConf:
Brokers: Brokers:
- 127.0.0.1:9092 - 127.0.0.1:9092
Topic: apirequest Topic: apirequest
WestConfig: WestConfig:
Url: "http://proxy.tianyuanapi.com/api/invoke" Url: "http://proxy.tianyuanapi.com/api/invoke"
Key: "121a1e41fc1690dd6b90afbcacd80cf4" Key: "121a1e41fc1690dd6b90afbcacd80cf4"
SecretId: "449159" SecretId: "449159"
SecretSecondId: "296804" SecretSecondId: "296804"
YushanConfig:
ApiKey: "4c566c4a4b543164535455685655316c"
AcctID: "YSSJ843926726"
Url: "https://api.yushanshuju.com/credit-gw/service"
UserRpc: UserRpc:
Etcd: Etcd:
Hosts: Hosts:
- 127.0.0.1:2379 - 127.0.0.1:2379
Key: user.rpc Key: user.rpc

View File

@ -3,25 +3,29 @@ Host: 0.0.0.0
Port: 10003 Port: 10003
DataSource: "tianyuanapi:g3h98u0291j@tcp(tyapi_mysql:3306)/tianyuanapi?charset=utf8mb4&parseTime=True&loc=Local" DataSource: "tianyuanapi:g3h98u0291j@tcp(tyapi_mysql:3306)/tianyuanapi?charset=utf8mb4&parseTime=True&loc=Local"
CacheRedis: CacheRedis:
- Host: "tyapi_redis:6379" - Host: "tyapi_redis:6379"
Pass: "" # Redis 密码,如果未设置则留空 Pass: "" # Redis 密码,如果未设置则留空
Type: "node" # 单节点模式 Type: "node" # 单节点模式
SentinelRpc: SentinelRpc:
Etcd: Etcd:
Hosts: Hosts:
- tyapi_etcd:2379 - tyapi_etcd:2379
Key: sentinel.rpc Key: sentinel.rpc
UserRpc: UserRpc:
Etcd: Etcd:
Hosts: Hosts:
- tyapi_etcd:2379 - tyapi_etcd:2379
Key: user.rpc Key: user.rpc
KqPusherConf: KqPusherConf:
Brokers: Brokers:
- tyapi_kafka:9092 - tyapi_kafka:9092
Topic: apirequest Topic: apirequest
WestConfig: WestConfig:
Url: "https://apimaster.westdex.com.cn/api/invoke" Url: "https://apimaster.westdex.com.cn/api/invoke"
Key: "121a1e41fc1690dd6b90afbcacd80cf4" Key: "121a1e41fc1690dd6b90afbcacd80cf4"
SecretId: "449159" SecretId: "449159"
SecretSecondId: "296804" SecretSecondId: "296804"
YushanConfig:
ApiKey: "4c566c4a4b543164535455685655316c"
AcctID: "YSSJ843926726"
Url: "https://api.yushanshuju.com/credit-gw/service"

View File

@ -14,6 +14,7 @@ type Config struct {
UserRpc zrpc.RpcClientConf UserRpc zrpc.RpcClientConf
KqPusherConf KqPusherConf KqPusherConf KqPusherConf
WestConfig WestConfig WestConfig WestConfig
YushanConfig YushanConfig
} }
type KqPusherConf struct { type KqPusherConf struct {
Brokers []string Brokers []string
@ -25,3 +26,8 @@ type WestConfig struct {
SecretId string SecretId string
SecretSecondId string SecretSecondId string
} }
type YushanConfig struct {
ApiKey string
AcctID string
Url string
}

View File

@ -4,11 +4,11 @@ import (
"context" "context"
"encoding/hex" "encoding/hex"
"encoding/json" "encoding/json"
"tianyuan-api/apps/api/internal/common" "errors"
"tianyuan-api/apps/api/internal/service"
"tianyuan-api/apps/api/internal/svc" "tianyuan-api/apps/api/internal/svc"
"tianyuan-api/apps/api/internal/types" "tianyuan-api/apps/api/internal/types"
"tianyuan-api/apps/api/internal/validator" "tianyuan-api/apps/api/internal/validator"
"tianyuan-api/apps/api/internal/westmodel"
"tianyuan-api/pkg/crypto" "tianyuan-api/pkg/crypto"
"tianyuan-api/pkg/errs" "tianyuan-api/pkg/errs"
@ -79,31 +79,42 @@ func (l *IVYZ5733Logic) IVYZ5733(req *types.Request) (resp string, err *errs.App
} }
// 3、西部加密 // 3、西部加密
westConfig := l.svcCtx.Config.WestConfig // westConfig := l.svcCtx.Config.WestConfig
encryptedFields, encryptStructFieldsErr := common.EncryptStructFields(data, westConfig.Key) // encryptedFields, encryptStructFieldsErr := common.EncryptStructFields(data, westConfig.Key)
if encryptStructFieldsErr != nil { // if encryptStructFieldsErr != nil {
logx.Errorf("西部加密错误:%v", encryptStructFieldsErr) // logx.Errorf("西部加密错误:%v", encryptStructFieldsErr)
return "", errs.ErrSystem // return "", errs.ErrSystem
} // }
// 4、发送请求到西部 // 4、发送请求到西部
logx.Infof("交易号:%s", transactionID) logx.Infof("交易号:%s", transactionID)
apiRequest := common.MapStructToAPIRequest(encryptedFields, westmodel.IVYZ5733FieldMapping, "data") // apiRequest := common.MapStructToAPIRequest(encryptedFields, westmodel.IVYZ5733FieldMapping, "data")
westResp, callAPIErr := l.svcCtx.WestDexService.CallAPI("G09SC02", apiRequest, l.svcCtx.Config.WestConfig.SecretId) // westResp, callAPIErr := l.svcCtx.WestDexService.CallAPI("G09SC02", apiRequest, l.svcCtx.Config.WestConfig.SecretId)
// if callAPIErr != nil {
// if callAPIErr.Code == errs.ErrDataSource.Code {
// encryptData, aesEncrypt := crypto.AesEncrypt(westResp, key)
// if aesEncrypt != nil {
// return "", errs.ErrSystem
// }
// return encryptData, callAPIErr
// }
// return "", callAPIErr
// }
apiRequest := map[string]interface{}{
"cardNo": data.IDCard,
"name": data.Name,
}
respData, callAPIErr := l.svcCtx.YushanService.Request("IDV044", apiRequest)
if callAPIErr != nil { if callAPIErr != nil {
if callAPIErr.Code == errs.ErrDataSource.Code { if errors.Is(callAPIErr, service.NotFound) {
encryptData, aesEncrypt := crypto.AesEncrypt(westResp, key) return "", errs.ErrNotFound
if aesEncrypt != nil {
return "", errs.ErrSystem
}
return encryptData, callAPIErr
} }
return "", callAPIErr return "", errs.ErrSystem
} }
encryptData, aesEncrypt := crypto.AesEncrypt(westResp, key) encryptData, aesEncrypt := crypto.AesEncrypt(respData, key)
if aesEncrypt != nil { if aesEncrypt != nil {
return "", errs.ErrSystem return "", errs.ErrSystem
} }

View File

@ -0,0 +1,190 @@
package service
import (
"bytes"
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"encoding/base64"
"encoding/hex"
"encoding/json"
"fmt"
"io"
"net/http"
"strings"
"tianyuan-api/apps/api/internal/config"
"time"
"github.com/tidwall/gjson"
)
var NotFound = fmt.Errorf("查询为空")
type YushanService struct {
config config.YushanConfig
}
func NewYushanService(c config.YushanConfig) *YushanService {
return &YushanService{
config: c,
}
}
func (y *YushanService) Request(prodID string, params map[string]interface{}) ([]byte, error) {
// 获取当前时间戳
unixMilliseconds := time.Now().UnixNano() / int64(time.Millisecond)
// 生成请求序列号
requestSN, _ := y.GenerateRandomString()
// 构建请求数据
reqData := map[string]interface{}{
"prod_id": prodID,
"req_time": unixMilliseconds,
"request_sn": requestSN,
"req_data": params,
}
// 将请求数据转换为 JSON 字节数组
messageBytes, err := json.Marshal(reqData)
if err != nil {
return nil, err
}
// 获取 API 密钥
key, err := hex.DecodeString(y.config.ApiKey)
if err != nil {
return nil, err
}
// 使用 AES CBC 加密请求数据
cipherText := y.AES_CBC_Encrypt(messageBytes, key)
// 将加密后的数据编码为 Base64 字符串
content := base64.StdEncoding.EncodeToString(cipherText)
// 发起 HTTP 请求
client := &http.Client{}
req, err := http.NewRequest("POST", y.config.Url, strings.NewReader(content))
if err != nil {
return nil, err
}
req.Header.Set("Content-Type", "application/json")
req.Header.Set("ACCT_ID", y.config.AcctID)
// 执行请求
resp, err := client.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
// 读取响应体
body, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}
var respData []byte
if IsJSON(string(body)) {
respData = body
} else {
sDec, err := base64.StdEncoding.DecodeString(string(body))
if err != nil {
return nil, err
}
respData = y.AES_CBC_Decrypt(sDec, key)
}
retCode := gjson.GetBytes(respData, "retcode").String()
if retCode == "100000" {
// retcode 为 100000表示查询为空
// return nil, fmt.Errorf("羽山请求查空: %s", string(respData))
return nil, NotFound
} else if retCode == "000000" {
// retcode 为 000000表示有数据返回 retdata
retData := gjson.GetBytes(respData, "retdata")
if !retData.Exists() {
return nil, fmt.Errorf("羽山请求retdata为空: %s", string(respData))
}
return []byte(retData.Raw), nil
} else {
return nil, fmt.Errorf("羽山请求未知的状态码: %s", string(respData))
}
}
// 判断字符串是否为 JSON 格式
func IsJSON(s string) bool {
var js interface{}
return json.Unmarshal([]byte(s), &js) == nil
}
// GenerateRandomString 生成一个32位的随机字符串订单号
func (y *YushanService) GenerateRandomString() (string, error) {
// 创建一个16字节的数组
bytes := make([]byte, 16)
// 读取随机字节到数组中
if _, err := rand.Read(bytes); err != nil {
return "", err
}
// 将字节数组编码为16进制字符串
return hex.EncodeToString(bytes), nil
}
// AEC加密CBC模式
func (y *YushanService) AES_CBC_Encrypt(plainText []byte, key []byte) []byte {
//指定加密算法返回一个AES算法的Block接口对象
block, err := aes.NewCipher(key)
if err != nil {
panic(err)
}
//进行填充
plainText = Padding(plainText, block.BlockSize())
//指定初始向量vi,长度和block的块尺寸一致
iv := []byte("0000000000000000")
//指定分组模式返回一个BlockMode接口对象
blockMode := cipher.NewCBCEncrypter(block, iv)
//加密连续数据库
cipherText := make([]byte, len(plainText))
blockMode.CryptBlocks(cipherText, plainText)
//返回base64密文
return cipherText
}
// AEC解密CBC模式
func (y *YushanService) AES_CBC_Decrypt(cipherText []byte, key []byte) []byte {
//指定解密算法返回一个AES算法的Block接口对象
block, err := aes.NewCipher(key)
if err != nil {
panic(err)
}
//指定初始化向量IV,和加密的一致
iv := []byte("0000000000000000")
//指定分组模式返回一个BlockMode接口对象
blockMode := cipher.NewCBCDecrypter(block, iv)
//解密
plainText := make([]byte, len(cipherText))
blockMode.CryptBlocks(plainText, cipherText)
//删除填充
plainText = UnPadding(plainText)
return plainText
} // 对明文进行填充
func Padding(plainText []byte, blockSize int) []byte {
//计算要填充的长度
n := blockSize - len(plainText)%blockSize
//对原来的明文填充n个n
temp := bytes.Repeat([]byte{byte(n)}, n)
plainText = append(plainText, temp...)
return plainText
}
// 对密文删除填充
func UnPadding(cipherText []byte) []byte {
//取出密文最后一个字节end
end := cipherText[len(cipherText)-1]
//删除填充
cipherText = cipherText[:len(cipherText)-int(end)]
return cipherText
}

View File

@ -1,16 +1,17 @@
package svc package svc
import ( import (
"github.com/zeromicro/go-queue/kq"
"github.com/zeromicro/go-zero/core/stores/redis"
"github.com/zeromicro/go-zero/rest"
"github.com/zeromicro/go-zero/zrpc"
"tianyuan-api/apps/api/internal/config" "tianyuan-api/apps/api/internal/config"
"tianyuan-api/apps/api/internal/middleware" "tianyuan-api/apps/api/internal/middleware"
"tianyuan-api/apps/api/internal/service" "tianyuan-api/apps/api/internal/service"
"tianyuan-api/apps/sentinel/sentinel" "tianyuan-api/apps/sentinel/sentinel"
"tianyuan-api/apps/user/user" "tianyuan-api/apps/user/user"
"time" "time"
"github.com/zeromicro/go-queue/kq"
"github.com/zeromicro/go-zero/core/stores/redis"
"github.com/zeromicro/go-zero/rest"
"github.com/zeromicro/go-zero/zrpc"
) )
type ServiceContext struct { type ServiceContext struct {
@ -23,6 +24,7 @@ type ServiceContext struct {
ProductRpc sentinel.ProductClient ProductRpc sentinel.ProductClient
UserProductRpc sentinel.UserProductClient UserProductRpc sentinel.UserProductClient
WestDexService *service.WestDexService WestDexService *service.WestDexService
YushanService *service.YushanService
ApiRequestMqsService *service.ApiRequestMqsService ApiRequestMqsService *service.ApiRequestMqsService
} }
type ApiRequestMessage struct { type ApiRequestMessage struct {
@ -61,5 +63,6 @@ func NewServiceContext(c config.Config) *ServiceContext {
ApiMqsInterceptor: middleware.NewApiMqsInterceptorMiddleware(apiRequestMqsService).Handle, ApiMqsInterceptor: middleware.NewApiMqsInterceptorMiddleware(apiRequestMqsService).Handle,
ApiRequestMqsService: apiRequestMqsService, ApiRequestMqsService: apiRequestMqsService,
WestDexService: service.NewWestDexService(c.WestConfig), // 假设你将密钥和 ID 配置在 config 中 WestDexService: service.NewWestDexService(c.WestConfig), // 假设你将密钥和 ID 配置在 config 中
YushanService: service.NewYushanService(c.YushanConfig),
} }
} }

3
go.mod
View File

@ -82,6 +82,9 @@ require (
github.com/smartwalle/ngx v1.0.9 // indirect github.com/smartwalle/ngx v1.0.9 // indirect
github.com/smartwalle/nsign v1.0.9 // indirect github.com/smartwalle/nsign v1.0.9 // indirect
github.com/spaolacci/murmur3 v1.1.0 // indirect github.com/spaolacci/murmur3 v1.1.0 // indirect
github.com/tidwall/gjson v1.18.0 // indirect
github.com/tidwall/match v1.1.1 // indirect
github.com/tidwall/pretty v1.2.0 // indirect
github.com/tjfoc/gmsm v1.3.2 // indirect github.com/tjfoc/gmsm v1.3.2 // indirect
go.etcd.io/etcd/api/v3 v3.5.15 // indirect go.etcd.io/etcd/api/v3 v3.5.15 // indirect
go.etcd.io/etcd/client/pkg/v3 v3.5.15 // indirect go.etcd.io/etcd/client/pkg/v3 v3.5.15 // indirect

6
go.sum
View File

@ -269,6 +269,12 @@ github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/tidwall/gjson v1.18.0 h1:FIDeeyB800efLX89e5a8Y0BNH+LOngJyGrIWxG2FKQY=
github.com/tidwall/gjson v1.18.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
github.com/tjfoc/gmsm v1.3.2 h1:7JVkAn5bvUJ7HtU08iW6UiD+UTmJTIToHCfeFzkcCxM= github.com/tjfoc/gmsm v1.3.2 h1:7JVkAn5bvUJ7HtU08iW6UiD+UTmJTIToHCfeFzkcCxM=
github.com/tjfoc/gmsm v1.3.2/go.mod h1:HaUcFuY0auTiaHB9MHFGCPx5IaLhTUd2atbCFBQXn9w= github.com/tjfoc/gmsm v1.3.2/go.mod h1:HaUcFuY0auTiaHB9MHFGCPx5IaLhTUd2atbCFBQXn9w=
github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c= github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c=

View File

@ -2,6 +2,7 @@ package errs
// 常见错误 // 常见错误
var ( var (
ErrNotFound = NewAppError(1000, "查询为空")
ErrSystem = NewAppError(1001, "接口异常") ErrSystem = NewAppError(1001, "接口异常")
ErrParamDecryption = NewAppError(1002, "参数解密失败") ErrParamDecryption = NewAppError(1002, "参数解密失败")
ErrParamValidation = NewAppError(1003, "基础参数校验不正确") ErrParamValidation = NewAppError(1003, "基础参数校验不正确")