PaymentCenter/app/services/thirdpay/thirdpay_notify/notify.go

221 lines
5.9 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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
}