221 lines
5.9 KiB
Go
221 lines
5.9 KiB
Go
package thirdpay_notify
|
||
|
||
import (
|
||
"PaymentCenter/app/constants/common"
|
||
"PaymentCenter/app/constants/errorcode"
|
||
"PaymentCenter/app/data"
|
||
"PaymentCenter/app/http/entities"
|
||
"PaymentCenter/app/models/appmodel"
|
||
"PaymentCenter/app/models/ordercallbacklogmodel"
|
||
"PaymentCenter/app/models/ordersmodel"
|
||
"PaymentCenter/app/services"
|
||
"PaymentCenter/app/utils"
|
||
"PaymentCenter/app/utils/httpclient"
|
||
"github.com/bytedance/sonic"
|
||
"time"
|
||
"xorm.io/builder"
|
||
)
|
||
|
||
type OrderNotify struct {
|
||
order *ordersmodel.Orders
|
||
Code int
|
||
app *appmodel.App
|
||
|
||
OrderId int64
|
||
Status int //订单状态
|
||
ActualAmount int // 支付上游返回的订单金额,单位为分。该参数的值为支付时传入的
|
||
PayerTotal int // 用户实际支付金额,单位为分
|
||
Msg string
|
||
CompleteTime time.Time
|
||
}
|
||
|
||
type OrderNotifyResp struct {
|
||
OrderId int64
|
||
Send bool
|
||
ErrCode int
|
||
SendTime time.Time
|
||
Content *OrderNotify
|
||
}
|
||
|
||
type OrderNotifySendContent struct {
|
||
OrderId int64 `json:"order_id"`
|
||
OutTradeNo string `json:"out_trade_no"`
|
||
CompleteTime string `json:"complete_time"`
|
||
OrderType int `json:"order_type"`
|
||
Status int `json:"status"`
|
||
Msg string `json:"msg"`
|
||
ErrCode int `json:"err_code"`
|
||
AppId int64 `json:"app_id"`
|
||
ChannelId int64 `json:"channel_id"`
|
||
//MerchantId int64 `json:"merchant_id"`
|
||
Amount int `json:"amount"`
|
||
PayerTotal int `json:"payer_total"`
|
||
}
|
||
|
||
// actualAmount 订单支付总金额,支付时传入
|
||
// payerTotal 用户实际支付金额,(有优惠券的情况下,payerTotal = actualAmount - 优惠金额)
|
||
func NewOrderNotifyWithHandle(orderId int64, code int, Status int, actualAmount int, payerTotal int, msg string) *OrderNotifyResp {
|
||
orderNotify := &OrderNotify{
|
||
OrderId: orderId,
|
||
Status: Status,
|
||
ActualAmount: actualAmount,
|
||
Msg: msg,
|
||
Code: code,
|
||
PayerTotal: payerTotal,
|
||
}
|
||
return orderNotify.Handle()
|
||
}
|
||
|
||
func (o *OrderNotify) NotifyRespFail(errorCode int) *OrderNotifyResp {
|
||
return &OrderNotifyResp{
|
||
OrderId: o.OrderId,
|
||
Send: false,
|
||
ErrCode: errorCode,
|
||
Content: o,
|
||
}
|
||
}
|
||
|
||
func (o *OrderNotify) Handle() (res *OrderNotifyResp) {
|
||
if o.Code != errorcode.Success {
|
||
return o.NotifyRespFail(o.Code)
|
||
}
|
||
o.checkOrder()
|
||
if o.Code != errorcode.Success {
|
||
return o.NotifyRespFail(o.Code)
|
||
}
|
||
o.checkApp()
|
||
if o.Code != errorcode.Success {
|
||
return o.NotifyRespFail(o.Code)
|
||
}
|
||
o.updateOrder()
|
||
if o.Code != errorcode.Success {
|
||
return o.NotifyRespFail(o.Code)
|
||
}
|
||
o.CompleteTime = time.Now()
|
||
o.sendNotify(o.setBody())
|
||
if o.Code != errorcode.Success {
|
||
return o.NotifyRespFail(o.Code)
|
||
}
|
||
return &OrderNotifyResp{
|
||
OrderId: o.OrderId,
|
||
Send: true,
|
||
ErrCode: o.Code,
|
||
Content: o,
|
||
}
|
||
}
|
||
|
||
// 发送下游回调通知
|
||
func (o *OrderNotify) sendNotify(body *OrderNotifySendContent) {
|
||
if o.app.NotifyUrl == "" {
|
||
o.Code = errorcode.AppNotifyUrlNotFound
|
||
return
|
||
}
|
||
var callbackStatus = common.STATUS_ENABLE
|
||
|
||
bodyByte, _ := sonic.Marshal(&body)
|
||
headers := make(map[string]string, 1)
|
||
headers["Content-Type"] = "application/json"
|
||
resByte, err := httpclient.FastHttpPost(o.app.NotifyUrl, headers, bodyByte, 0)
|
||
type errResp struct {
|
||
Url string `json:"url,omitempty"`
|
||
Response string `json:"response,omitempty"`
|
||
Error string `json:"error,omitempty"`
|
||
}
|
||
var errRespObj = errResp{}
|
||
// 处理错误
|
||
if err != nil || string(resByte) != "success" {
|
||
o.Code = errorcode.NotifySendFail
|
||
callbackStatus = common.STATUS_DISABLED
|
||
if err != nil {
|
||
errRespObj.Error = err.Error()
|
||
}
|
||
errRespObj.Url = o.app.NotifyUrl
|
||
utils.Log(nil, "回调通知失败error", string(resByte), err, errRespObj)
|
||
}
|
||
|
||
if len(resByte) > 255 {
|
||
resByte = resByte[0:255]
|
||
}
|
||
errRespObj.Response = string(resByte)
|
||
b, _ := sonic.Marshal(errRespObj)
|
||
|
||
// 记录回调日志
|
||
go func(orderId int64, status int, request, response string) {
|
||
repo := data.NewOrderCallbackLogRepo(ordercallbacklogmodel.GetInstance().GetDb())
|
||
log := ordercallbacklogmodel.OrderCallbackLog{
|
||
OrderId: orderId,
|
||
MerchantRequest: request,
|
||
Status: status,
|
||
MerchantResponse: response,
|
||
}
|
||
_, insertErr := repo.OrderCallbackLogInsertOne(&log)
|
||
if insertErr != nil {
|
||
utils.Log(nil, "回调写入日志error", insertErr)
|
||
}
|
||
}(o.OrderId, callbackStatus, string(bodyByte), string(b))
|
||
return
|
||
}
|
||
|
||
func (o *OrderNotify) setBody() *OrderNotifySendContent {
|
||
return &OrderNotifySendContent{
|
||
OrderId: o.OrderId,
|
||
OutTradeNo: o.order.OutTradeNo,
|
||
CompleteTime: o.CompleteTime.Format("2006-01-02 15:04:05"),
|
||
Status: o.order.Status,
|
||
OrderType: o.order.OrderType,
|
||
Msg: o.Msg,
|
||
ErrCode: o.Code,
|
||
AppId: o.order.AppId,
|
||
ChannelId: o.order.PayChannelId,
|
||
//MerchantId: o.order.MerchantId,
|
||
Amount: o.order.ActualAmount, // 订单支付总金额,支付时传入
|
||
PayerTotal: o.order.PayerTotal,
|
||
}
|
||
}
|
||
|
||
func (o *OrderNotify) updateOrder() {
|
||
if _, ok := common.OrderStatusMap[o.Status]; !ok {
|
||
|
||
o.Code = errorcode.OrderStatusErr
|
||
return
|
||
}
|
||
// 支付金额和上游支付金额不一致,记录日志
|
||
if o.order.Amount != o.ActualAmount {
|
||
utils.Log(nil, "支付金额和上游支付金额不一致", o.order.Id, o.order.Amount, o.ActualAmount)
|
||
}
|
||
o.order.Status = o.Status
|
||
o.order.ActualAmount = o.ActualAmount
|
||
o.order.PayerTotal = o.PayerTotal
|
||
o.Code = services.OrderUpdate(o.order, "status")
|
||
return
|
||
}
|
||
|
||
func (o *OrderNotify) checkApp() {
|
||
o.app, o.Code = services.AppFindOne(entities.IdRequest{Id: o.order.AppId})
|
||
if o.Code != errorcode.Success {
|
||
return
|
||
}
|
||
|
||
//if o.app.NotifyUrl == "" {
|
||
// o.Code = errorcode.AppNotifyUrlNotFound
|
||
// return
|
||
//}
|
||
|
||
return
|
||
}
|
||
|
||
func (o *OrderNotify) checkOrder() {
|
||
cond := builder.NewCond()
|
||
cond = cond.And(builder.Eq{"id": o.OrderId})
|
||
o.order, o.Code = services.OrderFindOne(&ordersmodel.Orders{}, cond)
|
||
if o.Code != errorcode.OrdersExist {
|
||
return
|
||
}
|
||
|
||
if o.order.Status != common.ORDER_STATUS_PAYING {
|
||
o.Code = errorcode.OrderStatusErr
|
||
return
|
||
}
|
||
return
|
||
}
|