diff --git a/business/model/api_config.go b/business/model/api_config.go index f5d16debd..1eb9f795c 100644 --- a/business/model/api_config.go +++ b/business/model/api_config.go @@ -18,6 +18,8 @@ const ( VendorIDPurchaseEnd = 11 VendorIDJX = 9 // 这是一个假的京西VendorID + VendorIDWXPay = 51 // 微信支付 + VendorIDDeliveryBegin = 101 VendorIDDada = 101 VendorIDMTPS = 102 diff --git a/business/partner/pay/pay.go b/business/partner/pay/pay.go new file mode 100644 index 000000000..246d86afa --- /dev/null +++ b/business/partner/pay/pay.go @@ -0,0 +1,51 @@ +package pay + +import ( + "time" + + "git.rosy.net.cn/jx-callback/business/jxutils/jxcontext" +) + +type PayOpStatus int + +const ( + OpStatusFailed PayOpStatus = 0 + OpStatusSuccessed PayOpStatus = 1 +) + +type CreatePayParam struct { + PayOrderID string + VendorPayType string + + VendorOrderID string + ProductDesc string + ProductDetail string + FeeType string + TotalFee int + TimeStart time.Time + TimeExpire time.Time + + UserData string +} + +type PayOpResult struct { + Status PayOpStatus + VendorStatus string + ErrMsg string + + ID string + VendorID string + + OriginalData string +} + +type ResponseHandler interface { + OnCreatePay(vendorID int, result *PayOpResult) (err error) + OnRefundPay(vendorID int, result *PayOpResult) (err error) +} + +type IPayPlatformHandler interface { + CreatePay(ctx *jxcontext.Context, param *CreatePayParam, isOffline bool) (prepayID, qrCodeURL string, err error) + ClosePay(ctx *jxcontext.Context, payOrderID, vendorPayOrderID string) (err error) + RefundPay(ctx *jxcontext.Context, payOrderID, vendorPayOrderID, refundID, reason string, totalFee, refundFee int) (vendorRefundID string, err error) +} diff --git a/business/partner/pay/wxpay/callback.go b/business/partner/pay/wxpay/callback.go new file mode 100644 index 000000000..e76447652 --- /dev/null +++ b/business/partner/pay/wxpay/callback.go @@ -0,0 +1,60 @@ +package wxpay + +import ( + "git.rosy.net.cn/baseapi/platformapi/wxpayapi" + "git.rosy.net.cn/baseapi/utils" + "git.rosy.net.cn/jx-callback/business/model" + "git.rosy.net.cn/jx-callback/business/partner/pay" + "git.rosy.net.cn/jx-callback/globals" +) + +func OnCallback(msg *wxpayapi.CallbackMsg) (err error) { + globals.SugarLogger.Debugf("wxpay OnCallback 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) { + opResult := &pay.PayOpResult{ + OriginalData: string(utils.MustMarshal(msg)), + } + if msg.ReturnCode == wxpayapi.ResponseCodeSuccess { + opResult.Status = pay.OpStatusSuccessed + opResult.ID = msg.OutTradeNo + if msg.ResultCode == wxpayapi.ResponseCodeSuccess { + opResult.VendorID = msg.TransactionID + } else { + opResult.VendorStatus = msg.ErrCode + opResult.ErrMsg = msg.ErrCodeDes + } + } else { + opResult.Status = pay.OpStatusFailed + } + err = payHandler.responseHandler.OnCreatePay(model.VendorIDWXPay, opResult) + return err +} + +func onWxpayRefund(msg *wxpayapi.RefundResultMsg) (err error) { + opResult := &pay.PayOpResult{ + OriginalData: string(utils.MustMarshal(msg)), + } + if msg.ReturnCode == wxpayapi.ResponseCodeSuccess { + opResult.Status = pay.OpStatusSuccessed + if msg.ResultCode == wxpayapi.ResponseCodeSuccess { + opResult.ID = msg.ReqInfoObj.OutRefundNo + opResult.VendorID = msg.ReqInfoObj.RefundID + } else { + opResult.VendorStatus = msg.ErrCode + opResult.ErrMsg = msg.ErrCodeDes + } + } else { + opResult.Status = pay.OpStatusFailed + } + err = payHandler.responseHandler.OnRefundPay(model.VendorIDWXPay, opResult) + return err +} diff --git a/business/partner/pay/wxpay/wxpay.go b/business/partner/pay/wxpay/wxpay.go new file mode 100644 index 000000000..ee161d7ed --- /dev/null +++ b/business/partner/pay/wxpay/wxpay.go @@ -0,0 +1,73 @@ +package wxpay + +import ( + "git.rosy.net.cn/baseapi/platformapi/wxpayapi" + "git.rosy.net.cn/jx-callback/business/auth2/authprovider/weixin" + "git.rosy.net.cn/jx-callback/business/jxutils/jxcontext" + "git.rosy.net.cn/jx-callback/business/partner/pay" + "git.rosy.net.cn/jx-callback/globals" + "git.rosy.net.cn/jx-callback/globals/api" +) + +type PayHandler struct { + responseHandler pay.ResponseHandler +} + +var ( + payHandler *PayHandler +) + +func New(responseHandler pay.ResponseHandler) (handler *PayHandler) { + return &PayHandler{ + responseHandler: responseHandler, + } +} + +func vendorPayType2WxpayType(vendorPayType string) string { + return vendorPayType +} + +func (p *PayHandler) CreatePay(ctx *jxcontext.Context, createParam *pay.CreatePayParam, isOffline bool) (prepayID, qrCodeURL string, err error) { + param := &wxpayapi.CreateOrderParam{ + OutTradeNo: createParam.PayOrderID, + Body: createParam.ProductDesc, + NotifyURL: globals.WxpayNotifyURL, + SpbillCreateIP: ctx.GetRealRemoteIP(), + TradeType: vendorPayType2WxpayType(createParam.VendorPayType), + TotalFee: createParam.TotalFee, + + TimeStart: wxpayapi.Time2PayTime(createParam.TimeStart), + TimeExpire: wxpayapi.Time2PayTime(createParam.TimeExpire), + } + if isOffline { + param.TradeType = wxpayapi.TradeTypeNative + } + if authInfo, err := ctx.GetV2AuthInfo(); err == nil && authInfo.GetAuthType() == weixin.AuthTypeMini { + param.OpenID = authInfo.GetAuthID() + } + if result, err := api.WxpayAPI.CreateUnifiedOrder(param); err == nil { + prepayID = result.PrepayID + qrCodeURL = result.CodeURL + } + return prepayID, qrCodeURL, err +} + +func (p *PayHandler) ClosePay(ctx *jxcontext.Context, payOrderID, vendorPayOrderID string) (err error) { + return api.WxpayAPI.CloseOrder(payOrderID) +} + +func (p *PayHandler) RefundPay(ctx *jxcontext.Context, payOrderID, vendorPayOrderID, refundID, reason string, totalFee, refundFee int) (vendorRefundID string, err error) { + param := &wxpayapi.PayRefundParam{ + OutTradeNo: payOrderID, + NotifyURL: globals.WxpayNotifyURL, + OutRefundNo: refundID, + TotalFee: totalFee, + RefundFee: refundFee, + RefundDesc: wxpayapi.CData(reason), + } + retVal, err := api.WxpayAPI.PayRefund(param) + if err == nil { + vendorRefundID = retVal.RefundID + } + return vendorRefundID, err +}