278 lines
9.3 KiB
Go
278 lines
9.3 KiB
Go
package financial
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"strings"
|
|
"time"
|
|
|
|
"git.rosy.net.cn/baseapi/platformapi/tonglianpayapi"
|
|
"git.rosy.net.cn/baseapi/platformapi/wxpayapi"
|
|
"git.rosy.net.cn/baseapi/utils"
|
|
"git.rosy.net.cn/jx-callback/business/auth2/authprovider/weixin"
|
|
"git.rosy.net.cn/jx-callback/business/jxutils"
|
|
"git.rosy.net.cn/jx-callback/business/jxutils/jxcontext"
|
|
"git.rosy.net.cn/jx-callback/business/model"
|
|
"git.rosy.net.cn/jx-callback/business/model/dao"
|
|
"git.rosy.net.cn/jx-callback/globals"
|
|
"git.rosy.net.cn/jx-callback/globals/api"
|
|
)
|
|
|
|
func (p *PayHandler) CreatePay() (err error) {
|
|
switch p.PayType {
|
|
case model.PayTypeTL:
|
|
param := &tonglianpayapi.CreateUnitorderOrderParam{
|
|
Trxamt: int(p.Order.PayPrice),
|
|
NotifyUrl: globals.TLPayNotifyURL,
|
|
Reqsn: utils.Int64ToStr(p.Order.OrderID),
|
|
PayType: p.VendorPayType,
|
|
}
|
|
if p.VendorPayType == tonglianpayapi.PayTypeWxXcx {
|
|
if authInfo, err := p.Ctx.GetV2AuthInfo(); err == nil && authInfo.GetAuthType() == weixin.AuthTypeWxApp {
|
|
param.Acct = authInfo.GetAuthID()
|
|
}
|
|
}
|
|
result, err := api.TLpayAPI.CreateUnitorderOrder(param)
|
|
if err == nil {
|
|
var result2 tonglianpayapi.PayInfo
|
|
json.Unmarshal([]byte(result.PayInfo), &result2)
|
|
p.Order.PrepayID = result2.Package[strings.LastIndex(result2.Package, "=")+1 : len(result2.Package)]
|
|
p.Order.TransactionID = result.TrxID
|
|
_, err = dao.UpdateEntity(dao.GetDB(), p.Order, "PrepayID", "TransactionID")
|
|
}
|
|
case model.PayTypeWX:
|
|
param := &wxpayapi.CreateOrderParam{
|
|
OutTradeNo: utils.Int64ToStr(p.Order.OrderID),
|
|
Body: fmt.Sprintf("付款给冲天猴儿app:%f 元", jxutils.IntPrice2Standard(int64(p.Order.PayPrice))),
|
|
NotifyURL: globals.WxpayNotifyURL,
|
|
SpbillCreateIP: p.Ctx.GetRealRemoteIP(),
|
|
TradeType: p.VendorPayType,
|
|
TotalFee: p.Order.PayPrice,
|
|
TimeStart: wxpayapi.Time2PayTime(time.Now()),
|
|
ProfitSharing: wxpayapi.OptYes,
|
|
}
|
|
if authInfo, err := p.Ctx.GetV2AuthInfo(); err == nil && authInfo.GetAuthType() == weixin.AuthTypeWxApp {
|
|
param.OpenID = authInfo.GetAuthID()
|
|
}
|
|
result, err := api.WxpayAPI.CreateUnifiedOrder(param)
|
|
if err == nil {
|
|
p.Order.PrepayID = result.PrepayID
|
|
p.Order.Comment = result.CodeURL
|
|
_, err = dao.UpdateEntity(dao.GetDB(), p.Order, "PrepayID", "Comment")
|
|
}
|
|
default:
|
|
err = fmt.Errorf("支付方式:%d当前不支持", p.PayType)
|
|
}
|
|
return err
|
|
}
|
|
|
|
func (p *PayHandler) CreateRefund() (err error) {
|
|
switch p.PayType {
|
|
case model.PayTypeTL:
|
|
case model.PayTypeWX:
|
|
//企业付款(提现)
|
|
if p.VendorPayType == model.VendorPayTypeCompanyPay {
|
|
param := &wxpayapi.TransfersParam{
|
|
PartnerTradeNo: utils.Int64ToStr(p.Order.OrderID),
|
|
CheckName: wxpayapi.CheckName,
|
|
Amount: p.Order.PayPrice,
|
|
Desc: "冲天猴儿app提现到账",
|
|
SpbillCreateIP: p.Ctx.GetRealRemoteIP(),
|
|
}
|
|
if authInfo, err := p.Ctx.GetV2AuthInfo(); err == nil && authInfo.GetAuthType() == weixin.AuthTypeWxApp {
|
|
param.OpenID = authInfo.GetAuthID()
|
|
}
|
|
result, err := api.WxpayAPI.Transfers(param)
|
|
if err == nil {
|
|
p.Order.PayFinishedAt = utils.Str2Time(result.PaymentTime)
|
|
p.Order.Comment = result.DeviceInfo
|
|
p.Order.OriginalData = utils.Format4Output(result, true)
|
|
if result.ReturnMsg == "" {
|
|
p.Order.Status = model.OrderStatusFinished
|
|
} else {
|
|
p.Order.Status = model.OrderStatusCanceled
|
|
}
|
|
dao.UpdateEntity(dao.GetDB(), p.Order)
|
|
if result.ReturnMsg == "" {
|
|
err = OnPayFinished(p.Order)
|
|
}
|
|
}
|
|
} else {
|
|
|
|
}
|
|
}
|
|
return err
|
|
}
|
|
|
|
func OnTLPayCallback(call *tonglianpayapi.CallBackResult) (err error) {
|
|
globals.SugarLogger.Debugf("OnTLPayCallback msg:%s", utils.Format4Output(call, true))
|
|
switch call.TrxCode {
|
|
case tonglianpayapi.MsgTypePay:
|
|
err = onTLpayFinished(call)
|
|
case tonglianpayapi.MsgTypeRefund:
|
|
err = onTLpayRefund(call)
|
|
}
|
|
return err
|
|
}
|
|
|
|
func onTLpayFinished(call *tonglianpayapi.CallBackResult) (err error) {
|
|
order := &model.Order{
|
|
OrderID: utils.Str2Int64(call.CusorderID),
|
|
}
|
|
db := dao.GetDB()
|
|
if err = dao.GetEntity(db, order, "OrderID"); err == nil {
|
|
if order.Status != model.OrderStatusWait4Pay {
|
|
globals.SugarLogger.Debugf("already pay msg:%s, err:%v", utils.Format4Output(call, true), err)
|
|
return err
|
|
}
|
|
loc, _ := time.LoadLocation("Local")
|
|
t1, _ := time.ParseInLocation("20060102150405", call.PayTime, loc)
|
|
order.PayFinishedAt = t1
|
|
// order.TransactionID = call.ChnlTrxID
|
|
order.OriginalData = utils.Format4Output(call, true)
|
|
if call.TrxStatus == tonglianpayapi.TrxStatusSuccess {
|
|
order.Status = model.OrderStatusFinished
|
|
} else {
|
|
order.Status = model.OrderStatusCanceled
|
|
}
|
|
dao.UpdateEntity(db, order)
|
|
if call.TrxStatus == tonglianpayapi.TrxStatusSuccess {
|
|
err = OnPayFinished(order)
|
|
}
|
|
} else {
|
|
globals.SugarLogger.Debugf("onTLpayFinished msg:%s, err:%v", utils.Format4Output(call, true), err)
|
|
}
|
|
return err
|
|
}
|
|
|
|
func onTLpayRefund(call *tonglianpayapi.CallBackResult) (err error) {
|
|
orderPayRefund := &model.OrderPayRefund{
|
|
RefundID: call.CusorderID,
|
|
}
|
|
db := dao.GetDB()
|
|
if err = dao.GetEntity(db, orderPayRefund, "RefundID"); err == nil {
|
|
if call.TrxStatus == tonglianpayapi.TrxStatusSuccess {
|
|
orderPayRefund.Status = model.RefundStatusYes
|
|
} else {
|
|
orderPayRefund.Status = model.RefundStatusFailed
|
|
}
|
|
orderPayRefund.OriginalData = utils.Format4Output(call, true)
|
|
dao.UpdateEntity(db, orderPayRefund)
|
|
} else if dao.IsNoRowsError(err) {
|
|
globals.SugarLogger.Warnf("收到异常的退款事件, call:%s", utils.Format4Output(call, true))
|
|
}
|
|
|
|
orderPay := &model.OrderPay{
|
|
VendorOrderID: orderPayRefund.VendorOrderID,
|
|
VendorID: jxutils.GetPossibleVendorIDFromVendorOrderID(orderPayRefund.VendorOrderID),
|
|
PayType: model.PayTypeWX,
|
|
Status: model.PayStatusYes,
|
|
}
|
|
orderPay.DeletedAt = utils.DefaultTimeValue
|
|
if err = dao.GetEntity(db, orderPay, "VendorOrderID", "VendorID", "PayType", "Status", "DeletedAt"); err == nil {
|
|
orderPay.Status = model.PayStatusRefund
|
|
dao.UpdateEntity(db, orderPay)
|
|
}
|
|
return err
|
|
}
|
|
|
|
func RefundOrderByTL(ctx *jxcontext.Context, orderPay *model.OrderPay, refundID string, refundFee int, refundDesc string) (orderPayRefund *model.OrderPayRefund, err error) {
|
|
result, err := api.TLpayAPI.PayRefund(&tonglianpayapi.PayRefundParam{
|
|
Trxamt: refundFee,
|
|
Reqsn: utils.GetUUID(),
|
|
Remark: refundDesc,
|
|
OldTrxID: orderPay.TransactionID,
|
|
})
|
|
if err == nil {
|
|
orderPayRefund = &model.OrderPayRefund{
|
|
RefundID: refundID,
|
|
VendorRefundID: result.TrxID,
|
|
VendorOrderID: orderPay.VendorOrderID,
|
|
VendorID: orderPay.VendorID,
|
|
Status: model.RefundStatusNo,
|
|
TransactionID: orderPay.TransactionID,
|
|
RefundFee: refundFee,
|
|
RefundCreatedAt: time.Now(),
|
|
}
|
|
dao.WrapAddIDCULDEntity(orderPayRefund, ctx.GetUserName())
|
|
db := dao.GetDB()
|
|
if result.TrxStatus == tonglianpayapi.TrxStatusSuccess {
|
|
orderPayRefund.Status = model.RefundStatusYes
|
|
} else {
|
|
orderPayRefund.Status = model.RefundStatusFailed
|
|
}
|
|
orderPayRefund.OriginalData = utils.Format4Output(result, true)
|
|
dao.CreateEntity(db, orderPayRefund)
|
|
|
|
orderPay.Status = model.PayStatusRefund
|
|
dao.UpdateEntity(db, orderPay)
|
|
}
|
|
return orderPayRefund, err
|
|
}
|
|
|
|
func OnWxPayCallback(msg *wxpayapi.CallbackMsg) (err error) {
|
|
globals.SugarLogger.Debugf("OnWxPayCallback msg:%s", utils.Format4Output(msg, true))
|
|
switch msg.MsgType {
|
|
case wxpayapi.MsgTypePay:
|
|
err = onWxpayFinished(msg.Data.(*wxpayapi.PayResultMsg))
|
|
case wxpayapi.MsgTypeRefund:
|
|
err = onWxpayRefund(msg.Data.(*wxpayapi.RefundResultMsg))
|
|
}
|
|
return err
|
|
}
|
|
|
|
func onWxpayFinished(msg *wxpayapi.PayResultMsg) (err error) {
|
|
order := &model.Order{
|
|
OrderID: utils.Str2Int64(msg.OutTradeNo),
|
|
}
|
|
db := dao.GetDB()
|
|
if err = dao.GetEntity(db, order, "OrderID"); err == nil {
|
|
order.PayFinishedAt = wxpayapi.PayTime2Time(msg.TimeEnd)
|
|
order.TransactionID = msg.TransactionID
|
|
order.OriginalData = utils.Format4Output(msg, true)
|
|
if msg.ResultCode == wxpayapi.ResponseCodeSuccess {
|
|
order.Status = model.OrderStatusFinished
|
|
} else {
|
|
order.Status = model.OrderStatusCanceled
|
|
}
|
|
dao.UpdateEntity(db, order)
|
|
if msg.ResultCode == wxpayapi.ResponseCodeSuccess {
|
|
err = OnPayFinished(order)
|
|
}
|
|
} else {
|
|
globals.SugarLogger.Debugf("onWxpayFinished msg:%s, err:%v", utils.Format4Output(msg, true), err)
|
|
}
|
|
return err
|
|
}
|
|
|
|
func onWxpayRefund(msg *wxpayapi.RefundResultMsg) (err error) {
|
|
orderPayRefund := &model.OrderPayRefund{
|
|
RefundID: msg.ReqInfoObj.OutRefundNo,
|
|
}
|
|
db := dao.GetDB()
|
|
if err = dao.GetEntity(db, orderPayRefund, "RefundID"); err == nil {
|
|
if msg.ResultCode == wxpayapi.ResponseCodeSuccess {
|
|
orderPayRefund.Status = model.RefundStatusYes
|
|
} else {
|
|
orderPayRefund.Status = model.RefundStatusFailed
|
|
}
|
|
orderPayRefund.OriginalData = utils.Format4Output(msg, true)
|
|
dao.UpdateEntity(db, orderPayRefund)
|
|
} else if dao.IsNoRowsError(err) {
|
|
globals.SugarLogger.Warnf("收到异常的退款事件, msg:%s", utils.Format4Output(msg, true))
|
|
}
|
|
|
|
orderPay := &model.OrderPay{
|
|
VendorOrderID: orderPayRefund.VendorOrderID,
|
|
VendorID: jxutils.GetPossibleVendorIDFromVendorOrderID(orderPayRefund.VendorOrderID),
|
|
PayType: model.PayTypeWX,
|
|
Status: model.PayStatusYes,
|
|
}
|
|
orderPay.DeletedAt = utils.DefaultTimeValue
|
|
if err = dao.GetEntity(db, orderPay, "VendorOrderID", "VendorID", "PayType", "Status", "DeletedAt"); err == nil {
|
|
orderPay.Status = model.PayStatusRefund
|
|
dao.UpdateEntity(db, orderPay)
|
|
}
|
|
return err
|
|
}
|