|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250 |
- 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"
- "github.com/tidwall/gjson"
- "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.Ticket)
- if err != nil {
- WXMsgReply(c, eventMsg.ToUserName, eventMsg.FromUserName, err.Error())
- }
- }
- if eventMsg.Event == "SCAN" {
- //用户已关注时的事件推送
- err := DealCallBack(eventMsg.FromUserName, eventMsg.Ticket)
- 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)
- if mod.Data == "" {
- return
- }
- if gjson.Get(mod.Data, "msgType").String() == "text" {
- svc.WXMsgTextReply(c, msg.ToUserName, msg.FromUserName, gjson.Get(mod.Data, "text.content").String())
- }
- if gjson.Get(mod.Data, "msgType").String() == "image" {
- svc.WXMsgImageReply(c, msg.ToUserName, msg.FromUserName, gjson.Get(mod.Data, "image.mediaId").String())
- }
- }
- }
- }
- 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.com/wx/redPackage/index", map[string]string{
- "openid": openId,
- "amount": utils.Float64ToStr(utils.StrToFloat64(qrcodeWithBatchRecord.Amount) * 100),
- }, nil)
- 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
- }
|