2025-01-13 18:03:49 +08:00

149 lines
4.2 KiB
Go

package service
import (
"bytes"
"crypto/aes"
"crypto/cipher"
"crypto/hmac"
"crypto/sha1"
"crypto/sha256"
"encoding/base64"
"encoding/binary"
"encoding/hex"
"main/constant"
"main/mt"
"sort"
"strings"
)
func (wp *wxpay) GenSHA256Signature(str string, key string) string {
mac := hmac.New(sha256.New, []byte(key))
_, _ = mac.Write([]byte(str))
return strings.ToLower(hex.EncodeToString(mac.Sum(nil)))
}
func (wp *wxpay) GetPurchaseSig(gameid int64, data string, sessionkey string) (pay_sig string, signature string) {
cfg := mt.Table.Wxconfig.GetById(gameid)
if cfg == nil {
return
}
pay_sig = wp.GenSHA256Signature("requestMidasPaymentGameItem&"+data, cfg.GetAppkey())
signature = wp.GenSHA256Signature(data, sessionkey)
return pay_sig, signature
}
func (wp *wxpay) DecryptMsg(sMsgSignature string, sTimeStamp string, sNonce string, sEncryptMsg string) (sMsg []byte, msgappid []byte) {
// 2.validate signature
if !wp.ValidateSignature(sMsgSignature, sTimeStamp, sNonce, sEncryptMsg) {
return
}
//3.decode base64
sAesData, err := base64.StdEncoding.DecodeString(sEncryptMsg)
if err != nil {
return
}
//4.decode aes
sAesKey := wp.GenAesKeyFromEncodingKey(mt.Table.Config.GetWxNotifyEncodingAesKey())
if len(sAesKey) == 0 {
return
}
sNoEncryptData := wp.AES_CBCDecrypt(sAesData, sAesKey)
// 5. remove kRandEncryptStrLen str
if len(sNoEncryptData) <= constant.WX_RANDENCRYPT_STRLEN+constant.WX_KMSG_LEN {
return
}
netlenbyte := sNoEncryptData[constant.WX_RANDENCRYPT_STRLEN : constant.WX_RANDENCRYPT_STRLEN+constant.WX_KMSG_LEN]
buf := bytes.NewReader(netlenbyte)
iMsgLen := int32(0) //ntohl(iNetLen);
binary.Read(buf, binary.BigEndian, &iMsgLen)
if len(sNoEncryptData) <= constant.WX_RANDENCRYPT_STRLEN+constant.WX_KMSG_LEN+int(iMsgLen) {
return
}
sMsg = sNoEncryptData[constant.WX_RANDENCRYPT_STRLEN+constant.WX_KMSG_LEN : constant.WX_RANDENCRYPT_STRLEN+constant.WX_KMSG_LEN+iMsgLen]
//6. validate appid
msgappid = sNoEncryptData[constant.WX_RANDENCRYPT_STRLEN+constant.WX_KMSG_LEN+iMsgLen:]
return
}
func (wp *wxpay) ValidateSignature(sMsgSignature string, sTimeStamp string, sNonce string, sEncryptMsg string) bool {
sSignature := wp.ComputeSignature(mt.Table.Config.GetWxNotifyToken(), sTimeStamp, sNonce, sEncryptMsg)
if sSignature == "" {
return false
}
return sMsgSignature == sSignature
}
func (wp *wxpay) ComputeSignature(sToken string, sTimeStamp string, sNonce string, sMessage string) string {
if sToken == "" || sNonce == "" || sMessage == "" || sTimeStamp == "" {
return ""
}
//sort
strs := []string{}
strs = append(strs, sToken)
strs = append(strs, sTimeStamp)
strs = append(strs, sNonce)
strs = append(strs, sMessage)
sort.Strings(strs)
sStr := strs[0] + strs[1] + strs[2] + strs[3]
//compute
sha1crypto := sha1.New()
_, err := sha1crypto.Write([]byte(sStr))
if err != nil {
return ""
}
return hex.EncodeToString(sha1crypto.Sum(nil))
}
func (wp *wxpay) GenAesKeyFromEncodingKey(sEncodingKey string) (aeskey []byte) {
if len(sEncodingKey) != len(mt.Table.Config.GetWxNotifyEncodingAesKey()) {
return
}
sBase64 := sEncodingKey + "="
data, err := base64.StdEncoding.DecodeString(sBase64)
if err != nil {
return
}
return data
}
func (wp *wxpay) AES_CBCDecrypt(sSource []byte, sKey []byte) []byte {
if len(sSource) < constant.WX_AESKEY_SIZE || len(sSource)%constant.WX_AESKEY_SIZE != 0 {
return []byte{}
}
key := sKey
if len(sKey) > constant.WX_AESKEY_SIZE {
key = key[0:constant.WX_AESKEY_SIZE]
}
return aesDecryptCBC(sSource, key)
}
func aesDecryptCBC(encrypted []byte, key []byte) (decrypted []byte) {
block, _ := aes.NewCipher(key) // 分组秘钥
blockSize := block.BlockSize() // 获取秘钥块的长度
blockMode := cipher.NewCBCDecrypter(block, key[:blockSize]) // 加密模式
decrypted = make([]byte, len(encrypted)) // 创建数组
blockMode.CryptBlocks(decrypted, encrypted) // 解密
decrypted = pkcs5UnPadding(decrypted) // 去除补全码
return decrypted
}
func pkcs5UnPadding(origData []byte) []byte {
length := len(origData)
unpadding := int(origData[length-1])
return origData[:(length - unpadding)]
}