一物一码
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

286 lines
8.5 KiB

  1. package hdl
  2. import (
  3. "applet/app/db"
  4. "applet/app/db/model"
  5. "applet/app/enum"
  6. "applet/app/md"
  7. "applet/app/svc"
  8. "applet/app/utils"
  9. "encoding/json"
  10. "encoding/xml"
  11. "errors"
  12. "fmt"
  13. "log"
  14. "strings"
  15. "time"
  16. "github.com/gin-gonic/gin"
  17. )
  18. const Token = "temptoken"
  19. // WXCheckSignature 微信接入校验
  20. func WXCheckSignature(c *gin.Context) {
  21. signature := c.Query("signature")
  22. timestamp := c.Query("timestamp")
  23. nonce := c.Query("nonce")
  24. echostr := c.Query("echostr")
  25. ok := utils.CheckSignature(signature, timestamp, nonce, Token)
  26. utils.FilePutContents("WXCheckSignature", utils.SerializeStr(map[string]interface{}{
  27. "signature": signature,
  28. "timestamp": timestamp,
  29. "nonce": nonce,
  30. "echostr": echostr,
  31. "ok": ok,
  32. }))
  33. if !ok {
  34. log.Println("[微信接入] - 微信公众号接入校验失败!")
  35. return
  36. }
  37. log.Println("[微信接入] - 微信公众号接入校验成功!")
  38. _, _ = c.Writer.WriteString(echostr)
  39. }
  40. // WXMsg 微信消息结构体
  41. type WXMsg struct {
  42. ToUserName string
  43. FromUserName string
  44. CreateTime int64
  45. MsgType string
  46. Content string
  47. MsgId int64
  48. Event string // 事件类型,subscribe
  49. EventKey string // 事件KEY值,qrscene_为前缀,后面为二维码的参数值
  50. Ticket string // 二维码的ticket,可用来换取二维码图片
  51. }
  52. // WXTextMsg 微信文本消息结构体
  53. type WXTextMsg struct {
  54. ToUserName string
  55. FromUserName string
  56. CreateTime int64
  57. MsgType string
  58. Content string
  59. MsgId int64
  60. }
  61. // WXEventForSubscribeMsg 扫描带参数二维码事件消息结构体(用户未关注时,进行关注后的事件推送)
  62. type WXEventForSubscribeMsg struct {
  63. ToUserName string // 开发者微信号
  64. FromUserName string // 发送方帐号(一个OpenID)
  65. CreateTime int64 // 消息创建时间 (整型)
  66. MsgType string // 消息类型,event
  67. Event string // 事件类型,subscribe
  68. EventKey string // 事件KEY值,qrscene_为前缀,后面为二维码的参数值
  69. Ticket string // 二维码的ticket,可用来换取二维码图片
  70. }
  71. // WXEventForScanMsg 扫描带参数二维码事件消息结构体(用户已关注时的事件推送)
  72. type WXEventForScanMsg struct {
  73. ToUserName string // 开发者微信号
  74. FromUserName string // 发送方帐号(一个OpenID)
  75. CreateTime int64 // 消息创建时间 (整型)
  76. MsgType string // 消息类型,event
  77. Event string // 事件类型,subscribe
  78. EventKey string // 事件KEY值,是一个32位无符号整数,即创建二维码时的二维码scene_id
  79. Ticket string // 二维码的ticket,可用来换取二维码图片
  80. }
  81. // WXMsgReceive 微信消息接收
  82. func WXMsgReceive(c *gin.Context) {
  83. log.Printf("[消息接收] - 收到新消息")
  84. var msg WXMsg
  85. err := c.ShouldBindXML(&msg)
  86. if err != nil {
  87. log.Printf("[消息接收] - XML数据包解析失败: %v\n", err)
  88. return
  89. }
  90. utils.FilePutContents("WXMsgReceive", utils.SerializeStr(msg))
  91. log.Printf("[消息接收] - 收到消息, 消息类型为: %s", msg.MsgType)
  92. if msg.MsgType == "event" {
  93. // 事件类型消息
  94. eventMsg := msg
  95. log.Printf("[事件类型]-收到消息, 事件类型为: %s, 事件KEY值为: %s\n, 二维码的ticket值为: %s\n", eventMsg.Event, eventMsg.EventKey, eventMsg.Ticket)
  96. if eventMsg.Event == "subscribe" {
  97. // 用户未关注时,进行关注后的事件推送
  98. err := DealCallBack(eventMsg.FromUserName, eventMsg.EventKey)
  99. if err != nil {
  100. WXMsgReply(c, eventMsg.ToUserName, eventMsg.FromUserName, err.Error())
  101. }
  102. }
  103. if eventMsg.Event == "SCAN" {
  104. // 用户已关注时的事件推送
  105. err := DealCallBack(eventMsg.FromUserName, eventMsg.EventKey)
  106. if err != nil {
  107. WXMsgReply(c, eventMsg.ToUserName, eventMsg.FromUserName, err.Error())
  108. }
  109. }
  110. if eventMsg.Event == "CLICK" { // 公众号点击
  111. if strings.Contains(strings.ToLower(eventMsg.EventKey), "official_account_custom_reply") {
  112. id := strings.ReplaceAll(strings.ToLower(eventMsg.EventKey), "official_account_custom_reply_", "")
  113. var mod model.SysModule
  114. db.Db.Where("mod_id=?", id).Get(&mod)
  115. fmt.Println(mod)
  116. if mod.Data == "" {
  117. fmt.Println(333)
  118. return
  119. }
  120. var data []md.ReplyContent
  121. json.Unmarshal([]byte(mod.Data), &data)
  122. for _, v := range data {
  123. if v.MsgType == "text" {
  124. fmt.Println(1111)
  125. svc.WXMsgTextReply(c, msg.ToUserName, msg.FromUserName, v.Text.Content)
  126. }
  127. if v.MsgType == "image" {
  128. fmt.Println(22222)
  129. svc.WXMsgImageReply(c, msg.ToUserName, msg.FromUserName, v.Image.MediaId)
  130. }
  131. }
  132. }
  133. }
  134. }
  135. if msg.MsgType == "text" {
  136. // 文本类型消息
  137. textMsg := msg
  138. log.Printf("[文本消息]-收到消息, 消息内容为: %s", textMsg.Content)
  139. WXMsgReply(c, textMsg.ToUserName, textMsg.FromUserName, textMsg.Content)
  140. }
  141. }
  142. // WXRepTextMsg 微信回复文本消息结构体
  143. type WXRepTextMsg struct {
  144. ToUserName string
  145. FromUserName string
  146. CreateTime int64
  147. MsgType string
  148. Content string
  149. // 若不标记XMLName, 则解析后的xml名为该结构体的名称
  150. XMLName xml.Name `xml:"xml"`
  151. }
  152. // WXMsgReply 微信消息回复
  153. func WXMsgReply(c *gin.Context, fromUser, toUser, content string) {
  154. repTextMsg := WXRepTextMsg{
  155. ToUserName: toUser,
  156. FromUserName: fromUser,
  157. CreateTime: time.Now().Unix(),
  158. MsgType: "text",
  159. Content: fmt.Sprintf("[消息回复] - %s \n %s", time.Now().Format("2006-01-02 15:04:05"), content),
  160. }
  161. msg, err := xml.Marshal(&repTextMsg)
  162. if err != nil {
  163. log.Printf("[消息回复] - 将对象进行XML编码出错: %v\n", err)
  164. return
  165. }
  166. _, _ = c.Writer.Write(msg)
  167. }
  168. func DealCallBack(openId, ticket string) error {
  169. // 1、查找对应的二维码记录
  170. qrcodeDb := db.QrcodeDb{}
  171. qrcodeDb.Set()
  172. qrcode, err := qrcodeDb.GetQrcodeByIndex(ticket)
  173. if err != nil {
  174. return err
  175. }
  176. if qrcode == nil {
  177. return errors.New("未查询到对应二维码记录")
  178. }
  179. // 2、查找当前二维码是否可用
  180. qrcodeWithBatchRecordsDb := db.QrcodeWithBatchRecordsDb{}
  181. qrcodeWithBatchRecordsDb.Set()
  182. qrcodeWithBatchRecord, err := qrcodeWithBatchRecordsDb.GetQrcodeWithBatchRecordsByQrcodeId(qrcode.Id)
  183. if err != nil {
  184. return err
  185. }
  186. if qrcodeWithBatchRecord == nil {
  187. return errors.New("当前二维码不可使用!")
  188. }
  189. // 3、查找当前用户是否使用过当前二维码
  190. userUseQrcodeRecordsDb := db.UserUseQrcodeRecordsDb{}
  191. userUseQrcodeRecordsDb.Set()
  192. userUseQrcodeRecords, err := userUseQrcodeRecordsDb.GetUserUseQrcodeRecordsByOpenId(openId)
  193. if err != nil {
  194. return err
  195. }
  196. if userUseQrcodeRecords != nil && userUseQrcodeRecords.RecordsId == int64(qrcode.Id) {
  197. return errors.New("请勿重复使用二维码!")
  198. }
  199. // 4、发送微信红包
  200. post, err := utils.CurlPost("http://pay.zhios.cn/wx/redPackage/index", utils.SerializeStr(map[string]string{
  201. "openid": openId,
  202. "amount": utils.Float64ToStr(utils.StrToFloat64(qrcodeWithBatchRecord.Amount) * 100),
  203. }), nil)
  204. if err != nil {
  205. return err
  206. }
  207. utils.FilePutContents("send_redPackage", utils.SerializeStr(map[string]interface{}{
  208. "args": map[string]string{
  209. "openid": openId,
  210. "amount": utils.Float64ToStr(utils.StrToFloat64(qrcodeWithBatchRecord.Amount) * 100),
  211. },
  212. "resp": string(post),
  213. }))
  214. var result struct {
  215. Code int `json:"code"`
  216. Msg string `json:"msg"`
  217. Data interface{} `json:"data"`
  218. }
  219. err = json.Unmarshal(post, &result)
  220. if err != nil {
  221. return err
  222. }
  223. var data md.SendRedPackageResp
  224. err = json.Unmarshal(utils.Serialize(result.Data), &data)
  225. if err != nil {
  226. return err
  227. }
  228. utils.FilePutContents("send_redPackage", utils.SerializeStr(map[string]interface{}{
  229. "data": data,
  230. }))
  231. if data.ReturnCode != "SUCCESS" || data.ResultCode != "SUCCESS" {
  232. return errors.New(data.ReturnMsg)
  233. }
  234. // 5、将当前二维码状态修改为“可用”
  235. qrcode.State = enum.QrcodeSateAllowUse
  236. _, err = qrcodeDb.BatchUpdateQrcode(qrcode, "state")
  237. if err != nil {
  238. return err
  239. }
  240. // 6、将当前二维码记录修改为“已使用”
  241. qrcodeWithBatchRecord.State = enum.QrcodeWithBatchRecordsStateForAlready
  242. _, err = qrcodeWithBatchRecordsDb.UpdateQrcodeWithBatchRecord(qrcodeWithBatchRecord)
  243. if err != nil {
  244. return err
  245. }
  246. // 7、新增用户使用记录
  247. _, err = userUseQrcodeRecordsDb.InsertUserUseQrcodeRecords(&model.UserUseQrcodeRecords{
  248. UserWxOpenId: openId,
  249. RecordsId: qrcodeWithBatchRecord.Id,
  250. State: 1,
  251. CreateAt: time.Now().Format("2006-01-02 15:04:05"),
  252. UpdateAt: time.Now().Format("2006-01-02 15:04:05"),
  253. })
  254. if err != nil {
  255. return err
  256. }
  257. return nil
  258. }