init
This commit is contained in:
145
myPay/alipay.go
Normal file
145
myPay/alipay.go
Normal file
@ -0,0 +1,145 @@
|
||||
package myPay
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"github.com/go-pay/gopay"
|
||||
"github.com/go-pay/gopay/alipay"
|
||||
"github.com/shopspring/decimal"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
type AliPay struct {
|
||||
ctx context.Context
|
||||
cli *alipay.Client
|
||||
params *AliPayImpl
|
||||
orderNo string
|
||||
amount int
|
||||
description string
|
||||
notifyUrl string
|
||||
returnUrl string
|
||||
}
|
||||
|
||||
func NewAliPay(params *AliPayImpl) *AliPay {
|
||||
client, err := alipay.NewClient(params.AppId, params.PrivateKey, params.IsProd)
|
||||
if err != nil {
|
||||
panic(err.Error())
|
||||
}
|
||||
|
||||
// 打开Debug开关,输出日志,默认是关闭的
|
||||
if params.IsProd {
|
||||
client.DebugSwitch = gopay.DebugOff
|
||||
} else {
|
||||
client.DebugSwitch = gopay.DebugOn
|
||||
}
|
||||
|
||||
client.SetLocation(alipay.LocationShanghai).
|
||||
SetCharset(alipay.UTF8).
|
||||
SetSignType(alipay.RSA2).
|
||||
AutoVerifySign([]byte(params.PublicKey))
|
||||
|
||||
if err := client.SetCertSnByContent([]byte(params.AppCertContent), []byte(params.AliPayRootCertContent), []byte(params.PublicKey)); err != nil {
|
||||
panic(err.Error())
|
||||
}
|
||||
|
||||
return &AliPay{params: params, cli: client, ctx: context.Background()}
|
||||
}
|
||||
|
||||
func (t *AliPay) GetCli() *alipay.Client {
|
||||
return t.cli
|
||||
}
|
||||
|
||||
func (t *AliPay) SetCommonConfig(notifyUrl string, returnUrl string) *AliPay {
|
||||
t.notifyUrl = notifyUrl
|
||||
t.returnUrl = returnUrl
|
||||
return t
|
||||
}
|
||||
|
||||
func (t *AliPay) SetOrderInfo(orderNo string, amount int, description string) *AliPay {
|
||||
t.orderNo = orderNo
|
||||
t.amount = amount
|
||||
t.description = description
|
||||
return t
|
||||
}
|
||||
|
||||
func (t *AliPay) SetCertSnByContent(appCertContent, aliPayRootCertContent []byte) error {
|
||||
return t.cli.SetCertSnByContent(appCertContent, aliPayRootCertContent, []byte(t.params.PublicKey))
|
||||
}
|
||||
|
||||
func (t *AliPay) SetCertSnByPath(appCertPath, aliPayRootCertPath, aliPayPublicCertPath string) error {
|
||||
return t.cli.SetCertSnByPath(appCertPath, aliPayRootCertPath, aliPayPublicCertPath)
|
||||
}
|
||||
|
||||
func (t *AliPay) setBodyMap() gopay.BodyMap {
|
||||
if t.description == "" || t.orderNo == "" || t.notifyUrl == "" {
|
||||
panic("param is empty")
|
||||
}
|
||||
if t.amount == 0 {
|
||||
panic("amount is zero")
|
||||
}
|
||||
|
||||
// 配置公共参数
|
||||
t.cli.SetNotifyUrl(t.notifyUrl).
|
||||
SetReturnUrl(t.returnUrl)
|
||||
|
||||
bm := make(gopay.BodyMap)
|
||||
bm.Set("subject", t.description)
|
||||
bm.Set("out_trade_no", t.orderNo)
|
||||
bm.Set("total_amount", t.fen2Yuan(uint64(t.amount)))
|
||||
return bm
|
||||
}
|
||||
|
||||
func (t *AliPay) GetWapPay(quitUrl string) (string, error) {
|
||||
bm := t.setBodyMap()
|
||||
bm.Set("quit_url", quitUrl)
|
||||
bm.Set("product_code", "QUICK_WAP_WAY")
|
||||
return t.cli.TradeWapPay(t.ctx, bm)
|
||||
}
|
||||
|
||||
func (t *AliPay) GetPagePay() (string, error) {
|
||||
bm := t.setBodyMap()
|
||||
bm.Set("product_code", "FAST_INSTANT_TRADE_PAY")
|
||||
return t.cli.TradePagePay(t.ctx, bm)
|
||||
}
|
||||
|
||||
func (t *AliPay) GetAppPay() (string, error) {
|
||||
bm := t.setBodyMap()
|
||||
bm.Set("product_code", "QUICK_MSECURITY_PAY")
|
||||
return t.cli.TradeAppPay(t.ctx, bm)
|
||||
}
|
||||
|
||||
func (t *AliPay) Notify(req *http.Request) (*AlipayNotifyResp, error) {
|
||||
notifyReq, err := alipay.ParseNotifyToBodyMap(req)
|
||||
if err != nil {
|
||||
return nil, errors.New("解析回调失败")
|
||||
}
|
||||
|
||||
if ok, err := alipay.VerifySign(t.params.PublicKey, notifyReq); err != nil || ok == false {
|
||||
return nil, errors.New("sign Error")
|
||||
}
|
||||
|
||||
return &AlipayNotifyResp{resp: notifyReq}, nil
|
||||
}
|
||||
|
||||
func (t *AliPay) GetOrderNo() string {
|
||||
return t.orderNo
|
||||
}
|
||||
|
||||
func (t *AliPay) GetAmount() int {
|
||||
return t.amount
|
||||
}
|
||||
|
||||
type AliPayImpl struct {
|
||||
AppId string
|
||||
PublicKey string
|
||||
PrivateKey string
|
||||
IsProd bool
|
||||
AppCertContent string
|
||||
AliPayRootCertContent string
|
||||
}
|
||||
|
||||
func (t *AliPay) fen2Yuan(price uint64) string {
|
||||
d := decimal.New(1, 2)
|
||||
result := decimal.NewFromInt(int64(price)).DivRound(d, 2).String()
|
||||
return result
|
||||
}
|
28
myPay/alipay_notify.go
Normal file
28
myPay/alipay_notify.go
Normal file
@ -0,0 +1,28 @@
|
||||
package myPay
|
||||
|
||||
import "github.com/go-pay/gopay"
|
||||
|
||||
type AlipayNotifyResp struct {
|
||||
resp gopay.BodyMap
|
||||
}
|
||||
type AlipayNotifyRespInfo struct {
|
||||
TradeStatus string
|
||||
OutTradeNo string
|
||||
SellerId string
|
||||
TradeNo string
|
||||
GmtPayment string
|
||||
}
|
||||
|
||||
func (t *AlipayNotifyResp) IsSuccess() bool {
|
||||
return t.resp.Get("trade_status") == "TRADE_SUCCESS"
|
||||
}
|
||||
|
||||
func (t *AlipayNotifyResp) GetResult() *AlipayNotifyRespInfo {
|
||||
return &AlipayNotifyRespInfo{
|
||||
TradeStatus: t.resp.Get("trade_status"),
|
||||
OutTradeNo: t.resp.Get("out_trade_no"),
|
||||
SellerId: t.resp.Get("seller_id"),
|
||||
TradeNo: t.resp.Get("trade_no"),
|
||||
GmtPayment: t.resp.Get("gmt_payment"),
|
||||
}
|
||||
}
|
261
myPay/wechat.go
Normal file
261
myPay/wechat.go
Normal file
@ -0,0 +1,261 @@
|
||||
package myPay
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"github.com/go-pay/gopay"
|
||||
"github.com/go-pay/gopay/wechat/v3"
|
||||
"net/http"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Wechat struct {
|
||||
ctx context.Context
|
||||
cli *wechat.ClientV3
|
||||
params *WechatPayV3Impl
|
||||
orderNo string
|
||||
amount int
|
||||
description string
|
||||
notifyUrl string
|
||||
profitSharing bool
|
||||
}
|
||||
|
||||
func NewWechat(params *WechatPayV3Impl) *Wechat {
|
||||
// NewClientV3 初始化微信客户端 v3
|
||||
// mchid:商户ID 或者服务商模式的 sp_mchid
|
||||
// serialNo:商户证书的证书序列号
|
||||
// apiV3Key:apiV3Key,商户平台获取
|
||||
// privateKey:私钥 apiclient_key.pem 读取后的内容
|
||||
client, err := wechat.NewClientV3(params.MchId, params.SerialNo, params.ApiV3Key, params.PKContent)
|
||||
if err != nil {
|
||||
panic(err.Error())
|
||||
}
|
||||
|
||||
// 设置微信平台API证书和序列号(推荐开启自动验签,无需手动设置证书公钥等信息)
|
||||
//client.SetPlatformCert([]byte(""), "")
|
||||
|
||||
// 启用自动同步返回验签,并定时更新微信平台API证书(开启自动验签时,无需单独设置微信平台API证书和序列号)
|
||||
client.SetPlatformCert([]byte(params.WxPkContent), params.WxPkSerialNo)
|
||||
// 启用自动同步返回验签,并定时更新微信平台API证书
|
||||
//err = client.AutoVerifySign()
|
||||
//if err != nil {
|
||||
// return nil, err
|
||||
//}
|
||||
|
||||
// 打开Debug开关,输出日志,默认是关闭的
|
||||
if params.IsProd {
|
||||
client.DebugSwitch = gopay.DebugOff
|
||||
} else {
|
||||
client.DebugSwitch = gopay.DebugOn
|
||||
}
|
||||
|
||||
return &Wechat{params: params, cli: client, ctx: context.Background()}
|
||||
}
|
||||
|
||||
func (t *Wechat) GetCli() *wechat.ClientV3 {
|
||||
return t.cli
|
||||
}
|
||||
|
||||
func (t *Wechat) SetCommonConfig(notifyUrl string) *Wechat {
|
||||
t.notifyUrl = notifyUrl
|
||||
return t
|
||||
}
|
||||
|
||||
func (t *Wechat) SetOrderInfo(orderNo string, amount int, description string) *Wechat {
|
||||
t.orderNo = orderNo
|
||||
t.amount = amount
|
||||
t.description = description
|
||||
return t
|
||||
}
|
||||
|
||||
func (t *Wechat) setBodyMap() gopay.BodyMap {
|
||||
if t.description == "" || t.orderNo == "" || t.notifyUrl == "" {
|
||||
panic("param is empty")
|
||||
}
|
||||
if t.amount == 0 {
|
||||
panic("amount is zero")
|
||||
}
|
||||
|
||||
bm := make(gopay.BodyMap)
|
||||
bm.Set("description", t.description).
|
||||
Set("out_trade_no", t.orderNo).
|
||||
Set("time_expire", time.Now().Add(10*time.Minute).Format(time.RFC3339)).
|
||||
Set("notify_url", t.notifyUrl).
|
||||
SetBodyMap("amount", func(bm gopay.BodyMap) {
|
||||
bm.Set("total", t.amount).Set("currency", "CNY")
|
||||
})
|
||||
if t.profitSharing {
|
||||
bm.SetBodyMap("settle_info", func(bm gopay.BodyMap) {
|
||||
bm.Set("profit_sharing", true)
|
||||
})
|
||||
}
|
||||
|
||||
return bm
|
||||
}
|
||||
|
||||
func (t *Wechat) SetProfitSharing(b bool) *Wechat {
|
||||
t.profitSharing = b
|
||||
return t
|
||||
}
|
||||
|
||||
func (t *Wechat) GetApp() (*wechat.AppPayParams, error) {
|
||||
wxRsp, err := t.cli.V3TransactionApp(t.ctx, t.setBodyMap().Set("appid", t.params.AppAppid))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if wxRsp.Code == wechat.Success {
|
||||
//校验签名
|
||||
if err2 := wechat.V3VerifySignByPK(wxRsp.SignInfo.HeaderTimestamp, wxRsp.SignInfo.HeaderNonce, wxRsp.SignInfo.SignBody, wxRsp.SignInfo.HeaderSignature, t.cli.WxPublicKey()); err != nil {
|
||||
return nil, err2
|
||||
}
|
||||
|
||||
//获取调起参数
|
||||
return t.cli.PaySignOfApp(t.params.AppAppid, wxRsp.Response.PrepayId)
|
||||
} else {
|
||||
return nil, errors.New(wxRsp.Error)
|
||||
}
|
||||
}
|
||||
|
||||
func (t *Wechat) GetJsapi(openId string) (*wechat.JSAPIPayParams, error) {
|
||||
wxRsp, err := t.cli.V3TransactionJsapi(t.ctx,
|
||||
t.setBodyMap().Set("appid", t.params.MpAppid).SetBodyMap("payer", func(bm gopay.BodyMap) {
|
||||
bm.Set("openid", openId)
|
||||
}),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if wxRsp.Code == wechat.Success {
|
||||
//校验签名
|
||||
if err2 := wechat.V3VerifySignByPK(wxRsp.SignInfo.HeaderTimestamp, wxRsp.SignInfo.HeaderNonce, wxRsp.SignInfo.SignBody, wxRsp.SignInfo.HeaderSignature, t.cli.WxPublicKey()); err != nil {
|
||||
return nil, err2
|
||||
}
|
||||
|
||||
//获取调起参数
|
||||
return t.cli.PaySignOfJSAPI(t.params.MpAppid, wxRsp.Response.PrepayId)
|
||||
} else {
|
||||
return nil, errors.New(wxRsp.Error)
|
||||
}
|
||||
}
|
||||
|
||||
func (t *Wechat) GetJsapiForMini(openId string) (*wechat.JSAPIPayParams, error) {
|
||||
wxRsp, err := t.cli.V3TransactionJsapi(t.ctx,
|
||||
t.setBodyMap().Set("appid", t.params.MiniAppid).SetBodyMap("payer", func(bm gopay.BodyMap) {
|
||||
bm.Set("openid", openId)
|
||||
}),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if wxRsp.Code == wechat.Success {
|
||||
//校验签名
|
||||
if err2 := wechat.V3VerifySignByPK(wxRsp.SignInfo.HeaderTimestamp, wxRsp.SignInfo.HeaderNonce, wxRsp.SignInfo.SignBody, wxRsp.SignInfo.HeaderSignature, t.cli.WxPublicKey()); err != nil {
|
||||
return nil, err2
|
||||
}
|
||||
|
||||
//获取调起参数
|
||||
return t.cli.PaySignOfJSAPI(t.params.MiniAppid, wxRsp.Response.PrepayId)
|
||||
} else {
|
||||
return nil, errors.New(wxRsp.Error)
|
||||
}
|
||||
}
|
||||
|
||||
func (t *Wechat) GetNative() (*wechat.Native, error) {
|
||||
wxRsp, err := t.cli.V3TransactionNative(t.ctx, t.setBodyMap().Set("appid", t.params.MpAppid))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if wxRsp.Code == wechat.Success {
|
||||
//校验签名
|
||||
if err2 := wechat.V3VerifySignByPK(wxRsp.SignInfo.HeaderTimestamp, wxRsp.SignInfo.HeaderNonce, wxRsp.SignInfo.SignBody, wxRsp.SignInfo.HeaderSignature, t.cli.WxPublicKey()); err != nil {
|
||||
return nil, err2
|
||||
}
|
||||
|
||||
//获取调起参数
|
||||
return wxRsp.Response, err
|
||||
} else {
|
||||
return nil, errors.New(wxRsp.Error)
|
||||
}
|
||||
}
|
||||
|
||||
func (t *Wechat) GetH5(ip string, appName string, appUrl string) (*wechat.H5Url, error) {
|
||||
wxRsp, err := t.cli.V3TransactionH5(t.ctx, t.setBodyMap().Set("appid", t.params.MpAppid).SetBodyMap("scene_info", func(bm gopay.BodyMap) {
|
||||
bm.Set("payer_client_ip", ip)
|
||||
bm.SetBodyMap("h5_info", func(bm gopay.BodyMap) {
|
||||
bm.Set("type", "Wap")
|
||||
bm.Set("app_url", appUrl)
|
||||
bm.Set("app_name", appName)
|
||||
})
|
||||
}))
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if wxRsp.Code == wechat.Success {
|
||||
//校验签名
|
||||
if err2 := wechat.V3VerifySignByPK(wxRsp.SignInfo.HeaderTimestamp, wxRsp.SignInfo.HeaderNonce, wxRsp.SignInfo.SignBody, wxRsp.SignInfo.HeaderSignature, t.cli.WxPublicKey()); err != nil {
|
||||
return nil, err2
|
||||
}
|
||||
|
||||
//获取调起参数
|
||||
return wxRsp.Response, nil
|
||||
} else {
|
||||
return nil, errors.New(wxRsp.Error)
|
||||
}
|
||||
}
|
||||
|
||||
func (t *Wechat) Notify(req *http.Request) (*WechatNotifyResp, error) {
|
||||
notifyReq, err := wechat.V3ParseNotify(req)
|
||||
if err != nil {
|
||||
return nil, errors.New("解析回调失败")
|
||||
}
|
||||
|
||||
err = notifyReq.VerifySignByPK(t.cli.WxPublicKey())
|
||||
if err != nil {
|
||||
return nil, errors.New("sign Error")
|
||||
}
|
||||
|
||||
if notifyReq.EventType == "TRANSACTION.SUCCESS" {
|
||||
result, err := notifyReq.DecryptPayCipherText(t.params.ApiV3Key)
|
||||
if err != nil {
|
||||
return nil, errors.New("解密错误")
|
||||
} else {
|
||||
return &WechatNotifyResp{resp: result}, nil
|
||||
}
|
||||
}
|
||||
|
||||
return nil, errors.New(notifyReq.EventType)
|
||||
}
|
||||
|
||||
func (t *Wechat) GetOrderNo() string {
|
||||
return t.orderNo
|
||||
}
|
||||
|
||||
func (t *Wechat) GetAmount() int {
|
||||
return t.amount
|
||||
}
|
||||
|
||||
func NotifySuccess(msg string) (int, *wechat.V3NotifyRsp) {
|
||||
return http.StatusOK, &wechat.V3NotifyRsp{Code: gopay.SUCCESS, Message: msg}
|
||||
}
|
||||
|
||||
func NotifyFail(msg string) (int, *wechat.V3NotifyRsp) {
|
||||
return http.StatusBadRequest, &wechat.V3NotifyRsp{Code: gopay.FAIL, Message: msg}
|
||||
}
|
||||
|
||||
type WechatPayV3Impl struct {
|
||||
MpAppid string
|
||||
AppAppid string
|
||||
MiniAppid string
|
||||
MchId string
|
||||
ApiV3Key string
|
||||
SerialNo string
|
||||
PKContent string
|
||||
WxPkSerialNo string
|
||||
WxPkContent string
|
||||
IsProd bool
|
||||
}
|
15
myPay/wechat_notify.go
Normal file
15
myPay/wechat_notify.go
Normal file
@ -0,0 +1,15 @@
|
||||
package myPay
|
||||
|
||||
import "github.com/go-pay/gopay/wechat/v3"
|
||||
|
||||
type WechatNotifyResp struct {
|
||||
resp *wechat.V3DecryptPayResult
|
||||
}
|
||||
|
||||
func (t *WechatNotifyResp) IsSuccess() bool {
|
||||
return t.resp.TradeState == "SUCCESS"
|
||||
}
|
||||
|
||||
func (t *WechatNotifyResp) GetResult() *wechat.V3DecryptPayResult {
|
||||
return t.resp
|
||||
}
|
Reference in New Issue
Block a user