feat:前台,api关闭的订单接口
This commit is contained in:
parent
9dac2644d4
commit
e77a7622b1
|
@ -73,6 +73,8 @@ const (
|
||||||
OrderAppidNotEqRefundAppid = 1412
|
OrderAppidNotEqRefundAppid = 1412
|
||||||
OrderNotSupportRefundPart = 1413
|
OrderNotSupportRefundPart = 1413
|
||||||
OrderRefundAmountError = 1414
|
OrderRefundAmountError = 1414
|
||||||
|
// 关闭订单
|
||||||
|
CloseOrderPayed = 1420
|
||||||
|
|
||||||
//请求日志
|
//请求日志
|
||||||
RequestLogErrors = 1500
|
RequestLogErrors = 1500
|
||||||
|
@ -165,6 +167,8 @@ var MsgZH = map[int]string{
|
||||||
OrderRefundAmountError: "退款金额错误",
|
OrderRefundAmountError: "退款金额错误",
|
||||||
RefundOutTradeNoSame: "支付商户单号和退款商户单号不能相同",
|
RefundOutTradeNoSame: "支付商户单号和退款商户单号不能相同",
|
||||||
|
|
||||||
|
CloseOrderPayed: "订单已支付成功,无法关闭",
|
||||||
|
|
||||||
ThirdRefundFail: "第三方退款失败",
|
ThirdRefundFail: "第三方退款失败",
|
||||||
}
|
}
|
||||||
var MsgMap map[string]map[int]string = map[string]map[int]string{"en": MsgZH}
|
var MsgMap map[string]map[int]string = map[string]map[int]string{"en": MsgZH}
|
||||||
|
|
|
@ -86,3 +86,16 @@ func QueryOrder(c *gin.Context) {
|
||||||
res.Order = data
|
res.Order = data
|
||||||
controllers.ApiRes(c, res, errorcode.Success)
|
controllers.ApiRes(c, res, errorcode.Success)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 关闭订单
|
||||||
|
func CloseOrder(c *gin.Context) {
|
||||||
|
req := controllers.GetRequest(c).(*front.CloseReqs)
|
||||||
|
c.Set("OutTradeNo", req.OutTradeNo)
|
||||||
|
appCheckInfo := controllers.GetAppCheckInfo(c).(*services.AppCheck)
|
||||||
|
|
||||||
|
code, message := thirdpay.ThirdCloseOrder(c.Request.Context(), *req, appCheckInfo, c.ClientIP())
|
||||||
|
|
||||||
|
var res front.ApiResponse
|
||||||
|
res.Order = message
|
||||||
|
controllers.ApiRes(c, res, code)
|
||||||
|
}
|
||||||
|
|
|
@ -43,8 +43,15 @@ type QueryReqs struct {
|
||||||
OutTradeNo string `json:"out_trade_no" validate:"required" label:"外侧商户订单号"`
|
OutTradeNo string `json:"out_trade_no" validate:"required" label:"外侧商户订单号"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 关闭订单
|
||||||
|
type CloseReqs struct {
|
||||||
|
ApiCommonBody
|
||||||
|
PayChannelId int64 `json:"pay_channel_id" validate:"required" label:"支付渠道"`
|
||||||
|
OutTradeNo string `json:"out_trade_no" validate:"required" label:"外侧商户订单号"`
|
||||||
|
}
|
||||||
|
|
||||||
// api 接口返回数据, 统一返回结构, order数据会进行加密
|
// api 接口返回数据, 统一返回结构, order数据会进行加密
|
||||||
type ApiResponse struct {
|
type ApiResponse struct {
|
||||||
Order interface{} `json:"order"`
|
Order interface{} `json:"order,omitempty"`
|
||||||
Url string `json:"url,omitempty"`
|
Url string `json:"url,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@ var FrontRequestMap = map[string]func() (validForm interface{}, isSaveLog bool){
|
||||||
common.FRONT_V1 + "/pay/url": func() (interface{}, bool) { return new(front.PayReqs), true },
|
common.FRONT_V1 + "/pay/url": func() (interface{}, bool) { return new(front.PayReqs), true },
|
||||||
common.FRONT_V1 + "/pay/refund": func() (interface{}, bool) { return new(front.RefundReqs), true },
|
common.FRONT_V1 + "/pay/refund": func() (interface{}, bool) { return new(front.RefundReqs), true },
|
||||||
common.FRONT_V1 + "/pay/query": func() (interface{}, bool) { return new(front.QueryReqs), false },
|
common.FRONT_V1 + "/pay/query": func() (interface{}, bool) { return new(front.QueryReqs), false },
|
||||||
|
common.FRONT_V1 + "/pay/close": func() (interface{}, bool) { return new(front.CloseReqs), true },
|
||||||
}
|
}
|
||||||
|
|
||||||
var FrontRequestMapBeforeDecrypt = map[string]func() interface{}{
|
var FrontRequestMapBeforeDecrypt = map[string]func() interface{}{
|
||||||
|
@ -16,4 +17,5 @@ var FrontRequestMapBeforeDecrypt = map[string]func() interface{}{
|
||||||
common.FRONT_V1 + "/pay/url": func() interface{} { return new(front.RequestBody) },
|
common.FRONT_V1 + "/pay/url": func() interface{} { return new(front.RequestBody) },
|
||||||
common.FRONT_V1 + "/pay/refund": func() interface{} { return new(front.RequestBody) },
|
common.FRONT_V1 + "/pay/refund": func() interface{} { return new(front.RequestBody) },
|
||||||
common.FRONT_V1 + "/pay/query": func() interface{} { return new(front.RequestBody) },
|
common.FRONT_V1 + "/pay/query": func() interface{} { return new(front.RequestBody) },
|
||||||
|
common.FRONT_V1 + "/pay/close": func() interface{} { return new(front.CloseReqs) },
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,6 +61,7 @@ func RegisterRoute(router *gin.Engine) {
|
||||||
pay.POST("/url", front.PayUrl)
|
pay.POST("/url", front.PayUrl)
|
||||||
pay.POST("/query", front.QueryOrder) //查询订单
|
pay.POST("/query", front.QueryOrder) //查询订单
|
||||||
pay.POST("/refund", front.Refund)
|
pay.POST("/refund", front.Refund)
|
||||||
|
pay.POST("/close", front.CloseOrder)
|
||||||
}
|
}
|
||||||
// 测试微信支付唤起
|
// 测试微信支付唤起
|
||||||
v1.GET("/brokerWechatUrl", front.BrokerWechatUrl)
|
v1.GET("/brokerWechatUrl", front.BrokerWechatUrl)
|
||||||
|
|
|
@ -7,6 +7,7 @@ import (
|
||||||
"PaymentCenter/app/models/paychannelmodel"
|
"PaymentCenter/app/models/paychannelmodel"
|
||||||
"PaymentCenter/app/services"
|
"PaymentCenter/app/services"
|
||||||
"PaymentCenter/app/third/paymentService/payCommon"
|
"PaymentCenter/app/third/paymentService/payCommon"
|
||||||
|
"PaymentCenter/app/utils"
|
||||||
"context"
|
"context"
|
||||||
"xorm.io/builder"
|
"xorm.io/builder"
|
||||||
|
|
||||||
|
@ -165,3 +166,41 @@ func (w *Pay) Refund() {
|
||||||
w.ThirdMsg = res.ErrorMsg
|
w.ThirdMsg = res.ErrorMsg
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 关闭订单
|
||||||
|
func (w *Pay) CloseOrder() {
|
||||||
|
|
||||||
|
var (
|
||||||
|
payFunc func(commonPayInfo *paymentService.PayOrderRequest, channel *paychannelmodel.PayChannel) error
|
||||||
|
ok bool
|
||||||
|
)
|
||||||
|
thirdPay := &paymentService.PayOrderRequest{
|
||||||
|
PayChannelId: w.PayParam.Channel.Id,
|
||||||
|
OrderId: w.Order.Id,
|
||||||
|
ChannelType: w.PayParam.Channel.ChannelType,
|
||||||
|
Description: w.Order.Desc,
|
||||||
|
Amount: w.Order.Amount,
|
||||||
|
PayerClientIp: w.PayParam.ClientIp,
|
||||||
|
ReturnUrl: w.PayParam.ReturnUrl,
|
||||||
|
}
|
||||||
|
if payFunc, ok = PayWayList[w.PayParam.Channel.ChannelType]; !ok {
|
||||||
|
w.PayCode = errorcode.PayChannelNotBuild
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err := payFunc(thirdPay, w.PayParam.Channel)
|
||||||
|
if err != nil {
|
||||||
|
w.PayCode = errorcode.PayChannelExtJsonError
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
closeRequest := paymentService.OrderCloseRequest{
|
||||||
|
OrderId: thirdPay.OrderId,
|
||||||
|
PayChannel: utils.PayType(thirdPay.ChannelType),
|
||||||
|
Wx: thirdPay.Wx,
|
||||||
|
Ali: thirdPay.Ali,
|
||||||
|
}
|
||||||
|
|
||||||
|
res := paymentService.OrderClose(*w.ctx, closeRequest)
|
||||||
|
w.ThirdMsg = res.ErrorMsg
|
||||||
|
w.PayCode = res.Code
|
||||||
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@ import (
|
||||||
"PaymentCenter/app/services/thirdpay/api"
|
"PaymentCenter/app/services/thirdpay/api"
|
||||||
thirdpay "PaymentCenter/app/services/thirdpay/do"
|
thirdpay "PaymentCenter/app/services/thirdpay/do"
|
||||||
"PaymentCenter/app/services/thirdpay/types"
|
"PaymentCenter/app/services/thirdpay/types"
|
||||||
|
"PaymentCenter/app/third/paymentService/payCommon"
|
||||||
"context"
|
"context"
|
||||||
"github.com/jinzhu/copier"
|
"github.com/jinzhu/copier"
|
||||||
)
|
)
|
||||||
|
@ -91,3 +92,54 @@ func ThirdPay(check *thirdpay.PayCheck) (pay *thirdpay.Pay) {
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func thirdPayCloseCheck(ctx context.Context, payReq *front.CloseReqs, appCheck *services.AppCheck, ip string) (check *thirdpay.PayCheck) {
|
||||||
|
var req types.Reqs
|
||||||
|
copier.Copy(&req, payReq)
|
||||||
|
check = thirdpay.NewPayCheck(&ctx, &req, appCheck, ip)
|
||||||
|
// 校验表单
|
||||||
|
check.CheckPayInfo()
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func ThirdCloseOrder(ctx context.Context, closeReq front.CloseReqs, appCheck *services.AppCheck, ip string) (code int, message string) {
|
||||||
|
check := thirdPayCloseCheck(ctx, &closeReq, appCheck, ip)
|
||||||
|
if check.CheckCode != errorcode.Success {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
check.GetOldOrder(&types.OrderFindOne{
|
||||||
|
OutTradeNo: check.Reqs.OutTradeNo,
|
||||||
|
})
|
||||||
|
if check.OldOrder != nil {
|
||||||
|
switch check.OldOrder.Status {
|
||||||
|
// 1待支付,2支付中, 4支付失败
|
||||||
|
case common.ORDER_STATUS_WAITPAY, common.ORDER_STATUS_PAYING, common.ORDER_STATUS_FAILED:
|
||||||
|
// 调用上游关闭订单
|
||||||
|
client := thirdpay.NewPayWithPayCheck(check)
|
||||||
|
client.Order = check.OldOrder
|
||||||
|
client.CloseOrder()
|
||||||
|
code = client.PayCode
|
||||||
|
message = client.ThirdMsg
|
||||||
|
// 修改订单状态为已关闭
|
||||||
|
if client.PayCode == payCommon.PAY_SUCCESS_CODE {
|
||||||
|
check.OldOrder.Status = common.ORDER_STATUS_CLOSE
|
||||||
|
code = services.OrderUpdate(check.OldOrder, "status")
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3支付成功
|
||||||
|
case common.ORDER_STATUS_PAYED:
|
||||||
|
code = errorcode.CloseOrderPayed
|
||||||
|
// 5已关闭
|
||||||
|
case common.ORDER_STATUS_CLOSE:
|
||||||
|
code = errorcode.Success
|
||||||
|
default:
|
||||||
|
code = errorcode.SystemError
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
code = errorcode.OrdersNotFound
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
|
@ -47,8 +47,7 @@ func GetHostIp() string {
|
||||||
}
|
}
|
||||||
func Log(c *gin.Context, name string, msg ...interface{}) {
|
func Log(c *gin.Context, name string, msg ...interface{}) {
|
||||||
_, file, line, _ := runtime.Caller(1)
|
_, file, line, _ := runtime.Caller(1)
|
||||||
timeLayout := "2006-01-01 03:04:05" //转化所需模板
|
var datetime = time.Now().Format("2006-01-02 15:04:05")
|
||||||
var datetime = time.Unix(time.Now().Unix(), 0).Format(timeLayout)
|
|
||||||
fmt.Println(name, msg, file, line, datetime)
|
fmt.Println(name, msg, file, line, datetime)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -462,3 +461,25 @@ func PayType(payChannel int) int {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// redis控制访问频率
|
||||||
|
func KeyExistsOrSet(key string, expire int) bool {
|
||||||
|
redisClient := redis.GetRedis()
|
||||||
|
|
||||||
|
// 假设Exists方法返回的是int64类型,表示键是否存在(0为不存在,1为存在)
|
||||||
|
if exists, err := redisClient.Exists(context.Background(), key).Result(); err == nil && exists == 1 {
|
||||||
|
return true
|
||||||
|
} else if err != nil {
|
||||||
|
// 处理错误情况,可以根据实际情况记录日志或返回错误
|
||||||
|
Log(nil, "redis_Exists异常", err)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果键不存在,则设置键并返回false
|
||||||
|
if err := redisClient.SetEX(context.Background(), key, "", time.Duration(expire)*time.Second).Err(); err != nil {
|
||||||
|
// 处理设置键时的错误情况
|
||||||
|
Log(nil, "redis_SetEX异常", err)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue