f
This commit is contained in:
@@ -59,6 +59,9 @@ type (
|
||||
PayTimeEnd string `form:"pay_time_end,optional"` // 支付时间结束
|
||||
RefundTimeStart string `form:"refund_time_start,optional"` // 退款时间开始
|
||||
RefundTimeEnd string `form:"refund_time_end,optional"` // 退款时间结束
|
||||
QueryUserName string `form:"query_user_name,optional"` // 被查询人姓名
|
||||
QueryUserIdCard string `form:"query_user_id_card,optional"` // 被查询人身份证号
|
||||
QueryUserMobile string `form:"query_user_mobile,optional"` // 被查询人手机号
|
||||
}
|
||||
// 列表响应
|
||||
AdminGetOrderListResp {
|
||||
|
||||
@@ -86,7 +86,7 @@ Tianyuanapi:
|
||||
BaseURL: "https://api.tianyuanapi.com"
|
||||
Timeout: 60
|
||||
Authorization:
|
||||
FileBaseURL: "https://www.quannengcha.com/api/v1/auth-docs" # 授权书文件访问基础URL
|
||||
FileBaseURL: "https://www.zhenaicha.com/api/v1/auth-docs" # 授权书文件访问基础URL
|
||||
Promotion:
|
||||
PromotionDomain: "http://localhost:8888" # 推广域名(用于生成短链)
|
||||
OfficialDomain: "http://localhost:5678" # 正式站点域名(短链重定向的目标域名)
|
||||
|
||||
@@ -2,6 +2,7 @@ package admin_order
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/hex"
|
||||
"sync"
|
||||
|
||||
"qnc-server/app/main/api/internal/svc"
|
||||
@@ -9,6 +10,7 @@ import (
|
||||
"qnc-server/app/main/model"
|
||||
"qnc-server/common/globalkey"
|
||||
"qnc-server/common/xerr"
|
||||
"qnc-server/pkg/lzkit/crypto"
|
||||
|
||||
"github.com/Masterminds/squirrel"
|
||||
"github.com/pkg/errors"
|
||||
@@ -74,6 +76,112 @@ func (l *AdminGetOrderListLogic) AdminGetOrderList(req *types.AdminGetOrderListR
|
||||
builder = builder.Where("refund_time <= ?", req.RefundTimeEnd)
|
||||
}
|
||||
|
||||
// 根据被查询人信息筛选订单(姓名、身份证、手机号)
|
||||
// 由于数据是加密存储的,需要先加密查询条件,然后通过子查询筛选
|
||||
// 支持单独使用任一要素查询,也支持组合查询(AND 关系)
|
||||
if req.QueryUserName != "" || req.QueryUserIdCard != "" || req.QueryUserMobile != "" {
|
||||
// 获取加密密钥
|
||||
secretKey := l.svcCtx.Config.Encrypt.SecretKey
|
||||
key, decodeErr := hex.DecodeString(secretKey)
|
||||
if decodeErr != nil {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "AdminGetOrderList, 解析加密密钥失败 err: %v", decodeErr)
|
||||
}
|
||||
|
||||
// 构建查询条件
|
||||
queryUserRecordBuilder := l.svcCtx.QueryUserRecordModel.SelectBuilder().
|
||||
Where("del_state = ?", globalkey.DelStateNo)
|
||||
|
||||
// 加密并添加姓名筛选条件
|
||||
if req.QueryUserName != "" {
|
||||
encryptedName, err := crypto.AesEcbEncrypt([]byte(req.QueryUserName), key)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "AdminGetOrderList, 加密姓名失败 err: %v", err)
|
||||
}
|
||||
logx.Infof("AdminGetOrderList, 姓名加密: 明文=%s, 密文=%s", req.QueryUserName, encryptedName)
|
||||
queryUserRecordBuilder = queryUserRecordBuilder.Where("name = ?", encryptedName)
|
||||
}
|
||||
|
||||
// 加密并添加身份证筛选条件
|
||||
if req.QueryUserIdCard != "" {
|
||||
encryptedIdCard, err := crypto.EncryptIDCard(req.QueryUserIdCard, key)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "AdminGetOrderList, 加密身份证号失败 err: %v", err)
|
||||
}
|
||||
logx.Infof("AdminGetOrderList, 身份证号加密: 明文=%s, 密文=%s", req.QueryUserIdCard, encryptedIdCard)
|
||||
queryUserRecordBuilder = queryUserRecordBuilder.Where("id_card = ?", encryptedIdCard)
|
||||
}
|
||||
|
||||
// 加密并添加手机号筛选条件
|
||||
if req.QueryUserMobile != "" {
|
||||
encryptedMobile, err := crypto.EncryptMobile(req.QueryUserMobile, secretKey)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "AdminGetOrderList, 加密手机号失败 err: %v", err)
|
||||
}
|
||||
logx.Infof("AdminGetOrderList, 手机号加密: 明文=%s, 密文=%s", req.QueryUserMobile, encryptedMobile)
|
||||
queryUserRecordBuilder = queryUserRecordBuilder.Where("mobile = ?", encryptedMobile)
|
||||
}
|
||||
|
||||
// 先查询符合条件的记录(包含 order_id 和 query_no)
|
||||
queryUserRecords, err := l.svcCtx.QueryUserRecordModel.FindAll(l.ctx, queryUserRecordBuilder, "")
|
||||
if err != nil && !errors.Is(err, model.ErrNotFound) {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "AdminGetOrderList, 查询用户记录失败 err: %v", err)
|
||||
}
|
||||
logx.Infof("AdminGetOrderList, 查询条件: 姓名=%s, 身份证=%s, 手机号=%s, 查询到 %d 条匹配的查询用户记录",
|
||||
req.QueryUserName, req.QueryUserIdCard, req.QueryUserMobile, len(queryUserRecords))
|
||||
|
||||
if len(queryUserRecords) == 0 {
|
||||
// 如果没有匹配的记录,返回空结果
|
||||
logx.Infof("AdminGetOrderList, 未找到匹配的查询用户记录,返回空结果")
|
||||
return &types.AdminGetOrderListResp{
|
||||
Total: 0,
|
||||
Items: []types.OrderListItem{},
|
||||
}, nil
|
||||
}
|
||||
|
||||
// 提取 order_id 和 query_no 列表
|
||||
orderIds := make([]string, 0, len(queryUserRecords))
|
||||
queryNos := make([]string, 0, len(queryUserRecords))
|
||||
|
||||
for _, record := range queryUserRecords {
|
||||
// 优先使用 order_id(如果已创建订单)
|
||||
if record.OrderId.Valid && record.OrderId.String != "" {
|
||||
orderIds = append(orderIds, record.OrderId.String)
|
||||
}
|
||||
// 同时收集 query_no(用于关联订单,query_no 与 order.order_no 一致)
|
||||
if record.QueryNo != "" {
|
||||
queryNos = append(queryNos, record.QueryNo)
|
||||
}
|
||||
}
|
||||
|
||||
logx.Infof("AdminGetOrderList, 提取到 %d 个 order_id, %d 个 query_no", len(orderIds), len(queryNos))
|
||||
|
||||
// 构建订单筛选条件
|
||||
// 使用 OR 条件:通过 order.id 或 order.order_no 匹配
|
||||
if len(orderIds) > 0 && len(queryNos) > 0 {
|
||||
// 同时有 order_id 和 query_no,使用 OR 条件
|
||||
builder = builder.Where(squirrel.Or{
|
||||
squirrel.Eq{"id": orderIds},
|
||||
squirrel.Eq{"order_no": queryNos},
|
||||
})
|
||||
logx.Infof("AdminGetOrderList, 使用 OR 条件: order_id IN (%d个), order_no IN (%d个)", len(orderIds), len(queryNos))
|
||||
} else if len(orderIds) > 0 {
|
||||
// 只有 order_id
|
||||
builder = builder.Where(squirrel.Eq{"id": orderIds})
|
||||
logx.Infof("AdminGetOrderList, 使用 order_id 条件: %d 个订单ID", len(orderIds))
|
||||
} else if len(queryNos) > 0 {
|
||||
// 只有 query_no
|
||||
builder = builder.Where(squirrel.Eq{"order_no": queryNos})
|
||||
logx.Infof("AdminGetOrderList, 使用 query_no 条件: %d 个查询单号", len(queryNos))
|
||||
} else {
|
||||
// 如果没有有效的订单ID或查询单号,返回空结果
|
||||
logx.Infof("AdminGetOrderList, 未找到有效的订单ID或查询单号,返回空结果")
|
||||
return &types.AdminGetOrderListResp{
|
||||
Total: 0,
|
||||
Items: []types.OrderListItem{},
|
||||
}, nil
|
||||
}
|
||||
}
|
||||
|
||||
// 并发获取总数和列表
|
||||
var total int64
|
||||
var orders []*model.Order
|
||||
|
||||
@@ -26,6 +26,6 @@ func NewGetAppVersionLogic(ctx context.Context, svcCtx *svc.ServiceContext) *Get
|
||||
func (l *GetAppVersionLogic) GetAppVersion() (resp *types.GetAppVersionResp, err error) {
|
||||
return &types.GetAppVersionResp{
|
||||
Version: "1.0.0",
|
||||
WgtUrl: "https://www.quannengcha.com/app_version/qnc_1.0.0.wgt",
|
||||
WgtUrl: "https://www.zhenaicha.com/app_version/qnc_1.0.0.wgt",
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -99,6 +99,24 @@ func (l *AlipayCallbackLogic) handleQueryOrderPayment(w http.ResponseWriter, not
|
||||
return nil
|
||||
}
|
||||
|
||||
// 更新 query_user_record 表的 platform_order_id
|
||||
queryUserRecords, findRecordErr := l.svcCtx.QueryUserRecordModel.FindAll(l.ctx,
|
||||
l.svcCtx.QueryUserRecordModel.SelectBuilder().
|
||||
Where("query_no = ?", notification.OutTradeNo).
|
||||
Where("del_state = ?", 0).
|
||||
Limit(1), "")
|
||||
if findRecordErr == nil && len(queryUserRecords) > 0 {
|
||||
record := queryUserRecords[0]
|
||||
record.PlatformOrderId = lzUtils.StringToNullString(notification.TradeNo)
|
||||
record.Version = record.Version + 1
|
||||
if updateRecordErr := l.svcCtx.QueryUserRecordModel.UpdateWithVersion(l.ctx, nil, record); updateRecordErr != nil {
|
||||
logx.Errorf("支付宝支付回调,更新查询用户记录失败: %+v", updateRecordErr)
|
||||
// 更新失败不影响主流程,只记录日志
|
||||
} else {
|
||||
logx.Infof("支付宝支付回调,更新查询用户记录成功,query_no: %s, platform_order_id: %s", notification.OutTradeNo, notification.TradeNo)
|
||||
}
|
||||
}
|
||||
|
||||
if order.Status == "paid" {
|
||||
if asyncErr := l.svcCtx.AsynqService.SendQueryTask(order.Id); asyncErr != nil {
|
||||
logx.Errorf("异步任务调度失败: %v", asyncErr)
|
||||
|
||||
@@ -3,19 +3,23 @@ package pay
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
"qnc-server/app/main/api/internal/svc"
|
||||
"qnc-server/app/main/api/internal/types"
|
||||
"qnc-server/app/main/model"
|
||||
"qnc-server/common/ctxdata"
|
||||
"qnc-server/common/globalkey"
|
||||
"qnc-server/common/xerr"
|
||||
"qnc-server/pkg/lzkit/crypto"
|
||||
"qnc-server/pkg/lzkit/lzUtils"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/Masterminds/squirrel"
|
||||
"github.com/google/uuid"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/redis/go-redis/v9"
|
||||
@@ -241,6 +245,16 @@ func (l *PaymentLogic) QueryOrderPayment(req *types.PaymentReq, session sqlx.Ses
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "生成订单, 获取代理链接失败: %+v", findAgentLinkErr)
|
||||
}
|
||||
amount = agentLinkModel.SetPrice
|
||||
|
||||
// 检查被查询人身份证在72小时内的已支付订单次数
|
||||
// 如果是代理渠道订单,需要检查该身份证在72小时内已支付的订单是否超过2次
|
||||
logx.Infof("生成订单, 检测到代理渠道订单,开始检查订单限制, AgentIdentifier: %s", data.AgentIdentifier)
|
||||
checkErr := l.checkIdCardPaidOrdersIn72Hours(data.Params)
|
||||
if checkErr != nil {
|
||||
logx.Errorf("生成订单, 订单限制检查失败: %v", checkErr)
|
||||
return nil, checkErr
|
||||
}
|
||||
logx.Infof("生成订单, 订单限制检查通过,允许创建订单")
|
||||
} else {
|
||||
amount = product.SellPrice
|
||||
}
|
||||
@@ -264,6 +278,24 @@ func (l *PaymentLogic) QueryOrderPayment(req *types.PaymentReq, session sqlx.Ses
|
||||
}
|
||||
orderID := order.Id
|
||||
|
||||
// 更新 query_user_record 表的 order_id(通过 query_no 匹配)
|
||||
queryUserRecords, findRecordErr := l.svcCtx.QueryUserRecordModel.FindAll(l.ctx,
|
||||
l.svcCtx.QueryUserRecordModel.SelectBuilder().
|
||||
Where("query_no = ?", outTradeNo).
|
||||
Where("del_state = ?", 0).
|
||||
Limit(1), "")
|
||||
if findRecordErr == nil && len(queryUserRecords) > 0 {
|
||||
record := queryUserRecords[0]
|
||||
record.OrderId = lzUtils.StringToNullString(orderID)
|
||||
record.Version = record.Version + 1
|
||||
if updateRecordErr := l.svcCtx.QueryUserRecordModel.UpdateWithVersion(l.ctx, session, record); updateRecordErr != nil {
|
||||
logx.Errorf("更新查询用户记录 order_id 失败: %+v", updateRecordErr)
|
||||
// 更新失败不影响主流程,只记录日志
|
||||
} else {
|
||||
logx.Infof("更新查询用户记录成功,query_no: %s, order_id: %s", outTradeNo, orderID)
|
||||
}
|
||||
}
|
||||
|
||||
// 如果是代理推广订单,创建完整的代理订单记录
|
||||
if data.AgentIdentifier != "" && agentLinkModel != nil {
|
||||
// 获取代理信息
|
||||
@@ -473,3 +505,158 @@ func (l *PaymentLogic) getConfigFloat(configKey string) (float64, error) {
|
||||
}
|
||||
return value, nil
|
||||
}
|
||||
|
||||
// checkIdCardPaidOrdersIn72Hours 检查被查询人身份证在72小时内的已支付订单次数
|
||||
// 如果72小时内已支付订单大于2次,则返回错误
|
||||
// encryptedParams: 加密的参数字符串(data.Params),需要解密后获取身份证号
|
||||
func (l *PaymentLogic) checkIdCardPaidOrdersIn72Hours(encryptedParams string) error {
|
||||
logx.Infof("检查订单限制, 开始检查代理渠道订单限制, encryptedParams长度: %d", len(encryptedParams))
|
||||
|
||||
// 1. 解密参数获取身份证号
|
||||
secretKey := l.svcCtx.Config.Encrypt.SecretKey
|
||||
key, decodeErr := hex.DecodeString(secretKey)
|
||||
if decodeErr != nil {
|
||||
return errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "检查订单限制, 解析加密密钥失败 err: %v", decodeErr)
|
||||
}
|
||||
|
||||
// 解密 data.Params(加密的 JSON 字符串)
|
||||
decryptData, aesDecryptErr := crypto.AesDecrypt(encryptedParams, key)
|
||||
if aesDecryptErr != nil {
|
||||
return errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "检查订单限制, 解密参数失败 err: %v", aesDecryptErr)
|
||||
}
|
||||
|
||||
// 解析解密后的 JSON 获取参数
|
||||
var params map[string]interface{}
|
||||
if unmarshalErr := json.Unmarshal(decryptData, ¶ms); unmarshalErr != nil {
|
||||
return errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "检查订单限制, 解析参数失败 err: %v, decryptData: %s", unmarshalErr, string(decryptData))
|
||||
}
|
||||
|
||||
idCard, ok := params["id_card"].(string)
|
||||
if !ok || idCard == "" {
|
||||
// 如果没有身份证号,跳过检查(可能是其他类型的查询)
|
||||
logx.Infof("检查订单限制, 未找到身份证号,跳过检查")
|
||||
return nil
|
||||
}
|
||||
|
||||
logx.Infof("检查订单限制, 被查询人身份证号: %s", idCard)
|
||||
|
||||
// 2. 加密身份证号用于查询
|
||||
logx.Infof("检查订单限制, 开始加密身份证号: %s", idCard)
|
||||
encryptedIdCard, encryptErr := crypto.EncryptIDCard(idCard, key)
|
||||
if encryptErr != nil {
|
||||
logx.Errorf("检查订单限制, 加密身份证号失败: %v", encryptErr)
|
||||
return errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "检查订单限制, 加密身份证号失败 err: %v", encryptErr)
|
||||
}
|
||||
logx.Infof("检查订单限制, 身份证号加密成功, encryptedIdCard长度: %d", len(encryptedIdCard))
|
||||
|
||||
// 3. 查询该身份证对应的所有查询记录(agent_identifier IS NOT NULL)
|
||||
// 统计该身份证的记录数,然后通过order_id关联订单表查询已支付的订单
|
||||
encryptedIdCardPreview := encryptedIdCard
|
||||
if len(encryptedIdCard) > 20 {
|
||||
encryptedIdCardPreview = encryptedIdCard[:20] + "..."
|
||||
}
|
||||
logx.Infof("检查订单限制, 开始查询数据库")
|
||||
logx.Infof("检查订单限制, 查询条件: id_card=%s, del_state=0, agent_identifier IS NOT NULL, agent_identifier != ''", encryptedIdCardPreview)
|
||||
logx.Infof("检查订单限制, 注意:不要求order_id必须存在,先查询所有记录")
|
||||
queryUserRecords, findRecordErr := l.svcCtx.QueryUserRecordModel.FindAll(l.ctx,
|
||||
l.svcCtx.QueryUserRecordModel.SelectBuilder().
|
||||
Where("id_card = ?", encryptedIdCard).
|
||||
Where("del_state = ?", globalkey.DelStateNo).
|
||||
Where("agent_identifier IS NOT NULL").
|
||||
Where("agent_identifier != ''"),
|
||||
"")
|
||||
if findRecordErr != nil {
|
||||
if errors.Is(findRecordErr, model.ErrNotFound) {
|
||||
logx.Infof("检查订单限制, 查询结果: 未找到记录 (ErrNotFound)")
|
||||
} else {
|
||||
logx.Errorf("检查订单限制, 查询数据库失败: %v", findRecordErr)
|
||||
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "检查订单限制, 查询用户记录失败 err: %v", findRecordErr)
|
||||
}
|
||||
} else {
|
||||
logx.Infof("检查订单限制, 查询数据库成功")
|
||||
}
|
||||
|
||||
logx.Infof("检查订单限制, 查询到 %d 条该身份证的查询记录(agent_identifier IS NOT NULL)", len(queryUserRecords))
|
||||
|
||||
// 统计记录详情
|
||||
if len(queryUserRecords) > 0 {
|
||||
logx.Infof("检查订单限制, ========== 记录详情 ==========")
|
||||
for i, record := range queryUserRecords {
|
||||
orderId := ""
|
||||
hasOrderId := false
|
||||
if record.OrderId.Valid && record.OrderId.String != "" {
|
||||
orderId = record.OrderId.String
|
||||
hasOrderId = true
|
||||
}
|
||||
agentId := ""
|
||||
if record.AgentIdentifier.Valid {
|
||||
agentId = record.AgentIdentifier.String
|
||||
}
|
||||
logx.Infof("检查订单限制, 记录[%d/%d]: order_id=%s (有order_id: %v), agent_identifier=%s, query_no=%s, create_time=%s, product=%s",
|
||||
i+1, len(queryUserRecords), orderId, hasOrderId, agentId, record.QueryNo, record.CreateTime.Format("2006-01-02 15:04:05"), record.Product)
|
||||
}
|
||||
logx.Infof("检查订单限制, ========== 记录详情结束 ==========")
|
||||
}
|
||||
|
||||
if len(queryUserRecords) == 0 {
|
||||
// 没有历史订单记录,可以继续
|
||||
logx.Infof("检查订单限制, 身份证 %s 无历史订单记录,允许支付", idCard)
|
||||
return nil
|
||||
}
|
||||
|
||||
// 4. 提取所有订单ID(去重),只提取有order_id的记录
|
||||
logx.Infof("检查订单限制, 开始提取订单ID,总记录数: %d", len(queryUserRecords))
|
||||
orderIdSet := make(map[string]bool)
|
||||
orderIds := make([]string, 0)
|
||||
recordsWithOrderId := 0
|
||||
for i, record := range queryUserRecords {
|
||||
if record.OrderId.Valid && record.OrderId.String != "" {
|
||||
recordsWithOrderId++
|
||||
orderId := record.OrderId.String
|
||||
if !orderIdSet[orderId] {
|
||||
orderIdSet[orderId] = true
|
||||
orderIds = append(orderIds, orderId)
|
||||
logx.Infof("检查订单限制, 记录[%d]有order_id: %s", i+1, orderId)
|
||||
} else {
|
||||
logx.Infof("检查订单限制, 记录[%d]order_id重复: %s (已存在)", i+1, orderId)
|
||||
}
|
||||
} else {
|
||||
logx.Infof("检查订单限制, 记录[%d]无order_id,跳过", i+1)
|
||||
}
|
||||
}
|
||||
|
||||
logx.Infof("检查订单限制, 有order_id的记录数: %d, 提取到 %d 个唯一订单ID: %v", recordsWithOrderId, len(orderIds), orderIds)
|
||||
|
||||
if len(orderIds) == 0 {
|
||||
logx.Infof("检查订单限制, 身份证 %s 无有效订单ID,允许支付", idCard)
|
||||
return nil
|
||||
}
|
||||
|
||||
// 5. 查询72小时内已支付的订单数量(只统计已支付状态的订单)
|
||||
// 计算72小时前的时间
|
||||
seventyTwoHoursAgo := time.Now().Add(-72 * time.Hour)
|
||||
logx.Infof("检查订单限制, 查询时间范围: %s 至今", seventyTwoHoursAgo.Format("2006-01-02 15:04:05"))
|
||||
logx.Infof("检查订单限制, 查询条件: status='paid', pay_time IS NOT NULL, pay_time >= %s", seventyTwoHoursAgo.Format("2006-01-02 15:04:05"))
|
||||
|
||||
// 只统计已支付状态的订单(status='paid')
|
||||
paidOrderCount, countErr := l.svcCtx.OrderModel.FindCount(l.ctx,
|
||||
l.svcCtx.OrderModel.SelectBuilder().
|
||||
Where(squirrel.Eq{"id": orderIds}).
|
||||
Where("status = ?", model.OrderStatusPaid). // 只查询已支付状态的订单
|
||||
Where("pay_time IS NOT NULL"). // 必须有支付时间
|
||||
Where("pay_time >= ?", seventyTwoHoursAgo). // 72小时内
|
||||
Where("del_state = ?", globalkey.DelStateNo),
|
||||
"id")
|
||||
if countErr != nil {
|
||||
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "检查订单限制, 查询已支付订单数量失败 err: %v", countErr)
|
||||
}
|
||||
|
||||
logx.Infof("检查订单限制, 身份证 %s 在72小时内已支付的订单数量: %d (限制: 已支付订单数量>2次则拒绝)", idCard, paidOrderCount)
|
||||
|
||||
// 6. 如果72小时内已支付订单数量大于2次,则拒绝支付
|
||||
if paidOrderCount > 2 {
|
||||
return errors.Wrapf(xerr.NewErrMsg("该身份证在72小时内已支付订单超过2次,无法进行代理渠道的报告查询支付"), "")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -97,6 +97,24 @@ func (l *WechatPayCallbackLogic) handleQueryOrderPayment(w http.ResponseWriter,
|
||||
return nil
|
||||
}
|
||||
|
||||
// 更新 query_user_record 表的 platform_order_id
|
||||
queryUserRecords, findRecordErr := l.svcCtx.QueryUserRecordModel.FindAll(l.ctx,
|
||||
l.svcCtx.QueryUserRecordModel.SelectBuilder().
|
||||
Where("query_no = ?", *notification.OutTradeNo).
|
||||
Where("del_state = ?", 0).
|
||||
Limit(1), "")
|
||||
if findRecordErr == nil && len(queryUserRecords) > 0 {
|
||||
record := queryUserRecords[0]
|
||||
record.PlatformOrderId = lzUtils.StringToNullString(*notification.TransactionId)
|
||||
record.Version = record.Version + 1
|
||||
if updateRecordErr := l.svcCtx.QueryUserRecordModel.UpdateWithVersion(l.ctx, nil, record); updateRecordErr != nil {
|
||||
logx.Errorf("微信支付回调,更新查询用户记录失败: %+v", updateRecordErr)
|
||||
// 更新失败不影响主流程,只记录日志
|
||||
} else {
|
||||
logx.Infof("微信支付回调,更新查询用户记录成功,query_no: %s, platform_order_id: %s", *notification.OutTradeNo, *notification.TransactionId)
|
||||
}
|
||||
}
|
||||
|
||||
if order.Status == "paid" {
|
||||
if asyncErr := l.svcCtx.AsynqService.SendQueryTask(order.Id); asyncErr != nil {
|
||||
logx.Errorf("异步任务调度失败: %v", asyncErr)
|
||||
|
||||
@@ -7,12 +7,15 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
"qnc-server/app/main/api/internal/service"
|
||||
"qnc-server/app/main/model"
|
||||
"qnc-server/common/ctxdata"
|
||||
"qnc-server/common/xerr"
|
||||
"qnc-server/pkg/lzkit/crypto"
|
||||
"qnc-server/pkg/lzkit/lzUtils"
|
||||
"qnc-server/pkg/lzkit/validator"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/zeromicro/go-zero/core/stores/redis"
|
||||
|
||||
@@ -107,6 +110,11 @@ func (l *QueryServiceLogic) ProcessMarriageLogic(req *types.QueryServiceReq) (*t
|
||||
if cacheDataErr != nil {
|
||||
return nil, cacheDataErr
|
||||
}
|
||||
// 插入业务操作记录
|
||||
if insertErr := l.InsertQueryUserRecord(params, "marriage", cacheNo, userID); insertErr != nil {
|
||||
logx.Errorf("插入查询用户记录失败: %v", insertErr)
|
||||
// 记录失败不影响主流程,只记录日志
|
||||
}
|
||||
token, err := l.svcCtx.UserService.GeneralUserToken(l.ctx, userID)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "查询服务, 生成token失败 : %v", err)
|
||||
@@ -167,7 +175,11 @@ func (l *QueryServiceLogic) ProcessHomeServiceLogic(req *types.QueryServiceReq)
|
||||
if cacheDataErr != nil {
|
||||
return nil, cacheDataErr
|
||||
}
|
||||
|
||||
// 插入业务操作记录
|
||||
if insertErr := l.InsertQueryUserRecord(params, "homeservice", cacheNo, userID); insertErr != nil {
|
||||
logx.Errorf("插入查询用户记录失败: %v", insertErr)
|
||||
// 记录失败不影响主流程,只记录日志
|
||||
}
|
||||
token, err := l.svcCtx.UserService.GeneralUserToken(l.ctx, userID)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "查询服务, 生成token失败 : %d", userID)
|
||||
@@ -228,7 +240,11 @@ func (l *QueryServiceLogic) ProcessRiskAssessmentLogic(req *types.QueryServiceRe
|
||||
if cacheDataErr != nil {
|
||||
return nil, cacheDataErr
|
||||
}
|
||||
|
||||
// 插入业务操作记录
|
||||
if insertErr := l.InsertQueryUserRecord(params, "riskassessment", cacheNo, userID); insertErr != nil {
|
||||
logx.Errorf("插入查询用户记录失败: %v", insertErr)
|
||||
// 记录失败不影响主流程,只记录日志
|
||||
}
|
||||
token, err := l.svcCtx.UserService.GeneralUserToken(l.ctx, userID)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "查询服务, 生成token失败 : %d", userID)
|
||||
@@ -288,7 +304,11 @@ func (l *QueryServiceLogic) ProcessCompanyInfoLogic(req *types.QueryServiceReq)
|
||||
if cacheDataErr != nil {
|
||||
return nil, cacheDataErr
|
||||
}
|
||||
|
||||
// 插入业务操作记录
|
||||
if insertErr := l.InsertQueryUserRecord(params, "companyinfo", cacheNo, userID); insertErr != nil {
|
||||
logx.Errorf("插入查询用户记录失败: %v", insertErr)
|
||||
// 记录失败不影响主流程,只记录日志
|
||||
}
|
||||
token, err := l.svcCtx.UserService.GeneralUserToken(l.ctx, userID)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "查询服务, 生成token失败 : %d", userID)
|
||||
@@ -349,7 +369,11 @@ func (l *QueryServiceLogic) ProcessRentalInfoLogic(req *types.QueryServiceReq) (
|
||||
if cacheDataErr != nil {
|
||||
return nil, cacheDataErr
|
||||
}
|
||||
|
||||
// 插入业务操作记录
|
||||
if insertErr := l.InsertQueryUserRecord(params, "rentalinfo", cacheNo, userID); insertErr != nil {
|
||||
logx.Errorf("插入查询用户记录失败: %v", insertErr)
|
||||
// 记录失败不影响主流程,只记录日志
|
||||
}
|
||||
token, err := l.svcCtx.UserService.GeneralUserToken(l.ctx, userID)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "查询服务, 生成token失败 : %d", userID)
|
||||
@@ -410,7 +434,11 @@ func (l *QueryServiceLogic) ProcessPreLoanBackgroundCheckLogic(req *types.QueryS
|
||||
if cacheDataErr != nil {
|
||||
return nil, cacheDataErr
|
||||
}
|
||||
|
||||
// 插入业务操作记录
|
||||
if insertErr := l.InsertQueryUserRecord(params, "preloanbackgroundcheck", cacheNo, userID); insertErr != nil {
|
||||
logx.Errorf("插入查询用户记录失败: %v", insertErr)
|
||||
// 记录失败不影响主流程,只记录日志
|
||||
}
|
||||
token, err := l.svcCtx.UserService.GeneralUserToken(l.ctx, userID)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "查询服务, 生成token失败 : %d", userID)
|
||||
@@ -470,7 +498,11 @@ func (l *QueryServiceLogic) ProcessBackgroundCheckLogic(req *types.QueryServiceR
|
||||
if cacheDataErr != nil {
|
||||
return nil, cacheDataErr
|
||||
}
|
||||
|
||||
// 插入业务操作记录
|
||||
if insertErr := l.InsertQueryUserRecord(params, "backgroundcheck", cacheNo, userID); insertErr != nil {
|
||||
logx.Errorf("插入查询用户记录失败: %v", insertErr)
|
||||
// 记录失败不影响主流程,只记录日志
|
||||
}
|
||||
token, err := l.svcCtx.UserService.GeneralUserToken(l.ctx, userID)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "查询服务, 生成token失败 : %d", userID)
|
||||
@@ -528,7 +560,11 @@ func (l *QueryServiceLogic) ProcessPersonalDataLogic(req *types.QueryServiceReq)
|
||||
if cacheDataErr != nil {
|
||||
return nil, cacheDataErr
|
||||
}
|
||||
|
||||
// 插入业务操作记录
|
||||
if insertErr := l.InsertQueryUserRecord(params, "personalData", cacheNo, userID); insertErr != nil {
|
||||
logx.Errorf("插入查询用户记录失败: %v", insertErr)
|
||||
// 记录失败不影响主流程,只记录日志
|
||||
}
|
||||
token, err := l.svcCtx.UserService.GeneralUserToken(l.ctx, userID)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "查询服务, 生成token失败 : %d", userID)
|
||||
@@ -586,7 +622,11 @@ func (l *QueryServiceLogic) ProcessConsumerFinanceReportLogic(req *types.QuerySe
|
||||
if cacheDataErr != nil {
|
||||
return nil, cacheDataErr
|
||||
}
|
||||
|
||||
// 插入业务操作记录
|
||||
if insertErr := l.InsertQueryUserRecord(params, "consumerFinanceReport", cacheNo, userID); insertErr != nil {
|
||||
logx.Errorf("插入查询用户记录失败: %v", insertErr)
|
||||
// 记录失败不影响主流程,只记录日志
|
||||
}
|
||||
token, err := l.svcCtx.UserService.GeneralUserToken(l.ctx, userID)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "查询服务, 生成token失败 : %d", userID)
|
||||
@@ -734,3 +774,61 @@ func (l *QueryServiceLogic) GetOrCreateUser() (string, error) {
|
||||
|
||||
return userID, nil
|
||||
}
|
||||
|
||||
// InsertQueryUserRecord 插入查询用户记录到 query_user_record 表
|
||||
// 业务场景:用户提交查询时,记录用户输入的姓名、身份证、手机号等信息
|
||||
func (l *QueryServiceLogic) InsertQueryUserRecord(params map[string]interface{}, product string, queryNo string, userID string) error {
|
||||
secretKey := l.svcCtx.Config.Encrypt.SecretKey
|
||||
key, decodeErr := hex.DecodeString(secretKey)
|
||||
if decodeErr != nil {
|
||||
return errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "插入查询用户记录, 获取AES秘钥失败: %+v", decodeErr)
|
||||
}
|
||||
|
||||
// 获取姓名、身份证、手机号
|
||||
name, _ := params["name"].(string)
|
||||
idCard, _ := params["id_card"].(string)
|
||||
mobile, _ := params["mobile"].(string)
|
||||
|
||||
// 加密敏感字段
|
||||
encryptedName, err := crypto.AesEcbEncrypt([]byte(name), key)
|
||||
if err != nil {
|
||||
return errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "插入查询用户记录, 加密姓名失败: %+v", err)
|
||||
}
|
||||
|
||||
encryptedIdCard, err := crypto.EncryptIDCard(idCard, key)
|
||||
if err != nil {
|
||||
return errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "插入查询用户记录, 加密身份证号失败: %+v", err)
|
||||
}
|
||||
|
||||
encryptedMobile, err := crypto.EncryptMobile(mobile, secretKey)
|
||||
if err != nil {
|
||||
return errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "插入查询用户记录, 加密手机号失败: %+v", err)
|
||||
}
|
||||
|
||||
// 获取代理标识
|
||||
agentIdentifier, _ := l.ctx.Value("agentIdentifier").(string)
|
||||
|
||||
// 创建记录
|
||||
record := &model.QueryUserRecord{
|
||||
Id: uuid.NewString(), // 生成 UUID
|
||||
UserId: userID, // user_id 是 UUID 字符串
|
||||
Name: encryptedName,
|
||||
IdCard: encryptedIdCard,
|
||||
Mobile: encryptedMobile,
|
||||
Product: product,
|
||||
QueryNo: queryNo,
|
||||
OrderId: lzUtils.StringToNullString(""), // 初始为 NULL,创建订单后更新
|
||||
PlatformOrderId: lzUtils.StringToNullString(""), // 初始为空,支付成功后更新
|
||||
AgentIdentifier: lzUtils.StringToNullString(agentIdentifier),
|
||||
DelState: 0,
|
||||
Version: 0,
|
||||
}
|
||||
|
||||
// 插入数据库
|
||||
_, err = l.svcCtx.QueryUserRecordModel.Insert(l.ctx, nil, record)
|
||||
if err != nil {
|
||||
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "插入查询用户记录失败: %+v", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -6,13 +6,13 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"regexp"
|
||||
"strings"
|
||||
"qnc-server/app/main/api/internal/svc"
|
||||
"qnc-server/app/main/api/internal/types"
|
||||
"qnc-server/app/main/model"
|
||||
"qnc-server/pkg/lzkit/crypto"
|
||||
"qnc-server/pkg/lzkit/lzUtils"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/hibiken/asynq"
|
||||
|
||||
@@ -38,6 +38,7 @@ type ServiceContext struct {
|
||||
OrderModel model.OrderModel
|
||||
OrderRefundModel model.OrderRefundModel
|
||||
QueryModel model.QueryModel
|
||||
QueryUserRecordModel model.QueryUserRecordModel
|
||||
QueryCleanupLogModel model.QueryCleanupLogModel
|
||||
QueryCleanupDetailModel model.QueryCleanupDetailModel
|
||||
QueryCleanupConfigModel model.QueryCleanupConfigModel
|
||||
@@ -118,6 +119,7 @@ func NewServiceContext(c config.Config) *ServiceContext {
|
||||
// ============================== 订单相关模型 ==============================
|
||||
orderModel := model.NewOrderModel(db, cacheConf)
|
||||
queryModel := model.NewQueryModel(db, cacheConf)
|
||||
queryUserRecordModel := model.NewQueryUserRecordModel(db, cacheConf)
|
||||
orderRefundModel := model.NewOrderRefundModel(db, cacheConf)
|
||||
queryCleanupLogModel := model.NewQueryCleanupLogModel(db, cacheConf)
|
||||
queryCleanupDetailModel := model.NewQueryCleanupDetailModel(db, cacheConf)
|
||||
@@ -217,6 +219,7 @@ func NewServiceContext(c config.Config) *ServiceContext {
|
||||
// 订单相关模型
|
||||
OrderModel: orderModel,
|
||||
QueryModel: queryModel,
|
||||
QueryUserRecordModel: queryUserRecordModel,
|
||||
OrderRefundModel: orderRefundModel,
|
||||
QueryCleanupLogModel: queryCleanupLogModel,
|
||||
QueryCleanupDetailModel: queryCleanupDetailModel,
|
||||
|
||||
@@ -61,6 +61,9 @@ type AdminGetOrderListReq struct {
|
||||
PayTimeEnd string `form:"pay_time_end,optional"` // 支付时间结束
|
||||
RefundTimeStart string `form:"refund_time_start,optional"` // 退款时间开始
|
||||
RefundTimeEnd string `form:"refund_time_end,optional"` // 退款时间结束
|
||||
QueryUserName string `form:"query_user_name,optional"` // 被查询人姓名
|
||||
QueryUserIdCard string `form:"query_user_id_card,optional"` // 被查询人身份证号
|
||||
QueryUserMobile string `form:"query_user_mobile,optional"` // 被查询人手机号
|
||||
}
|
||||
|
||||
type AdminGetOrderListResp struct {
|
||||
|
||||
Reference in New Issue
Block a user