Browse Source

设置企业微信回调

pull/1/head
超级管理员 4 years ago
parent
commit
ff0af0a806
  1. 2
      gin_server_admin/api/v1/enter.go
  2. 19
      gin_server_admin/api/v1/examtestpage/healthreportstat.go
  3. 85
      gin_server_admin/api/v1/examtestpage/healthreportstathand.go
  4. 5
      gin_server_admin/api/v1/wechatcallback/enter.go
  5. 31
      gin_server_admin/api/v1/wechatcallback/wechatcallbackmain.go
  6. 60
      gin_server_admin/commonus/publichaneld.go
  7. 11
      gin_server_admin/commonus/timeSub.go
  8. 2
      gin_server_admin/commonus/wechatapp.go
  9. 9
      gin_server_admin/config.yaml
  10. 4
      gin_server_admin/config/wechat.go
  11. 7
      gin_server_admin/initialize/router.go
  12. 12
      gin_server_admin/model/location/abnormal_people.go
  13. 2
      gin_server_admin/model/locationing/reportAddress.go
  14. 12
      gin_server_admin/router/enter.go
  15. 2
      gin_server_admin/router/examtestpage/healthreporthandle.go
  16. 5
      gin_server_admin/router/wechatcallbackrouter/enter.go
  17. 19
      gin_server_admin/router/wechatcallbackrouter/wechatcallbackhandle.go
  18. 313
      gin_server_admin/wechatjiexi/wxbizjsonmsgcrypt/wxbizjsonmsgcrypt.go
  19. 315
      gin_server_admin/wechatjiexi/wxbizmsgcrypt/wxbizmsgcrypt.go

2
gin_server_admin/api/v1/enter.go

@ -6,6 +6,7 @@ import (
"github.com/flipped-aurora/gin-vue-admin/server/api/v1/examtestpage"
"github.com/flipped-aurora/gin-vue-admin/server/api/v1/shiyan"
"github.com/flipped-aurora/gin-vue-admin/server/api/v1/system"
"github.com/flipped-aurora/gin-vue-admin/server/api/v1/wechatcallback"
)
type ApiGroup struct {
@ -14,6 +15,7 @@ type ApiGroup struct {
AutoCodeApiGroup autocode.ApiGroup
ShiyanApiGroup shiyan.ApiGroup
GroupHandleApiGroup examtestpage.ApiGroup
WeCahtCallBackGroup wechatcallback.ApiGroup
}
var ApiGroupApp = new(ApiGroup)

19
gin_server_admin/api/v1/examtestpage/healthreportstat.go

@ -249,7 +249,7 @@ func (h *HealthReportStat) PostReportAnswerListAll(c *gin.Context) {
returData["baojinglist"] = readBaoJinf
//计算未上报人员
CalculationNotReport(tadayTime, calCulTime, readDataMap)
// CalculationNotReport(tadayTime, calCulTime, readDataMap)
//判断报警人是不是超员
if len(readBaoJinf) > 0 {
//给相关人员发送信息
@ -341,7 +341,7 @@ func (d *dataLockStatistics) getUserAnswerList(jobid, tadayTime string, page int
d.mutext.Lock()
defer d.mutext.Unlock()
calCulTime := tadayTime + " 12:00:00"
fmt.Printf("page ------------> %v\n", page)
// fmt.Printf("page ------------> %v\n", page)
// timeStamp := commonus.DateToTimeStamp(calCulTime)
// var judgeWriteInfoUser locationing.ReportAddress
// getReportAddressErr := global.GVA_DB_HealthReport.Where("calcultime = ?", timeStamp).Take(&judgeWriteInfoUser).Error
@ -358,13 +358,16 @@ func (d *dataLockStatistics) getUserAnswerList(jobid, tadayTime string, page int
AdmDivMap := commonus.MapOut()
// writeInfoUser.Address = string(msgBtye)
countSplit := strings.Split(v_sun.Text, "省")
xieRuBaoJong := false
var groupIdCont int64
groupIdCont = 0
if len(countSplit) >= 2 {
writeInfoUser.WechatId = v.Userid
writeInfoUser.Userid = v.Userid
writeInfoUser.AddTime = time.Now().Unix()
writeInfoUser.Address = v_sun.Text
AdmDivMap["riskLevel"] = 0
writeInfoUser.RiskLevel = 0
writeInfoUser.CalCulTime = commonus.DateToTimeStamp(calCulTime)
@ -393,6 +396,9 @@ func (d *dataLockStatistics) getUserAnswerList(jobid, tadayTime string, page int
if riskAre.CityName == countSplitSun[0] {
writeInfoUser.RiskLevel = riskAre.RiskLevel
AdmDivMap["riskLevel"] = riskAre.RiskLevel
// commonus.WriteInMan(v.Userid)
xieRuBaoJong = true
}
}
}
@ -409,6 +415,8 @@ func (d *dataLockStatistics) getUserAnswerList(jobid, tadayTime string, page int
writeInfoUser.RiskLevel = riskAre.RiskLevel
writeInfoUser.RiskLevel = riskAre.RiskLevel
AdmDivMap["riskLevel"] = riskAre.RiskLevel
// commonus.WriteInMan(v.Userid)
xieRuBaoJong = true
}
}
}
@ -470,12 +478,14 @@ func (d *dataLockStatistics) getUserAnswerList(jobid, tadayTime string, page int
if len(arrAy) >= 2 {
if arrAy[0] == 1 {
writeInfoUser.GroupId = arrAy[1]
groupIdCont = arrAy[1]
isTrues, myDepartments := commonus.GetGroupInfo(arrAy[1])
if isTrues == true {
writeInfoUser.GroupName = fmt.Sprintf("%s", myDepartments.Name)
}
} else {
writeInfoUser.GroupId = arrAy[0]
groupIdCont = arrAy[0]
isTrues, myDepartments := commonus.GetGroupInfo(arrAy[0])
if isTrues == true {
writeInfoUser.GroupName = fmt.Sprintf("%s", myDepartments.Name)
@ -484,6 +494,9 @@ func (d *dataLockStatistics) getUserAnswerList(jobid, tadayTime string, page int
}
}
}
if xieRuBaoJong == true {
commonus.WriteInMan(v.Userid, calCulTime, groupIdCont)
}
// writeInfoUser.MainDepartment =
AdmDivStruct = append(AdmDivStruct, AdmDiv)
d.dataMap = append(d.dataMap, AdmDivMap)

85
gin_server_admin/api/v1/examtestpage/healthreportstathand.go

@ -10,6 +10,7 @@ import (
"github.com/flipped-aurora/gin-vue-admin/server/commonus"
"github.com/flipped-aurora/gin-vue-admin/server/global"
"github.com/flipped-aurora/gin-vue-admin/server/model/common/response"
"github.com/flipped-aurora/gin-vue-admin/server/model/location"
"github.com/flipped-aurora/gin-vue-admin/server/model/locationing"
"github.com/flipped-aurora/gin-vue-admin/server/model/wechat"
"github.com/gin-gonic/gin"
@ -438,82 +439,8 @@ func (h *HealthReportStat) NotReportedPeople(c *gin.Context) {
//获取全国风险地区列表(企鹅接口 https://view.inews.qq.com/g2/getOnsInfo?name=disease_h5)
func (h *HealthReportStat) NationalRiskArea(c *gin.Context) {
// nationalRiskArea := commonus.NationalRiskArea()
// var tencentJsonData commonus.TencentJsonData
// jsonErr := json.Unmarshal(nationalRiskArea, &tencentJsonData)
// if jsonErr != nil {
// response.Result(101, jsonErr, "未能全国风险地区数据!", c)
// return
// }
// var DataJSonTencent commonus.DataJSonTencent
// zhuanyi := json.RawMessage(tencentJsonData.Data)
// jsonErrs := json.Unmarshal(zhuanyi, &DataJSonTencent)
// if jsonErrs != nil {
// response.Result(102, zhuanyi, "未能全国风险地区数据!", c)
// return
// }
// var regionalRiskAry []commonus.RegionalRiskLevel
// for _, chinaAry := range DataJSonTencent.AreaTree { //国家级
// for _, provinceAry := range chinaAry.Children { //省级
// for _, cityAry := range provinceAry.Children { //市级
// var regionalRisk commonus.RegionalRiskLevel
// regionalRisk.ProvinceName = provinceAry.Name
// regionalRisk.CityName = cityAry.Name
// regionalRisk.RiskText = cityAry.Total.Grade
// countSplit := strings.Split(cityAry.Total.Grade, "中高")
// regionalRisk.Province = int64(len(countSplit))
// //0:无;1:低风险;2:中低风险;3:中风险;4:中高风险;5:高风险
// if len(countSplit) >= 2 {
// regionalRisk.RiskLevel = 4
// } else {
// countSplits := strings.Split(cityAry.Total.Grade, "中低")
// regionalRisk.City = int64(len(countSplits))
// if len(countSplits) >= 2 {
// regionalRisk.RiskLevel = 2
// } else {
// countSplitcont := strings.Split(cityAry.Total.Grade, "中")
// regionalRisk.County = int64(len(countSplitcont))
// if len(countSplitcont) >= 2 {
// regionalRisk.RiskLevel = 3
// } else {
// countSpliHigh := strings.Split(cityAry.Total.Grade, "高")
// regionalRisk.County = int64(len(countSpliHigh))
// if len(countSpliHigh) >= 2 {
// regionalRisk.RiskLevel = 5
// }
// countSpliLown := strings.Split(cityAry.Total.Grade, "低")
// regionalRisk.County = int64(len(countSpliLown))
// if len(countSpliLown) >= 2 {
// regionalRisk.RiskLevel = 1
// }
// }
// }
// }
// regionalRiskAry = append(regionalRiskAry, regionalRisk)
// // fmt.Printf("%v\n", cityAry.Name)
// }
// }
// }
// regionalRiskJson, regionalRiskjsonErr := json.Marshal(regionalRiskAry)
// if regionalRiskjsonErr == nil {
// }
jsondata, isyes := commonus.GetNationalRiskArea()
returnData := commonus.MapOut()
// var chianMap commonus.DataJSonTencent
// for i, v := range zhuanyi {
// fmt.Printf("%v---------------->%v\n", i, string(v))
// }
// returnData["jsonStr"] = string(tencentJsonData.Data)
// returnData["DataJSonTencent"] = DataJSonTencent
// returnData["china"] = DataJSonTencent.AreaTree
// returnData["regionalRiskAry"] = regionalRiskAry
// returnData["regionalRiskJson"] = string(regionalRiskJson)
// returnData["zhuanyi"] = zhuanyi
returnData["isyes"] = isyes
returnData["jsondata"] = jsondata
@ -521,3 +448,13 @@ func (h *HealthReportStat) NationalRiskArea(c *gin.Context) {
response.Result(0, returnData, "全国风险地区列表!", c)
}
//测试写入异常人员
func (h *HealthReportStat) TestMan(c *gin.Context) {
var reportAnswer location.AbnormalPeople
c.ShouldBindJSON(&reportAnswer)
commonus.WriteInMan(reportAnswer.WechatId, "2021-12-04", 1)
returnData := commonus.MapOut()
returnData["isyes"] = reportAnswer
response.Result(0, returnData, "全国风险地区列表!", c)
}

5
gin_server_admin/api/v1/wechatcallback/enter.go

@ -0,0 +1,5 @@
package wechatcallback
type ApiGroup struct {
WeChatCallBackApi
}

31
gin_server_admin/api/v1/wechatcallback/wechatcallbackmain.go

@ -0,0 +1,31 @@
package wechatcallback
import (
"github.com/flipped-aurora/gin-vue-admin/server/model/common/response"
"github.com/flipped-aurora/gin-vue-admin/server/wechatjiexi/wxbizmsgcrypt"
"github.com/gin-gonic/gin"
)
type WeChatCallBackApi struct{}
type MsgContent struct {
ToUsername string `xml:"ToUserName"`
FromUsername string `xml:"FromUserName"`
CreateTime uint32 `xml:"CreateTime"`
MsgType string `xml:"MsgType"`
Content string `xml:"Content"`
Msgid string `xml:"MsgId"`
Agentid uint32 `xml:"AgentId"`
}
//回调首页
func (w *WeChatCallBackApi) Index(c *gin.Context) {
token := "QDG6eK"
receiverId := "wx5823bf96d3bd56c7"
encodingAeskey := "jWmYm7qr5nMoAUwZRjGtBxmz3KA1tkAj3ykkR6q2B2C"
wxcpt := wxbizmsgcrypt.NewWXBizMsgCrypt(token, encodingAeskey, receiverId, wxbizmsgcrypt.XmlType)
response.Result(0, wxcpt, "获取成功", c)
}

60
gin_server_admin/commonus/publichaneld.go

@ -8,6 +8,7 @@ import (
"time"
"github.com/flipped-aurora/gin-vue-admin/server/global"
"github.com/flipped-aurora/gin-vue-admin/server/model/location"
"github.com/flipped-aurora/gin-vue-admin/server/model/testpage"
"github.com/flipped-aurora/gin-vue-admin/server/model/wechat"
"github.com/flipped-aurora/gin-vue-admin/server/utils/redishandel"
@ -54,13 +55,30 @@ func BubbleSort(slice []int64) []int64 {
//获取公司,分厂,工段
func GetGroupInfo(id int64) (isTrue bool, groupStruct wechat.GroupForm) {
isTrue = false
var groupStructs wechat.GroupForm //集团表结构
err := global.GVA_DB_WatchDate.Where("g_id = ?", id).First(&groupStruct).Error //获取集团信息
if err != nil {
groupStruct, isTrue = AddWechatGroup(id, groupStructs)
return
redisClient := redishandel.RunRedis()
isTrues, tokenInfo := redisClient.Get("organStructure:group_" + global.GVA_CONFIG.RedisPrefix.Alias + "_" + strconv.FormatInt(id, 10))
if isTrues == true {
jsonUserList := json.Unmarshal([]byte(tokenInfo), &groupStruct)
if jsonUserList != nil {
return
}
isTrue = true
} else {
var groupStructs wechat.GroupForm //集团表结构
err := global.GVA_DB_WatchDate.Where("g_id = ?", id).First(&groupStruct).Error //获取集团信息
if err != nil {
groupStruct, isTrue = AddWechatGroup(id, groupStructs)
return
}
jsonUserList, jsonErr := json.Marshal(groupStruct)
if jsonErr != nil {
return
}
redisClient.SetRedisTime(604800)
redisClient.Set("organStructure:group_"+global.GVA_CONFIG.RedisPrefix.Alias+"_"+strconv.FormatInt(id, 10), string(jsonUserList))
isTrue = true
}
isTrue = true
// groupInfo["name"] = groupStruct.Name
return
}
@ -431,6 +449,7 @@ func GetNationalRiskArea() (riskAreaCityList []RegionalRiskLevel, isTrue bool) {
regionalRisk.ProvinceName = provinceAry.Name
regionalRisk.CityName = cityAry.Name
regionalRisk.RiskText = cityAry.Total.Grade
regionalRisk.RiskLevel = 0
//切分数据结果,判断风险等级
countSplit := strings.Split(cityAry.Total.Grade, "中高")
regionalRisk.Province = int64(len(countSplit))
@ -484,3 +503,32 @@ func GetNationalRiskArea() (riskAreaCityList []RegionalRiskLevel, isTrue bool) {
}
return
}
//写入异常人员列表
func WriteInMan(wechat, calCulTime string, groupId int64) {
if wechat == "" {
return
}
timeVal := time.Now().Unix() - 86400
if calCulTime != "" {
timeVals, errTime := DateToTimeStampEs(calCulTime)
if errTime == true {
timeVal = timeVals
}
}
var abn location.AbnormalPeople
abnErr := global.GVA_DB_HealthReport.Where("abn_wechat_id = ?", wechat).First(&abn).Error
if abnErr != nil {
abn.WechatId = wechat
abn.GroupId = groupId
abn.Time = timeVal
global.GVA_DB_HealthReport.Create(&abn)
// fmt.Printf("Add -----> %v ------>%v\n", abnErr, abn)
} else {
abn.GroupId = groupId
abn.Time = timeVal
global.GVA_DB_HealthReport.Save(&abn)
// fmt.Printf("Eite -----> %v ------>%v\n", abnErr, abn)
}
}

11
gin_server_admin/commonus/timeSub.go

@ -115,6 +115,17 @@ func DateToTimeStamp(dataStr string) (timeStamp int64) {
return
}
func DateToTimeStampEs(dataStr string) (timeStamp int64, isTrue bool) {
isTrue = false
tmp := "2006-01-02 15:04:05"
res, err := time.ParseInLocation(tmp, dataStr, time.Local)
timeStamp = res.Unix()
if err == nil {
isTrue = true
}
return
}
/*
时间戳转日期
*/

2
gin_server_admin/commonus/wechatapp.go

@ -579,7 +579,7 @@ func GetUserWriteAnswer(jobid, date string, page int, pageSize int64) (btyDate [
}
addDePartMent := CurlPostJosn(getWechatApiUrl, sendJsonData)
btyDate = addDePartMent
fmt.Printf("结果---->%v\n", string(addDePartMent))
var reportAnswerJson ReportAnswerResult
err = json.Unmarshal(addDePartMent, &reportAnswerJson)
r = &reportAnswerJson

9
gin_server_admin/config.yaml

@ -273,6 +273,8 @@ workwechatschool: #知行学院
workwechatappmaillist: #通讯录
secretstr: 'yjcQXkh6_116QKjfZfbRSyzdrFFZ9jbVlKJtL2tn3OU'
token: ''
encodingaeskey: ''
healthreport: #健康上报
secretstr: 'smjpGmFo5wp18BZGiLaECFr84Blv429v_GFdKp4_0YQ'
@ -287,6 +289,13 @@ workwechatschools: #测试
workwechatappmaillists: #通讯录
secretstr: 'TSSsJXiqh3RKl0NYIoB-sPc43MUIRJ1ppALWtzyLY94'
token: ''
encodingaeskey: ''
healthreports: #健康上报
secretstr: 'smjpGmFo5wp18BZGiLaECFr84Blv429v_GFdKp4_0YQ'

4
gin_server_admin/config/wechat.go

@ -15,5 +15,7 @@ type workWechatApplication struct {
//企业微信内置应用
type workWechatSecret struct {
SecretStr string `json:secretstr` //应用Secret
SecretStr string `json:secretstr` //应用Secret
Token string `json:Token` //应用Secret
EncodingAESKey string `json:EncodingAESKey` //应用Secret
}

7
gin_server_admin/initialize/router.go

@ -44,8 +44,13 @@ func Routers() *gin.Engine {
groupHandleRouter := router.RouterGroupApp.GroupHandle
weChatCallBaclRouter := router.RouterGroupApp.WeChatCallBacl
PublicGroup := Router.Group("")
{
PublicGroup.GET("/", func(c *gin.Context) {
c.JSON(0, "is ok")
})
// 健康监测
PublicGroup.GET("/health", func(c *gin.Context) {
c.JSON(200, "ok")
@ -60,6 +65,8 @@ func Routers() *gin.Engine {
groupHandleRouter.InitGroupRouter(PublicGroup) //集团架构
shiyanRouter.InitShiyanRouter(PublicGroup) // 实验路由
weChatCallBaclRouter.InitGroupRouter(PublicGroup) // 微信回调
}
PrivateGroup := Router.Group("")
PrivateGroup.Use(middleware.JWTAuth()).Use(middleware.CasbinHandler())

12
gin_server_admin/model/location/abnormal_people.go

@ -0,0 +1,12 @@
package location
type AbnormalPeople struct {
Id int64 `json:"id" gorm:"column:abn_id;type:bigint(20);;primaryKey;unique;not null;autoIncrement;index"`
WechatId string `json:"wechatid" gorm:"column:abn_wechat_id;type:varchar(50);not null;comment:微信id"`
Time int64 `json:"time" gorm:"column:abn_time;type:bigint(20) unsigned;default:0;not null;comment:异常开始时间"` //'异常开始时间',
GroupId int64 `json:"groupId" gorm:"column:abn_group;type:bigint(20) unsigned;default:1;not null;comment:组织"` //'组织',
}
func (AbnormalPeople *AbnormalPeople) TableName() string {
return "abnormal_people"
}

2
gin_server_admin/model/locationing/reportAddress.go

@ -17,7 +17,7 @@ type ReportAddress struct {
MainDepartment int64 `json:"main_department" gorm:"column:main_department;type:bigint(20) unsigned;default:0;not null;comment:主部门"` //'主部门',
GroupName string `json:"groupName" gorm:"column:group_name;type:varchar(255);comment:集团名称"` //'集团名称',
GroupId int64 `json:"groupId" gorm:"column:group_id;type:bigint(20) unsigned;default:1;not null;comment:集团id"` //'集团id',
RiskLevel int `json:"riskLevel" gorm:"column:risk_level;type:int(3) unsigned;default:1;not null;comment:风险等级"` //'风险等级',
RiskLevel int `json:"riskLevel" gorm:"column:risk_level;type:int(3) unsigned;default:0;not null;comment:风险等级"` //'风险等级',
}
func (ReportAddress *ReportAddress) TableName() string {

12
gin_server_admin/router/enter.go

@ -6,14 +6,16 @@ import (
"github.com/flipped-aurora/gin-vue-admin/server/router/examtestpage"
"github.com/flipped-aurora/gin-vue-admin/server/router/shiyan"
"github.com/flipped-aurora/gin-vue-admin/server/router/system"
"github.com/flipped-aurora/gin-vue-admin/server/router/wechatcallbackrouter"
)
type RouterGroup struct {
System system.RouterGroup
Example example.RouterGroup
Autocode autocode.RouterGroup
Shiyan shiyan.RouterGroup
GroupHandle examtestpage.RouterGroup
System system.RouterGroup
Example example.RouterGroup
Autocode autocode.RouterGroup
Shiyan shiyan.RouterGroup
GroupHandle examtestpage.RouterGroup
WeChatCallBacl wechatcallbackrouter.RouterGroup
}
var RouterGroupApp = new(RouterGroup)

2
gin_server_admin/router/examtestpage/healthreporthandle.go

@ -34,6 +34,8 @@ func (g *GroupHandleRouter) InitHealthReporRouter(Router *gin.RouterGroup) (R gi
groupCodeRouter.POST("/nationalriskarea", authorityApi.NationalRiskArea) //全国异常地区
groupCodeRouter.POST("/testman", authorityApi.TestMan) //测试
}
return groupCodeRouter
}

5
gin_server_admin/router/wechatcallbackrouter/enter.go

@ -0,0 +1,5 @@
package wechatcallbackrouter
type RouterGroup struct {
WeChatCallBackRoute
}

19
gin_server_admin/router/wechatcallbackrouter/wechatcallbackhandle.go

@ -0,0 +1,19 @@
package wechatcallbackrouter
import (
v1 "github.com/flipped-aurora/gin-vue-admin/server/api/v1"
"github.com/gin-gonic/gin"
)
type WeChatCallBackRoute struct{}
func (g *WeChatCallBackRoute) InitGroupRouter(Router *gin.RouterGroup) {
groupCodeRouter := Router.Group("wechatcallback")
var authorityApi = v1.ApiGroupApp.WeCahtCallBackGroup.WeChatCallBackApi
{
groupCodeRouter.POST("", authorityApi.Index)
groupCodeRouter.POST("/", authorityApi.Index)
groupCodeRouter.GET("/", authorityApi.Index)
}
}

313
gin_server_admin/wechatjiexi/wxbizjsonmsgcrypt/wxbizjsonmsgcrypt.go

@ -0,0 +1,313 @@
package wxbizjsonmsgcrypt
import(
"crypto/sha1"
"crypto/aes"
"crypto/cipher"
"bytes"
"strings"
"fmt"
"sort"
"encoding/base64"
"math/rand"
"encoding/binary"
"encoding/json"
)
const letterBytes = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
const (
ValidateSignatureError int = -40001
ParseJsonError int = -40002
ComputeSignatureError int = -40003
IllegalAesKey int = -40004
ValidateCorpidError int = -40005
EncryptAESError int = -40006
DecryptAESError int = -40007
IllegalBuffer int = -40008
EncodeBase64Error int = -40009
DecodeBase64Error int = -40010
GenJsonError int = -40011
IllegalProtocolType int = -40012
)
type ProtocolType int
const (
JsonType ProtocolType = 1
)
type CryptError struct{
ErrCode int
ErrMsg string
}
func NewCryptError(err_code int, err_msg string) * CryptError{
return &CryptError{ErrCode:err_code, ErrMsg: err_msg}
}
type WXBizJsonMsg4Recv struct {
Tousername string `json:"tousername"`
Encrypt string `json:"encrypt"`
Agentid string `json:"agentid"`
}
type WXBizJsonMsg4Send struct {
Encrypt string `json:"encrypt"`
Signature string `json:"msgsignature"`
Timestamp string `json:"timestamp"`
Nonce string `json:"nonce"`
}
func NewWXBizJsonMsg4Send(encrypt, signature, timestamp, nonce string) * WXBizJsonMsg4Send {
return &WXBizJsonMsg4Send{Encrypt:encrypt, Signature:signature, Timestamp:timestamp, Nonce:nonce}
}
type ProtocolProcessor interface {
parse(src_data []byte) (* WXBizJsonMsg4Recv, * CryptError)
serialize(msg_send * WXBizJsonMsg4Send) ([]byte, * CryptError)
}
type WXBizMsgCrypt struct{
token string
encoding_aeskey string
receiver_id string
protocol_processor ProtocolProcessor
}
type JsonProcessor struct{
}
func (self * JsonProcessor) parse(src_data []byte) (* WXBizJsonMsg4Recv, * CryptError) {
var msg4_recv WXBizJsonMsg4Recv
err := json.Unmarshal(src_data, &msg4_recv)
if nil != err {
fmt.Println("Unmarshal fail", err)
return nil, NewCryptError(ParseJsonError, "json to msg fail")
}
return &msg4_recv, nil
}
func (self * JsonProcessor) serialize(msg4_send * WXBizJsonMsg4Send) ([]byte, * CryptError){
json_msg, err := json.Marshal(msg4_send)
if nil != err {
return nil, NewCryptError(GenJsonError, err.Error())
}
return json_msg, nil
}
func NewWXBizMsgCrypt(token, encoding_aeskey, receiver_id string, protocol_type ProtocolType) * WXBizMsgCrypt{
var protocol_processor ProtocolProcessor
if protocol_type != JsonType {
panic("unsupport protocal")
} else {
protocol_processor = new(JsonProcessor)
}
return &WXBizMsgCrypt{token:token, encoding_aeskey:(encoding_aeskey+"="), receiver_id:receiver_id, protocol_processor:protocol_processor}
}
func (self * WXBizMsgCrypt) randString(n int) string {
b := make([]byte, n)
for i := range b {
b[i] = letterBytes[rand.Int63() % int64(len(letterBytes))]
}
return string(b)
}
func (self * WXBizMsgCrypt) pKCS7Padding(plaintext string, block_size int) []byte {
padding := block_size- (len(plaintext) % block_size)
padtext := bytes.Repeat([]byte{byte(padding)}, padding)
var buffer bytes.Buffer
buffer.WriteString(plaintext)
buffer.Write(padtext)
return buffer.Bytes()
}
func (self * WXBizMsgCrypt) pKCS7Unpadding(plaintext []byte, block_size int) ([]byte, * CryptError) {
plaintext_len := len(plaintext)
if nil == plaintext || plaintext_len == 0 {
return nil, NewCryptError(DecryptAESError, "pKCS7Unpadding error nil or zero")
}
if plaintext_len % block_size != 0 {
return nil, NewCryptError(DecryptAESError, "pKCS7Unpadding text not a multiple of the block size")
}
padding_len := int(plaintext[plaintext_len - 1])
return plaintext[:plaintext_len - padding_len], nil
}
func (self * WXBizMsgCrypt) cbcEncrypter(plaintext string) ([]byte, * CryptError) {
aeskey, err := base64.StdEncoding.DecodeString(self.encoding_aeskey)
if nil != err {
return nil, NewCryptError(DecodeBase64Error, err.Error())
}
const block_size = 32
pad_msg := self.pKCS7Padding(plaintext, block_size)
block, err := aes.NewCipher(aeskey)
if err != nil {
return nil, NewCryptError(EncryptAESError, err.Error())
}
ciphertext := make([]byte, len(pad_msg))
iv := aeskey[:aes.BlockSize]
mode := cipher.NewCBCEncrypter(block, iv)
mode.CryptBlocks(ciphertext, pad_msg)
base64_msg := make([]byte, base64.StdEncoding.EncodedLen(len(ciphertext)))
base64.StdEncoding.Encode(base64_msg, ciphertext)
return base64_msg, nil
}
func (self * WXBizMsgCrypt) cbcDecrypter(base64_encrypt_msg string) ([]byte, * CryptError){
aeskey, err := base64.StdEncoding.DecodeString(self.encoding_aeskey)
if nil != err {
return nil, NewCryptError(DecodeBase64Error, err.Error())
}
encrypt_msg, err := base64.StdEncoding.DecodeString(base64_encrypt_msg)
if nil != err {
return nil, NewCryptError(DecodeBase64Error, err.Error())
}
block, err := aes.NewCipher(aeskey)
if err != nil {
return nil, NewCryptError(DecryptAESError, err.Error())
}
if len(encrypt_msg) < aes.BlockSize {
return nil, NewCryptError(DecryptAESError, "encrypt_msg size is not valid")
}
iv := aeskey[:aes.BlockSize]
if len(encrypt_msg) % aes.BlockSize != 0 {
return nil, NewCryptError(DecryptAESError, "encrypt_msg not a multiple of the block size")
}
mode := cipher.NewCBCDecrypter(block, iv)
mode.CryptBlocks(encrypt_msg, encrypt_msg)
return encrypt_msg, nil
}
func (self * WXBizMsgCrypt) calSignature(timestamp, nonce, data string) string{
sort_arr := []string{self.token, timestamp, nonce, data}
sort.Strings(sort_arr);
var buffer bytes.Buffer
for _, value := range sort_arr {
buffer.WriteString(value)
}
sha := sha1.New()
sha.Write(buffer.Bytes())
signature := fmt.Sprintf("%x", sha.Sum(nil))
return string(signature)
}
func (self * WXBizMsgCrypt) ParsePlainText(plaintext[]byte)([]byte, uint32, []byte, []byte, * CryptError){
const block_size = 32
plaintext, err := self.pKCS7Unpadding(plaintext, block_size)
if nil != err {
return nil, 0, nil, nil, err
}
text_len := uint32(len(plaintext))
if text_len < 20 {
return nil, 0, nil, nil, NewCryptError(IllegalBuffer, "plain is to small 1")
}
random := plaintext[:16]
msg_len := binary.BigEndian.Uint32(plaintext[16:20])
if text_len < (20 + msg_len) {
return nil, 0, nil, nil, NewCryptError(IllegalBuffer, "plain is to small 2")
}
msg := plaintext[20: 20 + msg_len]
receiver_id := plaintext[20+msg_len:]
return random, msg_len, msg, receiver_id, nil
}
func (self * WXBizMsgCrypt) VerifyURL(msg_signature, timestamp, nonce, echostr string) ([]byte, * CryptError){
signature := self.calSignature(timestamp, nonce, echostr)
if strings.Compare(signature, msg_signature) != 0{
return nil, NewCryptError(ValidateSignatureError, "signature not equal")
}
plaintext, err := self.cbcDecrypter(echostr)
if nil != err {
return nil, err
}
_, _, msg, receiver_id, err := self.ParsePlainText(plaintext)
if nil != err {
return nil, err
}
if len(self.receiver_id) > 0 && strings.Compare(string(receiver_id), self.receiver_id) != 0 {
fmt.Println(string(receiver_id), self.receiver_id, len(receiver_id), len(self.receiver_id))
return nil, NewCryptError(ValidateCorpidError, "receiver_id is not equil")
}
return msg, nil
}
func (self * WXBizMsgCrypt) EncryptMsg(reply_msg, timestamp, nonce string) ([]byte, * CryptError){
rand_str := self.randString(16)
var buffer bytes.Buffer
buffer.WriteString(rand_str)
msg_len_buf := make([]byte, 4)
binary.BigEndian.PutUint32(msg_len_buf, uint32(len(reply_msg)))
buffer.Write(msg_len_buf)
buffer.WriteString(reply_msg);
buffer.WriteString(self.receiver_id);
tmp_ciphertext, err := self.cbcEncrypter(buffer.String());
if nil != err {
return nil, err
}
ciphertext := string(tmp_ciphertext)
signature := self.calSignature(timestamp, nonce, ciphertext)
msg4_send := NewWXBizJsonMsg4Send(ciphertext, signature, timestamp, nonce)
return self.protocol_processor.serialize(msg4_send)
}
func (self * WXBizMsgCrypt) DecryptMsg(msg_signature, timestamp, nonce string, post_data []byte) ([]byte, * CryptError){
msg4_recv, crypt_err := self.protocol_processor.parse(post_data)
if nil != crypt_err {
return nil, crypt_err
}
signature := self.calSignature(timestamp, nonce, msg4_recv.Encrypt)
if strings.Compare(signature, msg_signature) != 0{
return nil, NewCryptError(ValidateSignatureError, "signature not equal")
}
plaintext, crypt_err := self.cbcDecrypter(msg4_recv.Encrypt)
if nil != crypt_err {
return nil, crypt_err
}
_, _, msg, receiver_id, crypt_err := self.ParsePlainText(plaintext)
if nil != crypt_err {
return nil, crypt_err
}
if len(self.receiver_id) > 0 && strings.Compare(string(receiver_id), self.receiver_id) != 0 {
return nil, NewCryptError(ValidateCorpidError, "receiver_id is not equil")
}
return msg, nil
}

315
gin_server_admin/wechatjiexi/wxbizmsgcrypt/wxbizmsgcrypt.go

@ -0,0 +1,315 @@
package wxbizmsgcrypt
import (
"bytes"
"crypto/aes"
"crypto/cipher"
"crypto/sha1"
"encoding/base64"
"encoding/binary"
"encoding/xml"
"fmt"
"math/rand"
"sort"
"strings"
)
const letterBytes = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
const (
ValidateSignatureError int = -40001
ParseXmlError int = -40002
ComputeSignatureError int = -40003
IllegalAesKey int = -40004
ValidateCorpidError int = -40005
EncryptAESError int = -40006
DecryptAESError int = -40007
IllegalBuffer int = -40008
EncodeBase64Error int = -40009
DecodeBase64Error int = -40010
GenXmlError int = -40010
ParseJsonError int = -40012
GenJsonError int = -40013
IllegalProtocolType int = -40014
)
type ProtocolType int
const (
XmlType ProtocolType = 1
)
type CryptError struct {
ErrCode int
ErrMsg string
}
func NewCryptError(err_code int, err_msg string) *CryptError {
return &CryptError{ErrCode: err_code, ErrMsg: err_msg}
}
type WXBizMsg4Recv struct {
Tousername string `xml:"ToUserName"`
Encrypt string `xml:"Encrypt"`
Agentid string `xml:"AgentID"`
}
type CDATA struct {
Value string `xml:",cdata"`
}
type WXBizMsg4Send struct {
XMLName xml.Name `xml:"xml"`
Encrypt CDATA `xml:"Encrypt"`
Signature CDATA `xml:"MsgSignature"`
Timestamp string `xml:"TimeStamp"`
Nonce CDATA `xml:"Nonce"`
}
func NewWXBizMsg4Send(encrypt, signature, timestamp, nonce string) *WXBizMsg4Send {
return &WXBizMsg4Send{Encrypt: CDATA{Value: encrypt}, Signature: CDATA{Value: signature}, Timestamp: timestamp, Nonce: CDATA{Value: nonce}}
}
type ProtocolProcessor interface {
parse(src_data []byte) (*WXBizMsg4Recv, *CryptError)
serialize(msg_send *WXBizMsg4Send) ([]byte, *CryptError)
}
type WXBizMsgCrypt struct {
token string
encoding_aeskey string
receiver_id string
protocol_processor ProtocolProcessor
}
type XmlProcessor struct {
}
func (self *XmlProcessor) parse(src_data []byte) (*WXBizMsg4Recv, *CryptError) {
var msg4_recv WXBizMsg4Recv
err := xml.Unmarshal(src_data, &msg4_recv)
if nil != err {
return nil, NewCryptError(ParseXmlError, "xml to msg fail")
}
return &msg4_recv, nil
}
func (self *XmlProcessor) serialize(msg4_send *WXBizMsg4Send) ([]byte, *CryptError) {
xml_msg, err := xml.Marshal(msg4_send)
if nil != err {
return nil, NewCryptError(GenXmlError, err.Error())
}
return xml_msg, nil
}
func NewWXBizMsgCrypt(token, encoding_aeskey, receiver_id string, protocol_type ProtocolType) *WXBizMsgCrypt {
var protocol_processor ProtocolProcessor
if protocol_type != XmlType {
panic("unsupport protocal")
} else {
protocol_processor = new(XmlProcessor)
}
return &WXBizMsgCrypt{token: token, encoding_aeskey: (encoding_aeskey + "="), receiver_id: receiver_id, protocol_processor: protocol_processor}
}
func (self *WXBizMsgCrypt) randString(n int) string {
b := make([]byte, n)
for i := range b {
b[i] = letterBytes[rand.Int63()%int64(len(letterBytes))]
}
return string(b)
}
func (self *WXBizMsgCrypt) pKCS7Padding(plaintext string, block_size int) []byte {
padding := block_size - (len(plaintext) % block_size)
padtext := bytes.Repeat([]byte{byte(padding)}, padding)
var buffer bytes.Buffer
buffer.WriteString(plaintext)
buffer.Write(padtext)
return buffer.Bytes()
}
func (self *WXBizMsgCrypt) pKCS7Unpadding(plaintext []byte, block_size int) ([]byte, *CryptError) {
plaintext_len := len(plaintext)
if nil == plaintext || plaintext_len == 0 {
return nil, NewCryptError(DecryptAESError, "pKCS7Unpadding error nil or zero")
}
if plaintext_len%block_size != 0 {
return nil, NewCryptError(DecryptAESError, "pKCS7Unpadding text not a multiple of the block size")
}
padding_len := int(plaintext[plaintext_len-1])
return plaintext[:plaintext_len-padding_len], nil
}
func (self *WXBizMsgCrypt) cbcEncrypter(plaintext string) ([]byte, *CryptError) {
aeskey, err := base64.StdEncoding.DecodeString(self.encoding_aeskey)
if nil != err {
return nil, NewCryptError(DecodeBase64Error, err.Error())
}
const block_size = 32
pad_msg := self.pKCS7Padding(plaintext, block_size)
block, err := aes.NewCipher(aeskey)
if err != nil {
return nil, NewCryptError(EncryptAESError, err.Error())
}
ciphertext := make([]byte, len(pad_msg))
iv := aeskey[:aes.BlockSize]
mode := cipher.NewCBCEncrypter(block, iv)
mode.CryptBlocks(ciphertext, pad_msg)
base64_msg := make([]byte, base64.StdEncoding.EncodedLen(len(ciphertext)))
base64.StdEncoding.Encode(base64_msg, ciphertext)
return base64_msg, nil
}
func (self *WXBizMsgCrypt) cbcDecrypter(base64_encrypt_msg string) ([]byte, *CryptError) {
aeskey, err := base64.StdEncoding.DecodeString(self.encoding_aeskey)
if nil != err {
return nil, NewCryptError(DecodeBase64Error, err.Error())
}
encrypt_msg, err := base64.StdEncoding.DecodeString(base64_encrypt_msg)
if nil != err {
return nil, NewCryptError(DecodeBase64Error, err.Error())
}
block, err := aes.NewCipher(aeskey)
if err != nil {
return nil, NewCryptError(DecryptAESError, err.Error())
}
if len(encrypt_msg) < aes.BlockSize {
return nil, NewCryptError(DecryptAESError, "encrypt_msg size is not valid")
}
iv := aeskey[:aes.BlockSize]
if len(encrypt_msg)%aes.BlockSize != 0 {
return nil, NewCryptError(DecryptAESError, "encrypt_msg not a multiple of the block size")
}
mode := cipher.NewCBCDecrypter(block, iv)
mode.CryptBlocks(encrypt_msg, encrypt_msg)
return encrypt_msg, nil
}
func (self *WXBizMsgCrypt) calSignature(timestamp, nonce, data string) string {
sort_arr := []string{self.token, timestamp, nonce, data}
sort.Strings(sort_arr)
var buffer bytes.Buffer
for _, value := range sort_arr {
buffer.WriteString(value)
}
sha := sha1.New()
sha.Write(buffer.Bytes())
signature := fmt.Sprintf("%x", sha.Sum(nil))
return string(signature)
}
func (self *WXBizMsgCrypt) ParsePlainText(plaintext []byte) ([]byte, uint32, []byte, []byte, *CryptError) {
const block_size = 32
plaintext, err := self.pKCS7Unpadding(plaintext, block_size)
if nil != err {
return nil, 0, nil, nil, err
}
text_len := uint32(len(plaintext))
if text_len < 20 {
return nil, 0, nil, nil, NewCryptError(IllegalBuffer, "plain is to small 1")
}
random := plaintext[:16]
msg_len := binary.BigEndian.Uint32(plaintext[16:20])
if text_len < (20 + msg_len) {
return nil, 0, nil, nil, NewCryptError(IllegalBuffer, "plain is to small 2")
}
msg := plaintext[20 : 20+msg_len]
receiver_id := plaintext[20+msg_len:]
return random, msg_len, msg, receiver_id, nil
}
func (self *WXBizMsgCrypt) VerifyURL(msg_signature, timestamp, nonce, echostr string) ([]byte, *CryptError) {
signature := self.calSignature(timestamp, nonce, echostr)
if strings.Compare(signature, msg_signature) != 0 {
return nil, NewCryptError(ValidateSignatureError, "signature not equal")
}
plaintext, err := self.cbcDecrypter(echostr)
if nil != err {
return nil, err
}
_, _, msg, receiver_id, err := self.ParsePlainText(plaintext)
if nil != err {
return nil, err
}
if len(self.receiver_id) > 0 && strings.Compare(string(receiver_id), self.receiver_id) != 0 {
fmt.Println(string(receiver_id), self.receiver_id, len(receiver_id), len(self.receiver_id))
return nil, NewCryptError(ValidateCorpidError, "receiver_id is not equil")
}
return msg, nil
}
func (self *WXBizMsgCrypt) EncryptMsg(reply_msg, timestamp, nonce string) ([]byte, *CryptError) {
rand_str := self.randString(16)
var buffer bytes.Buffer
buffer.WriteString(rand_str)
msg_len_buf := make([]byte, 4)
binary.BigEndian.PutUint32(msg_len_buf, uint32(len(reply_msg)))
buffer.Write(msg_len_buf)
buffer.WriteString(reply_msg)
buffer.WriteString(self.receiver_id)
tmp_ciphertext, err := self.cbcEncrypter(buffer.String())
if nil != err {
return nil, err
}
ciphertext := string(tmp_ciphertext)
signature := self.calSignature(timestamp, nonce, ciphertext)
msg4_send := NewWXBizMsg4Send(ciphertext, signature, timestamp, nonce)
return self.protocol_processor.serialize(msg4_send)
}
func (self *WXBizMsgCrypt) DecryptMsg(msg_signature, timestamp, nonce string, post_data []byte) ([]byte, *CryptError) {
msg4_recv, crypt_err := self.protocol_processor.parse(post_data)
if nil != crypt_err {
return nil, crypt_err
}
signature := self.calSignature(timestamp, nonce, msg4_recv.Encrypt)
if strings.Compare(signature, msg_signature) != 0 {
return nil, NewCryptError(ValidateSignatureError, "signature not equal")
}
plaintext, crypt_err := self.cbcDecrypter(msg4_recv.Encrypt)
if nil != crypt_err {
return nil, crypt_err
}
_, _, msg, receiver_id, crypt_err := self.ParsePlainText(plaintext)
if nil != crypt_err {
return nil, crypt_err
}
if len(self.receiver_id) > 0 && strings.Compare(string(receiver_id), self.receiver_id) != 0 {
return nil, NewCryptError(ValidateCorpidError, "receiver_id is not equil")
}
return msg, nil
}
Loading…
Cancel
Save