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 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"` } func NewOrderNotifyWithHandle(orderId int64, code int, Status int, actualAmount int, msg string) *OrderNotifyResp { orderNotify := &OrderNotify{ OrderId: orderId, Status: Status, ActualAmount: actualAmount, Msg: msg, Code: code, } 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.Status, AppId: o.order.AppId, ChannelId: o.order.PayChannelId, //MerchantId: o.order.MerchantId, Amount: o.order.Amount, PayerTotal: o.order.PayerTotal, } } func (o *OrderNotify) updateOrder() { if _, ok := common.OrderStatusMap[o.Status]; !ok { o.Code = errorcode.OrderStatusErr return } o.order.Status = o.Status o.order.PayerTotal = o.ActualAmount 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 }