service/vendor/github.com/go-pay/gopay/wechat/sign.go

216 lines
6.9 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package wechat
import (
"context"
"crypto/hmac"
"crypto/md5"
"crypto/sha256"
"encoding/hex"
"encoding/json"
"errors"
"fmt"
"hash"
"reflect"
"strings"
"github.com/go-pay/gopay"
"github.com/go-pay/gopay/pkg/util"
)
// VerifySign 微信同步返回参数验签或异步通知参数验签
// ApiKeyAPI秘钥值
// signType签名类型调用API方法时填写的类型
// bean微信同步返回的结构体 wxRsp 或 异步通知解析的结构体 notifyReq推荐通 BodyMap 验签
// 返回参数ok是否验签通过
// 返回参数err其他错误信息不要根据 error 是否为空来判断验签正确与否,需再单独判断返回的 ok
func VerifySign(apiKey, signType string, bean interface{}) (ok bool, err error) {
if bean == nil {
return false, errors.New("bean is nil")
}
kind := reflect.ValueOf(bean).Kind()
if kind == reflect.Map {
bm := bean.(gopay.BodyMap)
bodySign := bm.GetString("sign")
bm.Remove("sign")
return GetReleaseSign(apiKey, signType, bm) == bodySign, nil
}
bs, err := json.Marshal(bean)
if err != nil {
return false, fmt.Errorf("json.Marshal(%s)%w", string(bs), err)
}
bm := make(gopay.BodyMap)
if err = json.Unmarshal(bs, &bm); err != nil {
return false, fmt.Errorf("json.Marshal(%s)%w", string(bs), err)
}
bodySign := bm.GetString("sign")
bm.Remove("sign")
return GetReleaseSign(apiKey, signType, bm) == bodySign, nil
}
// GetMiniPaySign JSAPI支付统一下单获取支付参数后再次计算出小程序用的paySign
// appIdAPPID
// nonceStr随即字符串
// packages统一下单成功后拼接得到的值
// signType签名类型
// timeStamp时间
// ApiKeyAPI秘钥值
// 微信小程序支付APIhttps://developers.weixin.qq.com/miniprogram/dev/api/open-api/payment/wx.requestPayment.html
// 微信小程序支付PaySign计算文档https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=7_7&index=3
func GetMiniPaySign(appId, nonceStr, packages, signType, timeStamp, apiKey string) (paySign string) {
var (
buffer strings.Builder
h hash.Hash
)
buffer.WriteString("appId=")
buffer.WriteString(appId)
buffer.WriteString("&nonceStr=")
buffer.WriteString(nonceStr)
buffer.WriteString("&package=")
buffer.WriteString(packages)
buffer.WriteString("&signType=")
buffer.WriteString(signType)
buffer.WriteString("&timeStamp=")
buffer.WriteString(timeStamp)
buffer.WriteString("&key=")
buffer.WriteString(apiKey)
if signType == SignType_HMAC_SHA256 {
h = hmac.New(sha256.New, []byte(apiKey))
} else {
h = md5.New()
}
h.Write([]byte(buffer.String()))
return strings.ToUpper(hex.EncodeToString(h.Sum(nil)))
}
// Deprecated
// 微信内H5支付官方文档https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_7&index=6
func GetH5PaySign(appId, nonceStr, packages, signType, timeStamp, apiKey string) (paySign string) {
return GetJsapiPaySign(appId, nonceStr, packages, signType, timeStamp, apiKey)
}
// GetJsapiPaySign JSAPI调起支付统一下单获取支付参数后再次计算出微信内H5支付需要用的paySign
// appIdAPPID
// nonceStr随即字符串
// packages统一下单成功后拼接得到的值
// signType签名类型
// timeStamp时间
// ApiKeyAPI秘钥值
// 文档https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_7&index=6
func GetJsapiPaySign(appId, nonceStr, packages, signType, timeStamp, apiKey string) (paySign string) {
var (
buffer strings.Builder
h hash.Hash
)
buffer.WriteString("appId=")
buffer.WriteString(appId)
buffer.WriteString("&nonceStr=")
buffer.WriteString(nonceStr)
buffer.WriteString("&package=")
buffer.WriteString(packages)
buffer.WriteString("&signType=")
buffer.WriteString(signType)
buffer.WriteString("&timeStamp=")
buffer.WriteString(timeStamp)
buffer.WriteString("&key=")
buffer.WriteString(apiKey)
if signType == SignType_HMAC_SHA256 {
h = hmac.New(sha256.New, []byte(apiKey))
} else {
h = md5.New()
}
h.Write([]byte(buffer.String()))
paySign = strings.ToUpper(hex.EncodeToString(h.Sum(nil)))
return
}
// GetAppPaySign APP支付统一下单获取支付参数后再次计算APP支付所需要的的sign
// appIdAPPID
// partneridpartnerid
// nonceStr随即字符串
// prepayId统一下单成功后得到的值
// signType此处签名方式务必与统一下单时用的签名方式一致
// timeStamp时间
// ApiKeyAPI秘钥值
// 文档https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=9_12&index=2
func GetAppPaySign(appid, partnerid, noncestr, prepayid, signType, timestamp, apiKey string) (paySign string) {
var (
buffer strings.Builder
h hash.Hash
)
buffer.WriteString("appid=")
buffer.WriteString(appid)
buffer.WriteString("&noncestr=")
buffer.WriteString(noncestr)
buffer.WriteString("&package=Sign=WXPay")
buffer.WriteString("&partnerid=")
buffer.WriteString(partnerid)
buffer.WriteString("&prepayid=")
buffer.WriteString(prepayid)
buffer.WriteString("&timestamp=")
buffer.WriteString(timestamp)
buffer.WriteString("&key=")
buffer.WriteString(apiKey)
if signType == SignType_HMAC_SHA256 {
h = hmac.New(sha256.New, []byte(apiKey))
} else {
h = md5.New()
}
h.Write([]byte(buffer.String()))
paySign = strings.ToUpper(hex.EncodeToString(h.Sum(nil)))
return
}
// Deprecated
// GetParamSign 获取微信支付所需参数里的Sign值通过支付参数计算Sign值
// 注意BodyMap中如无 sign_type 参数,默认赋值 sign_type 为 MD5
// appId应用ID
// mchId商户ID
// ApiKeyAPI秘钥值
// 返回参数 sign通过Appid、MchId、ApiKey和BodyMap中的参数计算出的Sign值
func GetParamSign(appId, mchId, apiKey string, bm gopay.BodyMap) (sign string) {
bm.Set("appid", appId)
bm.Set("mch_id", mchId)
var (
signType string
h hash.Hash
)
signType = bm.GetString("sign_type")
if signType == util.NULL {
bm.Set("sign_type", SignType_MD5)
}
if signType == SignType_HMAC_SHA256 {
h = hmac.New(sha256.New, []byte(apiKey))
} else {
h = md5.New()
}
h.Write([]byte(bm.EncodeWeChatSignParams(apiKey)))
sign = strings.ToUpper(hex.EncodeToString(h.Sum(nil)))
return
}
// Deprecated
// GetSanBoxParamSign 获取微信支付沙箱环境所需参数里的Sign值通过支付参数计算Sign值
// 注意:沙箱环境默认 sign_type 为 MD5
// appId应用ID
// mchId商户ID
// ApiKeyAPI秘钥值
// 返回参数 sign通过Appid、MchId、ApiKey和BodyMap中的参数计算出的Sign值
func GetSanBoxParamSign(ctx context.Context, appId, mchId, apiKey string, bm gopay.BodyMap) (sign string, err error) {
bm.Set("appid", appId)
bm.Set("mch_id", mchId)
bm.Set("sign_type", SignType_MD5)
bm.Set("total_fee", 101)
var (
sandBoxApiKey string
hashMd5 hash.Hash
)
if sandBoxApiKey, err = getSanBoxKey(ctx, mchId, util.RandomString(32), apiKey, SignType_MD5); err != nil {
return
}
hashMd5 = md5.New()
hashMd5.Write([]byte(bm.EncodeWeChatSignParams(sandBoxApiKey)))
sign = strings.ToUpper(hex.EncodeToString(hashMd5.Sum(nil)))
return
}