enterprise/common/weixin/qypay.go

168 lines
4.2 KiB
Go
Raw Normal View History

2023-08-09 22:00:55 +08:00
package weixin
2023-08-08 23:54:30 +08:00
import (
"bytes"
"context"
"crypto/tls"
butil "enterprise/base/util"
"enterprise/common/config"
"errors"
"fmt"
log "github.com/sirupsen/logrus"
"github.com/smbrave/goutil"
2023-08-09 22:00:55 +08:00
"github.com/spf13/cast"
2023-08-08 23:54:30 +08:00
"github.com/wechatpay-apiv3/wechatpay-go/core"
"github.com/wechatpay-apiv3/wechatpay-go/core/option"
"github.com/wechatpay-apiv3/wechatpay-go/utils"
"io/ioutil"
"net/http"
"time"
)
2023-08-09 22:00:55 +08:00
type RedMoneyReq struct {
TotalAmount int64
Title string
Userid string
BillNo string
}
2023-08-08 23:54:30 +08:00
type QyPay struct {
cli *core.Client
tlsClient *http.Client
stdClient *http.Client
2023-08-09 22:00:55 +08:00
qyClient *QyWeixin
2023-08-08 23:54:30 +08:00
}
func NewQyPay() *QyPay {
cfg := config.GetConfig()
payCertPem, _ := ioutil.ReadFile(cfg.WxPay.PayCertPem)
payKeyPem, _ := ioutil.ReadFile(cfg.WxPay.PayKeyPem)
pay := &QyPay{}
client, err := pay.withCert(payCertPem, payKeyPem)
if err != nil {
log.Errorf("with cert error :%s", err.Error())
return nil
}
pay.tlsClient = client
2023-08-09 22:00:55 +08:00
pay.qyClient = NewQyWeixin(cfg.QyWeixin.Corpid, cfg.QyWeixin.HrSecret)
2023-08-08 23:54:30 +08:00
return pay
}
// 附着商户证书
func (c *QyPay) withCert(cert, key []byte) (*http.Client, error) {
tlsCert, err := tls.X509KeyPair(cert, key)
if err != nil {
return nil, err
}
conf := &tls.Config{
Certificates: []tls.Certificate{tlsCert},
}
trans := &http.Transport{
TLSClientConfig: conf,
}
return &http.Client{
Transport: trans,
}, nil
}
// 发送请求
func (c *QyPay) post(url string, params params, tls bool) ([]byte, error) {
var httpc *http.Client
if tls {
if c.tlsClient == nil {
return nil, errors.New("tls wepay is not initialized")
}
httpc = c.tlsClient
} else {
httpc = c.stdClient
}
buf := bytes.NewBuffer(params.Encode())
resp, err := httpc.Post(url, "application/xml; charset=utf-8", buf)
if err != nil {
return nil, err
}
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, err
}
return body, nil
}
func (w *QyPay) initPay() error {
cfg := config.GetConfig()
// 使用 utils 提供的函数从本地文件中加载商户私钥,商户私钥会用来生成请求的签名
mchPrivateKey, err := utils.LoadPrivateKeyWithPath(cfg.WxPay.PayKeyPem)
if err != nil {
log.Errorf("utils.LoadPrivateKeyWithPath error %s", err.Error())
return err
}
ctx := context.Background()
// 使用商户私钥等初始化 client并使它具有自动定时获取微信支付平台证书的能力
opts := []core.ClientOption{
option.WithWechatPayAutoAuthCipher(cfg.WxPay.PayMchId, cfg.WxPay.PaySerialNumber, mchPrivateKey, cfg.WxPay.PayApiKeyV3),
}
client, err := core.NewClient(ctx, opts...)
if err != nil {
log.Errorf("core.NewClient error :%s", err.Error())
return err
}
fmt.Println(goutil.EncodeJSON(cfg.WxPay))
w.cli = client
return nil
}
2023-08-09 22:00:55 +08:00
func (p *QyPay) PayRedMoney(req *RedMoneyReq) error {
2023-08-08 23:54:30 +08:00
if p.cli == nil {
if err := p.initPay(); err != nil {
return err
}
}
cfg := config.GetConfig()
param := newParams()
2023-08-09 22:00:55 +08:00
userOpenid, err := p.qyClient.GetOpenid(req.Userid)
if err != nil {
log.Errorf("get openid error :%s", err.Error())
return err
}
if req.BillNo == "" {
req.BillNo = fmt.Sprintf("QY%s%s", time.Now().Format("20060102150405"), butil.RandomStr(6))
}
2023-08-08 23:54:30 +08:00
param.Set("nonce_str", butil.RandomStr(32))
2023-08-09 22:00:55 +08:00
param.Set("mch_billno", req.BillNo)
2023-08-08 23:54:30 +08:00
param.Set("mch_id", cfg.WxPay.PayMchId)
param.Set("wxappid", cfg.QyWeixin.Corpid)
2023-08-09 22:00:55 +08:00
param.Set("agentid", cfg.QyWeixin.PayAgent)
param.Set("re_openid", userOpenid)
param.Set("total_amount", cast.ToString(req.TotalAmount))
param.Set("wishing", req.Title)
param.Set("act_name", "企业红包")
param.Set("remark", "企业红包")
2023-08-08 23:54:30 +08:00
param.Set("workwx_sign", param.QySignMd5(cfg.QyWeixin.PaySecret))
param.Set("sign", param.SignMd5(cfg.WxPay.PayApiKeyV2))
reqUrl := "https://api.mch.weixin.qq.com/mmpaymkttransfers/sendworkwxredpack"
rspBody, err := p.post(reqUrl, param, true)
if err != nil {
log.Errorf("Post [%s] [%s] error :%s", reqUrl, string(param.Encode()), err.Error())
return err
}
respParam := newParams()
respParam.Decode(rspBody)
2023-08-09 22:00:55 +08:00
returnCode := respParam.GetString("return_code")
resultCoce := respParam.GetString("result_code")
if resultCoce == "SUCCESS" && returnCode == "SUCCESS" {
return nil
}
return errors.New(string(respParam.Encode()))
2023-08-08 23:54:30 +08:00
}