From cfdce2798b8213aad31281201a485e0b854139a2 Mon Sep 17 00:00:00 2001 From: mofangmin Date: Wed, 14 Aug 2024 11:20:09 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9Epayplus=E6=94=AF=E4=BB=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modules/pay/allpay/all.go | 3 + modules/pay/payplus/base.go | 126 ++++++++++++++++++++++++++++++++++ modules/pay/payplus/values.go | 72 +++++++++++++++++++ modules/pay/values/values.go | 1 + 4 files changed, 202 insertions(+) create mode 100644 modules/pay/payplus/base.go create mode 100644 modules/pay/payplus/values.go diff --git a/modules/pay/allpay/all.go b/modules/pay/allpay/all.go index 23c1729..948b721 100644 --- a/modules/pay/allpay/all.go +++ b/modules/pay/allpay/all.go @@ -7,6 +7,7 @@ import ( "server/modules/pay/grepay" "server/modules/pay/mlpay" "server/modules/pay/moonpay2" + "server/modules/pay/payplus" "github.com/liangdas/mqant/log" ) @@ -55,6 +56,7 @@ type AllPay struct { LemonPay func(b *base.Base) CamelPay func(b *base.Base) Moonpay2 func(b *base.Base) + PayPlus func(b *base.Base) } var All = &AllPay{} @@ -64,6 +66,7 @@ func init() { All.Moonpay2 = moonpay2.NewSub All.GrePay = grepay.NewSub All.MLPay = mlpay.NewSub + All.PayPlus = payplus.NewSub } func NewSub(b *base.Base, index int) { diff --git a/modules/pay/payplus/base.go b/modules/pay/payplus/base.go new file mode 100644 index 0000000..8e33a9e --- /dev/null +++ b/modules/pay/payplus/base.go @@ -0,0 +1,126 @@ +package payplus + +import ( + "errors" + "fmt" + "net/http" + "server/common" + "server/modules/pay/base" + "server/modules/pay/values" + "server/pb" + + "github.com/gogo/protobuf/proto" + "github.com/liangdas/mqant/log" +) + +func NewSub(b *base.Base) { + sub := &Sub{ + Base: b, + } + b.SignKey = key + b.HttpType = base.HttpTypeForm + b.ShouldSignUpper = true + b.Channel = values.PayPlus + if b.Opt == 1 { + b.Resp = new(PayReq) + b.ReqURL = payApi + } else if b.Opt == 2 { + b.Resp = new(WithdrawReq) + b.ReqURL = withdrawApi + } else if b.Opt == 3 { + b.SignPassStr = []string{"sign"} + b.CallbackResp.Msg = "SUCCESS" + b.CallbackReq = new(PayCallbackReq) + } else if b.Opt == 4 { + b.SignPassStr = []string{"sign", "msg"} + b.CallbackResp.Msg = "SUCCESS" + b.CallbackReq = new(WithdrawCallbackReq) + } + b.Sub = sub +} + +type Sub struct { + Base *base.Base +} + +func (s *Sub) PackHeader(header http.Header) { + // header.Set("Merchant-Id", config.GetConfig().Pay.IGeek.MID) +} + +func (s *Sub) PackReq() interface{} { + if s.Base.Opt == 1 { + return s.PackPayReq() + } + return s.PackWithdrawReq() +} + +func (s *Sub) GetResp() (proto.Message, error) { + if s.Base.Opt == 1 { + resp := s.Base.Resp.(*PaymentResponse) + if resp.RetCode != StatusSuccess || resp.PayUrl == "" { + return nil, errors.New("pay fail") + } + return &pb.InnerRechargeResp{APIOrderID: fmt.Sprintf("%v", resp.OrderNo), URL: resp.PayUrl, Channel: uint32(values.PayPlus)}, nil + } + resp := s.Base.Resp.(*PayoutResponse) + if s.Base.Status == 0 && resp.RetCode != StatusSuccess { + return nil, errors.New("withdraw fail") + } + return &pb.InnerWithdrawResp{APIOrderID: fmt.Sprintf("%v", resp.MchTransNo), Channel: uint32(values.PayPlus)}, nil +} + +func (s *Sub) PackPayReq() interface{} { + r := s.Base.PayReq + send := &PayReq{ + Amount: r.Amount, + MchId: "", + OrderNo: r.OrderID, + NotifyUrl: values.GetPayCallback(values.PayPlus), + } + send.Sign = s.Base.SignMD5(send) + return send +} + +func (s *Sub) PackWithdrawReq() interface{} { + r := s.Base.WithdrawReq + if r.PayType != int64(common.PayTypeBank) { + return nil + } + send := &WithdrawReq{ + Amount: r.Amount, + MchId: "", + OrderNo: r.OrderID, + BankCode: r.PayCode, + AccountName: r.Name, + AccountNo: r.CardNo, + NotifyUrl: values.GetWithdrawCallback(values.PayPlus), + } + + send.Sign = s.Base.SignMD5(send) + return send +} + +func (s *Sub) CheckSign(str string) bool { + // str += "&key=" + key + checkSign := "" + s.Base.CallbackResp.Msg = "SUCCESS" + mySign := "" + if s.Base.Opt == 3 { + req := s.Base.CallbackReq.(*PayCallbackReq) + log.Debug("checkSign pay:%+v", *req) + checkSign = req.Sign + s.Base.CallbackResp.OrderID = req.OrderNo + s.Base.CallbackResp.Success = req.Status == StatusSuccess + mySign = s.Base.SignMD5(req) + } else if s.Base.Opt == 4 { + req := s.Base.CallbackReq.(*WithdrawCallbackReq) + log.Debug("checkSign withdraw:%+v", *req) + checkSign = req.Sign + s.Base.CallbackResp.OrderID = req.OrderNo + s.Base.CallbackResp.Success = req.Status == StatusSuccess + s.Base.CallbackResp.APIOrderID = req.TradeNo + s.Base.CallbackResp.FailMessage = "" + mySign = s.Base.SignMD5(req) + } + return mySign == checkSign +} diff --git a/modules/pay/payplus/values.go b/modules/pay/payplus/values.go new file mode 100644 index 0000000..393f368 --- /dev/null +++ b/modules/pay/payplus/values.go @@ -0,0 +1,72 @@ +package payplus + +// 常量定义 +const ( + key = "your_secret_key" + StatusSuccess = "SUCCESS" + StatusFail = "FAIL" + payApi = "http://api.letspayfast.com/apipay" + withdrawApi = "http://api.letspayfast.com/apitrans" +) + +// PayReq 支付请求结构体 +type PayReq struct { + MchId string `json:"mchId" binding:"required"` // 商户号 + OrderNo string `json:"orderNo" binding:"required"` // 订单号 + Amount int64 `json:"amount" binding:"required"` // 支付金额 + NotifyUrl string `json:"notifyUrl" binding:"required"` // 支付结果通知的回调URL + Sign string `json:"sign,omitempty"` // 签名,生成后填充 +} + +// PaymentResponse 支付响应结构体 +type PaymentResponse struct { + RetCode string `json:"retCode"` + PayUrl string `json:"payUrl"` + OrderNo string `json:"orderNo"` + PlatOrder string `json:"platOrder"` + Code string `json:"code"` + RetMsg string `json:"retMsg"` +} + +// PayCallbackReq 支付通知结构体 +type PayCallbackReq struct { + MchId string `json:"mchId" binding:"required"` // 商户号 + OrderNo string `json:"orderNo" binding:"required"` // 订单号 + Amount string `json:"amount" binding:"required"` // 支付金额 + TradeNo string `json:"tradeNo" binding:"required"` // 支付平台生成的交易号 + Status string `json:"status" binding:"required"` // 支付状态(如成功、失败) + Sign string `json:"sign" binding:"required"` // 签名,用于验证通知的真实性 +} + +// WithdrawReq 代付请求结构体 +type WithdrawReq struct { + MchId string `json:"mchId" binding:"required"` // 商户号 + OrderNo string `json:"orderNo" binding:"required"` // 订单号 + Amount int64 `json:"amount" binding:"required"` // 代付金额 + BankCode string `json:"bankCode" binding:"required"` // 收款银行代码 + AccountName string `json:"accountName" binding:"required"` // 收款人姓名 + AccountNo string `json:"accountNo" binding:"required"` // 收款账号 + NotifyUrl string `json:"notifyUrl" binding:"required"` // 代付结果通知的回调URL + Sign string `json:"sign,omitempty"` // 签名,生成后填充 +} + +// PayoutResponse 代付响应结构体 +type PayoutResponse struct { + RetCode string `json:"retCode"` + RetMsg string `json:"retMsg"` + MchTransNo string `json:"mchTransNo"` + PlatOrder string `json:"platOrder"` + Status string `json:"status"` +} + +// WithdrawCallbackReq 代付通知结构体 +type WithdrawCallbackReq struct { + MchId string `json:"mchId" binding:"required"` // 商户号 + OrderNo string `json:"orderNo" binding:"required"` // 订单号 + Amount string `json:"amount" binding:"required"` // 代付金额 + TradeNo string `json:"tradeNo" binding:"required"` // 代付平台生成的交易号 + Status string `json:"status" binding:"required"` // 代付状态(如成功、失败) + AccountName string `json:"accountName" binding:"required"` // 收款人姓名 + AccountNo string `json:"accountNo" binding:"required"` // 收款账号 + Sign string `json:"sign" binding:"required"` // 签名,用于验证通知的真实性 +} diff --git a/modules/pay/values/values.go b/modules/pay/values/values.go index 7edd81a..b1d4c33 100644 --- a/modules/pay/values/values.go +++ b/modules/pay/values/values.go @@ -67,6 +67,7 @@ const ( LemonPay CamelPay MoonPay2 + PayPlus PayAll )