wx notify
This commit is contained in:
parent
6f039a0d8d
commit
9e35fe6e5e
@ -1,10 +1,17 @@
|
||||
package mainservice
|
||||
|
||||
import (
|
||||
"crypto/sha1"
|
||||
"encoding/json"
|
||||
"f5"
|
||||
"io"
|
||||
"main/constant"
|
||||
"main/service"
|
||||
"payserver/model"
|
||||
"payserver/mt"
|
||||
"q5"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
@ -36,3 +43,186 @@ func (this *MainServiceApi) RefreshToken(c *gin.Context) {
|
||||
service.Wxpay.GetAccessTokenList(&rspObj.Data)
|
||||
c.JSON(200, rspObj)
|
||||
}
|
||||
|
||||
func (this *MainServiceApi) WxTNotify(c *gin.Context) {
|
||||
f5.GetSysLog().Debug("wx test notify:%s", c.Request.URL.RawQuery)
|
||||
|
||||
signature := c.Query("signature")
|
||||
timestamp := c.Query("timestamp")
|
||||
nonce := c.Query("nonce")
|
||||
echostr := c.Query("echostr")
|
||||
strs := []string{constant.WX_NOTIFY_TOKEN, timestamp, nonce}
|
||||
sort.Strings(strs)
|
||||
sb := strings.Builder{}
|
||||
sb.WriteString(strs[0])
|
||||
sb.WriteString(strs[1])
|
||||
sb.WriteString(strs[2])
|
||||
m := sha1.New()
|
||||
io.WriteString(m, sb.String())
|
||||
sign := string(m.Sum(nil))
|
||||
|
||||
f5.GetSysLog().Debug("wx sign:%s, %s", sign, signature)
|
||||
|
||||
if sign != signature {
|
||||
c.String(200, "wrong")
|
||||
return
|
||||
}
|
||||
c.String(200, echostr)
|
||||
}
|
||||
|
||||
func (this *MainServiceApi) WxNotifyPurchase(c *gin.Context) {
|
||||
f5.GetSysLog().Debug("wx notify purchase:%s", c.Request.URL.RawQuery)
|
||||
|
||||
signature := c.Query("signature")
|
||||
timestamp := c.Query("timestamp")
|
||||
nonce := c.Query("nonce")
|
||||
|
||||
strs := []string{constant.WX_NOTIFY_TOKEN, timestamp, nonce}
|
||||
sort.Strings(strs)
|
||||
sb := strings.Builder{}
|
||||
sb.WriteString(strs[0])
|
||||
sb.WriteString(strs[1])
|
||||
sb.WriteString(strs[2])
|
||||
m := sha1.New()
|
||||
io.WriteString(m, sb.String())
|
||||
sign := string(m.Sum(nil))
|
||||
|
||||
f5.GetSysLog().Debug("wx sign:%s, %s", sign, signature)
|
||||
if sign != signature {
|
||||
return
|
||||
}
|
||||
|
||||
rspObj := struct {
|
||||
ErrorCode int32 `json:"ErrCode"`
|
||||
ErrMsg string `json:"ErrMsg"`
|
||||
}{
|
||||
ErrorCode: 99999,
|
||||
ErrMsg: "internal error",
|
||||
}
|
||||
|
||||
msg_signature := c.Query("msg_signature")
|
||||
if msg_signature != "" {
|
||||
postObj := struct {
|
||||
Encrypt string `json:"Encrypt"`
|
||||
ToUserName string `json:"ToUserName"`
|
||||
}{}
|
||||
|
||||
if err := c.ShouldBindJSON(&postObj); err != nil {
|
||||
rspObj.ErrorCode = 401
|
||||
rspObj.ErrMsg = "post data error"
|
||||
c.JSON(200, rspObj)
|
||||
return
|
||||
}
|
||||
|
||||
smsg, appid := service.Wxpay.DecryptMsg(msg_signature, timestamp, nonce, postObj.Encrypt)
|
||||
if smsg == nil || appid == nil || len(smsg) == 0 || len(appid) == 0 {
|
||||
rspObj.ErrorCode = 402
|
||||
rspObj.ErrMsg = "decrypt data error"
|
||||
c.JSON(200, rspObj)
|
||||
return
|
||||
}
|
||||
|
||||
f5.GetSysLog().Debug("wx decrypt msg:%s", smsg)
|
||||
|
||||
wxnotifyobj := service.WxPurchaseNotify{}
|
||||
if json.Unmarshal(smsg, &wxnotifyobj) != nil {
|
||||
rspObj.ErrorCode = 403
|
||||
rspObj.ErrMsg = "unmarshal data error"
|
||||
c.JSON(200, rspObj)
|
||||
return
|
||||
}
|
||||
|
||||
gameid := int64(0)
|
||||
appkey := ""
|
||||
notifyurl := ""
|
||||
mt.Table.Wxconfig.Traverse(func(w *mt.Wxconfig) bool {
|
||||
if w.GetAppid() == string(appid) {
|
||||
gameid = w.GetGameid()
|
||||
appkey = w.GetAppkey()
|
||||
notifyurl = w.GetNotifyurl()
|
||||
return false
|
||||
}
|
||||
return true
|
||||
})
|
||||
|
||||
if appkey == "" {
|
||||
f5.GetSysLog().Error("wx app config error:%s", appid)
|
||||
c.JSON(200, rspObj)
|
||||
return
|
||||
}
|
||||
|
||||
oristr := wxnotifyobj.Event + "&" + wxnotifyobj.MiniGame.Payload
|
||||
sig := service.Wxpay.GenSHA256Signature(oristr, appkey)
|
||||
if sig != wxnotifyobj.MiniGame.PayEventSig {
|
||||
f5.GetSysLog().Error("pay event sig error:%s, %s, %s", appid, sig, wxnotifyobj.MiniGame.PayEventSig)
|
||||
c.JSON(200, rspObj)
|
||||
return
|
||||
}
|
||||
|
||||
payloadobj := new(service.WxPayload)
|
||||
if json.Unmarshal([]byte(wxnotifyobj.MiniGame.Payload), &payloadobj) != nil {
|
||||
c.JSON(200, rspObj)
|
||||
return
|
||||
}
|
||||
|
||||
envpass := true
|
||||
if f5.IsOnlineEnv() {
|
||||
if payloadobj.Env != 0 {
|
||||
f5.GetSysLog().Error("notify test info to prod url")
|
||||
envpass = false
|
||||
}
|
||||
} else {
|
||||
if payloadobj.Env != 1 {
|
||||
f5.GetSysLog().Error("notify prod info to test url")
|
||||
envpass = false
|
||||
}
|
||||
}
|
||||
|
||||
if !envpass {
|
||||
c.JSON(200, rspObj)
|
||||
return
|
||||
}
|
||||
|
||||
orderModel := new(model.InAppOrder)
|
||||
if err, found := orderModel.FindByOrderId(payloadobj.OutTradeNo); err != nil {
|
||||
c.JSON(200, rspObj)
|
||||
return
|
||||
} else if !found {
|
||||
c.JSON(200, rspObj)
|
||||
return
|
||||
}
|
||||
|
||||
if orderModel.Status > 1 {
|
||||
rspObj.ErrorCode = 0
|
||||
rspObj.ErrMsg = "Success"
|
||||
c.JSON(200, rspObj)
|
||||
return
|
||||
}
|
||||
|
||||
rediskey := "ls:accountid:" + orderModel.AccountId
|
||||
str, err := service.Redis.Get(constant.LOGIN_REDIS, rediskey)
|
||||
if err != nil {
|
||||
c.JSON(200, rspObj)
|
||||
return
|
||||
}
|
||||
|
||||
data := map[string]interface{}{}
|
||||
if json.Unmarshal([]byte(str), &data) != nil {
|
||||
c.JSON(200, rspObj)
|
||||
return
|
||||
}
|
||||
|
||||
openid := q5.SafeToString(data["openid"])
|
||||
if openid != payloadobj.OpenId {
|
||||
c.JSON(200, rspObj)
|
||||
return
|
||||
}
|
||||
|
||||
orderModel.GameId = int32(gameid)
|
||||
f5.GetSysLog().Debug("notify url:%s, %s", appid, notifyurl)
|
||||
|
||||
}
|
||||
|
||||
c.JSON(200, rspObj)
|
||||
|
||||
}
|
||||
|
@ -56,3 +56,12 @@ const (
|
||||
const (
|
||||
GLOBAL_SALT = "f3a6a9a5-217a-4079-ab99-b5d69b8212be"
|
||||
)
|
||||
|
||||
const (
|
||||
WX_NOTIFY_TOKEN = "dV93f4FwSGMwkYcvsRHD8egdW5egPMhF" //必须32位
|
||||
WX_NOTIFY_ENCODING_AES_KEY = "H60uFIXjyd431hLVhlsKyus3U28RVIzWncey424DqpY"
|
||||
WX_AESKEY_SIZE = 32
|
||||
WX_ENCODING_KEY_SIZE = 43
|
||||
WX_RANDENCRYPT_STRLEN = 16
|
||||
WX_KMSG_LEN = 4
|
||||
)
|
||||
|
@ -23,7 +23,7 @@ type InAppOrder struct {
|
||||
TryCount int32 `gorm:"column:try_count;comment:补单次数"`
|
||||
Price int32 `gorm:"column:price;comment:price"`
|
||||
IP string `gorm:"column:ipv4;comment:ipv4地址"`
|
||||
Status int32 `gorm:"column:status;comment:0: 新添加订单 1:已经完成订单"`
|
||||
Status int32 `gorm:"column:status;comment:0: 新添加订单 1:已支付 2:已发货"`
|
||||
ConfirmTime int32 `gorm:"column:confirmtime;comment:GameServer订单确认时间"`
|
||||
CreateTime int32 `gorm:"column:createtime;<-:create"`
|
||||
ModifyTime int32 `gorm:"column:modifytime"`
|
||||
|
@ -119,6 +119,7 @@ type Wxconfig struct {
|
||||
appsecret string
|
||||
zoneid string
|
||||
offerid string
|
||||
notifyurl string
|
||||
|
||||
_flags1_ uint64
|
||||
_flags2_ uint64
|
||||
@ -568,6 +569,14 @@ func (this *Wxconfig) HasOfferid() bool {
|
||||
return (this._flags1_ & (uint64(1) << 6)) > 0
|
||||
}
|
||||
|
||||
func (this *Wxconfig) GetNotifyurl() string {
|
||||
return this.notifyurl
|
||||
}
|
||||
|
||||
func (this *Wxconfig) HasNotifyurl() bool {
|
||||
return (this._flags1_ & (uint64(1) << 7)) > 0
|
||||
}
|
||||
|
||||
func (this *LoginRedis) GetHost() string {
|
||||
return this.host
|
||||
}
|
||||
@ -702,6 +711,7 @@ func (this *Wxconfig) LoadFromKv(kv map[string]interface{}) {
|
||||
f5.ReadMetaTableField(&this.appsecret, "appsecret", &this._flags1_, 4, kv)
|
||||
f5.ReadMetaTableField(&this.zoneid, "zoneid", &this._flags1_, 5, kv)
|
||||
f5.ReadMetaTableField(&this.offerid, "offerid", &this._flags1_, 6, kv)
|
||||
f5.ReadMetaTableField(&this.notifyurl, "notifyurl", &this._flags1_, 7, kv)
|
||||
}
|
||||
|
||||
func (this *LoginRedis) LoadFromKv(kv map[string]interface{}) {
|
||||
|
@ -98,6 +98,7 @@ message Wxconfig
|
||||
optional string appsecret = 4;
|
||||
optional string zoneid = 5;
|
||||
optional string offerid = 6;
|
||||
optional string notifyurl = 7;
|
||||
}
|
||||
|
||||
message LoginRedis
|
||||
|
@ -11,4 +11,6 @@ func (this *MainServiceRouter) InitRouter() {
|
||||
api := v1.ApiGroupApp.MainServiceApiGroup
|
||||
f5.GetApp().GetGinEngine().GET("/api/service/refresh",
|
||||
api.RefreshToken)
|
||||
f5.GetApp().GetGinEngine().GET("/wx/tnotify",
|
||||
api.WxTNotify)
|
||||
}
|
||||
|
@ -1,16 +1,12 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"crypto/hmac"
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"f5"
|
||||
"main/constant"
|
||||
"main/mt"
|
||||
"q5"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
@ -58,6 +54,50 @@ type WxPayRsp struct {
|
||||
UsedGift int64 `json:"used_present_amount"`
|
||||
}
|
||||
|
||||
type WxQueryOrderRsp struct {
|
||||
ErrCode int32 `json:"errcode"`
|
||||
ErrMsg string `json:"errmsg"`
|
||||
ProductId string `json:"product_id"` //道具id
|
||||
PayState int32 `json:"pay_state"` //1:未支付;2:已支付
|
||||
DeliverState int32 `json:"deliver_state"` //1:未发货;2:已发货
|
||||
PayTime int64 `json:"pay_finish_time"` //支付完成时间
|
||||
TrandNo string `json:"out_trade_no"` //用户订单号
|
||||
MchOrderNo string `json:"mch_order_no"` //微信支付商户单
|
||||
Trans string `json:"transaction_id"` //微信支付订单号
|
||||
}
|
||||
|
||||
type WxPurchaseNotify struct {
|
||||
ToUserName string `json:"ToUserName"` //小游戏原始ID
|
||||
FromUserName string `json:"FromUserName"` //该事件消息的openid,道具发货场景固定为微信官方的openid
|
||||
CreateTime int64 `json:"CreateTime"` //消息发送时间
|
||||
MsgType string `json:"MsgType"` //消息类型,道具发货场景固定为:event
|
||||
Event string `json:"Event"` //事件类型 商城道具场景固定为:minigame_h5_goods_deliver_notify 道具直购(游戏内)场景固定为:minigame_game_pay_goods_deliver_notify
|
||||
MiniGame struct {
|
||||
Payload string `json:"Payload"` // 携带的具体内容,格式为json,具体内容如下表格Payload(因为这里需要对消息内容统一签名,所以统一把消息内容设计成json格式)
|
||||
PayEventSig string `json:"PayEventSig"` //见https://docs.qq.com/doc/DVVZZdHFsYkttYmxl(PayEventSig)
|
||||
} `json:"MiniGame"` //道具直购发货参数
|
||||
}
|
||||
|
||||
type WxPayload struct {
|
||||
OpenId string `json:"OpenId"` //接收道具的玩家openid
|
||||
Env int32 `json:"Env"` //环境配置 0:现网环境(也叫正式环境) 1:沙箱环境
|
||||
OutTradeNo string `json:"OutTradeNo"` // 订单号
|
||||
GoodsInfo struct {
|
||||
ProductId string `json:"ProductId"` //游戏道具id标识
|
||||
Quantity int64 `json:"Quantity"` //购买道具数量
|
||||
ZoneId string `json:"ZoneId"` //分区
|
||||
OrigPrice int64 `json:"OrigPrice"` //物品原始价格 (单位:分)
|
||||
ActualPrice int64 `json:"ActualPrice"` //物品实际支付价格(单位:分)
|
||||
Attach string `json:"Attach"` //透传数据
|
||||
OrderSource int64 `json:"OrderSource"` // 1 游戏内 2 商城下单 3 商城测试下单
|
||||
} `json:"GoodsInfo"` //发货道具
|
||||
WeChatPayInfo struct {
|
||||
MchOrderNo string `json:"MchOrderNo"` // 微信支付商户单号
|
||||
TransactionId string `json:"TransactionId"` // 交易单号(微信支付订单号)
|
||||
} `json:"WeChatPayInfo"` //微信支付信息(仅微信支付渠道)
|
||||
|
||||
}
|
||||
|
||||
func (wp *wxpay) init() {
|
||||
wp.gamesGoods = q5.ConcurrentMap[int64, map[int64]int64]{}
|
||||
wp.accessTokens = q5.ConcurrentMap[int64, TokenInfo]{}
|
||||
@ -333,6 +373,82 @@ func (wp *wxpay) QueryPay(openid string, gameid int64, userip string, sessionkey
|
||||
return wxerrcode
|
||||
}
|
||||
|
||||
func (wp *wxpay) QueryPurchase(openid string, gameid int64, userip string, sessionkey string, amount int32, tradeno string) (wxerrcode int32) {
|
||||
cfg := mt.Table.Wxconfig.GetById(gameid)
|
||||
postbody := struct {
|
||||
OpenId string `json:"openid"`
|
||||
Ts int64 `json:"ts"`
|
||||
Env int32 `json:"env"`
|
||||
TradeNo string `json:"out_trade_no"`
|
||||
BizId int32 `json:"biz_id"`
|
||||
OfferId string `json:"offer_id"`
|
||||
}{
|
||||
OpenId: openid,
|
||||
Ts: f5.GetApp().GetRealSeconds(),
|
||||
BizId: 2, //1代币 2道具直购
|
||||
TradeNo: tradeno,
|
||||
OfferId: cfg.GetOfferid(),
|
||||
}
|
||||
|
||||
if !f5.IsOnlineEnv() {
|
||||
postbody.Env = 1
|
||||
}
|
||||
|
||||
poststr := q5.EncodeJson(postbody)
|
||||
|
||||
queryuri := "/wxa/game/queryorderinfo"
|
||||
query := WxQuery{
|
||||
AccessToken: wp.getAccessToken(gameid),
|
||||
Signature: wp.GenSHA256Signature(poststr, sessionkey),
|
||||
SigMethod: "hmac_sha256",
|
||||
PaySig: wp.GenSHA256Signature(queryuri+"&"+poststr, cfg.GetAppkey()),
|
||||
}
|
||||
|
||||
params := map[string]string{}
|
||||
data, _ := json.Marshal(query)
|
||||
json.Unmarshal(data, ¶ms)
|
||||
|
||||
sendRequest := false
|
||||
urls := mt.Table.Config.GetWxUrl()
|
||||
for _, wxhost := range urls {
|
||||
url := "https://" + wxhost + queryuri
|
||||
f5.GetHttpCliMgr().SendGoStylePost(
|
||||
url,
|
||||
params,
|
||||
"Content-Type: application/json",
|
||||
poststr,
|
||||
func(rsp f5.HttpCliResponse) {
|
||||
if rsp.GetErr() != nil {
|
||||
return
|
||||
}
|
||||
|
||||
sendRequest = true
|
||||
rspJson := WxQueryOrderRsp{}
|
||||
f5.GetSysLog().Debug("wx query order rsp:%s", rsp.GetRawData())
|
||||
err := q5.DecodeJson(rsp.GetRawData(), &rspJson)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
wxerrcode = rspJson.ErrCode
|
||||
switch rspJson.ErrCode {
|
||||
case constant.WX_ERRCODE_OK:
|
||||
case constant.WX_ERRCODE_BUSY:
|
||||
sendRequest = false
|
||||
default:
|
||||
f5.GetSysLog().Info("err msg:%s", rspJson.ErrMsg)
|
||||
wp.checkErrorCode(rspJson.ErrCode)
|
||||
}
|
||||
|
||||
})
|
||||
if sendRequest {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return wxerrcode
|
||||
}
|
||||
|
||||
func (wp *wxpay) AddExpireInfo(accountid string, sessiontime int64) {
|
||||
info := expireSession{
|
||||
SessionTime: sessiontime,
|
||||
@ -356,12 +472,6 @@ func (wp *wxpay) CheckExpireCache(accountid string, expire int64) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
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) GetAccessTokenList(data *[]TokenInfo) {
|
||||
wp.accessTokens.Range(func(key int64, value TokenInfo) bool {
|
||||
*data = append(*data, value)
|
||||
|
135
server/payserver/service/wxpaybase.go
Normal file
135
server/payserver/service/wxpaybase.go
Normal file
@ -0,0 +1,135 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/aes"
|
||||
"crypto/cipher"
|
||||
"crypto/hmac"
|
||||
"crypto/sha1"
|
||||
"crypto/sha256"
|
||||
"encoding/base64"
|
||||
"encoding/binary"
|
||||
"encoding/hex"
|
||||
"main/constant"
|
||||
"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) 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(constant.WX_NOTIFY_ENCODING_AES_KEY)
|
||||
if sAesKey == "" {
|
||||
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 := int(0) //ntohl(iNetLen);
|
||||
binary.Read(buf, binary.BigEndian, &iMsgLen)
|
||||
if len(sNoEncryptData) <= constant.WX_RANDENCRYPT_STRLEN+constant.WX_KMSG_LEN+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(constant.WX_NOTIFY_TOKEN, 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) string {
|
||||
if len(sEncodingKey) != len(constant.WX_NOTIFY_ENCODING_AES_KEY) {
|
||||
return ""
|
||||
}
|
||||
|
||||
sBase64 := sEncodingKey + "="
|
||||
data, err := base64.StdEncoding.DecodeString(sBase64)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
return string(data)
|
||||
}
|
||||
|
||||
func (wp *wxpay) AES_CBCDecrypt(sSource []byte, sKey string) []byte {
|
||||
if len(sSource) < constant.WX_AESKEY_SIZE || len(sSource)%constant.WX_AESKEY_SIZE != 0 {
|
||||
return []byte{}
|
||||
}
|
||||
|
||||
key := []byte(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)]
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user