123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397 |
- package global
-
- import (
- base_ctl "SCRM/controllers"
- "SCRM/enums"
- "SCRM/models"
- "fmt"
- "strings"
- "time"
-
- "github.com/astaxie/beego"
-
- "SCRM/service"
- "SCRM/utils"
- "encoding/base64"
- "encoding/json"
- "encoding/xml"
- "strconv"
-
- "SCRM/service/org_service"
- "SCRM/service/wechat_service"
-
- "io/ioutil"
-
- crypter "github.com/heroicyang/wechat-crypter"
- )
-
- //OpenWechatAPIController 微信开放平台相关
- type OpenWechatAPIController struct {
- base_ctl.BaseAPIController
- }
-
- func (c *OpenWechatAPIController) Prepare() {
- c.EnableXSRF = false
- }
-
- //OpenWechatCtlRegistRouters 微信开放平台注册路由
- func OpenWechatCtlRegistRouters() {
- beego.Router("/openwechat/authorizationevents", &OpenWechatAPIController{}, "*:AuthorizationEvents")
- beego.Router("/openwechat/mp/notice/:appid", &OpenWechatAPIController{}, "Post:MpWechatNotice")
- beego.Router("/openwechat/mp/authorization", &OpenWechatAPIController{}, "Get:Authorization")
- beego.Router("/openwechat/mp/authorizerinfo/:id/:vtime/:vcode", &OpenWechatAPIController{}, "*:AuthorizerInfo")
- }
-
- // AuthorizationEvents 接收微信服务器推送的 授权事件
- // 有四个处理功能,由解密后的infoType决定
- // 每隔10分钟定时推送 component_verify_ticket
- // 公众号授权给第三方平台 authorized
- // 公众号对第三方平台取消授权 unauthorized
- // 公众号对第三方平台更新授权 updateauthorized
- func (c *OpenWechatAPIController) AuthorizationEvents() {
- //接收微信服务器主动调起授权事件接收URL时,由微信服务器额外拼接在URL的几个参数,
- // nonce := c.GetString("nonce")
- // encryptType := c.GetString("encrypt_type")
- // msgSignature := c.GetString("msg_signature")
- // signature := c.GetString("signature")
- // timestamp := c.GetString("timestamp")
-
- // MsgEncrypt 类型的me,MsgEncrypt是根据接下来要读取的xml数据格式定义的struct,
- var me wechat_service.MsgEncrypt
- err := xml.Unmarshal(c.Ctx.Input.RequestBody, &me)
- if err != nil {
- utils.ErrorLog("read body error: %s", err)
- c.Ctx.WriteString("success")
- return
- }
-
- msgCrypter, _ := crypter.NewMessageCrypter(beego.AppConfig.String("openwechattoken"), beego.AppConfig.String("openwechatencodingaeskey"), beego.AppConfig.String("openwechatappid")) //这是github.com/heroicyang/config.WECHAT-crypter上的组件
- msgDecrypt, _, err := msgCrypter.Decrypt(me.Encrypt)
- if err != nil {
- utils.ErrorLog("msgDecrypt error: %s", err)
- c.Ctx.WriteString("success")
- return
- }
- fmt.Println("msgDecrypt:", string(msgDecrypt))
- //将上面解密后的xml读到InfoType struct
- var requestBody wechat_service.ComponentRequestBody
- err = xml.Unmarshal(msgDecrypt, &requestBody)
- if err != nil {
- utils.ErrorLog("Unmarshal ComponentRequestBody error: %s", err)
- c.Ctx.WriteString("success")
- return
- }
-
- //判断推送类型
- // 推送 component_verify_ticket
- // 公众号授权给第三方平台 authorized
- // 公众号对第三方平台取消授权 unauthorized
- // 公众号对第三方平台更新授权 updateauthorized
- if requestBody.InfoType == "component_verify_ticket" {
- utils.InfoLog("接收到component_verify_ticket:%s, ", requestBody.ComponentVerifyTicket)
- redisClient := service.RedisClient()
-
- defer redisClient.Close()
-
- err = redisClient.Set("sgj_patient:ComponentVerifyTicket", requestBody.ComponentVerifyTicket, 0).Err()
- if err != nil {
- utils.ErrorLog("redis set failed: %s", err)
- }
-
- componentID, err := beego.AppConfig.Int64("openwechatcomponentid")
- if err != nil {
- utils.ErrorLog("get component id failed: %s", err)
- }
-
- err = wechat_service.SaveWechatComponentVerifyTicket(componentID, requestBody.ComponentVerifyTicket)
- if err != nil {
- utils.ErrorLog("SaveWechatComponentVerifyTicket failed: %s", err)
- }
-
- } else if requestBody.InfoType == "authorized" {
- utils.InfoLog("authorized: %s", requestBody.AuthorizerAppid)
-
- } else if requestBody.InfoType == "unauthorized" {
- utils.InfoLog("unauthorized: %s", requestBody.AuthorizerAppid)
-
- err = wechat_service.SaveAuthorizerStatusByAppID(requestBody.AuthorizerAppid, 2)
- if err != nil {
- utils.ErrorLog("SaveAuthorizerStatus failed: %s", err)
- }
-
- } else if requestBody.InfoType == "updateauthorized" || requestBody.InfoType == "authorized" {
- utils.InfoLog("%s: %s", requestBody.AuthorizerAppid, requestBody.InfoType)
- } else {
- utils.ErrorLog("Unkown infotype")
- c.Ctx.WriteString("success")
- return
- }
-
- c.Ctx.WriteString("success")
- }
-
- //MpWechatNotice 授权后公众号消息与事件接收URL
- func (c *OpenWechatAPIController) MpWechatNotice() {
- appid := c.Ctx.Input.Param(":appid")
- if len(appid) == 0 {
- utils.ErrorLog("appid not found")
- c.Ctx.WriteString("success")
- return
- }
-
- authorizer, err := wechat_service.GetAuthorizationByOnlyAppID(appid)
- if err != nil {
- utils.ErrorLog("Get MP Info error: %s", err)
- c.Ctx.WriteString("success")
- return
- }
- if authorizer == nil {
- utils.ErrorLog("Get MP Info error: 信息不存在")
- c.Ctx.WriteString("success")
- return
- }
-
- orgID := authorizer.UserOrgId
- timestamp := c.GetString("timestamp")
- nonce := c.GetString("nonce")
- // openid := c.GetString("openid")
- // encryptType := c.GetString("encrypt_type")
- msgSignature := c.GetString("msg_signature")
- // signature := c.GetString("signature")
-
- r := c.Ctx.Request
-
- body, err := ioutil.ReadAll(r.Body)
- if err != nil {
- utils.ErrorLog("read body error: %s", err)
- c.Ctx.WriteString("success")
- return
- }
- encryptRequestBody := &wechat_service.EncryptRequestBody{}
- err = xml.Unmarshal(body, encryptRequestBody)
- if err != nil {
- utils.ErrorLog("Unmarshal body error: %s", err)
- c.Ctx.WriteString("success")
- return
- }
-
- // Validate mstBody signature
- if !wechat_service.ValidateMsg(timestamp, nonce, encryptRequestBody.Encrypt, msgSignature) {
- fmt.Println("aa")
- c.Ctx.WriteString("success")
- return
- }
-
- // Decode base64
- cipherData, err := base64.StdEncoding.DecodeString(encryptRequestBody.Encrypt)
- if err != nil {
- c.Ctx.WriteString("success")
- return
- }
-
- // AES Decrypt
- plainData, err := wechat_service.AesDecrypt(cipherData, wechat_service.AesKey)
- if err != nil {
- utils.ErrorLog("AesDecrypt error: %s", err)
- c.Ctx.WriteString("success")
- return
- }
-
- //封装struct
- textRequestBody, err := wechat_service.ParseEncryptTextRequestBody(plainData)
- if err != nil {
- c.Ctx.WriteString("success")
- return
- }
-
- fmt.Println(textRequestBody)
- tp := textRequestBody.MsgType
-
- FromUserName := textRequestBody.ToUserName
- ToUserName := textRequestBody.FromUserName
-
- if tp == "text" {
- //当用户向微信公众号发送消息时,回复ta
- wechat_service.SendMsgTypeTextMessage(appid, ToUserName, FromUserName, textRequestBody.Content, nonce, timestamp, c.Ctx, orgID)
- return
- }
- if tp == "event" {
- eventType := textRequestBody.Event
- if eventType == "subscribe" {
- //当用户关注微信公众号,回复ta
- wechat_service.SendSubscribeTextMessage(appid, ToUserName, FromUserName, nonce, timestamp, c.Ctx, orgID)
- return
- }
-
- if eventType == "CLICK" {
- //当用户点击click类型的菜单,回复ta
- wechat_service.SendClickButtonMessage(appid, ToUserName, FromUserName, textRequestBody.EventKey, nonce, timestamp, c.Ctx, orgID)
- return
- }
-
- if eventType == "unsubscribe" {
- org_service.SetFansUnsubscribe(orgID, ToUserName)
- }
-
- //某个类型的消息暂时后台不作处理,也需要向微信服务器做出响应
- c.Ctx.WriteString("success")
- return
- }
- c.Ctx.WriteString("success")
- }
-
- func (c *OpenWechatAPIController) Authorization() {
-
- id, _ := c.GetInt64("id", 0)
- if id <= 0 {
- c.Ctx.WriteString("没有选择授权对象")
- return
- }
- vtime, _ := c.GetInt64("vtime", 0)
- if vtime <= 0 {
- c.Ctx.WriteString("缺少vtime参数")
- return
- }
- vcode := c.GetString("vcode")
- if len(vcode) == 0 {
- c.Ctx.WriteString("缺少vtime参数")
- return
- }
- vtime, tcode := utils.GetOrgIdCode(id, vtime)
- if tcode != vcode {
- c.Ctx.WriteString("无效的vcode")
- return
- }
-
- code, err := wechat_service.GetReqPreAuthCode()
- fmt.Println("code是什么", code, "错误", err)
- if err != nil {
- c.ServeFailJsonSend(enums.ErrorCodeDataException, "获取授权URL失败:("+err.Error()+")")
- return
- }
-
- uri := fmt.Sprintf(beego.AppConfig.String("httpdomain")+"/openwechat/mp/authorizerinfo/%d/%d/%s", id, vtime, vcode)
- url := "https://mp.weixin.qq.com/safe/bindcomponent?action=bindcomponent&auth_type=1&no_scan=1&component_appid=" + beego.AppConfig.String("openwechatappid") + "&pre_auth_code=" + code + "&redirect_uri=" + uri + "&auth_type=1#wechat_redirect"
- fmt.Println("url是设么东西", url)
- c.Data["url"] = url
- c.TplName = "openwechat/authorization.html"
-
- }
-
- //AuthorizerInfo 拉取公众号授权信息和基本信息
- func (c *OpenWechatAPIController) AuthorizerInfo() {
- idS := c.Ctx.Input.Param(":id")
- vtimeS := c.Ctx.Input.Param(":vtime")
- vcode := c.Ctx.Input.Param(":vcode")
- id, err := strconv.ParseInt(idS, 10, 64)
- if err != nil {
- c.Data["msg"] = err.Error()
- c.TplName = "openwechat/errorauth.html"
- return
- }
- vtime, err := strconv.ParseInt(vtimeS, 10, 64)
- if err != nil {
- c.Data["msg"] = err.Error()
- c.TplName = "openwechat/errorauth.html"
- return
- }
- vtime, tcode := utils.GetOrgIdCode(id, vtime)
- if tcode != vcode {
- c.Data["msg"] = "无效的vcode"
- c.TplName = "openwechat/errorauth.html"
- return
- }
-
- authorizationCode := c.GetString("auth_code")
-
- redisClient := service.RedisClient()
-
- componentAccessToken, err := redisClient.Get("sgj_patient:component_access_token").Result()
- if err != nil {
- c.Data["msg"] = "需要component_access_token才能验证信息"
- c.TplName = "openwechat/errorauth.html"
- return
- }
-
- body, err := wechat_service.ComponentAPIQueryAuth(authorizationCode, componentAccessToken)
- if err != nil {
- c.Data["msg"] = "获取公众号授权信息失败"
- c.TplName = "openwechat/errorauth.html"
- return
- }
-
- var ai wechat_service.AuthorizationInfo
- err = json.Unmarshal([]byte(body), &ai)
- if err != nil {
- c.Data["msg"] = "解析公众号授权信息失败"
- c.TplName = "openwechat/errorauth.html"
- return
- }
-
- body, err = wechat_service.ComponentAPIGetAuthorizerInfo(ai.AuthorizationInfo.AuthorizerAppid, componentAccessToken)
- if err != nil {
- c.Data["msg"] = "获取公众号信息失败"
- c.TplName = "openwechat/errorauth.html"
- return
- }
-
- var aui wechat_service.AuthorizerInfo
- err = json.Unmarshal([]byte(body), &aui)
- if err != nil {
- c.Data["msg"] = "解析公众号信息失败"
- c.TplName = "openwechat/errorauth.html"
- return
- }
-
- var funcInfoItem []string
- for _, valjue := range ai.AuthorizationInfo.FuncInfo {
- funcInfoItem = append(funcInfoItem, strconv.FormatInt(valjue.FuncscopeCategory.ID, 10))
- }
-
- BusinessInfo, err := json.MarshalIndent(aui.AuthorizerInfo.BusinessInfo, "", " ")
- //用json,功能的开通状况(0代表未开通,1代表已开通): open_store:是否开通微信门店功能 open_scan:是否开通微信扫商品功能 open_pay:是否开通微信支付功能 open_card:是否开通微信卡券功能 open_shake:是否开通微信摇一摇功能
- if err != nil {
- c.Data["msg"] = "解析公众号功能的开通状况失败"
- c.TplName = "openwechat/errorauth.html"
- return
- }
-
- authorizationsInfo, err := wechat_service.GetAuthorizationByOrgID(id)
- if err != nil {
- c.Data["msg"] = "读取公众号信息失败"
- c.TplName = "openwechat/errorauth.html"
- return
- }
- var authorizations models.PatientAuthorizations
- if authorizationsInfo == nil {
- authorizations.UserOrgId = id
- authorizations.CreatedTime = time.Now().Unix()
- } else {
- authorizations = *authorizationsInfo
- }
- authorizations.UpdatedTime = time.Now().Unix()
- authorizations.AuthorizerAccessToken = ai.AuthorizationInfo.AuthorizerAccessToken
- authorizations.AuthorizerRefreshToken = ai.AuthorizationInfo.AuthorizerRefreshToken
- authorizations.AuthorizerFuncscopeCategory = strings.Join(funcInfoItem, ",")
- authorizations.AuthorizerAppid = ai.AuthorizationInfo.AuthorizerAppid
- authorizations.AuthorizerNickName = aui.AuthorizerInfo.NickName
- authorizations.AuthorizerHeadImg = aui.AuthorizerInfo.HeadImg
- authorizations.AuthorizerServiceTypeInfo = aui.AuthorizerInfo.ServiceTypeInfo.ID
- authorizations.AuthorizerVerifyTypeInfo = aui.AuthorizerInfo.VerifyTypeInfo.ID
- authorizations.AuthorizerUserName = aui.AuthorizerInfo.UserName
- authorizations.AuthorizerPrincipalName = aui.AuthorizerInfo.PrincipalName
- authorizations.AuthorizerBusinessInfo = string(BusinessInfo)
- authorizations.AuthorizerQrcodeUrl = aui.AuthorizerInfo.QrcodeURL
- authorizations.AuthorizerStatus = 1
-
- err = wechat_service.SaveAuthorizationInfo(&authorizations)
- if err != nil {
- c.Data["msg"] = "保存公众号信息失败"
- c.TplName = "openwechat/errorauth.html"
- return
- }
-
- c.TplName = "openwechat/successauth.html"
- return
- }
|