package weixin import ( "bytes" "context" "crypto/tls" butil "enterprise/base/util" "enterprise/common/config" "errors" "fmt" log "github.com/sirupsen/logrus" "github.com/smbrave/goutil" "github.com/spf13/cast" "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" ) type RedMoneyReq struct { TotalAmount int64 Title string Userid string BillNo string } type QyPay struct { cli *core.Client tlsClient *http.Client stdClient *http.Client qyClient *QyWeixin } 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 pay.qyClient = NewQyWeixin(cfg.QyWeixin.Corpid, cfg.QyWeixin.HrSecret, cfg.QyWeixin.HrAgent) 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 } func (p *QyPay) PayRedMoney(req *RedMoneyReq) error { if p.cli == nil { if err := p.initPay(); err != nil { return err } } cfg := config.GetConfig() param := newParams() 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.CutTail(req.Userid, 12)) } param.Set("nonce_str", butil.RandomStr(32)) param.Set("mch_billno", req.BillNo) param.Set("mch_id", cfg.WxPay.PayMchId) param.Set("wxappid", cfg.QyWeixin.Corpid) 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", "企业红包") 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) returnCode := respParam.GetString("return_code") resultCoce := respParam.GetString("result_code") if resultCoce == "SUCCESS" && returnCode == "SUCCESS" { return nil } return errors.New(string(respParam.Encode())) }