feat(user): temp

This commit is contained in:
2024-12-24 11:37:25 +08:00
parent 4748bb0cfb
commit 97e14bbe37
36 changed files with 1980 additions and 656 deletions

View File

@@ -58,6 +58,51 @@ func (a *AliPayService) CreateAlipayAppOrder(amount float64, subject string, out
return payStr, nil
}
// CreateAlipayH5Order 创建支付宝H5支付订单
func (a *AliPayService) CreateAlipayH5Order(amount float64, subject string, outTradeNo string) (string, error) {
amount = 0.01
client := a.AlipayClient
totalAmount := lzUtils.ToAlipayAmount(amount)
// 构造H5支付请求
p := alipay.TradeWapPay{
Trade: alipay.Trade{
Subject: subject,
OutTradeNo: outTradeNo,
TotalAmount: totalAmount,
ProductCode: "QUICK_WAP_WAY", // H5支付专用产品码
NotifyURL: a.config.NotifyUrl, // 异步回调通知地址
ReturnURL: "http://192.168.1.124:5173/#/pages/report",
},
}
// 获取H5支付请求字符串这里会签名
payUrl, err := client.TradeWapPay(p)
if err != nil {
return "", fmt.Errorf("创建支付宝H5订单失败: %v", err)
}
return payUrl.String(), nil
}
// CreateAlipayOrder 根据平台类型创建支付宝支付订单
func (a *AliPayService) CreateAlipayOrder(ctx context.Context, amount float64, subject string, outTradeNo string) (string, error) {
// 根据 ctx 中的 platform 判断平台
platform, platformOk := ctx.Value("platform").(string)
if !platformOk {
return "", fmt.Errorf("无的支付平台: %s", platform)
}
switch platform {
case "app":
// 调用App支付的创建方法
return a.CreateAlipayAppOrder(amount, subject, outTradeNo)
case "h5":
// 调用H5支付的创建方法并传入 returnUrl
return a.CreateAlipayH5Order(amount, subject, outTradeNo)
default:
return "", fmt.Errorf("不支持的支付平台: %s", platform)
}
}
// AliRefund 发起支付宝退款
func (a *AliPayService) AliRefund(ctx context.Context, outTradeNo string, refundAmount float64) (*alipay.TradeRefundRsp, error) {
refund := alipay.TradeRefund{

View File

@@ -0,0 +1,526 @@
package service
import (
"context"
"encoding/json"
"errors"
"fmt"
"github.com/Masterminds/squirrel"
"github.com/tidwall/gjson"
"github.com/zeromicro/go-zero/core/logx"
"qnc-server/app/user/cmd/api/internal/config"
"qnc-server/app/user/model"
"qnc-server/pkg/lzkit/crypto"
"sync"
"sync/atomic"
"time"
)
type ApiRequestService struct {
config config.Config
westDexService *WestDexService
featureModel model.FeatureModel
productFeatureModel model.ProductFeatureModel
}
// NewApiRequestService 是一个构造函数,用于初始化 ApiRequestService
func NewApiRequestService(c config.Config, westDexService *WestDexService, featureModel model.FeatureModel, productFeatureModel model.ProductFeatureModel) *ApiRequestService {
return &ApiRequestService{
config: c,
featureModel: featureModel,
productFeatureModel: productFeatureModel,
westDexService: westDexService,
}
}
type APIResponseData struct {
ApiID string `json:"apiID"`
Data json.RawMessage `json:"data"` // 这里用 RawMessage 来存储原始的 data
Success bool `json:"success"`
Timestamp string `json:"timestamp"`
Error string `json:"error,omitempty"`
}
// ProcessRequests 处理请求
func (a *ApiRequestService) ProcessRequests(params []byte, productID int64) ([]byte, error) {
var ctx, cancel = context.WithCancel(context.Background())
defer cancel()
build := a.productFeatureModel.SelectBuilder().Where(squirrel.Eq{
"product_id": productID,
})
productFeatureList, findProductFeatureErr := a.productFeatureModel.FindAll(ctx, build, "")
if findProductFeatureErr != nil {
return nil, findProductFeatureErr
}
var featureIDs []int64
for _, pf := range productFeatureList {
featureIDs = append(featureIDs, pf.FeatureId)
}
if len(featureIDs) == 0 {
return nil, errors.New("featureIDs 是空的")
}
builder := a.featureModel.SelectBuilder().Where(squirrel.Eq{"id": featureIDs})
featureList, findFeatureErr := a.featureModel.FindAll(ctx, builder, "")
if findFeatureErr != nil {
return nil, findFeatureErr
}
if len(featureList) == 0 {
return nil, errors.New("处理请求错误,产品无对应接口功能")
}
var (
wg sync.WaitGroup
resultsCh = make(chan APIResponseData, len(featureList))
errorsCh = make(chan error, len(featureList))
errorCount int32
errorLimit = len(featureList)
)
for i, feature := range featureList {
wg.Add(1)
go func(i int, feature *model.Feature) {
defer wg.Done()
select {
case <-ctx.Done():
return
default:
}
result := APIResponseData{
ApiID: feature.ApiId,
Success: false,
}
// 请求参数预处理
resp, preprocessErr := a.PreprocessRequestApi(params, feature.ApiId)
timestamp := time.Now().Format("2006-01-02 15:04:05")
if preprocessErr != nil {
result.Timestamp = timestamp
result.Error = preprocessErr.Error()
result.Data = resp
resultsCh <- result
errorsCh <- fmt.Errorf("请求预处理失败: %v", preprocessErr)
atomic.AddInt32(&errorCount, 1)
if atomic.LoadInt32(&errorCount) >= int32(errorLimit) {
cancel()
}
return
}
result.Data = resp
result.Success = true
result.Timestamp = timestamp
resultsCh <- result
}(i, feature)
}
go func() {
wg.Wait()
close(resultsCh)
close(errorsCh)
}()
// 收集所有结果并合并
var responseData []APIResponseData
for result := range resultsCh {
responseData = append(responseData, result)
}
if atomic.LoadInt32(&errorCount) >= int32(errorLimit) {
var allErrors []error
for err := range errorsCh {
allErrors = append(allErrors, err)
}
return nil, fmt.Errorf("请求失败次数超过 %d 次: %v", errorLimit, allErrors)
}
combinedResponse, err := json.Marshal(responseData)
if err != nil {
return nil, fmt.Errorf("响应数据转 JSON 失败: %+v", err)
}
return combinedResponse, nil
}
// ------------------------------------请求处理器--------------------------
var requestProcessors = map[string]func(*ApiRequestService, []byte) ([]byte, error){
"G09SC02": (*ApiRequestService).ProcessG09SC02Request,
"G27BJ05": (*ApiRequestService).ProcessG27BJ05Request,
"G26BJ05": (*ApiRequestService).ProcessG26BJ05Request,
"G34BJ03": (*ApiRequestService).ProcessG34BJ03Request,
"G35SC01": (*ApiRequestService).ProcessG35SC01Request,
"G28BJ05": (*ApiRequestService).ProcessG28BJ05Request,
"G05HZ01": (*ApiRequestService).ProcessG05HZ01Request,
"Q23SC01": (*ApiRequestService).ProcessQ23SC01Request,
}
// PreprocessRequestApi 调用指定的请求处理函数
func (a *ApiRequestService) PreprocessRequestApi(params []byte, apiID string) ([]byte, error) {
if processor, exists := requestProcessors[apiID]; exists {
return processor(a, params) // 调用 ApiRequestService 方法
}
return nil, errors.New("api请求, 未找到相应的处理程序")
}
func (a *ApiRequestService) ProcessG09SC02Request(params []byte) ([]byte, error) {
name := gjson.GetBytes(params, "name")
idCard := gjson.GetBytes(params, "id_card")
if !name.Exists() || !idCard.Exists() {
return nil, errors.New("api请求, G09SC02, 获取相关参数失败")
}
request := map[string]interface{}{
"data": map[string]interface{}{
"certNumMan": a.westDexService.Encrypt(idCard.String()),
"nameMan": a.westDexService.Encrypt(name.String()),
},
}
resp, callApiErr := a.westDexService.CallAPI("G09SC02", request)
if callApiErr != nil {
return nil, callApiErr
}
result := gjson.GetBytes(resp, "data.0.maritalStatus")
if result.Exists() {
responseMap := map[string]string{"status": result.String()}
jsonResponse, err := json.Marshal(responseMap)
if err != nil {
return nil, err
}
return jsonResponse, nil
} else {
return nil, errors.New("查询为空")
}
}
func (a *ApiRequestService) ProcessG27BJ05Request(params []byte) ([]byte, error) {
name := gjson.GetBytes(params, "name")
idCard := gjson.GetBytes(params, "id_card")
mobile := gjson.GetBytes(params, "mobile")
if !name.Exists() || !idCard.Exists() || !mobile.Exists() {
return nil, errors.New("api请求, G27BJ05, 获取相关参数失败")
}
request := map[string]interface{}{
"data": map[string]interface{}{
"id": a.westDexService.Encrypt(idCard.String()),
"name": a.westDexService.Encrypt(name.String()),
"cell": a.westDexService.Encrypt(mobile.String()),
},
}
resp, callApiErr := a.westDexService.CallAPI("G27BJ05", request)
if callApiErr != nil {
return nil, callApiErr
}
// 获取 code 字段
codeResult := gjson.GetBytes(resp, "code")
if !codeResult.Exists() {
return nil, fmt.Errorf("code 字段不存在")
}
if codeResult.String() != "00" {
return nil, fmt.Errorf("未匹配到相关结果")
}
// 获取 data 字段
dataResult := gjson.GetBytes(resp, "data")
if !dataResult.Exists() {
return nil, fmt.Errorf("data 字段不存在")
}
// 将 data 字段解析为 map
var dataMap map[string]interface{}
if err := json.Unmarshal([]byte(dataResult.Raw), &dataMap); err != nil {
return nil, fmt.Errorf("解析 data 字段失败: %v", err)
}
// 删除指定字段
delete(dataMap, "swift_number")
delete(dataMap, "DataStrategy")
// 重新编码为 JSON
modifiedData, err := json.Marshal(dataMap)
if err != nil {
return nil, fmt.Errorf("编码修改后的 data 失败: %v", err)
}
return modifiedData, nil
}
func (a *ApiRequestService) ProcessG26BJ05Request(params []byte) ([]byte, error) {
name := gjson.GetBytes(params, "name")
idCard := gjson.GetBytes(params, "id_card")
mobile := gjson.GetBytes(params, "mobile")
if !name.Exists() || !idCard.Exists() || !mobile.Exists() {
return nil, errors.New("api请求, G26BJ05, 获取相关参数失败")
}
request := map[string]interface{}{
"data": map[string]interface{}{
"id": a.westDexService.Encrypt(idCard.String()),
"name": a.westDexService.Encrypt(name.String()),
"cell": a.westDexService.Encrypt(mobile.String()),
"time_range": 5,
},
}
resp, callApiErr := a.westDexService.CallAPI("G26BJ05", request)
if callApiErr != nil {
return nil, callApiErr
}
codeResult := gjson.GetBytes(resp, "code")
if !codeResult.Exists() {
return nil, fmt.Errorf("code 字段不存在")
}
if codeResult.String() != "00" {
return nil, fmt.Errorf("未匹配到相关结果")
}
// 获取 data 字段
dataResult := gjson.GetBytes(resp, "data")
if !dataResult.Exists() {
return nil, fmt.Errorf("data 字段不存在")
}
// 将 data 字段解析为 map
var dataMap map[string]interface{}
if err := json.Unmarshal([]byte(dataResult.Raw), &dataMap); err != nil {
return nil, fmt.Errorf("解析 data 字段失败: %v", err)
}
// 删除指定字段
delete(dataMap, "swift_number")
delete(dataMap, "DataStrategy")
// 重新编码为 JSON
modifiedData, err := json.Marshal(dataMap)
if err != nil {
return nil, fmt.Errorf("编码修改后的 data 失败: %v", err)
}
return modifiedData, nil
}
func (a *ApiRequestService) ProcessG34BJ03Request(params []byte) ([]byte, error) {
name := gjson.GetBytes(params, "name")
idCard := gjson.GetBytes(params, "id_card")
if !name.Exists() || !idCard.Exists() {
return nil, errors.New("api请求, G34BJ03, 获取相关参数失败")
}
request := map[string]interface{}{
"data": map[string]interface{}{
"id_card": a.westDexService.Encrypt(idCard.String()),
"name": a.westDexService.Encrypt(name.String()),
},
}
resp, callApiErr := a.westDexService.CallAPI("G34BJ03", request)
if callApiErr != nil {
return nil, callApiErr
}
dataResult := gjson.GetBytes(resp, "negative_info.data.risk_level")
if dataResult.Exists() {
// 如果字段存在,构造包含 "status" 的 JSON 响应
responseMap := map[string]string{"risk_level": dataResult.String()}
jsonResponse, err := json.Marshal(responseMap)
if err != nil {
return nil, err
}
return jsonResponse, nil
} else {
return nil, errors.New("查询为空")
}
}
func (a *ApiRequestService) ProcessG35SC01Request(params []byte) ([]byte, error) {
name := gjson.GetBytes(params, "name")
idCard := gjson.GetBytes(params, "id_card")
if !name.Exists() || !idCard.Exists() {
return nil, errors.New("api请求, G35SC01, 获取相关参数失败")
}
request := map[string]interface{}{
"data": map[string]interface{}{
"idcard": a.westDexService.Encrypt(idCard.String()),
"name": a.westDexService.Encrypt(name.String()),
"inquired_auth": a.westDexService.GetDateRange(),
},
}
resp, callApiErr := a.westDexService.CallAPI("G35SC01", request)
if callApiErr != nil {
return nil, callApiErr
}
// 第一步:提取外层的 data 字段
dataResult := gjson.GetBytes(resp, "data")
if !dataResult.Exists() {
return nil, fmt.Errorf("外层 data 字段不存在")
}
// 第二步:解析外层 data 的 JSON 字符串
var outerDataMap map[string]interface{}
if err := json.Unmarshal([]byte(dataResult.String()), &outerDataMap); err != nil {
return nil, fmt.Errorf("解析外层 data 字段失败: %v", err)
}
// 第三步:提取内层的 data 字段
innerData, ok := outerDataMap["data"].(string)
if !ok {
return nil, fmt.Errorf("内层 data 字段不存在或类型错误")
}
// 第四步:解析内层 data 的 JSON 字符串
var finalDataMap map[string]interface{}
if err := json.Unmarshal([]byte(innerData), &finalDataMap); err != nil {
return nil, fmt.Errorf("解析内层 data 字段失败: %v", err)
}
// 将最终的 JSON 对象编码为字节数组返回
finalDataBytes, err := json.Marshal(finalDataMap)
if err != nil {
return nil, fmt.Errorf("编码最终的 JSON 对象失败: %v", err)
}
return finalDataBytes, nil
}
func (a *ApiRequestService) ProcessG28BJ05Request(params []byte) ([]byte, error) {
name := gjson.GetBytes(params, "name")
idCard := gjson.GetBytes(params, "id_card")
mobile := gjson.GetBytes(params, "mobile")
if !name.Exists() || !idCard.Exists() || !mobile.Exists() {
return nil, errors.New("api请求, G28BJ05, 获取相关参数失败")
}
request := map[string]interface{}{
"data": map[string]interface{}{
"id": a.westDexService.Encrypt(idCard.String()),
"name": a.westDexService.Encrypt(name.String()),
"cell": a.westDexService.Encrypt(mobile.String()),
},
}
resp, callApiErr := a.westDexService.CallAPI("G28BJ05", request)
if callApiErr != nil {
return nil, callApiErr
}
// 获取 code 字段
codeResult := gjson.GetBytes(resp, "code")
if !codeResult.Exists() {
return nil, fmt.Errorf("code 字段不存在")
}
if codeResult.String() != "00" {
return nil, fmt.Errorf("未匹配到相关结果")
}
// 获取 data 字段
dataResult := gjson.GetBytes(resp, "data")
if !dataResult.Exists() {
return nil, fmt.Errorf("data 字段不存在")
}
// 将 data 字段解析为 map
var dataMap map[string]interface{}
if err := json.Unmarshal([]byte(dataResult.Raw), &dataMap); err != nil {
return nil, fmt.Errorf("解析 data 字段失败: %v", err)
}
// 删除指定字段
delete(dataMap, "swift_number")
delete(dataMap, "DataStrategy")
// 重新编码为 JSON
modifiedData, err := json.Marshal(dataMap)
if err != nil {
return nil, fmt.Errorf("编码修改后的 data 失败: %v", err)
}
return modifiedData, nil
}
func (a *ApiRequestService) ProcessG05HZ01Request(params []byte) ([]byte, error) {
idCard := gjson.GetBytes(params, "id_card")
if !idCard.Exists() {
return nil, errors.New("api请求, G05HZ01, 获取相关参数失败")
}
request := map[string]interface{}{
"pid": crypto.Md5Encrypt(idCard.String()),
}
resp, callApiErr := a.westDexService.G05HZ01CallAPI("G05HZ01", request)
if callApiErr != nil {
return nil, callApiErr
}
// 处理股东人企关系的响应数据
code := gjson.GetBytes(resp, "code")
if !code.Exists() {
return nil, fmt.Errorf("响应中缺少 code 字段")
}
// 判断 code 是否等于 "0000"
if code.String() == "0000" {
// 获取 data 字段的值
data := gjson.GetBytes(resp, "data")
if !data.Exists() {
return nil, fmt.Errorf("响应中缺少 data 字段")
}
// 返回 data 字段的内容
return []byte(data.Raw), nil
}
// code 不等于 "0000",返回错误
return nil, fmt.Errorf("响应code错误%s", code.String())
}
func (a *ApiRequestService) ProcessQ23SC01Request(params []byte) ([]byte, error) {
entName := gjson.GetBytes(params, "ent_name")
entCode := gjson.GetBytes(params, "ent_code")
if !entName.Exists() || !entCode.Exists() {
return nil, errors.New("api请求, Q23SC01, 获取相关参数失败")
}
request := map[string]interface{}{
"data": map[string]interface{}{
"uscc": a.westDexService.Encrypt(entCode.String()),
"org_name": a.westDexService.Encrypt(entName.String()),
"inquired_auth": a.westDexService.GetDateRange(),
},
}
resp, callApiErr := a.westDexService.CallAPI("Q23SC01", request)
logx.Infof("企业涉诉返回%+v", string(resp))
if callApiErr != nil {
return nil, callApiErr
}
// 第一步:提取外层的 data 字段
dataResult := gjson.GetBytes(resp, "data")
if !dataResult.Exists() {
return nil, fmt.Errorf("外层 data 字段不存在")
}
// 第二步:解析外层 data 的 JSON 字符串
var outerDataMap map[string]interface{}
if err := json.Unmarshal([]byte(dataResult.String()), &outerDataMap); err != nil {
return nil, fmt.Errorf("解析外层 data 字段失败: %v", err)
}
// 第三步:提取内层的 data 字段
innerData, ok := outerDataMap["data"].(string)
if !ok {
return nil, fmt.Errorf("内层 data 字段不存在或类型错误")
}
// 第四步:解析内层 data 的 JSON 字符串
var finalDataMap map[string]interface{}
if err := json.Unmarshal([]byte(innerData), &finalDataMap); err != nil {
return nil, fmt.Errorf("解析内层 data 字段失败: %v", err)
}
// 将最终的 JSON 对象编码为字节数组返回
finalDataBytes, err := json.Marshal(finalDataMap)
if err != nil {
return nil, fmt.Errorf("编码最终的 JSON 对象失败: %v", err)
}
statusResult := gjson.GetBytes(finalDataBytes, "status.status")
if statusResult.Exists() || statusResult.Int() == -1 {
return nil, fmt.Errorf("企业涉诉为空: %+v", finalDataBytes)
}
return finalDataBytes, nil
}

View File

@@ -103,6 +103,65 @@ func (w *WechatPayService) CreateWechatAppOrder(ctx context.Context, amount floa
return *resp.PrepayId, nil
}
// CreateWechatMiniProgramOrder 创建微信小程序支付订单
func (w *WechatPayService) CreateWechatMiniProgramOrder(ctx context.Context, amount float64, description string, outTradeNo string, openid string) (string, error) {
totalAmount := lzUtils.ToWechatAmount(amount)
// 构建支付请求参数
payRequest := jsapi.PrepayRequest{
Appid: core.String(w.config.AppID),
Mchid: core.String(w.config.MchID),
Description: core.String(description),
OutTradeNo: core.String(outTradeNo),
NotifyUrl: core.String(w.config.NotifyUrl),
Amount: &jsapi.Amount{
Total: core.Int64(totalAmount),
},
Payer: &jsapi.Payer{
Openid: core.String(openid), // 用户的 OpenID通过前端传入
}}
// 初始化 AppApiService
svc := jsapi.JsapiApiService{Client: w.wechatClient}
// 发起预支付请求
resp, result, err := svc.PrepayWithRequestPayment(ctx, payRequest)
if err != nil {
return "", fmt.Errorf("微信支付订单创建失败: %v, 状态码: %d", err, result.Response.StatusCode)
}
// 返回预支付交易会话标识
return *resp.PrepayId, nil
}
// CreateWechatOrder 创建微信支付订单(集成 APP、H5、小程序
func (w *WechatPayService) CreateWechatOrder(ctx context.Context, amount float64, description string, outTradeNo string) (string, error) {
// 根据 ctx 中的 platform 判断平台
platform := ctx.Value("platform").(string)
var prepayId string
var err error
switch platform {
case "mp-weixin":
// 如果是小程序平台,调用小程序支付订单创建
prepayId, err = w.CreateWechatMiniProgramOrder(ctx, amount, description, outTradeNo, "asdasd")
case "app":
// 如果是 APP 平台,调用 APP 支付订单创建
prepayId, err = w.CreateWechatAppOrder(ctx, amount, description, outTradeNo)
default:
return "", fmt.Errorf("不支持的支付平台: %s", platform)
}
// 如果创建支付订单失败,返回错误
if err != nil {
return "", fmt.Errorf("支付订单创建失败: %v", err)
}
// 返回预支付ID
return prepayId, nil
}
// HandleWechatPayNotification 处理微信支付回调
func (w *WechatPayService) HandleWechatPayNotification(ctx context.Context, req *http.Request) (*payments.Transaction, error) {
transaction := new(payments.Transaction)

View File

@@ -2,21 +2,14 @@ package service
import (
"bytes"
"context"
"encoding/json"
"fmt"
"github.com/pkg/errors"
"github.com/tidwall/gjson"
"github.com/zeromicro/go-zero/core/logx"
"io"
"net/http"
"qnc-server/app/user/cmd/api/internal/config"
"qnc-server/app/user/cmd/api/internal/types"
"qnc-server/pkg/lzkit/crypto"
"reflect"
"strconv"
"sync"
"sync/atomic"
"time"
)
@@ -39,13 +32,6 @@ type G05HZ01WestResp struct {
type WestDexService struct {
config config.WestConfig
}
type APIResponseData struct {
ApiID string `json:"apiID"`
Data json.RawMessage `json:"data"` // 这里用 RawMessage 来存储原始的 data
Success bool `json:"success"`
Timestamp string `json:"timestamp"`
Error string `json:"error,omitempty"`
}
// NewWestDexService 是一个构造函数,用于初始化 WestDexService
func NewWestDexService(c config.Config) *WestDexService {
@@ -103,7 +89,6 @@ func (w *WestDexService) CallAPI(code string, reqData map[string]interface{}) (r
if UnmarshalErr != nil {
return nil, UnmarshalErr
}
logx.Infof("西部数据请求响应, code: %s, response: %v", code, westDexResp)
if westDexResp.Code != "00000" {
if westDexResp.Data == "" {
return nil, errors.New(westDexResp.Message)
@@ -178,7 +163,6 @@ func (w *WestDexService) G05HZ01CallAPI(code string, reqData map[string]interfac
if UnmarshalErr != nil {
return nil, UnmarshalErr
}
logx.Infof("西部数据请求响应, code: %s, response: %v", code, westDexResp)
if westDexResp.Code != "0000" {
if westDexResp.Data == nil {
return nil, errors.New(westDexResp.Message)
@@ -194,512 +178,16 @@ func (w *WestDexService) G05HZ01CallAPI(code string, reqData map[string]interfac
return nil, fmt.Errorf("西部请求失败Code: %d", httpResp.StatusCode)
}
// EncryptStructFields 加密字段的函数,处理不同类型,并跳过空值字段
func (w *WestDexService) EncryptStructFields(inputStruct interface{}) (map[string]interface{}, error) {
encryptedFields := make(map[string]interface{})
// 使用反射获取结构体的类型和值
v := reflect.ValueOf(inputStruct)
// 检查并解引用指针类型
if v.Kind() == reflect.Ptr {
v = v.Elem()
}
if v.Kind() != reflect.Struct {
return nil, errors.New("传入的interfact不是struct")
}
// 遍历结构体字段
for i := 0; i < v.NumField(); i++ {
field := v.Type().Field(i)
fieldValue := v.Field(i)
// 检查字段的 encrypt 标签是否为 "false"
encryptTag := field.Tag.Get("encrypt")
if encryptTag == "false" {
encryptedFields[field.Name] = fieldValue.Interface()
continue
}
// 如果字段为空值,跳过
if fieldValue.IsZero() {
continue
}
// 将字段的值转换为字符串进行加密
strValue := fmt.Sprintf("%v", fieldValue.Interface())
// 执行加密操作
encryptedValue, err := crypto.WestDexEncrypt(strValue, w.config.Key)
if err != nil {
return nil, err
}
// 将加密后的值存入结果映射
encryptedFields[field.Name] = encryptedValue
}
return encryptedFields, nil
}
// MapStructToAPIRequest 字段映射
func (w *WestDexService) MapStructToAPIRequest(encryptedFields map[string]interface{}, fieldMapping map[string]string, wrapField string) map[string]interface{} {
apiRequest := make(map[string]interface{})
// 遍历字段映射表
for structField, apiField := range fieldMapping {
// 如果加密后的字段存在,才添加到请求
if structField == "InquiredAuth" {
apiRequest[apiField] = GetDateRange()
} else if structField == "TimeRange" {
apiRequest[apiField] = "5"
} else if value, exists := encryptedFields[structField]; exists {
apiRequest[apiField] = value
}
}
// 如果 wrapField 不为空,将 apiRequest 包裹到该字段下
if wrapField != "" {
return map[string]interface{}{
wrapField: apiRequest,
}
}
return apiRequest
}
// ProcessRequests 批量处理
func (w *WestDexService) ProcessRequests(data interface{}, requests []types.WestDexServiceRequestParams) ([]byte, error) {
var (
wg sync.WaitGroup
resultsCh = make(chan APIResponseData, len(requests))
errorsCh = make(chan error, len(requests))
ctx, cancel = context.WithCancel(context.Background())
errorCount int32
errorLimit = 4
)
defer cancel()
for i, req := range requests {
wg.Add(1)
go func(i int, req types.WestDexServiceRequestParams) {
defer wg.Done()
select {
case <-ctx.Done():
return
default:
}
// 请求参数预处理
apiRequest, preprocessErr := w.PreprocessRequestParams(req.ApiID, data)
if preprocessErr != nil {
errorsCh <- fmt.Errorf("请求预处理失败: %v", preprocessErr)
atomic.AddInt32(&errorCount, 1)
if atomic.LoadInt32(&errorCount) >= int32(errorLimit) {
cancel()
}
return
}
var resp []byte
var callApiErr error
if req.ApiID == "G05HZ01" {
resp, callApiErr = w.G05HZ01CallAPI(req.ApiID, apiRequest)
} else {
resp, callApiErr = w.CallAPI(req.ApiID, apiRequest)
}
timestamp := time.Now().Format("2006-01-02 15:04:05")
result := APIResponseData{
ApiID: req.ApiID,
Success: false,
Timestamp: timestamp,
}
if callApiErr != nil {
errorsCh <- fmt.Errorf("西部请求, 请求失败: %+v", callApiErr)
atomic.AddInt32(&errorCount, 1)
if atomic.LoadInt32(&errorCount) >= int32(errorLimit) {
cancel()
}
result.Error = callApiErr.Error()
result.Data = resp
resultsCh <- result
return
}
processedResp, processErr := processResponse(resp, req.ApiID)
if processErr != nil {
errorsCh <- fmt.Errorf("处理响应失败: %v", processErr)
atomic.AddInt32(&errorCount, 1)
if atomic.LoadInt32(&errorCount) >= int32(errorLimit) {
cancel()
}
result.Error = processErr.Error()
} else {
result.Data = processedResp
result.Success = true
}
resultsCh <- result
}(i, req)
}
go func() {
wg.Wait()
close(resultsCh)
close(errorsCh)
}()
// 收集所有结果并合并
var responseData []APIResponseData
for result := range resultsCh {
responseData = append(responseData, result)
}
if atomic.LoadInt32(&errorCount) >= int32(errorLimit) {
var allErrors []error
for err := range errorsCh {
allErrors = append(allErrors, err)
}
return nil, fmt.Errorf("请求失败次数超过 %d 次: %v", errorLimit, allErrors)
}
combinedResponse, err := json.Marshal(responseData)
func (w *WestDexService) Encrypt(data string) string {
encryptedValue, err := crypto.WestDexEncrypt(data, w.config.Key)
if err != nil {
return nil, fmt.Errorf("响应数据转 JSON 失败: %+v", err)
panic("WestDexEncrypt error: " + err.Error())
}
return combinedResponse, nil
}
// ------------------------------------请求处理器--------------------------
var requestProcessors = map[string]func(*WestDexService, interface{}) (map[string]interface{}, error){
"G09SC02": (*WestDexService).ProcessG09SC02Request,
"G27BJ05": (*WestDexService).ProcessG27BJ05Request,
"G26BJ05": (*WestDexService).ProcessG26BJ05Request,
"G34BJ03": (*WestDexService).ProcessG34BJ03Request,
"G35SC01": (*WestDexService).ProcessG35SC01Request,
"G28BJ05": (*WestDexService).ProcessG28BJ05Request,
"G05HZ01": (*WestDexService).ProcessG05HZ01Request,
}
// PreprocessRequestParams 调用指定的请求处理函数
func (w *WestDexService) PreprocessRequestParams(apiID string, params interface{}) (map[string]interface{}, error) {
if processor, exists := requestProcessors[apiID]; exists {
return processor(w, params) // 调用 WestDexService 方法
}
var request map[string]interface{}
return request, nil
}
// / 将处理函数作为 WestDexService 的方法
func (w *WestDexService) ProcessG09SC02Request(params interface{}) (map[string]interface{}, error) {
encryptedFields, err := w.EncryptStructFields(params)
if err != nil {
return nil, fmt.Errorf("西部请求, 生成请求数据失败: %+v", err)
}
apiRequest := w.MapStructToAPIRequest(encryptedFields, types.G09SC02FieldMapping, "data")
return apiRequest, nil
}
func (w *WestDexService) ProcessG27BJ05Request(params interface{}) (map[string]interface{}, error) {
encryptedFields, err := w.EncryptStructFields(params)
if err != nil {
return nil, fmt.Errorf("西部请求, 生成请求数据失败: %+v", err)
}
apiRequest := w.MapStructToAPIRequest(encryptedFields, types.G27BJ05FieldMapping, "data")
return apiRequest, nil
}
func (w *WestDexService) ProcessG26BJ05Request(params interface{}) (map[string]interface{}, error) {
// 特殊名单 G26BJ05
encryptedFields, err := w.EncryptStructFields(params)
if err != nil {
return nil, fmt.Errorf("西部请求, 生成请求数据失败: %+v", err)
}
apiRequest := w.MapStructToAPIRequest(encryptedFields, types.G26BJ05FieldMapping, "data")
return apiRequest, nil
}
func (w *WestDexService) ProcessG34BJ03Request(params interface{}) (map[string]interface{}, error) {
// 个人不良 G34BJ03
encryptedFields, err := w.EncryptStructFields(params)
if err != nil {
return nil, fmt.Errorf("西部请求, 生成请求数据失败: %+v", err)
}
apiRequest := w.MapStructToAPIRequest(encryptedFields, types.G34BJ03FieldMapping, "data")
return apiRequest, nil
}
func (w *WestDexService) ProcessG35SC01Request(params interface{}) (map[string]interface{}, error) {
// 个人涉诉 G35SC01
encryptedFields, err := w.EncryptStructFields(params)
if err != nil {
return nil, fmt.Errorf("西部请求, 生成请求数据失败: %+v", err)
}
apiRequest := w.MapStructToAPIRequest(encryptedFields, types.G35SC01FieldMapping, "data")
return apiRequest, nil
}
func (w *WestDexService) ProcessG28BJ05Request(params interface{}) (map[string]interface{}, error) {
// 借贷行为 G28BJ05
encryptedFields, err := w.EncryptStructFields(params)
if err != nil {
return nil, fmt.Errorf("西部请求, 生成请求数据失败: %+v", err)
}
apiRequest := w.MapStructToAPIRequest(encryptedFields, types.G28BJ05FieldMapping, "data")
return apiRequest, nil
}
func (w *WestDexService) ProcessG05HZ01Request(params interface{}) (map[string]interface{}, error) {
// 使用 reflect 获取 params 的值和类型
val := reflect.ValueOf(params)
if val.Kind() == reflect.Ptr {
val = val.Elem() // 如果是指针,获取指向的实际值
}
if val.Kind() != reflect.Struct {
return nil, fmt.Errorf("请求参数必须是结构体类型")
}
// 初始化一个 map 来存储加密后的字段
encryptedFields := make(map[string]interface{})
// 遍历结构体字段,将其转换为 map[string]interface{}
valType := val.Type()
for i := 0; i < val.NumField(); i++ {
field := val.Field(i)
fieldName := valType.Field(i).Name
// 如果字段名为 "IDCard",对其值进行加密
if fieldName == "IDCard" {
if field.Kind() != reflect.String {
return nil, fmt.Errorf("IDCard 字段不是字符串类型")
}
idCard := field.String()
encryptedIDCard := crypto.Md5Encrypt(idCard)
encryptedFields[fieldName] = encryptedIDCard
} else {
// 否则直接将字段值添加到 map 中
encryptedFields[fieldName] = field.Interface()
}
}
// 使用字段映射表生成最终的 API 请求
apiRequest := w.MapStructToAPIRequest(encryptedFields, types.G05HZ01FieldMapping, "")
return apiRequest, nil
}
// -----------------------------------------------------------------------------
// 响应处理器
var responseProcessors = map[string]func([]byte) ([]byte, error){
"G09SC02": processG09SC02Response, // 单人婚姻
"G27BJ05": processG27BJ05Response, // 借贷意向
"G28BJ05": processG28BJ05Response, // 借贷行为
"G26BJ05": processG26BJ05Response, // 特殊名单
"G05HZ01": processG05HZ01Response, // 股东人企关系
"G34BJ03": processG34BJ03Response, // 个人不良
"G35SC01": processG35SC01Response, // 个人涉诉
}
// processResponse 处理响应数据
func processResponse(resp []byte, apiID string) ([]byte, error) {
if processor, exists := responseProcessors[apiID]; exists {
return processor(resp)
}
return resp, nil
}
func processG09SC02Response(resp []byte) ([]byte, error) {
result := gjson.GetBytes(resp, "data.0.maritalStatus")
if result.Exists() {
// 如果字段存在,构造包含 "status" 的 JSON 响应
responseMap := map[string]string{"status": result.String()}
jsonResponse, err := json.Marshal(responseMap)
if err != nil {
return nil, err
}
return jsonResponse, nil
} else {
return nil, errors.New("查询为空")
}
}
func processG27BJ05Response(resp []byte) ([]byte, error) {
// 获取 code 字段
codeResult := gjson.GetBytes(resp, "code")
if !codeResult.Exists() {
return nil, fmt.Errorf("code 字段不存在")
}
if codeResult.String() != "00" {
return nil, fmt.Errorf("未匹配到相关结果")
}
// 获取 data 字段
dataResult := gjson.GetBytes(resp, "data")
if !dataResult.Exists() {
return nil, fmt.Errorf("data 字段不存在")
}
// 将 data 字段解析为 map
var dataMap map[string]interface{}
if err := json.Unmarshal([]byte(dataResult.Raw), &dataMap); err != nil {
return nil, fmt.Errorf("解析 data 字段失败: %v", err)
}
// 删除指定字段
delete(dataMap, "swift_number")
delete(dataMap, "DataStrategy")
// 重新编码为 JSON
modifiedData, err := json.Marshal(dataMap)
if err != nil {
return nil, fmt.Errorf("编码修改后的 data 失败: %v", err)
}
return modifiedData, nil
}
func processG28BJ05Response(resp []byte) ([]byte, error) {
// 处理借贷行为的响应数据
// 获取 code 字段
codeResult := gjson.GetBytes(resp, "code")
if !codeResult.Exists() {
return nil, fmt.Errorf("code 字段不存在")
}
if codeResult.String() != "00" {
return nil, fmt.Errorf("未匹配到相关结果")
}
// 获取 data 字段
dataResult := gjson.GetBytes(resp, "data")
if !dataResult.Exists() {
return nil, fmt.Errorf("data 字段不存在")
}
// 将 data 字段解析为 map
var dataMap map[string]interface{}
if err := json.Unmarshal([]byte(dataResult.Raw), &dataMap); err != nil {
return nil, fmt.Errorf("解析 data 字段失败: %v", err)
}
// 删除指定字段
delete(dataMap, "swift_number")
delete(dataMap, "DataStrategy")
// 重新编码为 JSON
modifiedData, err := json.Marshal(dataMap)
if err != nil {
return nil, fmt.Errorf("编码修改后的 data 失败: %v", err)
}
return modifiedData, nil
}
func processG26BJ05Response(resp []byte) ([]byte, error) {
// 处理特殊名单的响应数据
// 获取 code 字段
codeResult := gjson.GetBytes(resp, "code")
if !codeResult.Exists() {
return nil, fmt.Errorf("code 字段不存在")
}
if codeResult.String() != "00" {
return nil, fmt.Errorf("未匹配到相关结果")
}
// 获取 data 字段
dataResult := gjson.GetBytes(resp, "data")
if !dataResult.Exists() {
return nil, fmt.Errorf("data 字段不存在")
}
// 将 data 字段解析为 map
var dataMap map[string]interface{}
if err := json.Unmarshal([]byte(dataResult.Raw), &dataMap); err != nil {
return nil, fmt.Errorf("解析 data 字段失败: %v", err)
}
// 删除指定字段
delete(dataMap, "swift_number")
delete(dataMap, "DataStrategy")
// 重新编码为 JSON
modifiedData, err := json.Marshal(dataMap)
if err != nil {
return nil, fmt.Errorf("编码修改后的 data 失败: %v", err)
}
return modifiedData, nil
}
func processG05HZ01Response(resp []byte) ([]byte, error) {
// 处理股东人企关系的响应数据
code := gjson.GetBytes(resp, "code")
if !code.Exists() {
return nil, fmt.Errorf("响应中缺少 code 字段")
}
// 判断 code 是否等于 "0000"
if code.String() == "0000" {
// 获取 data 字段的值
data := gjson.GetBytes(resp, "data")
if !data.Exists() {
return nil, fmt.Errorf("响应中缺少 data 字段")
}
// 返回 data 字段的内容
return []byte(data.Raw), nil
}
// code 不等于 "0000",返回错误
return nil, fmt.Errorf("响应code错误%s", code.String())
}
func processG34BJ03Response(resp []byte) ([]byte, error) {
// 处理个人不良的响应数据
dataResult := gjson.GetBytes(resp, "negative_info.data.risk_level")
if dataResult.Exists() {
// 如果字段存在,构造包含 "status" 的 JSON 响应
responseMap := map[string]string{"risk_level": dataResult.String()}
jsonResponse, err := json.Marshal(responseMap)
if err != nil {
return nil, err
}
return jsonResponse, nil
} else {
return nil, errors.New("查询为空")
}
}
func processG35SC01Response(resp []byte) ([]byte, error) {
// 第一步:提取外层的 data 字段
dataResult := gjson.GetBytes(resp, "data")
if !dataResult.Exists() {
return nil, fmt.Errorf("外层 data 字段不存在")
}
// 第二步:解析外层 data 的 JSON 字符串
var outerDataMap map[string]interface{}
if err := json.Unmarshal([]byte(dataResult.String()), &outerDataMap); err != nil {
return nil, fmt.Errorf("解析外层 data 字段失败: %v", err)
}
// 第三步:提取内层的 data 字段
innerData, ok := outerDataMap["data"].(string)
if !ok {
return nil, fmt.Errorf("内层 data 字段不存在或类型错误")
}
// 第四步:解析内层 data 的 JSON 字符串
var finalDataMap map[string]interface{}
if err := json.Unmarshal([]byte(innerData), &finalDataMap); err != nil {
return nil, fmt.Errorf("解析内层 data 字段失败: %v", err)
}
// 将最终的 JSON 对象编码为字节数组返回
finalDataBytes, err := json.Marshal(finalDataMap)
if err != nil {
return nil, fmt.Errorf("编码最终的 JSON 对象失败: %v", err)
}
return finalDataBytes, nil
return encryptedValue
}
// GetDateRange 返回今天到明天的日期范围,格式为 "yyyyMMdd-yyyyMMdd"
func GetDateRange() string {
func (w *WestDexService) GetDateRange() string {
today := time.Now().Format("20060102") // 获取今天的日期
tomorrow := time.Now().Add(24 * time.Hour).Format("20060102") // 获取明天的日期
return fmt.Sprintf("%s-%s", today, tomorrow) // 拼接日期范围并返回