149 lines
4.2 KiB
Go
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)]
|
|
}
|