hotime/vendor/github.com/go-pay/gopay/wechat/v3/sign.go

170 lines
4.8 KiB
Go
Raw Normal View History

2022-05-24 05:49:25 +00:00
package wechat
import (
"crypto"
"crypto/rand"
"crypto/rsa"
"crypto/sha256"
"encoding/base64"
"errors"
"fmt"
"time"
"github.com/go-pay/gopay"
"github.com/go-pay/gopay/pkg/util"
"github.com/go-pay/gopay/pkg/xlog"
"github.com/go-pay/gopay/pkg/xpem"
)
// Deprecated
// 推荐使用 wechat.V3VerifySignByPK()
func V3VerifySign(timestamp, nonce, signBody, sign, wxPubKeyContent string) (err error) {
publicKey, err := xpem.DecodePublicKey([]byte(wxPubKeyContent))
if err != nil {
return err
}
str := timestamp + "\n" + nonce + "\n" + signBody + "\n"
signBytes, _ := base64.StdEncoding.DecodeString(sign)
h := sha256.New()
h.Write([]byte(str))
if err = rsa.VerifyPKCS1v15(publicKey, crypto.SHA256, h.Sum(nil), signBytes); err != nil {
return fmt.Errorf("[%w]: %v", gopay.VerifySignatureErr, err)
}
return nil
}
// 微信V3 版本验签(同步/异步)
// wxPublicKey微信平台证书公钥内容通过 client.WxPublicKey() 获取
func V3VerifySignByPK(timestamp, nonce, signBody, sign string, wxPublicKey *rsa.PublicKey) (err error) {
str := timestamp + "\n" + nonce + "\n" + signBody + "\n"
signBytes, _ := base64.StdEncoding.DecodeString(sign)
h := sha256.New()
h.Write([]byte(str))
if err = rsa.VerifyPKCS1v15(wxPublicKey, crypto.SHA256, h.Sum(nil), signBytes); err != nil {
return fmt.Errorf("[%w]: %v", gopay.VerifySignatureErr, err)
}
return nil
}
// PaySignOfJSAPI 获取 JSAPI paySign
// 文档https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_1_4.shtml
func (c *ClientV3) PaySignOfJSAPI(appid, prepayid string) (jsapi *JSAPIPayParams, err error) {
ts := util.Int642String(time.Now().Unix())
nonceStr := util.RandomString(32)
pkg := "prepay_id=" + prepayid
_str := appid + "\n" + ts + "\n" + nonceStr + "\n" + pkg + "\n"
sign, err := c.rsaSign(_str)
if err != nil {
return nil, err
}
jsapi = &JSAPIPayParams{
AppId: appid,
TimeStamp: ts,
NonceStr: nonceStr,
Package: pkg,
SignType: SignTypeRSA,
PaySign: sign,
}
return jsapi, nil
}
// PaySignOfApp 获取 App sign
// 文档https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_2_4.shtml
func (c *ClientV3) PaySignOfApp(appid, prepayid string) (app *AppPayParams, err error) {
ts := util.Int642String(time.Now().Unix())
nonceStr := util.RandomString(32)
_str := appid + "\n" + ts + "\n" + nonceStr + "\n" + prepayid + "\n"
sign, err := c.rsaSign(_str)
if err != nil {
return nil, err
}
app = &AppPayParams{
Appid: appid,
Partnerid: c.Mchid,
Prepayid: prepayid,
Package: "Sign=WXPay",
Noncestr: nonceStr,
Timestamp: ts,
Sign: sign,
}
return app, nil
}
// PaySignOfApplet 获取 小程序 paySign
// 文档https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_5_4.shtml
func (c *ClientV3) PaySignOfApplet(appid, prepayid string) (applet *AppletParams, err error) {
jsapi, err := c.PaySignOfJSAPI(appid, prepayid)
if err != nil {
return nil, err
}
applet = &AppletParams{
AppId: jsapi.AppId,
TimeStamp: jsapi.TimeStamp,
NonceStr: jsapi.NonceStr,
Package: jsapi.Package,
SignType: jsapi.SignType,
PaySign: jsapi.PaySign,
}
return applet, nil
}
// v3 鉴权请求Header
func (c *ClientV3) authorization(method, path string, bm gopay.BodyMap) (string, error) {
var (
jb = ""
timestamp = time.Now().Unix()
nonceStr = util.RandomString(32)
)
if bm != nil {
jb = bm.JsonBody()
}
ts := util.Int642String(timestamp)
_str := method + "\n" + path + "\n" + ts + "\n" + nonceStr + "\n" + jb + "\n"
if c.DebugSwitch == gopay.DebugOn {
xlog.Debugf("Wechat_V3_SignString:\n%s", _str)
}
sign, err := c.rsaSign(_str)
if err != nil {
return "", err
}
return Authorization + ` mchid="` + c.Mchid + `",nonce_str="` + nonceStr + `",timestamp="` + ts + `",serial_no="` + c.SerialNo + `",signature="` + sign + `"`, nil
}
func (c *ClientV3) rsaSign(str string) (string, error) {
if c.privateKey == nil {
return "", errors.New("privateKey can't be nil")
}
h := sha256.New()
h.Write([]byte(str))
result, err := rsa.SignPKCS1v15(rand.Reader, c.privateKey, crypto.SHA256, h.Sum(nil))
if err != nil {
return util.NULL, fmt.Errorf("[%w]: %+v", gopay.SignatureErr, err)
}
return base64.StdEncoding.EncodeToString(result), nil
}
// 自动同步请求验签
func (c *ClientV3) verifySyncSign(si *SignInfo) (err error) {
if c.autoSign && c.wxPublicKey != nil {
if si != nil {
str := si.HeaderTimestamp + "\n" + si.HeaderNonce + "\n" + si.SignBody + "\n"
signBytes, _ := base64.StdEncoding.DecodeString(si.HeaderSignature)
h := sha256.New()
h.Write([]byte(str))
if err = rsa.VerifyPKCS1v15(c.wxPublicKey, crypto.SHA256, h.Sum(nil), signBytes); err != nil {
return fmt.Errorf("[%w]: %v", gopay.VerifySignatureErr, err)
}
return nil
}
return errors.New("auto verify sign, bug SignInfo is nil")
}
return nil
}