qnc init
This commit is contained in:
716
api/car.go
Normal file
716
api/car.go
Normal file
@@ -0,0 +1,716 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/gin-gonic/gin"
|
||||
"gorm.io/gorm"
|
||||
"io"
|
||||
"log"
|
||||
"qnc-server/config"
|
||||
"qnc-server/db"
|
||||
"qnc-server/model/model"
|
||||
"qnc-server/model/request"
|
||||
"qnc-server/model/response"
|
||||
"qnc-server/service"
|
||||
"qnc-server/utils"
|
||||
"strconv"
|
||||
"sync"
|
||||
)
|
||||
|
||||
type Car struct {
|
||||
}
|
||||
|
||||
var carService service.CarService
|
||||
|
||||
// 注册路由
|
||||
func InitCar(group *gin.RouterGroup) {
|
||||
var c Car
|
||||
{
|
||||
carPrivateGroup := group.Group("car")
|
||||
carPrivateGroup.Use(JWTAuth())
|
||||
carPrivateGroup.POST("insurance", c.Insurance)
|
||||
carPrivateGroup.POST("maintenance", c.Maintenance)
|
||||
carPrivateGroup.GET("get_query", c.GetQueryRecord)
|
||||
carPrivateGroup.POST("person_car_verify", c.PersonCarVerify)
|
||||
carPrivateGroup.POST("under_name", c.UnderName)
|
||||
carPrivateGroup.POST("insurance_info", c.InsuranceInfo)
|
||||
//carPrivateGroup.POST("new_energy_power", c.NewEnergyPower)
|
||||
carPrivateGroup.POST("vin_check_info", c.VinCheckInfo)
|
||||
carPrivateGroup.POST("vehicle_transfer", c.VehicleTransfer)
|
||||
carPrivateGroup.POST("vehicle_valuation", c.VehicleValuation)
|
||||
|
||||
carPrivateGroup.GET("get_maintenance_history", c.QueryHistoryList)
|
||||
|
||||
}
|
||||
|
||||
{
|
||||
carPublicGroup := group.Group("car")
|
||||
carPublicGroup.POST("callback", c.CarCallback)
|
||||
}
|
||||
}
|
||||
|
||||
// 出险综合查询
|
||||
func (car *Car) Insurance(c *gin.Context) {
|
||||
|
||||
var reqBody request.CarInsuranceReq
|
||||
if err := c.ShouldBindJSON(&reqBody); err != nil {
|
||||
response.FailWithMessage("Failed to read request body", c)
|
||||
return
|
||||
}
|
||||
|
||||
userid := utils.GetUserID(c)
|
||||
// 查找是否有 未消费 已付费 的订单
|
||||
order, err := orderService.QueryConsumedOrder(userid, "chexian")
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
// 为空就没有消费资格
|
||||
response.OkNeedPay(c)
|
||||
return
|
||||
} else {
|
||||
log.Printf("QueryConsumedOrder err:%s", err.Error())
|
||||
response.FailWithMessage("服务器错误请稍后再试", c)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
var carInsurance model.CarInsurance
|
||||
reqData := map[string]interface{}{
|
||||
"vin": reqBody.Vin,
|
||||
}
|
||||
plainText, err := carService.CarReqYuShan("CAR074", &reqData)
|
||||
if err != nil {
|
||||
log.Printf("YuShan request at %s error: %s", "CAR074", err.Error())
|
||||
notifyService.SendNotification("羽山接口请求错误,请及时处理", "出险综合查询", userid, order.ID)
|
||||
response.FailRefund(c)
|
||||
return
|
||||
}
|
||||
|
||||
_, err = carService.CarInsuranceDataAnalysis(string(plainText))
|
||||
if err != nil {
|
||||
if errors.Is(err, utils.ErrNoRecord) {
|
||||
notifyService.SendNotification("用户查询数据为空,请及时处理", "出险综合查询", userid, order.ID)
|
||||
} else {
|
||||
notifyService.SendNotification("接口系统响应错误,请及时处理", "出险综合查询", userid, order.ID)
|
||||
}
|
||||
response.FailRefund(c)
|
||||
return
|
||||
}
|
||||
carInsurance.Resp = string(plainText)
|
||||
carInsurance.Vin = reqBody.Vin
|
||||
carInsurance.UserID = userid
|
||||
carInsurance.OrderID = order.ID
|
||||
err = db.DB.Create(&carInsurance).Error
|
||||
if err != nil {
|
||||
log.Printf("汽车出险综合记录失败:%v", err)
|
||||
notifyService.SendNotification("汽车查询数据保存错误,请及时处理", "出险综合查询", userid, order.ID)
|
||||
response.FailRefund(c)
|
||||
return
|
||||
}
|
||||
orderService.OrderConsumed(order)
|
||||
|
||||
response.OkWithData(gin.H{
|
||||
"record_id": carInsurance.OrderID,
|
||||
}, c)
|
||||
|
||||
}
|
||||
|
||||
// 维保记录
|
||||
func (car *Car) Maintenance(c *gin.Context) {
|
||||
var reqBody request.CarMaintenanceReq
|
||||
if err := c.ShouldBindJSON(&reqBody); err != nil {
|
||||
response.FailWithMessage("Failed to read request body", c)
|
||||
return
|
||||
}
|
||||
|
||||
userid := utils.GetUserID(c)
|
||||
order, err := orderService.QueryConsumedOrder(userid, "weibao")
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
// 为空就没有消费资格
|
||||
response.OkNeedPay(c)
|
||||
return
|
||||
} else {
|
||||
log.Printf("QueryConsumedOrder err:%s", err.Error())
|
||||
response.FailWithMessage("服务器错误请稍后再试", c)
|
||||
return
|
||||
}
|
||||
}
|
||||
notifySN, _ := utils.GenerateRandomString()
|
||||
var carMaintenance model.CarMaintenance
|
||||
reqData := map[string]interface{}{
|
||||
"vin": reqBody.Vin,
|
||||
"image": reqBody.ImageBase64,
|
||||
"notifyUrl": fmt.Sprintf("%s?notify_sn=%s", config.ConfigData.Car.Callback, notifySN),
|
||||
}
|
||||
plainText, err := carService.CarReqYuShan("CAR058", &reqData)
|
||||
if err != nil {
|
||||
log.Printf("YuShan request at %s error: %s", "CAR058", err.Error())
|
||||
notifyService.SendNotification("羽山接口请求错误,请及时处理", "维保记录CAR058", userid, order.ID)
|
||||
response.FailRefund(c)
|
||||
return
|
||||
}
|
||||
data, err := carService.CarDataAnalysis(string(plainText))
|
||||
if err != nil {
|
||||
if errors.Is(err, utils.ErrNoRecord) {
|
||||
notifyService.SendNotification("用户查询数据为空,请及时处理", "维保记录CAR058", userid, order.ID)
|
||||
} else {
|
||||
notifyService.SendNotification("接口系统响应错误,请及时处理", "维保记录CAR058", userid, order.ID)
|
||||
}
|
||||
response.FailRefund(c)
|
||||
return
|
||||
}
|
||||
|
||||
// 检查 report 中是否存在 "orderId"
|
||||
orderId, exists := data.Retdata["orderId"]
|
||||
if !exists {
|
||||
log.Printf("orderId不存在")
|
||||
response.FailWithMessage("信息输入不匹配,无相关数据", c)
|
||||
return
|
||||
}
|
||||
carMaintenance.Vin = reqBody.Vin
|
||||
carMaintenance.UserID = userid
|
||||
carMaintenance.YuShanOrderID = orderId.(string)
|
||||
carMaintenance.OrderID = order.ID
|
||||
carMaintenance.Status = model.StatusPending
|
||||
carMaintenance.NotifySN = notifySN
|
||||
err = db.DB.Create(&carMaintenance).Error
|
||||
if err != nil {
|
||||
log.Printf("汽车出险综合订单记录失败:%v", err)
|
||||
notifyService.SendNotification("汽车查询订单保存错误,请及时处理", "维保记录", userid, order.ID)
|
||||
response.FailRefund(c)
|
||||
return
|
||||
}
|
||||
orderService.OrderConsumed(order)
|
||||
|
||||
response.OkWait(c)
|
||||
}
|
||||
|
||||
func (car *Car) GetQueryRecord(c *gin.Context) {
|
||||
var req request.GetQueryRecordReq
|
||||
|
||||
if err := c.ShouldBindQuery(&req); err != nil {
|
||||
response.FailWithMessage("Failed to read request", c)
|
||||
return
|
||||
}
|
||||
|
||||
userid := utils.GetUserID(c)
|
||||
var record interface{}
|
||||
var err error
|
||||
if req.IsCase {
|
||||
record, err = carService.GetRecordCaseByFeature(req.Feature)
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
log.Printf("无相关示例记录:%v", err)
|
||||
response.FailWithMessage("无相关示例记录", c)
|
||||
return
|
||||
} else {
|
||||
log.Printf("查询示例记录错误:%v", err)
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
}
|
||||
} else {
|
||||
record, err = carService.GetRecordByFeature(req.Feature, req.ID, userid)
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
log.Printf("无相关查车记录:%v", err)
|
||||
response.FailWithMessage("无相关查车记录", c)
|
||||
return
|
||||
} else {
|
||||
log.Printf("查询查车记录错误:%v", err)
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
response.OkWithData(record, c)
|
||||
}
|
||||
|
||||
// 人车核验 CAR012
|
||||
// 行驶证信息核验
|
||||
func (car *Car) PersonCarVerify(c *gin.Context) {
|
||||
|
||||
var reqBody request.CarNameTypeNumberReq
|
||||
if err := c.ShouldBindJSON(&reqBody); err != nil {
|
||||
response.FailWithMessage("Failed to read request body", c)
|
||||
return
|
||||
}
|
||||
|
||||
userid := utils.GetUserID(c)
|
||||
|
||||
// 查找是否有 未消费 已付费 的订单
|
||||
order, err := orderService.QueryConsumedOrder(userid, "rencheheyan")
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
// 为空就没有消费资格
|
||||
response.OkNeedPay(c)
|
||||
return
|
||||
} else {
|
||||
log.Printf("QueryConsumedOrder err:%s", err.Error())
|
||||
response.FailWithMessage("服务器错误请稍后再试", c)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
var carModel model.CarPersonCarVerify
|
||||
reqData := map[string]interface{}{
|
||||
"name": reqBody.Name,
|
||||
"carType": reqBody.CarType,
|
||||
"carNumber": reqBody.CarNumber,
|
||||
}
|
||||
plainText, err := carService.CarReqYuShan("P_C_B332", &reqData)
|
||||
if err != nil {
|
||||
log.Printf("YuShan request at %s error: %s", "P_C_B332", err.Error())
|
||||
notifyService.SendNotification("羽山接口请求错误,请及时处理", "人车核验P_C_B332", userid, order.ID)
|
||||
response.FailRefund(c)
|
||||
return
|
||||
}
|
||||
|
||||
_, err = carService.CarPersonCarVerifyDataAnalysis(string(plainText))
|
||||
if err != nil {
|
||||
if errors.Is(err, utils.ErrNoRecord) {
|
||||
notifyService.SendNotification("用户查询数据为空,请及时处理", "人车核验P_C_B332", userid, order.ID)
|
||||
} else {
|
||||
notifyService.SendNotification("接口系统响应错误,请及时处理", "人车核验P_C_B332", userid, order.ID)
|
||||
}
|
||||
response.FailRefund(c)
|
||||
return
|
||||
}
|
||||
carModel.Resp = string(plainText)
|
||||
carModel.Name = reqBody.Name
|
||||
carModel.CarNumber = reqBody.CarNumber
|
||||
carModel.CarType = reqBody.CarType
|
||||
carModel.UserID = userid
|
||||
err = db.DB.Create(&carModel).Error
|
||||
if err != nil {
|
||||
log.Printf("人车核验保存错误:%v", err)
|
||||
notifyService.SendNotification("人车核验保存错误,请及时处理", "人车核验P_C_B332", userid, order.ID)
|
||||
response.FailRefund(c)
|
||||
return
|
||||
}
|
||||
orderService.OrderConsumed(order)
|
||||
response.OkWithData(gin.H{
|
||||
"record_id": carModel.OrderID,
|
||||
}, c)
|
||||
|
||||
}
|
||||
|
||||
// CAR061名下车辆
|
||||
func (car *Car) UnderName(c *gin.Context) {
|
||||
|
||||
var reqBody request.CarCardNoReq
|
||||
if err := c.ShouldBindJSON(&reqBody); err != nil {
|
||||
response.FailWithMessage("Failed to read request body", c)
|
||||
return
|
||||
}
|
||||
|
||||
userid := utils.GetUserID(c)
|
||||
order, err := orderService.QueryConsumedOrder(userid, "mingxiacheliang")
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
// 为空就没有消费资格
|
||||
response.OkNeedPay(c)
|
||||
return
|
||||
} else {
|
||||
log.Printf("QueryConsumedOrder err:%s", err.Error())
|
||||
response.FailWithMessage("服务器错误请稍后再试", c)
|
||||
return
|
||||
}
|
||||
}
|
||||
var carModel model.CarUnderName
|
||||
reqData := map[string]interface{}{
|
||||
"cardNo": reqBody.CardNo,
|
||||
}
|
||||
plainText, err := carService.CarReqYuShan("CAR061", &reqData)
|
||||
if err != nil {
|
||||
log.Printf("YuShan request at %s error: %s", "CAR061", err.Error())
|
||||
notifyService.SendNotification("羽山接口请求错误,请及时处理", "CAR061名下车辆", userid, order.ID)
|
||||
response.FailRefund(c)
|
||||
return
|
||||
}
|
||||
|
||||
_, err = carService.CarInsuranceDataAnalysis(string(plainText))
|
||||
if err != nil {
|
||||
if errors.Is(err, utils.ErrNoRecord) {
|
||||
notifyService.SendNotification("用户查询数据为空,请及时处理", "CAR061名下车辆", userid, order.ID)
|
||||
} else {
|
||||
notifyService.SendNotification("接口系统响应错误,请及时处理", "CAR061名下车辆", userid, order.ID)
|
||||
}
|
||||
response.FailRefund(c)
|
||||
return
|
||||
}
|
||||
carModel.Resp = string(plainText)
|
||||
carModel.UserID = userid
|
||||
carModel.OrderID = order.ID
|
||||
err = db.DB.Create(&carModel).Error
|
||||
if err != nil {
|
||||
log.Printf("名下车辆查询保存错误:%v", err)
|
||||
notifyService.SendNotification("汽车查询数据保存错误,请及时处理", "CAR061名下车辆", userid, order.ID)
|
||||
response.FailRefund(c)
|
||||
return
|
||||
}
|
||||
orderService.OrderConsumed(order)
|
||||
|
||||
response.OkWithData(gin.H{
|
||||
"record_id": carModel.OrderID,
|
||||
}, c)
|
||||
|
||||
}
|
||||
|
||||
// CAR070车辆上险信息
|
||||
func (car *Car) InsuranceInfo(c *gin.Context) {
|
||||
var reqBody request.CarVinReq
|
||||
if err := c.ShouldBindJSON(&reqBody); err != nil {
|
||||
response.FailWithMessage("Failed to read request body", c)
|
||||
return
|
||||
}
|
||||
|
||||
userid := utils.GetUserID(c)
|
||||
order, err := orderService.QueryConsumedOrder(userid, "cheliangshangxian")
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
// 为空就没有消费资格
|
||||
response.OkNeedPay(c)
|
||||
return
|
||||
} else {
|
||||
log.Printf("QueryConsumedOrder err:%s", err.Error())
|
||||
response.FailWithMessage("服务器错误请稍后再试", c)
|
||||
return
|
||||
}
|
||||
}
|
||||
var carModel model.CarInsuranceInfo
|
||||
reqData := map[string]interface{}{
|
||||
"vin": reqBody.Vin,
|
||||
}
|
||||
var wg sync.WaitGroup
|
||||
|
||||
var plainTextSx, plainTextWx []byte
|
||||
var sxErr, WxErr error
|
||||
|
||||
wg.Add(2)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
plainTextSx, sxErr = carService.CarReqYuShan("CAR070", &reqData)
|
||||
}()
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
plainTextWx, WxErr = carService.CarReqYuShan("CAR095", &reqData)
|
||||
}()
|
||||
wg.Wait()
|
||||
|
||||
if sxErr != nil {
|
||||
log.Printf("YuShan request at %s error: %s", "CAR070", sxErr.Error())
|
||||
notifyService.SendNotification("羽山接口请求错误,请及时处理", "CAR070", userid, order.ID)
|
||||
response.FailRefund(c)
|
||||
return
|
||||
}
|
||||
if WxErr != nil {
|
||||
log.Printf("YuShan request at %s error: %s", "CAR095", WxErr.Error())
|
||||
notifyService.SendNotification("羽山接口请求错误,请及时处理", "CAR095", userid, order.ID)
|
||||
response.FailRefund(c)
|
||||
return
|
||||
}
|
||||
|
||||
_, err = carService.CarInsuranceDataAnalysis(string(plainTextSx))
|
||||
if err != nil {
|
||||
if errors.Is(err, utils.ErrNoRecord) {
|
||||
notifyService.SendNotification("用户查询数据为空,请及时处理", "CAR070", userid, order.ID)
|
||||
} else {
|
||||
notifyService.SendNotification("接口系统响应错误,请及时处理", "CAR070", userid, order.ID)
|
||||
}
|
||||
response.FailRefund(c)
|
||||
return
|
||||
}
|
||||
_, err = carService.CarInsuranceDataAnalysis(string(plainTextWx))
|
||||
if err != nil {
|
||||
if errors.Is(err, utils.ErrNoRecord) {
|
||||
notifyService.SendNotification("用户查询数据为空,请及时处理", "CAR095", userid, order.ID)
|
||||
} else {
|
||||
notifyService.SendNotification("接口系统响应错误,请及时处理", "CAR095", userid, order.ID)
|
||||
}
|
||||
response.FailRefund(c)
|
||||
return
|
||||
}
|
||||
carModel.Resp = string(plainTextSx)
|
||||
carModel.FiveResp = string(plainTextWx)
|
||||
carModel.UserID = userid
|
||||
carModel.Vin = reqBody.Vin
|
||||
carModel.OrderID = order.ID
|
||||
|
||||
err = db.DB.Create(&carModel).Error
|
||||
if err != nil {
|
||||
log.Printf("车辆上险信息保存错误:%v", err)
|
||||
notifyService.SendNotification("汽车查询数据保存错误,请及时处理", "车辆上险信息", userid, order.ID)
|
||||
response.FailRefund(c)
|
||||
return
|
||||
}
|
||||
orderService.OrderConsumed(order)
|
||||
|
||||
response.OkWithData(gin.H{
|
||||
"record_id": carModel.OrderID,
|
||||
}, c)
|
||||
|
||||
}
|
||||
|
||||
// CAR079 车辆VIN码查车辆信息
|
||||
func (car *Car) VinCheckInfo(c *gin.Context) {
|
||||
var reqBody request.CarVinReq
|
||||
if err := c.ShouldBindJSON(&reqBody); err != nil {
|
||||
response.FailWithMessage("Failed to read request body", c)
|
||||
return
|
||||
}
|
||||
|
||||
userid := utils.GetUserID(c)
|
||||
order, err := orderService.QueryConsumedOrder(userid, "vinchache")
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
// 为空就没有消费资格
|
||||
response.OkNeedPay(c)
|
||||
return
|
||||
} else {
|
||||
log.Printf("QueryConsumedOrder err:%s", err.Error())
|
||||
response.FailWithMessage("服务器错误请稍后再试", c)
|
||||
return
|
||||
}
|
||||
}
|
||||
var carModel model.CarVinCheckInfo
|
||||
reqData := map[string]interface{}{
|
||||
"vin": reqBody.Vin,
|
||||
}
|
||||
plainText, err := carService.CarReqYuShan("CAR079", &reqData)
|
||||
if err != nil {
|
||||
log.Printf("YuShan request at %s error: %s", "CAR079", err.Error())
|
||||
notifyService.SendNotification("羽山接口请求错误,请及时处理", "车辆VIN码查车辆信息", userid, order.ID)
|
||||
response.FailRefund(c)
|
||||
return
|
||||
}
|
||||
|
||||
_, err = carService.CarInsuranceDataAnalysis(string(plainText))
|
||||
if err != nil {
|
||||
if errors.Is(err, utils.ErrNoRecord) {
|
||||
notifyService.SendNotification("用户查询数据为空,请及时处理", "车辆VIN码查车辆信息", userid, order.ID)
|
||||
} else {
|
||||
notifyService.SendNotification("接口系统响应错误,请及时处理", "车辆VIN码查车辆信息", userid, order.ID)
|
||||
}
|
||||
response.FailRefund(c)
|
||||
return
|
||||
}
|
||||
carModel.Resp = string(plainText)
|
||||
carModel.UserID = userid
|
||||
carModel.Vin = reqBody.Vin
|
||||
carModel.OrderID = order.ID
|
||||
|
||||
err = db.DB.Create(&carModel).Error
|
||||
if err != nil {
|
||||
log.Printf("VIN查车辆信息保存错误:%v", err)
|
||||
notifyService.SendNotification("汽车查询数据保存错误,请及时处理", "VIN查车辆信息", userid, order.ID)
|
||||
response.FailRefund(c)
|
||||
return
|
||||
}
|
||||
orderService.OrderConsumed(order)
|
||||
|
||||
response.OkWithData(gin.H{
|
||||
"record_id": carModel.OrderID,
|
||||
}, c)
|
||||
}
|
||||
|
||||
// 车辆维保记录CAR058回调
|
||||
func (car *Car) CarCallback(c *gin.Context) {
|
||||
// 读取请求体
|
||||
encryptedData, err := io.ReadAll(c.Request.Body)
|
||||
if err != nil {
|
||||
log.Printf("CarCallback ReadAll err:%s", err.Error())
|
||||
return
|
||||
}
|
||||
NotifySN := c.Query("notify_sn")
|
||||
apiKey := config.ConfigData.Car.ApiKey
|
||||
respStr, err := utils.Decrypt(string(encryptedData), []byte(apiKey))
|
||||
if err != nil {
|
||||
log.Printf("CarCallback DecodeYushan err:%s", err.Error())
|
||||
}
|
||||
log.Printf("%sCarCallback:%s", NotifySN, respStr)
|
||||
_, err = carService.CarDataAnalysis(respStr)
|
||||
if err != nil {
|
||||
if errors.Is(err, utils.ErrUnmashal) {
|
||||
log.Printf("CarCallback Unmashal err:%s", err.Error())
|
||||
return
|
||||
}
|
||||
}
|
||||
maintenance, GetMaintenanceErr := carService.GetMaintenanceBySn(NotifySN)
|
||||
if GetMaintenanceErr != nil {
|
||||
log.Printf("GetMaintenanceBySn err:%s", GetMaintenanceErr.Error())
|
||||
return
|
||||
}
|
||||
maintenance.Resp = respStr
|
||||
if err != nil {
|
||||
if errors.Is(err, utils.ErrNoRecord) {
|
||||
notifyService.SendNotification("用户查询数据为空,请及时处理", "维保记录CAR059", maintenance.UserID, maintenance.OrderID)
|
||||
} else {
|
||||
notifyService.SendNotification("接口系统响应错误,请及时处理", "维保记录CAR059", maintenance.UserID, maintenance.OrderID)
|
||||
}
|
||||
maintenance.Status = model.StatusFailed
|
||||
} else {
|
||||
maintenance.Status = model.StatusSuccess
|
||||
}
|
||||
err = db.DB.Save(&maintenance).Error
|
||||
if err != nil {
|
||||
log.Printf("callback maintenance save err:%s", err.Error())
|
||||
}
|
||||
response.Ok(c)
|
||||
}
|
||||
|
||||
// 查询维保历史
|
||||
func (car *Car) QueryHistoryList(c *gin.Context) {
|
||||
// 从查询参数中获取分页参数
|
||||
pageSizeStr := c.DefaultQuery("page_size", "10")
|
||||
pageNumStr := c.DefaultQuery("page_num", "1")
|
||||
userId := utils.GetUserID(c)
|
||||
pageSize, err := strconv.Atoi(pageSizeStr)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
|
||||
pageNum, err := strconv.Atoi(pageNumStr)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
|
||||
list, err := carService.GetMaintenanceList(pageSize, pageNum, userId)
|
||||
if err != nil {
|
||||
log.Println("GetMaintenanceList:", err)
|
||||
response.FailWithMessage("系统错误,请稍后再试", c)
|
||||
return
|
||||
}
|
||||
response.OkWithData(list, c)
|
||||
}
|
||||
|
||||
// CAR066 车辆过户次数
|
||||
func (car *Car) VehicleTransfer(c *gin.Context) {
|
||||
var reqBody request.CarVinReq
|
||||
if err := c.ShouldBindJSON(&reqBody); err != nil {
|
||||
response.FailWithMessage("Failed to read request body", c)
|
||||
return
|
||||
}
|
||||
|
||||
userid := utils.GetUserID(c)
|
||||
order, err := orderService.QueryConsumedOrder(userid, "cheliangguohu")
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
// 为空就没有消费资格
|
||||
response.OkNeedPay(c)
|
||||
return
|
||||
} else {
|
||||
log.Printf("QueryConsumedOrder err:%s", err.Error())
|
||||
response.FailWithMessage("服务器错误请稍后再试", c)
|
||||
return
|
||||
}
|
||||
}
|
||||
var carModel model.CarVehicleTransfer
|
||||
reqData := map[string]interface{}{
|
||||
"vin": reqBody.Vin,
|
||||
}
|
||||
plainText, err := carService.CarReqYuShan("CAR066", &reqData)
|
||||
if err != nil {
|
||||
log.Printf("YuShan request at %s error: %s", "CAR066", err.Error())
|
||||
notifyService.SendNotification("羽山接口请求错误,请及时处理", "车辆过户次数", userid, order.ID)
|
||||
response.FailRefund(c)
|
||||
return
|
||||
}
|
||||
|
||||
_, err = carService.CarInsuranceDataAnalysis(string(plainText))
|
||||
if err != nil {
|
||||
if errors.Is(err, utils.ErrNoRecord) {
|
||||
notifyService.SendNotification("用户查询数据为空,请及时处理", "车辆过户次数", userid, order.ID)
|
||||
} else {
|
||||
notifyService.SendNotification("接口系统响应错误,请及时处理", "车辆过户次数", userid, order.ID)
|
||||
}
|
||||
response.FailRefund(c)
|
||||
return
|
||||
}
|
||||
carModel.Resp = string(plainText)
|
||||
carModel.UserID = userid
|
||||
carModel.Vin = reqBody.Vin
|
||||
carModel.OrderID = order.ID
|
||||
|
||||
err = db.DB.Create(&carModel).Error
|
||||
if err != nil {
|
||||
log.Printf("车辆过户次数信息保存错误:%v", err)
|
||||
notifyService.SendNotification("汽车查询数据保存错误,请及时处理", "车辆过户次数", userid, order.ID)
|
||||
response.FailRefund(c)
|
||||
return
|
||||
}
|
||||
orderService.OrderConsumed(order)
|
||||
|
||||
response.OkWithData(gin.H{
|
||||
"record_id": carModel.OrderID,
|
||||
}, c)
|
||||
}
|
||||
|
||||
// CAR100 车辆估值
|
||||
func (car *Car) VehicleValuation(c *gin.Context) {
|
||||
var reqBody request.VehicleValuationReq
|
||||
if err := c.ShouldBindJSON(&reqBody); err != nil {
|
||||
response.FailWithMessage("Failed to read request body", c)
|
||||
return
|
||||
}
|
||||
|
||||
userid := utils.GetUserID(c)
|
||||
order, err := orderService.QueryConsumedOrder(userid, "cheliangguzhi")
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
// 为空就没有消费资格
|
||||
response.OkNeedPay(c)
|
||||
return
|
||||
} else {
|
||||
log.Printf("QueryConsumedOrder err:%s", err.Error())
|
||||
response.FailWithMessage("服务器错误请稍后再试", c)
|
||||
return
|
||||
}
|
||||
}
|
||||
var carModel model.CarVehicleValuation
|
||||
reqData := map[string]interface{}{
|
||||
"vin": reqBody.Vin,
|
||||
"carNumber": reqBody.CarNumber,
|
||||
"cardNo": "",
|
||||
}
|
||||
plainText, err := carService.CarReqYuShan("CAR100", &reqData)
|
||||
if err != nil {
|
||||
log.Printf("YuShan request at %s error: %s", "CAR066", err.Error())
|
||||
notifyService.SendNotification("羽山接口请求错误,请及时处理", "车辆估值", userid, order.ID)
|
||||
response.FailRefund(c)
|
||||
return
|
||||
}
|
||||
|
||||
_, err = carService.CarInsuranceDataAnalysis(string(plainText))
|
||||
if err != nil {
|
||||
if errors.Is(err, utils.ErrNoRecord) {
|
||||
notifyService.SendNotification("用户查询数据为空,请及时处理", "车辆估值", userid, order.ID)
|
||||
} else {
|
||||
notifyService.SendNotification("接口系统响应错误,请及时处理", "车辆估值", userid, order.ID)
|
||||
}
|
||||
response.FailRefund(c)
|
||||
return
|
||||
}
|
||||
carModel.Resp = string(plainText)
|
||||
carModel.UserID = userid
|
||||
carModel.Vin = reqBody.Vin
|
||||
carModel.CarNumber = reqBody.CarNumber
|
||||
carModel.OrderID = order.ID
|
||||
|
||||
err = db.DB.Create(&carModel).Error
|
||||
if err != nil {
|
||||
log.Printf("车辆估值信息保存错误:%v", err)
|
||||
notifyService.SendNotification("汽车查询数据保存错误,请及时处理", "车辆估值", userid, order.ID)
|
||||
response.FailRefund(c)
|
||||
return
|
||||
}
|
||||
orderService.OrderConsumed(order)
|
||||
|
||||
response.OkWithData(gin.H{
|
||||
"record_id": carModel.OrderID,
|
||||
}, c)
|
||||
}
|
||||
225
api/ent.go
Normal file
225
api/ent.go
Normal file
@@ -0,0 +1,225 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"github.com/gin-gonic/gin"
|
||||
"gorm.io/gorm"
|
||||
"log"
|
||||
"net/http"
|
||||
"qnc-server/model/model"
|
||||
"qnc-server/model/request"
|
||||
"qnc-server/model/response"
|
||||
"qnc-server/service"
|
||||
"qnc-server/utils"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Ent struct {
|
||||
}
|
||||
|
||||
var entService service.EntSerivce
|
||||
|
||||
// 注册路由
|
||||
func InitEnt(group *gin.RouterGroup) {
|
||||
var e Ent
|
||||
entPrivateGroup := group.Group("ent")
|
||||
entPrivateGroup.Use(JWTAuth())
|
||||
entPrivateGroup.GET("search", e.search)
|
||||
entPrivateGroup.GET("query_details", e.queryDetails)
|
||||
entPrivateGroup.GET("query_feature/:feature", e.queryFeature)
|
||||
entPrivateGroup.GET("query_list_feature/:feature", e.queryListFeature)
|
||||
|
||||
}
|
||||
func (e *Ent) search(c *gin.Context) {
|
||||
var reqBody request.EntSearchReq
|
||||
if err := c.ShouldBindQuery(&reqBody); err != nil {
|
||||
response.FailWithMessage("Failed to read request body", c)
|
||||
return
|
||||
}
|
||||
resp, err := entService.RequestTycOpen(reqBody, model.Links["search"])
|
||||
time.Sleep(2 * time.Second)
|
||||
if err != nil {
|
||||
response.FailWithMessage("服务器错误请稍后再试", c)
|
||||
return
|
||||
}
|
||||
if resp == nil {
|
||||
response.OkWithEmpty(c)
|
||||
return
|
||||
}
|
||||
|
||||
response.OkWithData(resp, c)
|
||||
}
|
||||
func (e *Ent) queryDetails(c *gin.Context) {
|
||||
|
||||
var reqBody request.EntReq
|
||||
if err := c.ShouldBindQuery(&reqBody); err != nil {
|
||||
response.FailWithMessage("Failed to read request body", c)
|
||||
return
|
||||
}
|
||||
var wg sync.WaitGroup
|
||||
var baseinfoResp, holderResp interface{}
|
||||
var baseinfoErr, holderErr error
|
||||
wg.Add(2)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
baseinfoResp, baseinfoErr = entService.RequestTycOpen(reqBody, model.Links["baseinfo"])
|
||||
}()
|
||||
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
holderResp, holderErr = entService.RequestTycOpen(reqBody, model.Links["holder"])
|
||||
}()
|
||||
wg.Wait()
|
||||
if baseinfoErr != nil || holderErr != nil {
|
||||
return
|
||||
}
|
||||
response.OkWithData(gin.H{
|
||||
"baseinfo": baseinfoResp,
|
||||
"holder": holderResp,
|
||||
}, c)
|
||||
}
|
||||
func (e *Ent) queryListFeature(c *gin.Context) {
|
||||
feature := c.Param("feature")
|
||||
if _, exists := model.Links[feature]; !exists {
|
||||
c.AbortWithStatus(http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
|
||||
userid := utils.GetUserID(c)
|
||||
// 查找是否有 未消费 已付费 的订单
|
||||
order, err := orderService.QueryConsumedOrder(userid, feature)
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
// 为空就没有消费资格
|
||||
response.OkNeedPay(c)
|
||||
return
|
||||
} else {
|
||||
log.Printf("QueryConsumedOrder err:%s", err.Error())
|
||||
response.FailWithMessage("服务器错误请稍后再试", c)
|
||||
return
|
||||
}
|
||||
}
|
||||
entFeatureOrder, err := entService.QueryEntFeatureOrder(order.ID)
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
|
||||
} else {
|
||||
response.FailWithMessage("服务器错误请稍后再试", c)
|
||||
return
|
||||
}
|
||||
}
|
||||
if len(entFeatureOrder) > 1 {
|
||||
response.OkNeedPay(c)
|
||||
return
|
||||
}
|
||||
|
||||
var reqBody request.EntListReq
|
||||
if err := c.ShouldBindQuery(&reqBody); err != nil {
|
||||
response.FailWithMessage("Failed to read request body", c)
|
||||
return
|
||||
}
|
||||
|
||||
resp, err := entService.RequestTycOpen(reqBody, model.Links[feature])
|
||||
if err != nil {
|
||||
log.Printf("天眼查接口错误:%s", err.Error())
|
||||
notifyService.SendNotification("天眼查接口错误,请及时处理", model.Links[feature], userid, order.ID)
|
||||
response.FailRefund(c)
|
||||
return
|
||||
}
|
||||
RespJSON, err := json.Marshal(resp)
|
||||
if err != nil {
|
||||
log.Printf("failed to marshal feature data: ", err)
|
||||
}
|
||||
|
||||
var entFeatureRecord = model.EntFeature{
|
||||
UserID: userid,
|
||||
OrderID: order.ID,
|
||||
FeatureName: feature,
|
||||
Resp: string(RespJSON),
|
||||
}
|
||||
err = entService.SaveEntFeatureRecords(entFeatureRecord)
|
||||
if err != nil {
|
||||
log.Printf("SaveEntFeatureRecords err:%s", err.Error())
|
||||
}
|
||||
if resp != nil || len(entFeatureOrder) > 0 {
|
||||
orderService.OrderConsumed(order)
|
||||
}
|
||||
if resp == nil {
|
||||
response.OkWithEmpty(c)
|
||||
return
|
||||
}
|
||||
response.OkWithData(resp, c)
|
||||
}
|
||||
func (e *Ent) queryFeature(c *gin.Context) {
|
||||
feature := c.Param("feature")
|
||||
if _, exists := model.Links[feature]; !exists {
|
||||
c.AbortWithStatus(http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
userid := utils.GetUserID(c)
|
||||
// 查找是否有 未消费 已付费 的订单
|
||||
order, err := orderService.QueryConsumedOrder(userid, feature)
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
// 为空就没有消费资格
|
||||
response.OkNeedPay(c)
|
||||
return
|
||||
} else {
|
||||
log.Printf("QueryConsumedOrder err:%s", err.Error())
|
||||
response.FailWithMessage("服务器错误请稍后再试", c)
|
||||
return
|
||||
}
|
||||
}
|
||||
entFeatureOrder, err := entService.QueryEntFeatureOrder(order.ID)
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
|
||||
} else {
|
||||
response.FailWithMessage("服务器错误请稍后再试", c)
|
||||
return
|
||||
}
|
||||
}
|
||||
if len(entFeatureOrder) > 1 {
|
||||
response.OkNeedPay(c)
|
||||
return
|
||||
}
|
||||
|
||||
var reqBody request.EntReq
|
||||
if err := c.ShouldBindQuery(&reqBody); err != nil {
|
||||
response.FailWithMessage("Failed to read request body", c)
|
||||
return
|
||||
}
|
||||
|
||||
resp, err := entService.RequestTycOpen(reqBody, model.Links[feature])
|
||||
|
||||
if err != nil {
|
||||
response.FailWithMessage("服务器错误请稍后再试", c)
|
||||
return
|
||||
}
|
||||
RespJSON, err := json.Marshal(resp)
|
||||
if err != nil {
|
||||
log.Printf("failed to marshal feature data: ", err)
|
||||
}
|
||||
|
||||
var entFeatureRecord = model.EntFeature{
|
||||
UserID: userid,
|
||||
OrderID: order.ID,
|
||||
FeatureName: feature,
|
||||
Resp: string(RespJSON),
|
||||
}
|
||||
err = entService.SaveEntFeatureRecords(entFeatureRecord)
|
||||
if err != nil {
|
||||
response.FailWithMessage("服务器错误请稍后再试", c)
|
||||
return
|
||||
}
|
||||
if resp != nil || len(entFeatureOrder) > 0 {
|
||||
orderService.OrderConsumed(order)
|
||||
}
|
||||
if resp == nil {
|
||||
response.OkWithEmpty(c)
|
||||
return
|
||||
}
|
||||
response.OkWithData(resp, c)
|
||||
}
|
||||
160
api/feature.go
Normal file
160
api/feature.go
Normal file
@@ -0,0 +1,160 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/gin-gonic/gin"
|
||||
"log"
|
||||
"net/http"
|
||||
request2 "qnc-server/model/request"
|
||||
"qnc-server/model/response"
|
||||
"qnc-server/service"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type Feature struct {
|
||||
}
|
||||
|
||||
var featureService service.Feature
|
||||
|
||||
// 注册路由
|
||||
func InitFeature(group *gin.RouterGroup) {
|
||||
var f Feature
|
||||
featruePrivate := group.Group("feature")
|
||||
featruePrivate.Use(JWTAuth())
|
||||
featruePrivate.POST("ocr_name", f.OcrName)
|
||||
featruePrivate.POST("verify_elements", f.VerifyElements)
|
||||
|
||||
}
|
||||
func (f *Feature) OcrName(c *gin.Context) {
|
||||
var request request2.FeatureOcrReq
|
||||
|
||||
// 绑定 JSON 请求体到 OcrRequest 结构体
|
||||
if err := c.ShouldBindJSON(&request); err != nil {
|
||||
response.Fail(c)
|
||||
return
|
||||
}
|
||||
|
||||
// 调用 OCRService
|
||||
ocrResult, err := featureService.OCRService(request.Base64)
|
||||
if err != nil {
|
||||
log.Printf("【OCR校验】请求错误:%v", err)
|
||||
response.FailWithMessage("系统错误,请稍后再试", c)
|
||||
return
|
||||
}
|
||||
// 尝试解析为错误响应
|
||||
var ocrError response.OcrErrorResponse
|
||||
json.Unmarshal([]byte(ocrResult), &ocrError)
|
||||
if ocrError.ErrorCode != 0 {
|
||||
// 如果解析成功,且存在 error_code,则返回错误信息
|
||||
response.FailWithMessage("检测签名错误,请重新签名", c)
|
||||
return
|
||||
}
|
||||
|
||||
// 尝试解析为成功响应
|
||||
var ocrSuccess response.OcrSuccessResponse
|
||||
err = json.Unmarshal([]byte(ocrResult), &ocrSuccess)
|
||||
if err != nil {
|
||||
// 如果解析失败,则返回解析错误
|
||||
response.FailWithMessage("系统错误错误,请稍后再试", c)
|
||||
return
|
||||
}
|
||||
|
||||
// 判断 words_result_num 是否等于 1
|
||||
if ocrSuccess.WordsResultNum != 1 {
|
||||
response.FailWithMessage("检测签名错误,请重新签名", c)
|
||||
return
|
||||
}
|
||||
|
||||
// 判断 OCR 结果的第一个 words 是否与 name 匹配
|
||||
if len(ocrSuccess.WordsResult) > 0 && strings.Contains(ocrSuccess.WordsResult[0].Words, request.Name) {
|
||||
response.Ok(c)
|
||||
} else {
|
||||
response.FailWithMessage("签名不匹配,请输入签入正确的姓名", c)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func (f *Feature) VerifyElements(c *gin.Context) {
|
||||
var reqBody request2.FeatureVerifyElementsReq
|
||||
if err := c.ShouldBindJSON(&reqBody); err != nil {
|
||||
response.FailWithMessage("Failed to read request body", c)
|
||||
return
|
||||
}
|
||||
// 二要素核验
|
||||
twoElementsParams := map[string]any{
|
||||
"name": reqBody.Name,
|
||||
"idcard": reqBody.CardNo,
|
||||
}
|
||||
twoElementsRespStr, err := requestService.AliYunRequest(http.MethodPost, "https://kzidcardv1.market.alicloudapi.com/api-mall/api/id_card/check", nil, twoElementsParams)
|
||||
var twoElementsResp response.TwoElementsResp
|
||||
err = json.Unmarshal([]byte(twoElementsRespStr), &twoElementsResp)
|
||||
if err != nil {
|
||||
log.Printf("二要素解析错误:%v", err)
|
||||
response.FailWithMessage("系统错误,请稍后再试", c)
|
||||
return
|
||||
}
|
||||
|
||||
if twoElementsResp.Success == false {
|
||||
response.FailWithMessage("请输入有效的身份证号码", c)
|
||||
return
|
||||
}
|
||||
if twoElementsResp.Code != 200 {
|
||||
response.FailWithMessage(twoElementsResp.Msg, c)
|
||||
return
|
||||
}
|
||||
if twoElementsResp.Data.Result == 1 {
|
||||
response.FailWithMessage("姓名与身份证不一致", c)
|
||||
return
|
||||
}
|
||||
response.Ok(c)
|
||||
// 三要素
|
||||
//westName, err := utils.WestDexEncrypt(reqBody.Name, "121a1e41fc1690dd6b90afbcacd80cf4")
|
||||
//if err != nil {
|
||||
// log.Printf("西部加密错误:%v", err)
|
||||
// response.FailWithMessage("系统错误,请稍后再试", c)
|
||||
// return
|
||||
//}
|
||||
//westIDCard, err := utils.WestDexEncrypt(reqBody.CardNo, "121a1e41fc1690dd6b90afbcacd80cf4")
|
||||
//if err != nil {
|
||||
// log.Printf("西部加密错误:%v", err)
|
||||
// response.FailWithMessage("系统错误,请稍后再试", c)
|
||||
// return
|
||||
//}
|
||||
//westPhone, err := utils.WestDexEncrypt(reqBody.Mobile, "121a1e41fc1690dd6b90afbcacd80cf4")
|
||||
//if err != nil {
|
||||
// log.Printf("西部加密错误:%v", err)
|
||||
// response.FailWithMessage("系统错误,请稍后再试", c)
|
||||
// return
|
||||
//}
|
||||
//threeElementsReq := map[string]interface{}{
|
||||
// "name": westName,
|
||||
// "idNo": westIDCard,
|
||||
// "phone": westPhone,
|
||||
//}
|
||||
//
|
||||
//threeElements, err := requestService.WestDexRequest("G15BJ02", threeElementsReq)
|
||||
//var data response.Wrapper[response.ThreeElementsResponse]
|
||||
//err = json.Unmarshal([]byte(threeElements), &data)
|
||||
//if err != nil {
|
||||
// log.Printf("响应解析失败:%v", err)
|
||||
// response.FailWithMessage("系统错误,请稍后再试", c)
|
||||
// return
|
||||
//}
|
||||
//
|
||||
//switch data.Data.Code {
|
||||
//case "1000":
|
||||
//case "1003":
|
||||
// response.FailWithMessage("姓名、证件号均与手机号实名信息不一致", c)
|
||||
// return
|
||||
//case "1004":
|
||||
// response.FailWithMessage("姓名不正确", c)
|
||||
// return
|
||||
//case "1005":
|
||||
// response.FailWithMessage("证件号码不正确", c)
|
||||
// return
|
||||
//default:
|
||||
// log.Printf("三要素检测错误%v", data.Data.Msg)
|
||||
// response.FailWithMessage("服务器错误请稍后再试", c)
|
||||
// return
|
||||
//}
|
||||
}
|
||||
18
api/init.go
Normal file
18
api/init.go
Normal file
@@ -0,0 +1,18 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func InitApi(group *gin.RouterGroup) {
|
||||
InitUser(group)
|
||||
InitSingleQuery(group)
|
||||
InitLawsuitQuery(group)
|
||||
InitEnt(group)
|
||||
InitPay(group)
|
||||
InitProduct(group)
|
||||
InitRender(group)
|
||||
InitCar(group)
|
||||
InitVerif(group)
|
||||
InitFeature(group)
|
||||
}
|
||||
299
api/lawsuitQuery.go
Normal file
299
api/lawsuitQuery.go
Normal file
@@ -0,0 +1,299 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/redis/go-redis/v9"
|
||||
"gorm.io/gorm"
|
||||
"log"
|
||||
"net/http"
|
||||
"qnc-server/config"
|
||||
"qnc-server/db"
|
||||
"qnc-server/model/model"
|
||||
"qnc-server/model/request"
|
||||
"qnc-server/model/response"
|
||||
"qnc-server/model/types"
|
||||
"qnc-server/service"
|
||||
"qnc-server/utils"
|
||||
)
|
||||
|
||||
type LawsuitQuery struct {
|
||||
}
|
||||
|
||||
// 注册路由
|
||||
func InitLawsuitQuery(group *gin.RouterGroup) {
|
||||
var l LawsuitQuery
|
||||
lawsuitQueryPrivateGroup := group.Group("lawsuitQuery")
|
||||
lawsuitQueryPrivateGroup.Use(JWTAuth())
|
||||
lawsuitQueryPrivateGroup.POST("query_v2", l.queryListV2)
|
||||
lawsuitQueryPrivateGroup.GET("get_record", l.GetRecord)
|
||||
}
|
||||
|
||||
var lawsuitQueryService service.LawsuitQueryService
|
||||
var orderService service.OrderService
|
||||
|
||||
func (l *LawsuitQuery) queryListV2(c *gin.Context) {
|
||||
ctx := c.Request.Context()
|
||||
var reqBody request.LawsuitQueryV2Req
|
||||
if err := c.ShouldBindJSON(&reqBody); err != nil {
|
||||
response.FailWithMessage("Failed to read request body", c)
|
||||
return
|
||||
}
|
||||
if *reqBody.Type == types.Individual {
|
||||
if config.ConfigData.Verify.Three {
|
||||
// 三要素校验
|
||||
westName, err := utils.WestDexEncrypt(reqBody.Name, "121a1e41fc1690dd6b90afbcacd80cf4")
|
||||
if err != nil {
|
||||
log.Printf("西部加密错误:%v", err)
|
||||
response.FailWithMessage("系统错误,请稍后再试", c)
|
||||
return
|
||||
}
|
||||
westIDCard, err := utils.WestDexEncrypt(reqBody.CardNo, "121a1e41fc1690dd6b90afbcacd80cf4")
|
||||
if err != nil {
|
||||
log.Printf("西部加密错误:%v", err)
|
||||
response.FailWithMessage("系统错误,请稍后再试", c)
|
||||
return
|
||||
}
|
||||
westPhone, err := utils.WestDexEncrypt(reqBody.Mobile, "121a1e41fc1690dd6b90afbcacd80cf4")
|
||||
if err != nil {
|
||||
log.Printf("西部加密错误:%v", err)
|
||||
response.FailWithMessage("系统错误,请稍后再试", c)
|
||||
return
|
||||
}
|
||||
threeElementsReq := map[string]interface{}{
|
||||
"name": westName,
|
||||
"idNo": westIDCard,
|
||||
"phone": westPhone,
|
||||
}
|
||||
|
||||
threeElements, err := requestService.WestDexRequest("G15BJ02", threeElementsReq)
|
||||
var data response.Wrapper[response.ThreeElementsResponse]
|
||||
err = json.Unmarshal([]byte(threeElements), &data)
|
||||
if err != nil {
|
||||
log.Printf("响应解析失败:%v", err)
|
||||
response.FailWithMessage("系统错误,请稍后再试", c)
|
||||
return
|
||||
}
|
||||
|
||||
switch data.Data.Code {
|
||||
case 1000:
|
||||
case 1001:
|
||||
response.FailWithMessage("姓名、证件号、手机号信息不一致", c)
|
||||
return
|
||||
case 1003:
|
||||
response.FailWithMessage("姓名、证件号、手机号信息不一致", c)
|
||||
return
|
||||
case 1004:
|
||||
response.FailWithMessage("姓名不正确", c)
|
||||
return
|
||||
case 1005:
|
||||
response.FailWithMessage("证件号码不正确", c)
|
||||
return
|
||||
default:
|
||||
log.Printf("三要素检测错误%v", data.Data.Msg)
|
||||
response.FailWithMessage("服务器错误请稍后再试", c)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
// 二要素核验
|
||||
twoElementsParams := map[string]any{
|
||||
"name": reqBody.Name,
|
||||
"idcard": reqBody.CardNo,
|
||||
}
|
||||
twoElementsRespStr, err := requestService.AliYunRequest(http.MethodPost, "https://kzidcardv1.market.alicloudapi.com/api-mall/api/id_card/check", nil, twoElementsParams)
|
||||
var twoElementsResp response.TwoElementsResp
|
||||
err = json.Unmarshal([]byte(twoElementsRespStr), &twoElementsResp)
|
||||
if err != nil {
|
||||
log.Printf("【二要素】解析错误:%v", err)
|
||||
response.FailWithMessage("系统错误,请稍后再试", c)
|
||||
return
|
||||
}
|
||||
|
||||
if twoElementsResp.Success == false {
|
||||
fmt.Printf("【二要素】身份证无效")
|
||||
response.FailWithMessage("请输入有效的身份证号码", c)
|
||||
return
|
||||
}
|
||||
if twoElementsResp.Code != 200 {
|
||||
response.FailWithMessage(twoElementsResp.Msg, c)
|
||||
return
|
||||
}
|
||||
if twoElementsResp.Data.Result == 1 {
|
||||
fmt.Printf("【二要素】姓名与身份证不一致")
|
||||
response.FailWithMessage("姓名与身份证不一致", c)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
// 校验企业社会统一信用代码
|
||||
isCreditCode := utils.ValidateUnifiedSocialCreditCode(reqBody.CardNo)
|
||||
if isCreditCode == false {
|
||||
response.FailWithMessage("请输入企业社会统一信用代码", c)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// 校验验证码
|
||||
isRight, err := utils.VerifyCode(reqBody.Mobile, reqBody.VerifyCode)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
} else if !isRight {
|
||||
response.FailWithMessage("验证码错误", c)
|
||||
return
|
||||
}
|
||||
|
||||
userid := utils.GetUserID(c)
|
||||
// 查找是否有 未消费 已付费 的订单
|
||||
order, err := orderService.QueryConsumedOrder(userid, "justiceLawsuit")
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
// 为空就没有消费资格
|
||||
response.OkNeedPay(c)
|
||||
return
|
||||
} else {
|
||||
log.Printf("QueryConsumedOrder err:%s", err.Error())
|
||||
response.FailWithMessage("服务器错误请稍后再试", c)
|
||||
return
|
||||
}
|
||||
}
|
||||
var lawsuitReq map[string]interface{}
|
||||
var reqCode string
|
||||
if *reqBody.Type == types.Individual {
|
||||
encodeName, err := utils.WestDexEncrypt(reqBody.Name, "121a1e41fc1690dd6b90afbcacd80cf4")
|
||||
if err != nil {
|
||||
log.Printf("【司法涉诉】加密错误:%v", err)
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
encodeID, err := utils.WestDexEncrypt(reqBody.CardNo, "121a1e41fc1690dd6b90afbcacd80cf4")
|
||||
if err != nil {
|
||||
log.Printf("【司法涉诉】加密错误:%v", err)
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
lawsuitReq = map[string]interface{}{
|
||||
"name": encodeName,
|
||||
"id_card": encodeID,
|
||||
}
|
||||
reqCode = "G22BJ03"
|
||||
} else {
|
||||
encodeID, err := utils.WestDexEncrypt(reqBody.CardNo, "121a1e41fc1690dd6b90afbcacd80cf4")
|
||||
if err != nil {
|
||||
log.Printf("【司法涉诉】加密错误:%v", err)
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
lawsuitReq = map[string]interface{}{
|
||||
"ent_name": encodeID,
|
||||
}
|
||||
reqCode = "Q03BJ03"
|
||||
}
|
||||
|
||||
// 发起请求并处理响应
|
||||
plainText, err := requestService.WestDexRequest(reqCode, lawsuitReq)
|
||||
if err != nil {
|
||||
handleErrorAndRefund(order, userid, "接口系统错误,将自动退款", c)
|
||||
return
|
||||
}
|
||||
|
||||
var resp model.LawsuitResponse
|
||||
err = json.Unmarshal([]byte(plainText), &resp)
|
||||
if err != nil {
|
||||
handleErrorAndRefund(order, userid, "司法诉讼记录解析错误", c)
|
||||
return
|
||||
}
|
||||
|
||||
if resp.Data.ErrCode != "200" {
|
||||
handleErrorAndRefund(order, userid, fmt.Sprintf("司法诉讼响应错误:%s", resp.Data.ErrMsg), c)
|
||||
return
|
||||
}
|
||||
|
||||
// 根据类型判断是个人信息还是公司信息
|
||||
|
||||
var respData json.RawMessage
|
||||
|
||||
if *reqBody.Type == types.Individual {
|
||||
if resp.Data.Data.PersonInfo == nil || resp.Data.Data.PersonInfo.Code == "-1000" {
|
||||
handleErrorAndRefund(order, userid, fmt.Sprintf("司法诉讼查询失败:%s", resp.Data.Data.PersonInfo.Msg), c)
|
||||
return
|
||||
}
|
||||
respData = resp.Data.Data.PersonInfo.Data
|
||||
} else {
|
||||
if resp.Data.Data.CompanyInfo == nil || resp.Data.Data.CompanyInfo.Code == "-1000" {
|
||||
handleErrorAndRefund(order, userid, fmt.Sprintf("司法诉讼查询失败:%s", resp.Data.Data.CompanyInfo.Msg), c)
|
||||
return
|
||||
}
|
||||
respData = resp.Data.Data.CompanyInfo.Data
|
||||
}
|
||||
|
||||
var query model.Query
|
||||
query.OrderID = order.ID
|
||||
query.Code, _ = utils.EncryptCode(reqBody.Mobile, "776d538f1265a814437d2e12ac10b45b85045bc208a1eb129ef301f4157aa82f")
|
||||
query.Userid = userid
|
||||
query.ProductID = order.ProductID
|
||||
db.DB.Create(&query)
|
||||
uniqueID := utils.SetCacheData(ctx, respData)
|
||||
// 更新订单状态并返回成功响应
|
||||
orderService.OrderConsumed(order)
|
||||
response.OkWithData(gin.H{
|
||||
"record_id": uniqueID,
|
||||
}, c)
|
||||
}
|
||||
|
||||
// 错误处理和退款函数
|
||||
func handleErrorAndRefund(order model.PayOrder, userid uint, msg string, c *gin.Context) {
|
||||
log.Printf("【司法诉讼】%s", msg)
|
||||
notifyService.SendNotification(msg, "司法诉讼", userid, order.ID)
|
||||
if order.PaymentMethod == model.PaymentMethod_ALIPAY {
|
||||
err := orderService.AliRefund(ctx, order)
|
||||
if err != nil {
|
||||
notifyService.SendNotification("【支付宝】"+msg+",自动退款失败", "司法诉讼", userid, order.ID)
|
||||
} else {
|
||||
notifyService.SendNotification("【支付宝】自动退款成功", order.Product.ProductName, order.Userid, order.ID)
|
||||
}
|
||||
} else {
|
||||
err := orderService.WeChatRefund(order)
|
||||
if err != nil {
|
||||
notifyService.SendNotification(msg+",自动退款失败", "司法诉讼", userid, order.ID)
|
||||
}
|
||||
}
|
||||
response.FailRefund(c)
|
||||
}
|
||||
func (l *LawsuitQuery) GetRecord(c *gin.Context) {
|
||||
var req request.GetLawsuitRecordReq
|
||||
if err := c.ShouldBindQuery(&req); err != nil {
|
||||
response.FailWithMessage("Failed to read request", c)
|
||||
return
|
||||
}
|
||||
|
||||
//userid := utils.GetUserID(c)
|
||||
//record, err := lawsuitQueryService.QueryLawsuitByOrder(req.ID, userid)
|
||||
//if err != nil {
|
||||
// log.Printf("【司法涉诉】获取司法涉诉记录错误:%v", err)
|
||||
// notifyService.SendNotification("系统错误,获取司法涉诉记录错误,请及时处理", "司法涉诉", userid, record.OrderID)
|
||||
// response.FailRefund(c)
|
||||
// return
|
||||
//}
|
||||
//var resp any
|
||||
//err = json.Unmarshal([]byte(record.Resp), &resp)
|
||||
//if err != nil {
|
||||
// log.Printf("【司法涉诉】获取司法涉诉解析错误:%v", err)
|
||||
// notifyService.SendNotification("系统错误,获取司法涉诉解析错误,请及时处理", "司法涉诉", userid, record.OrderID)
|
||||
// return
|
||||
//}
|
||||
data, err := utils.GetCacheData(ctx, req.ID)
|
||||
if err != nil {
|
||||
if errors.Is(err, redis.Nil) {
|
||||
response.Ok(c)
|
||||
return
|
||||
} else {
|
||||
response.FailWithMessage("系统错误", c)
|
||||
return
|
||||
}
|
||||
}
|
||||
response.OkWithData(data, c)
|
||||
}
|
||||
92
api/middleware.go
Normal file
92
api/middleware.go
Normal file
@@ -0,0 +1,92 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/golang-jwt/jwt/v5"
|
||||
"log"
|
||||
"qnc-server/config"
|
||||
"qnc-server/model/response"
|
||||
"qnc-server/utils"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
func JWTAuth() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
token := utils.GetToken(c)
|
||||
if token == "" {
|
||||
response.NoAuth("未登录", c)
|
||||
c.Abort()
|
||||
return
|
||||
}
|
||||
j := utils.NewJWT()
|
||||
// parseToken 解析token包含的信息
|
||||
claims, err := j.ParseToken(token)
|
||||
if err != nil {
|
||||
if errors.Is(err, utils.TokenExpired) {
|
||||
response.NoAuth("授权已过期", c)
|
||||
utils.ClearToken(c)
|
||||
c.Abort()
|
||||
return
|
||||
}
|
||||
response.NoAuth(err.Error(), c)
|
||||
utils.ClearToken(c)
|
||||
c.Abort()
|
||||
return
|
||||
}
|
||||
|
||||
if claims.Disable {
|
||||
response.Fail(c)
|
||||
c.Abort()
|
||||
return
|
||||
}
|
||||
|
||||
c.Set("claims", claims)
|
||||
if claims.ExpiresAt.Unix()-time.Now().Unix() < claims.BufferTime {
|
||||
dr, _ := utils.ParseDuration(config.ConfigData.JWT.ExpiresTime)
|
||||
claims.ExpiresAt = jwt.NewNumericDate(time.Now().Add(dr))
|
||||
newToken, _ := j.CreateTokenByOldToken(token, *claims)
|
||||
newClaims, _ := j.ParseToken(newToken)
|
||||
c.Header("new-token", newToken)
|
||||
c.Header("new-expires-at", strconv.FormatInt(newClaims.ExpiresAt.Unix(), 10))
|
||||
utils.SetToken(c, newToken, int(dr.Seconds()))
|
||||
}
|
||||
c.Next()
|
||||
|
||||
if newToken, exists := c.Get("new-token"); exists {
|
||||
c.Header("new-token", newToken.(string))
|
||||
}
|
||||
if newExpiresAt, exists := c.Get("new-expires-at"); exists {
|
||||
c.Header("new-expires-at", newExpiresAt.(string))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// NotifyMiddleware 中间件
|
||||
func NotifyMiddleware() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
if config.ConfigData.Notify.Switch {
|
||||
startTime, err := utils.ParseTime(config.ConfigData.Notify.StartTime)
|
||||
if err != nil {
|
||||
log.Printf("【通知中间件】起始时间解析错误:%v", err)
|
||||
c.Next()
|
||||
return
|
||||
}
|
||||
|
||||
endTime, err := utils.ParseTime(config.ConfigData.Notify.EndTime)
|
||||
if err != nil {
|
||||
log.Printf("【通知中间件】结束时间解析错误:%v", err)
|
||||
c.Next()
|
||||
return
|
||||
}
|
||||
|
||||
if utils.IsInTimeRange(startTime, endTime) {
|
||||
response.FailNotify(c)
|
||||
c.Abort()
|
||||
return
|
||||
}
|
||||
}
|
||||
c.Next()
|
||||
}
|
||||
}
|
||||
696
api/pay.go
Normal file
696
api/pay.go
Normal file
@@ -0,0 +1,696 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/redis/go-redis/v9"
|
||||
"github.com/smartwalle/alipay/v3"
|
||||
wxcore "github.com/wechatpay-apiv3/wechatpay-go/core"
|
||||
"github.com/wechatpay-apiv3/wechatpay-go/core/auth/verifiers"
|
||||
"github.com/wechatpay-apiv3/wechatpay-go/core/downloader"
|
||||
"github.com/wechatpay-apiv3/wechatpay-go/core/notify"
|
||||
"github.com/wechatpay-apiv3/wechatpay-go/services/payments"
|
||||
"github.com/wechatpay-apiv3/wechatpay-go/services/refunddomestic"
|
||||
wxutils "github.com/wechatpay-apiv3/wechatpay-go/utils"
|
||||
"gorm.io/gorm"
|
||||
"log"
|
||||
"net/http"
|
||||
"qnc-server/config"
|
||||
"qnc-server/db"
|
||||
"qnc-server/global"
|
||||
"qnc-server/model/model"
|
||||
"qnc-server/model/request"
|
||||
"qnc-server/model/response"
|
||||
"qnc-server/service"
|
||||
"qnc-server/utils"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Pay struct {
|
||||
}
|
||||
|
||||
var ctx = context.Background()
|
||||
var productService service.ProductService
|
||||
|
||||
// 注册路由
|
||||
func InitPay(group *gin.RouterGroup) {
|
||||
var p Pay
|
||||
{
|
||||
payPublicGroup := group.Group("pay")
|
||||
payPublicGroup.POST("callback/:platform", p.Callback) // 微信支付支付回调
|
||||
payPublicGroup.GET("refund_details/:id", p.RefundDetailsHTML) // 内部退款订单详情页面
|
||||
payPublicGroup.POST("refund/:id", p.Refund) // 内部退款按钮
|
||||
payPublicGroup.POST("refund_callback/:platform", p.RefundCallback) // 微信退款回调
|
||||
payPublicGroup.POST("ali_callback", p.AlipayCallback) // 阿里退款回调
|
||||
payPublicGroup.POST("complaint_callback/:platform", p.WxPayComplaintCallback)
|
||||
}
|
||||
{
|
||||
payPrivateGroup := group.Group("pay")
|
||||
payPrivateGroup.Use(JWTAuth())
|
||||
payPrivateGroup.POST("prepay", p.Prepay) // 创建微信支付订单
|
||||
payPrivateGroup.GET("order_list", p.GetOrderList) // 获取订单列表
|
||||
payPrivateGroup.POST("ali_prepay", p.AliPrepay) // 创建支付宝支付订单
|
||||
payPrivateGroup.GET("get_query_cache", p.GetQueryCache) // 获取网页的查询缓存
|
||||
}
|
||||
}
|
||||
func (p *Pay) GetOrderList(c *gin.Context) {
|
||||
// 从查询参数中获取分页参数
|
||||
pageSizeStr := c.DefaultQuery("page_size", "10")
|
||||
pageNumStr := c.DefaultQuery("page_num", "1")
|
||||
userId := utils.GetUserID(c)
|
||||
pageSize, err := strconv.Atoi(pageSizeStr)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
|
||||
pageNum, err := strconv.Atoi(pageNumStr)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
|
||||
list, err := orderService.GetList(pageSize, pageNum, userId)
|
||||
if err != nil {
|
||||
log.Println("get order list error:", err)
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
response.OkWithData(list, c)
|
||||
}
|
||||
func (p *Pay) Prepay(c *gin.Context) {
|
||||
Claims, err := utils.GetClaims(c)
|
||||
if err != nil {
|
||||
log.Println("get claims error:", err)
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
|
||||
var reqBody request.PrepayReq
|
||||
err = c.ShouldBindJSON(&reqBody)
|
||||
if err != nil {
|
||||
response.FailWithMessage("Failed to read request body, need product", c)
|
||||
return
|
||||
}
|
||||
|
||||
var (
|
||||
userid = Claims.Userid
|
||||
openid string
|
||||
appid string
|
||||
mchID string
|
||||
)
|
||||
// 获取用户ip
|
||||
clientIP := c.ClientIP()
|
||||
switch reqBody.Platform {
|
||||
case model.PlatformMPWEIXIN:
|
||||
openid = Claims.AuthIdentifiers.OpenID
|
||||
appid = config.ConfigData.System.WxAppId
|
||||
mchID = config.ConfigData.WxPay.MchID
|
||||
case model.PlatformMPH5:
|
||||
openid = Claims.AuthIdentifiers.OpenID
|
||||
appid = config.ConfigData.System.WxH5AppId
|
||||
mchID = config.ConfigData.WxPay.MchH5ID
|
||||
case model.PlatformH5:
|
||||
appid = config.ConfigData.System.WxH5AppId
|
||||
mchID = config.ConfigData.WxPay.MchH5ID
|
||||
default:
|
||||
response.FailWithMessage("ProductName Must be wx or mp-h5 or h5", c)
|
||||
return
|
||||
}
|
||||
|
||||
product, err := productService.GetProduct(reqBody.ProductName)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
|
||||
// 查看用户是否内部号
|
||||
user, err := userService.GetUserByUserid(Claims.Userid)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
var amount int64
|
||||
if user.Inside {
|
||||
amount = int64(1)
|
||||
} else {
|
||||
amount = int64(product.SellPrice)
|
||||
}
|
||||
|
||||
var outTradeNo = fmt.Sprintf("wx_%s", utils.GenerateOrderNumber())
|
||||
|
||||
var resp interface{}
|
||||
|
||||
if reqBody.Platform == model.PlatformMPWEIXIN {
|
||||
resp, err = orderService.WechatJSAPIPrepay(appid, mchID, product, outTradeNo, amount, openid, model.PlatformMPWEIXIN, global.GlobalData.PayClient)
|
||||
if err != nil {
|
||||
log.Printf("【创建微信支付订单】创建支付失败,系统错误: %v", err)
|
||||
response.FailWithMessage("创建支付失败,系统错误", c)
|
||||
return
|
||||
}
|
||||
} else if reqBody.Platform == model.PlatformMPH5 {
|
||||
resp, err = orderService.WechatJSAPIPrepay(appid, mchID, product, outTradeNo, amount, model.PlatformMPH5, openid, global.GlobalData.PayH5Client)
|
||||
if err != nil {
|
||||
log.Printf("【创建微信支付订单】创建支付失败,系统错误: %v", err)
|
||||
response.FailWithMessage("创建支付失败,系统错误", c)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
resp, err = orderService.WechatH5Prepay(appid, mchID, product, outTradeNo, amount, clientIP, global.GlobalData.PayH5Client)
|
||||
if err != nil {
|
||||
log.Printf("【创建微信支付订单】创建支付失败,系统错误: %v", err)
|
||||
response.FailWithMessage("创建支付失败,系统错误", c)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
var payOrder = model.PayOrder{
|
||||
OutTradeNo: outTradeNo,
|
||||
Amount: amount,
|
||||
Userid: userid,
|
||||
PayStatus: model.PayStatusNotPay,
|
||||
ProductID: product.ID,
|
||||
Product: &product,
|
||||
Platform: reqBody.Platform,
|
||||
PaymentMethod: model.PaymentMethod_WECHAT,
|
||||
}
|
||||
err = db.DB.Create(&payOrder).Error
|
||||
if err != nil {
|
||||
log.Printf("create payOrder error:%v", err)
|
||||
}
|
||||
response.OkWithData(resp, c)
|
||||
}
|
||||
|
||||
func (p *Pay) Callback(c *gin.Context) {
|
||||
|
||||
ctx := c //这个参数是context.Background()
|
||||
cRequest := c.Request //这个值是*http.Request
|
||||
platform := c.Param("platform")
|
||||
var mchID string
|
||||
var mchCertificateSerialNumber string
|
||||
var mchAPIv3Key string
|
||||
var privateKeyPath string
|
||||
switch platform {
|
||||
case model.PlatformMPWEIXIN:
|
||||
mchID = config.ConfigData.WxPay.MchID
|
||||
mchCertificateSerialNumber = config.ConfigData.WxPay.MchCertificateSerialNumber
|
||||
mchAPIv3Key = config.ConfigData.WxPay.MchAPIv3Key
|
||||
privateKeyPath = "merchant/mp/apiclient_key.pem"
|
||||
case model.PlatformH5, model.PlatformMPH5:
|
||||
mchID = config.ConfigData.WxPay.MchH5ID
|
||||
mchCertificateSerialNumber = config.ConfigData.WxPay.MchH5CertificateSerialNumber
|
||||
mchAPIv3Key = config.ConfigData.WxPay.MchH5APIv3Key
|
||||
privateKeyPath = "merchant/mph5/apiclient_key.pem"
|
||||
}
|
||||
|
||||
mchPrivateKey, err := wxutils.LoadPrivateKeyWithPath(privateKeyPath)
|
||||
if err != nil {
|
||||
log.Printf("load merchant private key error")
|
||||
return
|
||||
}
|
||||
// 1. 使用 `RegisterDownloaderWithPrivateKey` 注册下载器
|
||||
err = downloader.MgrInstance().RegisterDownloaderWithPrivateKey(ctx, mchPrivateKey, mchCertificateSerialNumber, mchID, mchAPIv3Key)
|
||||
if err != nil {
|
||||
log.Printf("register downloader with private key error")
|
||||
return
|
||||
}
|
||||
// 2. 获取商户号对应的微信支付平台证书访问器
|
||||
certificateVisitor := downloader.MgrInstance().GetCertificateVisitor(mchID)
|
||||
// 3. 使用证书访问器初始化 `notify.Handler`
|
||||
handler := notify.NewNotifyHandler(mchAPIv3Key, verifiers.NewSHA256WithRSAVerifier(certificateVisitor))
|
||||
transaction := new(payments.Transaction)
|
||||
notifyReq, err := handler.ParseNotifyRequest(context.Background(), cRequest, transaction)
|
||||
// 如果验签未通过,或者解密失败
|
||||
if err != nil {
|
||||
log.Printf("parse notify request error")
|
||||
return
|
||||
}
|
||||
log.Printf("微信支付回调响应: %+v", notifyReq)
|
||||
var status string
|
||||
if notifyReq.Summary == "支付成功" {
|
||||
status = model.PayStatusSuccess
|
||||
} else {
|
||||
status = model.PayStatusPayError
|
||||
}
|
||||
err = db.DB.Model(&model.PayOrder{}).Where("out_trade_no = ?", transaction.OutTradeNo).Updates(model.PayOrder{PayStatus: status, TransactionId: *transaction.TransactionId}).Error
|
||||
if err != nil {
|
||||
log.Printf("订单回调处理错误%v", err)
|
||||
}
|
||||
c.String(http.StatusOK, "success")
|
||||
}
|
||||
func (p *Pay) RefundDetailsHTML(c *gin.Context) {
|
||||
encryptedOrderID := c.Param("id")
|
||||
|
||||
// 解密订单ID
|
||||
decryptedOrderID, err := utils.IDDecrypt(encryptedOrderID, "njbh287yfbuyh18suygbhd98")
|
||||
if err != nil {
|
||||
log.Printf("解密订单ID(%s)失败:%v", decryptedOrderID, err)
|
||||
c.String(http.StatusNotFound, "")
|
||||
return
|
||||
}
|
||||
|
||||
// 将字符串转换为 uint64
|
||||
u64, err := strconv.ParseUint(decryptedOrderID, 10, 64)
|
||||
if err != nil {
|
||||
log.Printf("uint64转换失败: %v", err)
|
||||
c.String(http.StatusNotFound, "")
|
||||
return
|
||||
}
|
||||
|
||||
// 将 uint64 转换为 uint
|
||||
orderID := uint(u64)
|
||||
|
||||
order, err := orderService.GetOrderByid(orderID)
|
||||
if err != nil {
|
||||
log.Printf("订单(%d)获取失败:%v", orderID, err)
|
||||
c.String(http.StatusNotFound, "")
|
||||
return
|
||||
}
|
||||
type RenderOrder struct {
|
||||
ID string
|
||||
OutTradeNo string
|
||||
TransactionId string
|
||||
Userid uint
|
||||
CreatedAt string
|
||||
Product string
|
||||
Amount float64
|
||||
PayStatus string
|
||||
}
|
||||
renderOrder := RenderOrder{
|
||||
ID: encryptedOrderID,
|
||||
OutTradeNo: order.OutTradeNo,
|
||||
TransactionId: order.TransactionId,
|
||||
Userid: order.Userid,
|
||||
CreatedAt: order.CreatedAt.Format("2006-01-02 15:04:05"),
|
||||
Product: order.Product.ProductName,
|
||||
Amount: float64(order.Amount) / 100,
|
||||
PayStatus: order.PayStatus,
|
||||
}
|
||||
|
||||
c.HTML(http.StatusOK, "refund.html", renderOrder)
|
||||
}
|
||||
|
||||
func (p *Pay) Refund(c *gin.Context) {
|
||||
encryptedOrderID := c.Param("id")
|
||||
|
||||
// 解密订单ID
|
||||
decryptedOrderID, err := utils.IDDecrypt(encryptedOrderID, "njbh287yfbuyh18suygbhd98")
|
||||
if err != nil {
|
||||
log.Printf("解密订单ID(%s)失败:%v", decryptedOrderID, err)
|
||||
c.String(http.StatusNotFound, "")
|
||||
return
|
||||
}
|
||||
|
||||
// 将字符串转换为 uint64
|
||||
u64, err := strconv.ParseUint(decryptedOrderID, 10, 64)
|
||||
if err != nil {
|
||||
log.Printf("uint64转换失败: %v", err)
|
||||
c.String(http.StatusNotFound, "")
|
||||
return
|
||||
}
|
||||
|
||||
// 将 uint64 转换为 uint
|
||||
orderID := uint(u64)
|
||||
|
||||
order, err := orderService.GetOrderByid(orderID)
|
||||
if err != nil {
|
||||
log.Printf("订单(%d)获取失败:%v", orderID, err)
|
||||
c.String(http.StatusNotFound, "")
|
||||
return
|
||||
}
|
||||
var payClient *wxcore.Client
|
||||
switch order.Platform {
|
||||
case model.PlatformMPWEIXIN:
|
||||
payClient = global.GlobalData.PayClient
|
||||
case model.PlatformH5, model.PlatformMPH5:
|
||||
payClient = global.GlobalData.PayH5Client
|
||||
}
|
||||
outRefundNo := utils.GenerateOrderRefundNumber()
|
||||
svc := refunddomestic.RefundsApiService{Client: payClient}
|
||||
resp, result, err := svc.Create(ctx,
|
||||
refunddomestic.CreateRequest{
|
||||
OutTradeNo: wxcore.String(order.OutTradeNo),
|
||||
OutRefundNo: wxcore.String(outRefundNo), //退款单号
|
||||
NotifyUrl: wxcore.String(fmt.Sprintf("%s/%s", config.ConfigData.WxPay.RefundNotifyURL, order.Platform)),
|
||||
Amount: &refunddomestic.AmountReq{
|
||||
Currency: wxcore.String("CNY"),
|
||||
Refund: wxcore.Int64(order.Amount),
|
||||
Total: wxcore.Int64(order.Amount),
|
||||
},
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
// 处理错误
|
||||
log.Printf("微信订单申请退款错误:%s", err)
|
||||
response.Fail(c)
|
||||
} else {
|
||||
// 处理返回结果
|
||||
log.Printf("微信订单申请退款 response status=%d resp=%s", result.Response.StatusCode, resp)
|
||||
order.PayStatus = model.PayStatusUnderRefund
|
||||
err = db.DB.Save(order).Error
|
||||
if err != nil {
|
||||
log.Printf("微信订单退款状态修改失败 underRefund Error:%v", err)
|
||||
}
|
||||
response.Ok(c)
|
||||
}
|
||||
}
|
||||
func (p *Pay) RefundCallback(c *gin.Context) {
|
||||
ctx := c //这个参数是context.Background()
|
||||
cRequest := c.Request //这个值是*http.Request
|
||||
platform := c.Param("platform")
|
||||
var mchID string
|
||||
var mchCertificateSerialNumber string
|
||||
var mchAPIv3Key string
|
||||
var privateKeyPath string
|
||||
switch platform {
|
||||
case model.PlatformMPWEIXIN:
|
||||
mchID = config.ConfigData.WxPay.MchID
|
||||
mchCertificateSerialNumber = config.ConfigData.WxPay.MchCertificateSerialNumber
|
||||
mchAPIv3Key = config.ConfigData.WxPay.MchAPIv3Key
|
||||
privateKeyPath = "merchant/mp/apiclient_key.pem"
|
||||
case model.PlatformH5, model.PlatformMPH5:
|
||||
mchID = config.ConfigData.WxPay.MchH5ID
|
||||
mchCertificateSerialNumber = config.ConfigData.WxPay.MchH5CertificateSerialNumber
|
||||
mchAPIv3Key = config.ConfigData.WxPay.MchH5APIv3Key
|
||||
privateKeyPath = "merchant/mph5/apiclient_key.pem"
|
||||
}
|
||||
|
||||
mchPrivateKey, err := wxutils.LoadPrivateKeyWithPath(privateKeyPath)
|
||||
if err != nil {
|
||||
log.Printf("load merchant private key error")
|
||||
return
|
||||
}
|
||||
// 1. 使用 `RegisterDownloaderWithPrivateKey` 注册下载器
|
||||
err = downloader.MgrInstance().RegisterDownloaderWithPrivateKey(ctx, mchPrivateKey, mchCertificateSerialNumber, mchID, mchAPIv3Key)
|
||||
if err != nil {
|
||||
log.Printf("register downloader with private key error")
|
||||
return
|
||||
}
|
||||
// 2. 获取商户号对应的微信支付平台证书访问器
|
||||
certificateVisitor := downloader.MgrInstance().GetCertificateVisitor(mchID)
|
||||
// 3. 使用证书访问器初始化 `notify.Handler`
|
||||
handler := notify.NewNotifyHandler(mchAPIv3Key, verifiers.NewSHA256WithRSAVerifier(certificateVisitor))
|
||||
transaction := new(payments.Transaction)
|
||||
notifyReq, err := handler.ParseNotifyRequest(context.Background(), cRequest, transaction)
|
||||
// 如果验签未通过,或者解密失败
|
||||
if err != nil {
|
||||
log.Printf("parse notify request error")
|
||||
return
|
||||
}
|
||||
log.Printf("微信退款回调响应 notifyReq: %+v", notifyReq)
|
||||
log.Printf("微信退款回调响应 transaction: %+v", transaction)
|
||||
|
||||
order := model.PayOrder{}
|
||||
err = db.DB.Preload("Product").Where("out_trade_no = ?", transaction.OutTradeNo).First(&order).Error
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
log.Printf("【微信退款回调响应】找不到回调相关的订单。OutTradeNo:%s", transaction.OutTradeNo)
|
||||
return
|
||||
} else {
|
||||
log.Printf("退款回调处理错误%v", err)
|
||||
}
|
||||
}
|
||||
if notifyReq.EventType == "REFUND.SUCCESS" {
|
||||
order.PayStatus = model.PayStatusRefund
|
||||
err = db.DB.Save(&order).Error
|
||||
if err != nil {
|
||||
log.Printf("退款回调处理错误%v", err)
|
||||
} else {
|
||||
notifyService.SendNotification("退款成功", order.Product.ProductName, order.Userid, order.ID)
|
||||
}
|
||||
} else if notifyReq.EventType == "REFUND.ABNORMAL" {
|
||||
order.PayStatus = model.PayStatusRefundError
|
||||
err = db.DB.Save(&order).Error
|
||||
if err != nil {
|
||||
log.Printf("退款回调处理错误%v", err)
|
||||
} else {
|
||||
notifyService.SendNotification("退款异常,请及时处理", order.Product.ProductName, order.Userid, order.ID)
|
||||
}
|
||||
}
|
||||
//log.Printf("微信退款回调响应: %+v", transaction)
|
||||
c.String(http.StatusOK, "success")
|
||||
}
|
||||
|
||||
// AliPrepay 阿里支付
|
||||
func (p *Pay) AliPrepay(c *gin.Context) {
|
||||
var reqBody request.H5PrepayReq
|
||||
err := c.ShouldBindJSON(&reqBody)
|
||||
if err != nil {
|
||||
response.FailWithMessage("Failed to read request body, need product", c)
|
||||
return
|
||||
}
|
||||
Claims, err := utils.GetClaims(c)
|
||||
if err != nil {
|
||||
log.Println("get claims error:", err)
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
|
||||
// 获取商品信息
|
||||
product, err := productService.GetProduct(reqBody.ProductName)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
|
||||
// 生成单号
|
||||
outTradeNo := fmt.Sprintf("ali_%s", utils.GenerateOrderNumber())
|
||||
// 查看用户是否内部号
|
||||
user, err := userService.GetUserByUserid(Claims.Userid)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
var amount string
|
||||
var orderAmount int64
|
||||
log.Printf("is inside%+v,is %t", user, user.Inside)
|
||||
if user.Inside {
|
||||
amount = "0.01"
|
||||
orderAmount = 1
|
||||
} else {
|
||||
amount = utils.ConvertCentsToYuan(product.SellPrice)
|
||||
orderAmount = int64(product.SellPrice)
|
||||
}
|
||||
|
||||
pay := alipay.TradeWapPay{}
|
||||
pay.NotifyURL = config.ConfigData.AliPay.NotifyURL // 替换为您的回调地址
|
||||
pay.ReturnURL = fmt.Sprintf("%s%s?callback=true", config.ConfigData.Server.Domain, reqBody.Href) // 支付成功后跳转的地址
|
||||
pay.Subject = product.ProductName // 订单标题
|
||||
pay.OutTradeNo = outTradeNo // 生成的唯一订单号
|
||||
pay.TotalAmount = amount // 支付金额,单位元
|
||||
pay.ProductCode = "QUICK_WAP_PAY" // WAP支付的产品代码
|
||||
|
||||
payURL, err := global.GlobalData.AliPayClient.TradeWapPay(pay)
|
||||
if err != nil {
|
||||
log.Printf("【阿里支付创建】创建订单错误:%v", err)
|
||||
response.Fail(c)
|
||||
return
|
||||
}
|
||||
ctx := context.Background()
|
||||
expiration := 5 * time.Minute // 5分钟超时
|
||||
err = db.RedisClient.Set(ctx, fmt.Sprintf("alipay_%s", outTradeNo), reqBody.QueryData, expiration).Err()
|
||||
if err != nil {
|
||||
log.Printf("【阿里支付创建】前端请求数据缓存错误:%v", err)
|
||||
response.Fail(c)
|
||||
return
|
||||
}
|
||||
var payOrder = model.PayOrder{
|
||||
OutTradeNo: outTradeNo,
|
||||
Amount: orderAmount,
|
||||
Userid: Claims.Userid,
|
||||
PayStatus: model.PayStatusNotPay,
|
||||
ProductID: product.ID,
|
||||
Product: &product,
|
||||
Platform: reqBody.Platform,
|
||||
PaymentMethod: model.PaymentMethod_ALIPAY,
|
||||
}
|
||||
err = db.DB.Create(&payOrder).Error
|
||||
if err != nil {
|
||||
log.Printf("【阿里支付创建】订单保存错误:%v", err)
|
||||
response.Fail(c)
|
||||
return
|
||||
}
|
||||
response.OkWithData(gin.H{
|
||||
"PayUrl": payURL.String(),
|
||||
}, c)
|
||||
}
|
||||
|
||||
// AlipayCallback 阿里支付回调
|
||||
func (p *Pay) AlipayCallback(c *gin.Context) {
|
||||
// 解析表单
|
||||
err := c.Request.ParseForm()
|
||||
if err != nil {
|
||||
log.Printf("ali pay callback解析请求表单失败:%v", err)
|
||||
return
|
||||
}
|
||||
|
||||
// DecodeNotification 内部已调用 VerifySign 方法验证签名
|
||||
noti, err := global.GlobalData.AliPayClient.DecodeNotification(c.Request.Form)
|
||||
if err != nil {
|
||||
log.Printf("【阿里支付回调】通知解码失败失败:%v", err)
|
||||
return
|
||||
}
|
||||
|
||||
log.Printf("【阿里支付回调】接收到支付宝回调,商户订单号:%s", noti.OutTradeNo)
|
||||
log.Printf("【阿里支付回调】接收到支付宝回调,支付宝订单号:%s", noti.OutTradeNo)
|
||||
|
||||
log.Printf("【阿里支付回调】交易状态:%s", noti.TradeStatus)
|
||||
if noti.TradeStatus == alipay.TradeStatusSuccess {
|
||||
log.Printf("【阿里支付回调】交易成功")
|
||||
err = db.DB.Model(&model.PayOrder{}).Where("out_trade_no = ?", noti.OutTradeNo).Updates(model.PayOrder{PayStatus: model.PayStatusSuccess, AliTradeNo: noti.TradeNo}).Error
|
||||
if err != nil {
|
||||
log.Printf("【阿里支付回调】订单回调处理错误%v", err)
|
||||
}
|
||||
// 确认收到通知消息,不然支付宝后续会继续推送相同的消息
|
||||
alipay.ACKNotification(c.Writer)
|
||||
}
|
||||
}
|
||||
func (p *Pay) GetQueryCache(c *gin.Context) {
|
||||
var reqBody request.QueryDataReq
|
||||
err := c.ShouldBindQuery(&reqBody)
|
||||
if err != nil {
|
||||
response.FailWithMessage("Failed to read request body, need out_trade_no", c)
|
||||
return
|
||||
}
|
||||
ctx := context.Background()
|
||||
key := fmt.Sprintf("alipay_%s", reqBody.OutTradeNo)
|
||||
result, err := db.RedisClient.Get(ctx, key).Result()
|
||||
if errors.Is(err, redis.Nil) {
|
||||
response.FailWithMessage("超时,请重新手动输入数据查询", c)
|
||||
return
|
||||
} else if err != nil {
|
||||
log.Printf("【阿里支付】获取缓存表单数据错误%v", err)
|
||||
response.FailWithMessage("请重新手动输入数据", c)
|
||||
return
|
||||
}
|
||||
response.OkWithData(result, c)
|
||||
}
|
||||
|
||||
func (p *Pay) WxPayComplaintCallback(c *gin.Context) {
|
||||
|
||||
ctx := context.Background()
|
||||
cRequest := c.Request
|
||||
|
||||
platform := c.Param("platform")
|
||||
|
||||
var mchID string
|
||||
var mchCertificateSerialNumber string
|
||||
var mchAPIv3Key string
|
||||
var privateKeyPath string
|
||||
var platformString string
|
||||
switch platform {
|
||||
case model.PlatformMPWEIXIN:
|
||||
platformString = "微信小程序"
|
||||
mchID = config.ConfigData.WxPay.MchID
|
||||
mchCertificateSerialNumber = config.ConfigData.WxPay.MchCertificateSerialNumber
|
||||
mchAPIv3Key = config.ConfigData.WxPay.MchAPIv3Key
|
||||
privateKeyPath = "merchant/mp/apiclient_key.pem"
|
||||
case model.PlatformH5, model.PlatformMPH5:
|
||||
platformString = "公众号"
|
||||
mchID = config.ConfigData.WxPay.MchH5ID
|
||||
mchCertificateSerialNumber = config.ConfigData.WxPay.MchH5CertificateSerialNumber
|
||||
mchAPIv3Key = config.ConfigData.WxPay.MchH5APIv3Key
|
||||
privateKeyPath = "merchant/mph5/apiclient_key.pem"
|
||||
}
|
||||
notifyService.SendComplaintNotification(fmt.Sprintf("%s投诉", platformString), "", platformString, "")
|
||||
mchPrivateKey, err := wxutils.LoadPrivateKeyWithPath(privateKeyPath)
|
||||
if err != nil {
|
||||
log.Printf("【%s投诉通知回调】加载商户私钥失败: %v", platformString, err)
|
||||
return
|
||||
}
|
||||
|
||||
// 注册下载器
|
||||
err = downloader.MgrInstance().RegisterDownloaderWithPrivateKey(ctx, mchPrivateKey, mchCertificateSerialNumber, mchID, mchAPIv3Key)
|
||||
if err != nil {
|
||||
log.Printf("【%s投诉通知回调】注册下载器失败: %v", platformString, err)
|
||||
return
|
||||
}
|
||||
|
||||
// 获取微信支付平台证书访问器
|
||||
certificateVisitor := downloader.MgrInstance().GetCertificateVisitor(mchID)
|
||||
|
||||
// 初始化 notify.Handler
|
||||
handler := notify.NewNotifyHandler(mchAPIv3Key, verifiers.NewSHA256WithRSAVerifier(certificateVisitor))
|
||||
|
||||
// 解析并验证通知请求
|
||||
content := make(map[string]interface{})
|
||||
notifyReq, err := handler.ParseNotifyRequest(ctx, cRequest, &content)
|
||||
if err != nil {
|
||||
log.Printf("【%s投诉通知回调】解析通知请求失败: %v", platformString, err)
|
||||
return
|
||||
}
|
||||
|
||||
// 打印通知摘要和解析后的内容
|
||||
log.Printf("【%s投诉通知回调】通知信息: %s", platformString, notifyReq.Summary)
|
||||
log.Printf("【%s投诉通知回调】通知数据: %s", platformString, content)
|
||||
|
||||
// 根据解析后的数据处理通知
|
||||
actionType, ok := content["action_type"].(string)
|
||||
if !ok {
|
||||
log.Printf("【%s投诉通知回调】通知内容中缺少action_type字段", platformString)
|
||||
return
|
||||
}
|
||||
|
||||
complaintID, ok := content["complaint_id"].(string)
|
||||
if !ok {
|
||||
log.Printf("【%s投诉通知回调】通知内容中缺少complaint_id字段", platformString)
|
||||
return
|
||||
}
|
||||
|
||||
switch actionType {
|
||||
case "CREATE_COMPLAINT":
|
||||
message := "用户提交了新的投诉"
|
||||
notifyService.SendComplaintNotification(message, "新投诉", platformString, complaintID)
|
||||
|
||||
case "CONTINUE_COMPLAINT":
|
||||
message := "用户继续投诉"
|
||||
notifyService.SendComplaintNotification(message, "继续投诉", platformString, complaintID)
|
||||
|
||||
case "USER_RESPONSE":
|
||||
message := "用户在投诉单中添加了新留言"
|
||||
notifyService.SendComplaintNotification(message, "用户留言", platformString, complaintID)
|
||||
|
||||
case "RESPONSE_BY_PLATFORM":
|
||||
message := "平台在投诉单中添加了新留言"
|
||||
notifyService.SendComplaintNotification(message, "平台留言", platformString, complaintID)
|
||||
|
||||
case "SELLER_REFUND":
|
||||
message := "商户发起了全额退款"
|
||||
notifyService.SendComplaintNotification(message, "全额退款", platformString, complaintID)
|
||||
|
||||
case "MERCHANT_RESPONSE":
|
||||
message := "商户对投诉进行了回复"
|
||||
notifyService.SendComplaintNotification(message, "商户回复", platformString, complaintID)
|
||||
|
||||
case "MERCHANT_CONFIRM_COMPLETE":
|
||||
message := "商户标记投诉处理完成"
|
||||
notifyService.SendComplaintNotification(message, "投诉处理完成", platformString, complaintID)
|
||||
|
||||
case "MERCHANT_APPROVE_REFUND":
|
||||
message := "商户同意了退款"
|
||||
notifyService.SendComplaintNotification(message, "同意退款", platformString, complaintID)
|
||||
|
||||
case "MERCHANT_REJECT_REFUND":
|
||||
message := "商户拒绝了退款"
|
||||
notifyService.SendComplaintNotification(message, "拒绝退款", platformString, complaintID)
|
||||
|
||||
case "REFUND_SUCCESS":
|
||||
message := "退款已成功到账"
|
||||
notifyService.SendComplaintNotification(message, "退款到账", platformString, complaintID)
|
||||
|
||||
default:
|
||||
message := "未知投诉类型"
|
||||
notifyService.SendComplaintNotification(message, "未知投诉类型", platformString, complaintID)
|
||||
log.Printf("【%s投诉通知回调】收到未知类型的投诉通知: %s", platformString, actionType)
|
||||
}
|
||||
|
||||
// 返回成功响应
|
||||
c.String(http.StatusOK, "success")
|
||||
}
|
||||
54
api/product.go
Normal file
54
api/product.go
Normal file
@@ -0,0 +1,54 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"qnc-server/model/request"
|
||||
"qnc-server/model/response"
|
||||
"qnc-server/service"
|
||||
)
|
||||
|
||||
type Product struct {
|
||||
}
|
||||
|
||||
var product service.ProductService
|
||||
|
||||
// 注册路由
|
||||
func InitProduct(group *gin.RouterGroup) {
|
||||
var p Product
|
||||
productPrivateGroup := group.Group("product")
|
||||
productPublicGroup := group.Group("product")
|
||||
productPrivateGroup.Use(JWTAuth())
|
||||
productPrivateGroup.GET("/product_notes", p.GetProductNotes)
|
||||
productPublicGroup.GET("/product_info", p.GetProductInfo)
|
||||
|
||||
}
|
||||
func (p *Product) GetProductNotes(c *gin.Context) {
|
||||
var req request.GetProductNotesReq
|
||||
if err := c.ShouldBindQuery(&req); err != nil {
|
||||
response.FailWithMessage("Failed to read request query", c)
|
||||
return
|
||||
}
|
||||
product, err := product.GetProduct(req.ProductName)
|
||||
if err != nil {
|
||||
response.FailWithMessage("get product err", c)
|
||||
return
|
||||
}
|
||||
response.OkWithData(product.Notes, c)
|
||||
}
|
||||
func (p *Product) GetProductInfo(c *gin.Context) {
|
||||
var req request.GetProductNotesReq
|
||||
if err := c.ShouldBindQuery(&req); err != nil {
|
||||
response.FailWithMessage("Failed to read request query", c)
|
||||
return
|
||||
}
|
||||
product, err := product.GetProduct(req.ProductName)
|
||||
if err != nil {
|
||||
response.FailWithMessage("get product err", c)
|
||||
return
|
||||
}
|
||||
response.OkWithData(gin.H{
|
||||
"id": product.ProductEn,
|
||||
"name": product.ProductName,
|
||||
"price": product.SellPrice,
|
||||
}, c)
|
||||
}
|
||||
69
api/render.go
Normal file
69
api/render.go
Normal file
@@ -0,0 +1,69 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"qnc-server/config"
|
||||
"qnc-server/model/response"
|
||||
"qnc-server/service"
|
||||
)
|
||||
|
||||
type Render struct {
|
||||
}
|
||||
|
||||
var renderService service.RenderService
|
||||
|
||||
// 注册路由
|
||||
func InitRender(group *gin.RouterGroup) {
|
||||
var r Render
|
||||
RenderPublicGroup := group.Group("render")
|
||||
RenderPublicGroup.GET("get_index", r.GetIndex)
|
||||
RenderPublicGroup.GET("get_car_index", r.GetCarIndex)
|
||||
RenderPublicGroup.GET("get_verify_index", r.GetVerifyIndex)
|
||||
RenderPublicGroup.GET("get_notification", r.GetNotification)
|
||||
RenderPublicGroup.GET("get_shadow", r.GetShade)
|
||||
RenderPublicGroup.GET("setting", r.GetSetting)
|
||||
}
|
||||
func (r *Render) GetSetting(c *gin.Context) {
|
||||
sign := config.ConfigData.Setting.Sign
|
||||
response.OkWithData(gin.H{"sign": sign}, c)
|
||||
}
|
||||
func (r *Render) GetIndex(c *gin.Context) {
|
||||
renderlist, err := renderService.GetIndex()
|
||||
if err != nil {
|
||||
response.FailWithMessage("系统错误,请稍后再试", c)
|
||||
return
|
||||
}
|
||||
response.OkWithData(renderlist, c)
|
||||
}
|
||||
func (r *Render) GetCarIndex(c *gin.Context) {
|
||||
renderlist, err := renderService.GetCarIndex()
|
||||
if err != nil {
|
||||
response.FailWithMessage("系统错误,请稍后再试", c)
|
||||
return
|
||||
}
|
||||
response.OkWithData(renderlist, c)
|
||||
}
|
||||
func (r *Render) GetVerifyIndex(c *gin.Context) {
|
||||
renderlist, err := renderService.GetVerifyIndex()
|
||||
if err != nil {
|
||||
response.FailWithMessage("系统错误,请稍后再试", c)
|
||||
return
|
||||
}
|
||||
response.OkWithData(renderlist, c)
|
||||
}
|
||||
func (r *Render) GetNotification(c *gin.Context) {
|
||||
notification, err := renderService.GetNotificationList()
|
||||
if err != nil {
|
||||
response.FailWithMessage("系统错误,请稍后再试", c)
|
||||
return
|
||||
}
|
||||
response.OkWithData(notification, c)
|
||||
}
|
||||
func (r *Render) GetShade(c *gin.Context) {
|
||||
shadow, err := renderService.GetShadow()
|
||||
if err != nil {
|
||||
response.FailWithMessage("系统错误,请稍后再试", c)
|
||||
return
|
||||
}
|
||||
response.OkWithData(shadow, c)
|
||||
}
|
||||
293
api/singleQuery.go
Normal file
293
api/singleQuery.go
Normal file
@@ -0,0 +1,293 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"github.com/gin-gonic/gin"
|
||||
"net/http"
|
||||
"qnc-server/config"
|
||||
|
||||
"github.com/redis/go-redis/v9"
|
||||
"gorm.io/gorm"
|
||||
"log"
|
||||
"qnc-server/db"
|
||||
"qnc-server/model/model"
|
||||
"qnc-server/model/request"
|
||||
"qnc-server/model/response"
|
||||
"qnc-server/service"
|
||||
"qnc-server/utils"
|
||||
)
|
||||
|
||||
type SingleQuery struct {
|
||||
}
|
||||
|
||||
var singleQueryService service.SingleQueryService
|
||||
var notifyService service.Notify
|
||||
var requestService service.RequestService
|
||||
|
||||
// 注册路由
|
||||
func InitSingleQuery(group *gin.RouterGroup) {
|
||||
var s SingleQuery
|
||||
singQueryPrivate := group.Group("single")
|
||||
singQueryPrivate.Use(JWTAuth())
|
||||
singQueryPrivate.POST("bc_evaluate_marriage", NotifyMiddleware(), s.EvaluateMarriageQuery)
|
||||
singQueryPrivate.GET("get_merriage_record", s.GetMerriageRecord)
|
||||
}
|
||||
|
||||
func (s *SingleQuery) EvaluateMarriageQuery(c *gin.Context) {
|
||||
ctx := c.Request.Context()
|
||||
var reqBody request.EvaluateMarriageReq
|
||||
if err := c.ShouldBindJSON(&reqBody); err != nil {
|
||||
response.FailWithMessage("Failed to read request body", c)
|
||||
return
|
||||
}
|
||||
if config.ConfigData.Setting.Sign {
|
||||
if reqBody.SignImage == "" {
|
||||
response.FailWithMessage("Failed to read request body", c)
|
||||
return
|
||||
}
|
||||
}
|
||||
if len(reqBody.Mobile) != 11 {
|
||||
response.FailWithMessage("请输入正确的手机号码", c)
|
||||
return
|
||||
}
|
||||
|
||||
// 校验验证码
|
||||
isRight, err := utils.VerifyCode(reqBody.Mobile, reqBody.VerifyCode)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
} else if !isRight {
|
||||
response.FailWithMessage("验证码错误", c)
|
||||
return
|
||||
}
|
||||
if config.ConfigData.Verify.Three {
|
||||
// 三要素
|
||||
westName, err := utils.WestDexEncrypt(reqBody.Name, "121a1e41fc1690dd6b90afbcacd80cf4")
|
||||
if err != nil {
|
||||
log.Printf("西部加密错误:%v", err)
|
||||
response.FailWithMessage("系统错误,请稍后再试", c)
|
||||
return
|
||||
}
|
||||
westIDCard, err := utils.WestDexEncrypt(reqBody.CardNo, "121a1e41fc1690dd6b90afbcacd80cf4")
|
||||
if err != nil {
|
||||
log.Printf("西部加密错误:%v", err)
|
||||
response.FailWithMessage("系统错误,请稍后再试", c)
|
||||
return
|
||||
}
|
||||
westPhone, err := utils.WestDexEncrypt(reqBody.Mobile, "121a1e41fc1690dd6b90afbcacd80cf4")
|
||||
if err != nil {
|
||||
log.Printf("西部加密错误:%v", err)
|
||||
response.FailWithMessage("系统错误,请稍后再试", c)
|
||||
return
|
||||
}
|
||||
threeElementsReq := map[string]interface{}{
|
||||
"name": westName,
|
||||
"idNo": westIDCard,
|
||||
"phone": westPhone,
|
||||
}
|
||||
|
||||
threeElements, err := requestService.WestDexRequest("G15BJ02", threeElementsReq)
|
||||
var data response.Wrapper[response.ThreeElementsResponse]
|
||||
err = json.Unmarshal([]byte(threeElements), &data)
|
||||
if err != nil {
|
||||
log.Printf("响应解析失败:%v", err)
|
||||
response.FailWithMessage("系统错误,请稍后再试", c)
|
||||
return
|
||||
}
|
||||
|
||||
switch data.Data.Code {
|
||||
case 1000:
|
||||
case 1001:
|
||||
response.FailWithMessage("姓名、证件号、手机号信息不一致", c)
|
||||
return
|
||||
case 1003:
|
||||
response.FailWithMessage("姓名、证件号、手机号信息不一致", c)
|
||||
return
|
||||
case 1004:
|
||||
response.FailWithMessage("姓名不正确", c)
|
||||
return
|
||||
case 1005:
|
||||
response.FailWithMessage("证件号码不正确", c)
|
||||
return
|
||||
default:
|
||||
log.Printf("三要素检测错误%v", data.Data.Msg)
|
||||
response.FailWithMessage("服务器错误请稍后再试", c)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
// 二要素核验
|
||||
twoElementsParams := map[string]any{
|
||||
"name": reqBody.Name,
|
||||
"idcard": reqBody.CardNo,
|
||||
}
|
||||
twoElementsRespStr, err := requestService.AliYunRequest(http.MethodPost, "https://kzidcardv1.market.alicloudapi.com/api-mall/api/id_card/check", nil, twoElementsParams)
|
||||
var twoElementsResp response.TwoElementsResp
|
||||
err = json.Unmarshal([]byte(twoElementsRespStr), &twoElementsResp)
|
||||
if err != nil {
|
||||
log.Printf("二要素解析错误:%v", err)
|
||||
response.FailWithMessage("系统错误,请稍后再试", c)
|
||||
return
|
||||
}
|
||||
|
||||
if twoElementsResp.Success == false {
|
||||
response.FailWithMessage("请输入有效的身份证号码", c)
|
||||
return
|
||||
}
|
||||
if twoElementsResp.Code != 200 {
|
||||
response.FailWithMessage(twoElementsResp.Msg, c)
|
||||
return
|
||||
}
|
||||
if twoElementsResp.Data.Result == 1 {
|
||||
response.FailWithMessage("姓名与身份证不一致", c)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
userid := utils.GetUserID(c)
|
||||
//查找是否有 未消费并且已付费 的订单
|
||||
order, err := orderService.QueryConsumedOrder(userid, "evaluateMarriage")
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
// 为空就没有消费资格
|
||||
response.OkNeedPay(c)
|
||||
return
|
||||
} else {
|
||||
log.Printf("QueryConsumedOrder err:%s", err.Error())
|
||||
response.FailWithMessage("服务器错误请稍后再试", c)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
encodeName, err := utils.WestDexEncrypt(reqBody.Name, "121a1e41fc1690dd6b90afbcacd80cf4")
|
||||
if err != nil {
|
||||
log.Printf("【婚姻查询】加密错误:%v", err)
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
encodeID, err := utils.WestDexEncrypt(reqBody.CardNo, "121a1e41fc1690dd6b90afbcacd80cf4")
|
||||
if err != nil {
|
||||
log.Printf("【婚姻查询】加密错误:%v", err)
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
evaluateMarriageReq := map[string]interface{}{
|
||||
"name": encodeName,
|
||||
"id": encodeID,
|
||||
}
|
||||
plainText, err := requestService.WestDexRequest("G09GX01", evaluateMarriageReq)
|
||||
if err != nil {
|
||||
notifyService.SendNotification("接口系统错误,将自动退款", "婚姻查询", userid, order.ID)
|
||||
if order.PaymentMethod == model.PaymentMethod_ALIPAY {
|
||||
err := orderService.AliRefund(ctx, order)
|
||||
if err != nil {
|
||||
notifyService.SendNotification("【支付宝】接口系统错误,自动退款失败", "婚姻查询", userid, order.ID)
|
||||
} else {
|
||||
notifyService.SendNotification("【支付宝】自动退款成功", order.Product.ProductName, order.Userid, order.ID)
|
||||
}
|
||||
} else {
|
||||
err := orderService.WeChatRefund(order)
|
||||
if err != nil {
|
||||
notifyService.SendNotification("接口系统响应错误,自动退款失败", "婚姻查询", userid, order.ID)
|
||||
}
|
||||
}
|
||||
response.FailRefund(c)
|
||||
return
|
||||
}
|
||||
result, err := singleQueryService.MarryAnalysis(plainText)
|
||||
if err != nil {
|
||||
if errors.Is(err, utils.ErrNoRecord) {
|
||||
notifyService.SendNotification("用户查询数据为空,将自动退款", "婚姻查询", userid, order.ID)
|
||||
if order.PaymentMethod == model.PaymentMethod_ALIPAY {
|
||||
err := orderService.AliRefund(ctx, order)
|
||||
if err != nil {
|
||||
notifyService.SendNotification("【支付宝】用户查询数据为空,自动退款失败", "婚姻查询", userid, order.ID)
|
||||
} else {
|
||||
notifyService.SendNotification("【支付宝】自动退款成功", order.Product.ProductName, order.Userid, order.ID)
|
||||
}
|
||||
} else {
|
||||
err := orderService.WeChatRefund(order)
|
||||
if err != nil {
|
||||
notifyService.SendNotification("用户查询数据为空,自动退款失败", "婚姻查询", userid, order.ID)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
notifyService.SendNotification("接口系统错误,将自动退款", "婚姻查询", userid, order.ID)
|
||||
if order.PaymentMethod == model.PaymentMethod_ALIPAY {
|
||||
err := orderService.AliRefund(ctx, order)
|
||||
if err != nil {
|
||||
notifyService.SendNotification("【支付宝】接口系统错误,自动退款失败", "婚姻查询", userid, order.ID)
|
||||
} else {
|
||||
notifyService.SendNotification("【支付宝】自动退款成功", order.Product.ProductName, order.Userid, order.ID)
|
||||
}
|
||||
} else {
|
||||
err := orderService.WeChatRefund(order)
|
||||
if err != nil {
|
||||
notifyService.SendNotification("接口系统响应错误,自动退款失败", "婚姻查询", userid, order.ID)
|
||||
}
|
||||
}
|
||||
}
|
||||
log.Printf("【婚姻查询】%s", err.Error())
|
||||
response.FailRefund(c)
|
||||
return
|
||||
}
|
||||
|
||||
var code string
|
||||
if result.Code == 201 {
|
||||
code = "1"
|
||||
} else if result.Code == 202 {
|
||||
code = "2"
|
||||
} else if result.Code == 203 {
|
||||
code = "0"
|
||||
} else {
|
||||
response.FailRefund(c)
|
||||
return
|
||||
}
|
||||
orderService.OrderConsumed(order)
|
||||
var query model.Query
|
||||
query.OrderID = order.ID
|
||||
query.Code, _ = utils.EncryptCode(reqBody.Mobile, "776d538f1265a814437d2e12ac10b45b85045bc208a1eb129ef301f4157aa82f")
|
||||
query.Userid = userid
|
||||
query.ProductID = order.ProductID
|
||||
db.DB.Create(&query)
|
||||
|
||||
fileName, err := featureService.GenerateSignPDF(reqBody.Name, query.ID, reqBody.SignImage)
|
||||
query.SignFile = fileName
|
||||
db.DB.Save(&query)
|
||||
var respData = gin.H{
|
||||
"card_no": utils.EncryptIDCard(reqBody.CardNo),
|
||||
"name": utils.EncryptName(reqBody.Name),
|
||||
"result": []map[string]string{
|
||||
{
|
||||
"maritalStatus": code,
|
||||
},
|
||||
},
|
||||
}
|
||||
uniqueID := utils.SetCacheData(ctx, respData)
|
||||
|
||||
response.OkWithData(gin.H{
|
||||
"record_id": uniqueID,
|
||||
}, c)
|
||||
}
|
||||
|
||||
func (s *SingleQuery) GetMerriageRecord(c *gin.Context) {
|
||||
ctx := c.Request.Context()
|
||||
var req request.GetMerriageRecordReq
|
||||
|
||||
if err := c.ShouldBindQuery(&req); err != nil {
|
||||
response.FailWithMessage("Failed to read request", c)
|
||||
return
|
||||
}
|
||||
|
||||
data, err := utils.GetCacheData(ctx, req.ID)
|
||||
if err != nil {
|
||||
if errors.Is(err, redis.Nil) {
|
||||
response.Ok(c)
|
||||
return
|
||||
} else {
|
||||
response.FailWithMessage("系统错误", c)
|
||||
return
|
||||
}
|
||||
}
|
||||
response.OkWithData(data, c)
|
||||
}
|
||||
367
api/user.go
Normal file
367
api/user.go
Normal file
@@ -0,0 +1,367 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/gin-gonic/gin"
|
||||
"log"
|
||||
"math/rand"
|
||||
"qnc-server/config"
|
||||
common "qnc-server/model/common"
|
||||
model "qnc-server/model/model"
|
||||
"qnc-server/model/request"
|
||||
"qnc-server/model/response"
|
||||
"qnc-server/service"
|
||||
"qnc-server/utils"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
type User struct {
|
||||
}
|
||||
|
||||
var userService service.UserService
|
||||
var verifyService service.VerifyCode
|
||||
|
||||
// 注册路由
|
||||
func InitUser(group *gin.RouterGroup) {
|
||||
var u User
|
||||
userPublicGroup := group.Group("user")
|
||||
userPrivateGroup := group.Group("user")
|
||||
{
|
||||
userPublicGroup.GET("test", u.Test)
|
||||
userPublicGroup.POST("log", u.Log)
|
||||
userPublicGroup.POST("login", u.Login)
|
||||
userPublicGroup.POST("h5_login", u.H5Login)
|
||||
userPublicGroup.POST("phone_login", u.PhoneLogin)
|
||||
userPublicGroup.POST("verify", u.GetVerify)
|
||||
userPublicGroup.GET("get_config", u.GetSDKConfig)
|
||||
}
|
||||
{
|
||||
userPrivateGroup.Use(JWTAuth())
|
||||
}
|
||||
}
|
||||
func (u *User) Test(c *gin.Context) {
|
||||
authIdentifier := model.AuthIdentifier{
|
||||
OpenID: "oR_hJ6kv2bmH7YWPzuZdwQvN4B5g",
|
||||
UnionID: "ogzHA6W4T7vHGl-99nlHkSJDczBc",
|
||||
}
|
||||
authentications, err := userService.MatchingAuthentications(authIdentifier)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
response.OkWithData(authentications, c)
|
||||
}
|
||||
func (u *User) Log(c *gin.Context) {
|
||||
postForm := c.Request.PostForm
|
||||
log.Printf("前端请求打印:%s", postForm)
|
||||
response.Ok(c)
|
||||
}
|
||||
func (u *User) Login(c *gin.Context) {
|
||||
var reqBody request.UserLoginReq
|
||||
|
||||
// 尝试将请求的 JSON body 绑定到 reqBody 结构体
|
||||
if err := c.ShouldBindJSON(&reqBody); err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
|
||||
// 检查请求体中是否包含 code 字段
|
||||
if reqBody.Code == "" {
|
||||
response.FailWithMessage("code is required", c)
|
||||
return
|
||||
}
|
||||
|
||||
// Code获取用户信息
|
||||
wxResponse, err := userService.RequestWx(reqBody.Code)
|
||||
if err != nil {
|
||||
response.FailWithMessage(fmt.Errorf("request weixin err:%w", err).Error(), c)
|
||||
return
|
||||
}
|
||||
authIdentifier := model.AuthIdentifier{
|
||||
OpenID: wxResponse.OpenId,
|
||||
UnionID: wxResponse.Unionid,
|
||||
}
|
||||
// 是否有匹配的校验信息
|
||||
authentications, err := userService.MatchingAuthentications(authIdentifier)
|
||||
|
||||
if err != nil {
|
||||
log.Printf("MatchingAuthentications Error:%v", err)
|
||||
response.FailWithMessage("系统错误,请稍后再试", c)
|
||||
return
|
||||
}
|
||||
var authentication model.Authentication
|
||||
if len(authentications) == 0 {
|
||||
authentication, err = userService.Register(model.User{}, model.AUTHTYPE_WECHAT_MP, authIdentifier)
|
||||
if err != nil {
|
||||
log.Printf("注册用户错误:%v", err)
|
||||
response.FailWithMessage("系统错误,请稍后再试", c)
|
||||
return
|
||||
}
|
||||
//成功创建用户
|
||||
} else {
|
||||
// 校验信息是否有该平台
|
||||
hasWechatMP := false
|
||||
for _, auth := range authentications {
|
||||
if auth.AuthType == model.AUTHTYPE_WECHAT_MP {
|
||||
hasWechatMP = true
|
||||
authentication = auth
|
||||
}
|
||||
}
|
||||
// 没有则创建该平台校验并关联用户
|
||||
if !hasWechatMP {
|
||||
userid := authentication.UserID
|
||||
authentication, err = userService.CreateAuthentications(userid, authIdentifier, model.AUTHTYPE_WECHAT_MP)
|
||||
if err != nil {
|
||||
log.Printf("创建平台校验错误:%v", err)
|
||||
response.FailWithMessage("系统错误,请稍后再试", c)
|
||||
return
|
||||
}
|
||||
//成功校验该平台成功
|
||||
}
|
||||
}
|
||||
user, err := userService.GetUser(authentication.UserID)
|
||||
if err != nil {
|
||||
log.Printf("authentication获取关联用户失败:%v", err)
|
||||
response.FailWithMessage("系统错误,请稍后再试", c)
|
||||
return
|
||||
}
|
||||
u.TokenNext(c, user, authIdentifier, model.AUTHTYPE_WECHAT_MP)
|
||||
}
|
||||
|
||||
// 公众号h5登录
|
||||
func (u *User) H5Login(c *gin.Context) {
|
||||
var reqBody request.H5UserLoginReq
|
||||
|
||||
// 尝试将请求的 JSON body 绑定到 reqBody 结构体
|
||||
if err := c.ShouldBindJSON(&reqBody); err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
if reqBody.UserinfoAuth == nil {
|
||||
response.FailWithDetailed(reqBody, "根本没有Auth", c)
|
||||
return
|
||||
}
|
||||
// 检查请求体中是否包含 code 字段
|
||||
if reqBody.Code == "" {
|
||||
response.FailWithMessage("code is required", c)
|
||||
return
|
||||
}
|
||||
|
||||
// 获取到h5的openid token
|
||||
wxH5Response, err := userService.RequestWxH5(reqBody.Code)
|
||||
if err != nil {
|
||||
log.Printf("request weixin err:%v", err)
|
||||
response.FailWithMessage(fmt.Sprintf("登录失败,请稍后再试:%v", err), c)
|
||||
return
|
||||
}
|
||||
authIdentifier := model.AuthIdentifier{
|
||||
OpenID: wxH5Response.Openid,
|
||||
}
|
||||
// 是否有匹配的校验信息
|
||||
authentications, err := userService.MatchingAuthentications(authIdentifier)
|
||||
if err != nil {
|
||||
log.Printf("GetUserByH5 err:%v", err)
|
||||
response.FailWithMessage(fmt.Sprintf("系统错误登录失败,请稍后再试:%v", err), c)
|
||||
return
|
||||
}
|
||||
var authentication model.Authentication
|
||||
if len(authentications) == 0 {
|
||||
// 是否手动授权登录
|
||||
if *reqBody.UserinfoAuth {
|
||||
userinfo, err := userService.GetSnsUserInfo(wxH5Response.AccessToken, wxH5Response.Openid)
|
||||
if err != nil {
|
||||
log.Printf("request weixin getuserinfo err:%v", err)
|
||||
response.FailWithMessage(fmt.Sprintf("登录失败,请稍后再试:%v", err), c)
|
||||
return
|
||||
}
|
||||
log.Printf("UserInfo:%v", userinfo)
|
||||
authIdentifier.UnionID = userinfo.UnionID
|
||||
log.Printf("authIdentifier:%v", authIdentifier)
|
||||
//查找匹配UnionID
|
||||
authentications, err = userService.MatchingAuthentications(authIdentifier)
|
||||
log.Printf("authentications:%v", authentications)
|
||||
if err != nil {
|
||||
log.Printf("get user err:%v", err)
|
||||
response.FailWithMessage(fmt.Sprintf("登录失败,请稍后再试:%v", err), c)
|
||||
return
|
||||
}
|
||||
if len(authentications) == 0 {
|
||||
//没有则创建用户
|
||||
authentication, err = userService.Register(model.User{}, model.AUTHTYPE_WECHAT_H5, authIdentifier)
|
||||
if err != nil {
|
||||
log.Printf("注册用户错误:%v", err)
|
||||
response.FailWithMessage("系统错误,请稍后再试", c)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
// 有则创建平台校验
|
||||
authentication, err = userService.CreateAuthentications(authentications[0].UserID, authIdentifier, model.AUTHTYPE_WECHAT_H5)
|
||||
if err != nil {
|
||||
log.Printf("创建平台校验错误:%v", err)
|
||||
response.FailWithMessage("系统错误,请稍后再试", c)
|
||||
return
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 静默登录并且库中无openid,让前端重新进行手动授权
|
||||
response.ManualAuth(c)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
for _, auth := range authentications {
|
||||
if auth.AuthType == model.AUTHTYPE_WECHAT_H5 {
|
||||
authentication = auth
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
user, err := userService.GetUser(authentication.UserID)
|
||||
if err != nil {
|
||||
log.Printf("authentication获取关联用户失败:%v", err)
|
||||
response.FailWithMessage("系统错误,请稍后再试", c)
|
||||
return
|
||||
}
|
||||
//有则直接登录
|
||||
u.TokenNext(c, user, authIdentifier, model.AUTHTYPE_WECHAT_H5)
|
||||
}
|
||||
|
||||
// 手机号登录
|
||||
func (u *User) PhoneLogin(c *gin.Context) {
|
||||
var reqBody request.PhoneLoginReq
|
||||
// 尝试将请求的 JSON body 绑定到 reqBody 结构体
|
||||
if err := c.ShouldBindJSON(&reqBody); err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
|
||||
// 校验验证码
|
||||
isRight, err := utils.VerifyCode(reqBody.PhoneNumber, reqBody.VerifyCode)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
} else if !isRight {
|
||||
response.FailWithMessage("验证码错误", c)
|
||||
return
|
||||
}
|
||||
authIdentifier := model.AuthIdentifier{
|
||||
Phone: reqBody.PhoneNumber,
|
||||
}
|
||||
authentications, err := userService.MatchingAuthentications(authIdentifier)
|
||||
|
||||
var authentication model.Authentication
|
||||
if len(authentications) == 0 {
|
||||
authentication, err = userService.Register(model.User{Phone: reqBody.PhoneNumber}, model.AUTHTYPE_PHONE, authIdentifier)
|
||||
if err != nil {
|
||||
log.Printf("注册用户错误:%v", err)
|
||||
response.FailWithMessage("系统错误,请稍后再试", c)
|
||||
return
|
||||
}
|
||||
//成功创建用户
|
||||
} else {
|
||||
authentication = authentications[0]
|
||||
}
|
||||
user, err := userService.GetUser(authentication.UserID)
|
||||
if err != nil {
|
||||
log.Printf("authentication获取关联用户失败:%v", err)
|
||||
response.FailWithMessage("系统错误,请稍后再试", c)
|
||||
return
|
||||
}
|
||||
u.TokenNext(c, user, authIdentifier, model.AUTHTYPE_PHONE)
|
||||
}
|
||||
|
||||
// TokenNext 登录以后签发jwt
|
||||
func (u *User) TokenNext(c *gin.Context, user *model.User, authIdentifiers model.AuthIdentifier, platform model.AuthType) {
|
||||
j := &utils.JWT{SigningKey: []byte(config.ConfigData.JWT.SigningKey)} // 唯一签名
|
||||
claims := j.CreateClaims(common.BaseClaims{
|
||||
Userid: user.Userid,
|
||||
Disable: user.Disable != nil && *user.Disable,
|
||||
AuthIdentifiers: authIdentifiers,
|
||||
Platform: platform,
|
||||
})
|
||||
token, err := j.CreateToken(claims)
|
||||
if err != nil {
|
||||
response.FailWithMessage("获取token失败", c)
|
||||
return
|
||||
}
|
||||
utils.SetToken(c, token, int(claims.RegisteredClaims.ExpiresAt.Unix()-time.Now().Unix()))
|
||||
response.OkWithDetailed(response.LoginResponse{
|
||||
User: *user,
|
||||
//AuthIdentifiers: authIdentifiers,
|
||||
Token: token,
|
||||
ExpiresAt: claims.RegisteredClaims.ExpiresAt.Unix() * 1000,
|
||||
}, "登录成功", c)
|
||||
return
|
||||
}
|
||||
|
||||
// 获取验证码
|
||||
func (u *User) GetVerify(c *gin.Context) {
|
||||
var req request.VerifyCodeReq
|
||||
|
||||
// 绑定JSON数据到结构体
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
response.FailWithMessage("PhoneNumber is required", c)
|
||||
return
|
||||
}
|
||||
|
||||
// 验证手机号码格式
|
||||
if !utils.IsValidPhoneNumber(req.PhoneNumber) {
|
||||
response.FailWithMessage("Invalid phone number format", c)
|
||||
return
|
||||
}
|
||||
existsCode, err := utils.CanRequestCode(req.PhoneNumber)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if existsCode {
|
||||
response.FailWithMessage("请求过于频繁,请稍后再试", c)
|
||||
return
|
||||
}
|
||||
var code = utils.GenerateVerificationCode()
|
||||
|
||||
defaultTemplateCode := config.ConfigData.VerifyCode.TemplateCode
|
||||
if req.Template == "marriage" {
|
||||
defaultTemplateCode = config.ConfigData.VerifyCode.MarriageTemplateCode
|
||||
}
|
||||
|
||||
err = verifyService.Send(code, req.PhoneNumber, defaultTemplateCode)
|
||||
if err != nil {
|
||||
log.Printf("【获取验证码】请求验证码发送失败:%v", err)
|
||||
response.FailWithMessage("系统错误,请稍后再试", c)
|
||||
return
|
||||
}
|
||||
err = utils.StoreVerificationCode(req.PhoneNumber, code)
|
||||
if err != nil {
|
||||
log.Printf("【获取验证码】验证码缓存失败:%v", err)
|
||||
response.FailWithMessage("系统错误,请稍后再试", c)
|
||||
return
|
||||
}
|
||||
response.OkWithMessage("获取成功", c)
|
||||
}
|
||||
|
||||
// h5 sdk config
|
||||
func (u *User) GetSDKConfig(c *gin.Context) {
|
||||
pageURL := c.Query("url")
|
||||
if pageURL == "" {
|
||||
log.Printf("GetSDKConfig url 没传")
|
||||
response.FailWithMessage("系统错误", c)
|
||||
return
|
||||
}
|
||||
ticket, err := userService.GetJsapiTicket()
|
||||
if err != nil || ticket == "" {
|
||||
log.Printf("get jsapi ticket err:%v", err)
|
||||
response.FailWithMessage("获取配置失败", c)
|
||||
return
|
||||
}
|
||||
|
||||
nonceStr := strconv.Itoa(rand.Int())
|
||||
timestamp := strconv.FormatInt(time.Now().Unix(), 10)
|
||||
signature := userService.CreateSignature(ticket, nonceStr, timestamp, pageURL)
|
||||
|
||||
response.OkWithData(gin.H{
|
||||
"ticket": ticket,
|
||||
"appId": config.ConfigData.System.WxH5AppId,
|
||||
"timestamp": timestamp,
|
||||
"nonceStr": nonceStr,
|
||||
"signature": signature,
|
||||
}, c)
|
||||
}
|
||||
359
api/verify.go
Normal file
359
api/verify.go
Normal file
@@ -0,0 +1,359 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/gin-gonic/gin"
|
||||
"gorm.io/gorm"
|
||||
"log"
|
||||
"net/http"
|
||||
"qnc-server/db"
|
||||
"qnc-server/model/model"
|
||||
"qnc-server/model/request"
|
||||
"qnc-server/model/response"
|
||||
"qnc-server/service"
|
||||
"qnc-server/utils"
|
||||
)
|
||||
|
||||
type Verify struct {
|
||||
}
|
||||
|
||||
var verifisService service.VerifyService
|
||||
|
||||
// 注册路由
|
||||
func InitVerif(group *gin.RouterGroup) {
|
||||
var c Verify
|
||||
{
|
||||
verifPrivateGroup := group.Group("verify")
|
||||
verifPrivateGroup.Use(JWTAuth())
|
||||
verifPrivateGroup.POST("phone", c.VerifyNamePhone)
|
||||
verifPrivateGroup.GET("get_query", c.GetQueryRecord)
|
||||
verifPrivateGroup.POST("card_no", c.VerifyNameCard)
|
||||
verifPrivateGroup.POST("bank_card", c.VerifyBankCard)
|
||||
verifPrivateGroup.POST("skill_cert", c.VerifySkillCert)
|
||||
}
|
||||
}
|
||||
|
||||
// 姓名手机二要素核验
|
||||
func (verify *Verify) VerifyNamePhone(c *gin.Context) {
|
||||
var reqBody request.VerifyNamePhoneReq
|
||||
if err := c.ShouldBindJSON(&reqBody); err != nil {
|
||||
response.FailWithMessage("Failed to read request body", c)
|
||||
return
|
||||
}
|
||||
|
||||
userid := utils.GetUserID(c)
|
||||
// 查找是否有 未消费 已付费 的订单
|
||||
order, err := orderService.QueryConsumedOrder(userid, "shoujiheyan")
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
// 为空就没有消费资格
|
||||
response.OkNeedPay(c)
|
||||
return
|
||||
} else {
|
||||
log.Printf("【手机号核验】查询订单错误:%s", err.Error())
|
||||
response.FailWithMessage("服务器错误请稍后再试", c)
|
||||
return
|
||||
}
|
||||
}
|
||||
// 二要素核验
|
||||
body := map[string]any{
|
||||
"mobile": reqBody.Phone,
|
||||
"name": reqBody.Name,
|
||||
}
|
||||
respStr, err := requestService.AliYunRequest(http.MethodPost, "http://yyseys.qianshutong.com/web/interface/yyseysyz", nil, body)
|
||||
if err != nil {
|
||||
log.Printf("【手机号核验】阿里响应错误: %s", err.Error())
|
||||
notifyService.SendNotification("阿里响应错误请及时处理", "手机号核验", userid, order.ID)
|
||||
response.FailRefund(c)
|
||||
return
|
||||
}
|
||||
var verifyPhoneName = model.VerifyPhoneName{}
|
||||
verifyPhoneName.Resp = respStr
|
||||
verifyPhoneName.Code, _ = utils.EncryptCode(reqBody.Phone, "776d538f1265a814437d2e12ac10b45b85045bc208a1eb129ef301f4157aa82f")
|
||||
verifyPhoneName.OrderID = order.ID
|
||||
verifyPhoneName.UserID = userid
|
||||
err = db.DB.Create(&verifyPhoneName).Error
|
||||
if err != nil {
|
||||
log.Printf("【手机号核验】记录失败:%v", err)
|
||||
notifyService.SendNotification("【手机号核验】数据保存错误,请及时处理", "手机号核验", userid, order.ID)
|
||||
response.FailRefund(c)
|
||||
return
|
||||
}
|
||||
orderService.OrderConsumed(order)
|
||||
|
||||
response.OkWithData(gin.H{
|
||||
"record_id": verifyPhoneName.OrderID,
|
||||
}, c)
|
||||
|
||||
}
|
||||
|
||||
// 姓名身份证二要素核验
|
||||
func (verify *Verify) VerifyNameCard(c *gin.Context) {
|
||||
var reqBody request.VerifyNameCardReq
|
||||
if err := c.ShouldBindJSON(&reqBody); err != nil {
|
||||
response.FailWithMessage("Failed to read request body", c)
|
||||
return
|
||||
}
|
||||
|
||||
userid := utils.GetUserID(c)
|
||||
// 查找是否有 未消费 已付费 的订单
|
||||
order, err := orderService.QueryConsumedOrder(userid, "shenfenzhengheyan")
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
// 为空就没有消费资格
|
||||
response.OkNeedPay(c)
|
||||
return
|
||||
} else {
|
||||
log.Printf("【身份证核验】查询订单错误:%s", err.Error())
|
||||
response.FailWithMessage("服务器错误请稍后再试", c)
|
||||
return
|
||||
}
|
||||
}
|
||||
// 二要素核验
|
||||
body := map[string]any{
|
||||
"idcard": reqBody.Card,
|
||||
"name": reqBody.Name,
|
||||
}
|
||||
respStr, err := requestService.AliYunRequest(http.MethodPost, "https://kzidcardv1.market.alicloudapi.com/api-mall/api/id_card/check", nil, body)
|
||||
if err != nil {
|
||||
log.Printf("【身份证核验】阿里响应错误: %s", err.Error())
|
||||
notifyService.SendNotification("阿里响应错误请及时处理", "身份证核验", userid, order.ID)
|
||||
response.FailRefund(c)
|
||||
return
|
||||
}
|
||||
var verifyCardName = model.VerifyCardName{}
|
||||
verifyCardName.Resp = respStr
|
||||
verifyCardName.OrderID = order.ID
|
||||
verifyCardName.UserID = userid
|
||||
|
||||
err = db.DB.Create(&verifyCardName).Error
|
||||
if err != nil {
|
||||
log.Printf("【身份证核验】记录失败:%v", err)
|
||||
notifyService.SendNotification("【身份证核验】数据保存错误,请及时处理", "身份证核验", userid, order.ID)
|
||||
response.FailRefund(c)
|
||||
return
|
||||
}
|
||||
orderService.OrderConsumed(order)
|
||||
response.OkWithData(gin.H{
|
||||
"record_id": verifyCardName.OrderID,
|
||||
}, c)
|
||||
}
|
||||
|
||||
// 银行卡黑名单
|
||||
func (verify *Verify) VerifyBankCard(c *gin.Context) {
|
||||
var reqBody request.VerifyBankCardReq
|
||||
if err := c.ShouldBindJSON(&reqBody); err != nil {
|
||||
response.FailWithMessage("Failed to read request body", c)
|
||||
return
|
||||
}
|
||||
|
||||
userid := utils.GetUserID(c)
|
||||
|
||||
// 查找是否有 未消费 已付费 的订单
|
||||
order, err := orderService.QueryConsumedOrder(userid, "yinhangkaheimingdan")
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
// 为空就没有消费资格
|
||||
response.OkNeedPay(c)
|
||||
return
|
||||
} else {
|
||||
log.Printf("QueryConsumedOrder err:%s", err.Error())
|
||||
response.FailWithMessage("服务器错误请稍后再试", c)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
var verifModel model.VerifyBankCard
|
||||
reqData := map[string]interface{}{
|
||||
"cardNo": reqBody.CardNo,
|
||||
"cardld": reqBody.CardID,
|
||||
"mobile": reqBody.Phone,
|
||||
"name": reqBody.Name,
|
||||
}
|
||||
plainText, err := verifisService.VerifReqYuShan("FIN019", &reqData)
|
||||
if err != nil {
|
||||
log.Printf("【羽山接口请求错误】 %s error: %s", "FIN019", err.Error())
|
||||
notifyService.SendNotification("羽山接口请求错误,请及时处理", "银行卡黑名单查询V1", userid, order.ID)
|
||||
response.FailRefund(c)
|
||||
return
|
||||
}
|
||||
_, err = verifisService.VerifyDataAnalysis(string(plainText))
|
||||
if err != nil {
|
||||
if errors.Is(err, utils.ErrNoRecord) {
|
||||
notifyService.SendNotification("用户查询数据为空,请及时处理", "银行卡黑名单查询V1", userid, order.ID)
|
||||
} else {
|
||||
notifyService.SendNotification("接口系统响应错误,请及时处理", "银行卡黑名单查询V1", userid, order.ID)
|
||||
}
|
||||
response.FailRefund(c)
|
||||
return
|
||||
}
|
||||
verifModel.Resp = string(plainText)
|
||||
verifModel.Code, _ = utils.EncryptCode(reqBody.Phone, "776d538f1265a814437d2e12ac10b45b85045bc208a1eb129ef301f4157aa82f")
|
||||
verifModel.UserID = userid
|
||||
err = db.DB.Create(&verifModel).Error
|
||||
if err != nil {
|
||||
log.Printf("银行卡黑名单查询V1保存错误:%v", err)
|
||||
notifyService.SendNotification("银行卡黑名单查询V1保存错误,请及时处理", "银行卡黑名单查询V1", userid, order.ID)
|
||||
response.FailRefund(c)
|
||||
return
|
||||
}
|
||||
orderService.OrderConsumed(order)
|
||||
response.OkWithData(gin.H{
|
||||
"record_id": verifModel.OrderID,
|
||||
}, c)
|
||||
|
||||
}
|
||||
|
||||
// 技能资格证书查询 HRD004
|
||||
func (verify *Verify) VerifySkillCert(c *gin.Context) {
|
||||
var reqBody request.VerifyNameCardReq
|
||||
if err := c.ShouldBindJSON(&reqBody); err != nil {
|
||||
response.FailWithMessage("Failed to read request body", c)
|
||||
return
|
||||
}
|
||||
// 二要素核验
|
||||
twoElementsParams := map[string]any{
|
||||
"name": reqBody.Name,
|
||||
"idcard": reqBody.Card,
|
||||
}
|
||||
twoElementsRespStr, err := requestService.AliYunRequest(http.MethodPost, "https://kzidcardv1.market.alicloudapi.com/api-mall/api/id_card/check", nil, twoElementsParams)
|
||||
var twoElementsResp response.TwoElementsResp
|
||||
err = json.Unmarshal([]byte(twoElementsRespStr), &twoElementsResp)
|
||||
if err != nil {
|
||||
log.Printf("二要素解析错误:%v", err)
|
||||
response.FailWithMessage("系统错误,请稍后再试", c)
|
||||
return
|
||||
}
|
||||
|
||||
if twoElementsResp.Success == false {
|
||||
response.FailWithMessage("请输入有效的身份证号码", c)
|
||||
return
|
||||
}
|
||||
|
||||
if twoElementsResp.Data.Result == 1 {
|
||||
response.FailWithMessage("姓名与身份证不一致", c)
|
||||
return
|
||||
}
|
||||
userid := utils.GetUserID(c)
|
||||
|
||||
// 查找是否有 未消费 已付费 的订单
|
||||
order, err := orderService.QueryConsumedOrder(userid, "jinengzigezhengshu")
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
// 为空就没有消费资格
|
||||
response.OkNeedPay(c)
|
||||
return
|
||||
} else {
|
||||
log.Printf("QueryConsumedOrder err:%s", err.Error())
|
||||
response.FailWithMessage("服务器错误请稍后再试", c)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
var verifModel model.VerifySkillCert
|
||||
reqData := map[string]interface{}{
|
||||
"cardNo": reqBody.Card,
|
||||
"name": reqBody.Name,
|
||||
}
|
||||
plainText, err := verifisService.VerifReqYuShan("HRD004", &reqData)
|
||||
if err != nil {
|
||||
log.Printf("【羽山接口请求错误】 %s error: %s", "HRD004", err.Error())
|
||||
var isNoRecord = "羽山接口请求错误"
|
||||
if order.PaymentMethod == model.PaymentMethod_ALIPAY {
|
||||
err := orderService.AliRefund(ctx, order)
|
||||
if err != nil {
|
||||
notifyService.SendNotification(fmt.Sprintf("【支付宝】%s,自动退款失败", isNoRecord), "技能资格证书查询", userid, order.ID)
|
||||
} else {
|
||||
notifyService.SendNotification("【支付宝】自动退款成功", order.Product.ProductName, order.Userid, order.ID)
|
||||
}
|
||||
} else {
|
||||
err := orderService.WeChatRefund(order)
|
||||
if err != nil {
|
||||
notifyService.SendNotification(fmt.Sprintf("%s,自动退款失败", isNoRecord), "技能资格证书查询", userid, order.ID)
|
||||
}
|
||||
}
|
||||
response.FailRefund(c)
|
||||
return
|
||||
}
|
||||
_, err = verifisService.VerifyCertDataAnalysis(string(plainText))
|
||||
if err != nil {
|
||||
var isNoRecord string
|
||||
if errors.Is(err, utils.ErrNoRecord) {
|
||||
isNoRecord = "用户查询为空"
|
||||
} else {
|
||||
isNoRecord = "接口系统错误"
|
||||
}
|
||||
if order.PaymentMethod == model.PaymentMethod_ALIPAY {
|
||||
err := orderService.AliRefund(ctx, order)
|
||||
if err != nil {
|
||||
notifyService.SendNotification(fmt.Sprintf("【支付宝】%s,自动退款失败", isNoRecord), "技能资格证书查询", userid, order.ID)
|
||||
} else {
|
||||
notifyService.SendNotification("【支付宝】自动退款成功", order.Product.ProductName, order.Userid, order.ID)
|
||||
}
|
||||
} else {
|
||||
err := orderService.WeChatRefund(order)
|
||||
if err != nil {
|
||||
notifyService.SendNotification(fmt.Sprintf("%s,自动退款失败", isNoRecord), "技能资格证书查询", userid, order.ID)
|
||||
}
|
||||
}
|
||||
response.FailRefund(c)
|
||||
return
|
||||
}
|
||||
verifModel.Resp = string(plainText)
|
||||
verifModel.UserID = userid
|
||||
err = db.DB.Create(&verifModel).Error
|
||||
if err != nil {
|
||||
log.Printf("技能资格证书查询保存错误:%v", err)
|
||||
notifyService.SendNotification("技能资格证书查询保存错误,请及时处理", "技能资格证书查询", userid, order.ID)
|
||||
response.FailRefund(c)
|
||||
return
|
||||
}
|
||||
orderService.OrderConsumed(order)
|
||||
response.OkWithData(gin.H{
|
||||
"record_id": verifModel.OrderID,
|
||||
}, c)
|
||||
}
|
||||
|
||||
func (verify *Verify) GetQueryRecord(c *gin.Context) {
|
||||
var req request.GetQueryRecordReq
|
||||
|
||||
if err := c.ShouldBindQuery(&req); err != nil {
|
||||
response.FailWithMessage("Failed to read request", c)
|
||||
return
|
||||
}
|
||||
|
||||
userid := utils.GetUserID(c)
|
||||
var record interface{}
|
||||
var err error
|
||||
if req.IsCase {
|
||||
record, err = verifisService.GetRecordCaseByFeature(req.Feature)
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
log.Printf("无相关示例记录:%v", err)
|
||||
response.FailWithMessage("无相关示例记录", c)
|
||||
return
|
||||
} else {
|
||||
log.Printf("查询示例记录错误:%v", err)
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
}
|
||||
} else {
|
||||
record, err = verifisService.GetRecordByFeature(req.Feature, req.ID, userid)
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
log.Printf("无相关记录:%v", err)
|
||||
response.FailWithMessage("无相关记录", c)
|
||||
return
|
||||
} else {
|
||||
log.Printf("查询记录错误:%v", err)
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
response.OkWithData(record, c)
|
||||
}
|
||||
Reference in New Issue
Block a user