package hdl import ( "applet/app/db" "applet/app/db/model" "applet/app/enum" "applet/app/md" "applet/app/svc" "applet/app/utils" "encoding/json" "encoding/xml" "errors" "fmt" "log" "net/http" "strings" "time" "github.com/gin-gonic/gin" ) const Token = "temptoken" // WXCheckSignature 微信接入校验 func WXCheckSignature(c *gin.Context) { signature := c.Query("signature") timestamp := c.Query("timestamp") nonce := c.Query("nonce") echostr := c.Query("echostr") ok := utils.CheckSignature(signature, timestamp, nonce, Token) if !ok { log.Println("[微信接入] - 微信公众号接入校验失败!") return } log.Println("[微信接入] - 微信公众号接入校验成功!") _, _ = c.Writer.WriteString(echostr) } // WXMsg 微信消息结构体 type WXMsg struct { ToUserName string FromUserName string CreateTime int64 MsgType string Content string MsgId int64 Event string //事件类型,subscribe EventKey string //事件KEY值,qrscene_为前缀,后面为二维码的参数值 Ticket string //二维码的ticket,可用来换取二维码图片 } // WXTextMsg 微信文本消息结构体 type WXTextMsg struct { ToUserName string FromUserName string CreateTime int64 MsgType string Content string MsgId int64 } // WXEventForSubscribeMsg 扫描带参数二维码事件消息结构体(用户未关注时,进行关注后的事件推送) type WXEventForSubscribeMsg struct { ToUserName string //开发者微信号 FromUserName string //发送方帐号(一个OpenID) CreateTime int64 //消息创建时间 (整型) MsgType string //消息类型,event Event string //事件类型,subscribe EventKey string //事件KEY值,qrscene_为前缀,后面为二维码的参数值 Ticket string //二维码的ticket,可用来换取二维码图片 } // WXEventForScanMsg 扫描带参数二维码事件消息结构体(用户已关注时的事件推送) type WXEventForScanMsg struct { ToUserName string //开发者微信号 FromUserName string //发送方帐号(一个OpenID) CreateTime int64 //消息创建时间 (整型) MsgType string //消息类型,event Event string //事件类型,subscribe EventKey string //事件KEY值,是一个32位无符号整数,即创建二维码时的二维码scene_id Ticket string //二维码的ticket,可用来换取二维码图片 } // WXMsgReceive 微信消息接收 func WXMsgReceive(c *gin.Context) { log.Printf("[消息接收] - 收到新消息") var msg WXMsg err := c.ShouldBindXML(&msg) if err != nil { log.Printf("[消息接收] - XML数据包解析失败: %v\n", err) return } utils.FilePutContents("WXMsgReceive", utils.SerializeStr(msg)) log.Printf("[消息接收] - 收到消息, 消息类型为: %s", msg.MsgType) if msg.MsgType == "event" { //事件类型消息 eventMsg := msg log.Printf("[事件类型]-收到消息, 事件类型为: %s, 事件KEY值为: %s\n, 二维码的ticket值为: %s\n", eventMsg.Event, eventMsg.EventKey, eventMsg.Ticket) if eventMsg.Event == "subscribe" { //用户未关注时,进行关注后的事件推送 err := DealCallBack(eventMsg.FromUserName, eventMsg.EventKey) if err != nil { WXMsgReply(c, eventMsg.ToUserName, eventMsg.FromUserName, err.Error()) } } if eventMsg.Event == "SCAN" { //用户已关注时的事件推送 err := DealCallBack(eventMsg.FromUserName, eventMsg.EventKey) if err != nil { WXMsgReply(c, eventMsg.ToUserName, eventMsg.FromUserName, err.Error()) } } if eventMsg.Event == "CLICK" { //公众号点击 if strings.Contains(strings.ToLower(eventMsg.EventKey), "official_account_custom_reply") { id := strings.ReplaceAll(strings.ToLower(eventMsg.EventKey), "official_account_custom_reply_", "") var mod model.SysModule db.Db.Where("mod_id=?", id).Get(&mod) fmt.Println(mod) if mod.Data == "" { fmt.Println(333) return } var data []md.ReplyContent json.Unmarshal([]byte(mod.Data), &data) for _, v := range data { if v.MsgType == "text" { fmt.Println(1111) svc.WXMsgTextReply(c, msg.ToUserName, msg.FromUserName, v.Text.Content) } if v.MsgType == "image" { fmt.Println(22222) svc.WXMsgImageReply(c, msg.ToUserName, msg.FromUserName, v.Image.MediaId) } } } } } if msg.MsgType == "text" { //文本类型消息 textMsg := msg log.Printf("[文本消息]-收到消息, 消息内容为: %s", textMsg.Content) WXMsgReply(c, textMsg.ToUserName, textMsg.FromUserName, textMsg.Content) } c.String(http.StatusOK, "") } // WXRepTextMsg 微信回复文本消息结构体 type WXRepTextMsg struct { ToUserName string FromUserName string CreateTime int64 MsgType string Content string // 若不标记XMLName, 则解析后的xml名为该结构体的名称 XMLName xml.Name `xml:"xml"` } // WXMsgReply 微信消息回复 func WXMsgReply(c *gin.Context, fromUser, toUser, content string) { repTextMsg := WXRepTextMsg{ ToUserName: toUser, FromUserName: fromUser, CreateTime: time.Now().Unix(), MsgType: "text", Content: fmt.Sprintf("[消息回复] - %s \n %s", time.Now().Format("2006-01-02 15:04:05"), content), } msg, err := xml.Marshal(&repTextMsg) if err != nil { log.Printf("[消息回复] - 将对象进行XML编码出错: %v\n", err) return } _, _ = c.Writer.Write(msg) } func DealCallBack(openId, ticket string) error { //1、查找对应的二维码记录 qrcodeDb := db.QrcodeDb{} qrcodeDb.Set() qrcode, err := qrcodeDb.GetQrcodeByIndex(ticket) if err != nil { return err } if qrcode == nil { return errors.New("未查询到对应二维码记录") } //2、查找当前二维码是否可用 qrcodeWithBatchRecordsDb := db.QrcodeWithBatchRecordsDb{} qrcodeWithBatchRecordsDb.Set() qrcodeWithBatchRecord, err := qrcodeWithBatchRecordsDb.GetQrcodeWithBatchRecordsByQrcodeId(qrcode.Id) if err != nil { return err } if qrcodeWithBatchRecord == nil { return errors.New("当前二维码不可使用!") } //3、查找当前用户是否使用过当前二维码 userUseQrcodeRecordsDb := db.UserUseQrcodeRecordsDb{} userUseQrcodeRecordsDb.Set() userUseQrcodeRecords, err := userUseQrcodeRecordsDb.GetUserUseQrcodeRecordsByOpenId(openId) if err != nil { return err } if userUseQrcodeRecords != nil { return errors.New("请勿重复使用二维码!") } //4、发送微信红包 post, err := utils.CurlPost("http://pay.izhyin.com/wx/redPackage/index", map[string]string{ "openid": openId, "amount": utils.Float64ToStr(utils.StrToFloat64(qrcodeWithBatchRecord.Amount) * 100), }, nil) utils.FilePutContents("send_redPackage", utils.SerializeStr(map[string]interface{}{ "args": map[string]string{ "openid": openId, "amount": utils.Float64ToStr(utils.StrToFloat64(qrcodeWithBatchRecord.Amount) * 100), }, "resp": post, })) if err != nil { return err } var data md.SendRedPackageResp err = json.Unmarshal(post, &data) if err != nil { return err } if data.ReturnCode != "SUCCESS" || data.ResultCode != "SUCCESS" { return errors.New(data.ReturnMsg) } //5、将当前二维码状态修改为“可用” qrcode.State = enum.QrcodeSateAllowUse _, err = qrcodeDb.BatchUpdateQrcode(qrcode, "state") if err != nil { return err } //6、将当前二维码记录修改为“已使用” qrcodeWithBatchRecord.State = enum.QrcodeWithBatchRecordsStateForAlready _, err = qrcodeWithBatchRecordsDb.UpdateQrcodeWithBatchRecord(qrcodeWithBatchRecord) if err != nil { return err } //7、新增用户使用记录 _, err = userUseQrcodeRecordsDb.InsertUserUseQrcodeRecords(&model.UserUseQrcodeRecords{ UserWxOpenId: openId, RecordsId: qrcodeWithBatchRecord.Id, State: 1, CreateAt: time.Now().Format("2006-01-02 15:04:05"), UpdateAt: time.Now().Format("2006-01-02 15:04:05"), }) if err != nil { return err } return nil }