/** * @Author: jager * @Email: lhj168os@gmail.com * @File: wxgzh * @Date: 2021/12/20 6:53 下午 * @package: wxgzh * @Version: v1.0.0 * * @Description: * */ package wxgzh import ( "fmt" "github.com/gin-gonic/gin" "github.com/jageros/hawox/errcode" "github.com/jageros/hawox/httpc" "github.com/jageros/hawox/logx" "net/http" "stock/fund" "stock/stock" "stock/user" "strings" "time" ) var ( appid = "wxba88e64e7342b027" secret = "ab8130a7bf55b78992e3d17f59909e0a" accessTokenUrl = fmt.Sprintf("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s", appid, secret) sendUrl = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=%s" accessToken = "" expiresIn int64 ) func InitCfg(appid_, secret_ string) { appid = appid_ secret = secret_ } type Resp struct { Errcode int `json:"errcode"` Errmsg string `json:"errmsg"` Msgid int `json:"msgid"` } type AccessToken struct { AccessToken string `json:"access_token"` ExpiresIn int64 `json:"expires_in"` Errcode int `json:"errcode"` Errmsg string `json:"errmsg"` } type IArg interface { Arg(openid string) map[string]interface{} } type IMsg interface { Msg() string Name() string } func getAccessToken(update bool) (string, error) { if !update && time.Now().Unix() < expiresIn { return accessToken, nil } resp := &AccessToken{} err := httpc.RequestWithInterface(httpc.GET, accessTokenUrl, httpc.FORM, nil, nil, resp) if err != nil { return "", err } if resp.Errcode != 0 { return "", errcode.New(int32(resp.Errcode), resp.Errmsg) } accessToken = resp.AccessToken expiresIn = time.Now().Unix() + resp.ExpiresIn return resp.AccessToken, nil } func send(openID string, arg IArg, recall bool) error { token, err := getAccessToken(false) if err != nil { return err } url := fmt.Sprintf(sendUrl, token) msg := arg.Arg(openID) if msg == nil { return nil } resp := &Resp{} err = httpc.RequestWithInterface(httpc.POST, url, httpc.JSON, msg, nil, resp) if err != nil { return err } if resp.Errcode != 0 { if resp.Errcode == 40014 { _, err = getAccessToken(true) if err != nil { return err } if recall { return send(openID, arg, false) } } return errcode.New(int32(resp.Errcode), resp.Errmsg) } return nil } func Send(openId string, stk IArg) error { return send(openId, stk, true) } //func SendAll(stk IArg) error { // user.ForEachUser(func(u *user.User) bool { // if u.HasSubscribed(false, "") { // err := Send(u.OpenID(), stk) // if err != nil { // logx.Error(err) // return false // } // } // return true // }) // return nil //} type rData struct { ToUserName string `xml:"ToUserName"` FromUserName string `xml:"FromUserName"` CreateTime int64 `xml:"CreateTime"` MsgType string `xml:"MsgType"` Content string `xml:"Content"` MsgID int64 `xml:"MsgId"` Event string `xml:"Event"` } type xml struct { ToUserName string `xml:"ToUserName"` FromUserName string `xml:"FromUserName"` CreateTime int64 `xml:"CreateTime"` MsgType string `xml:"MsgType"` Content string `xml:"Content"` } func Handle(c *gin.Context) { rMsg := &rData{} err := c.BindXML(rMsg) if err != nil { c.String(http.StatusOK, err.Error()) c.Abort() return } wMsg := &xml{ ToUserName: rMsg.FromUserName, FromUserName: rMsg.ToUserName, MsgType: "text", CreateTime: time.Now().Unix(), Content: "查询股票:=st股票代码(例如:=st600905)\n查询基金:=fd基金代码(例如:=fd161725)\n\n" + "订阅股票:+st股票代码(例如:+st600905)\n订阅基金:+fd基金代码(例如:+fd161725)\n\n" + "取消订阅股票:-st股票代码(例如:-st600905)\n取消订阅基金:-fd基金代码(例如:-fd161725)\n\n" + "查询已订阅股票:lst\n" + "查询已订阅基金:lfd\n" + "停止通知:stop\n" + "启动通知:start\n", } u, err := user.GetUser(rMsg.FromUserName) if err != nil { wMsg.Content = err.Error() rMsg.MsgType = "" } if rMsg.MsgType == "text" { switch { case strings.ToLower(rMsg.Content) == "stop": u.Stop() wMsg.Content = "已停止通知!" case strings.ToLower(rMsg.Content) == "start": u.Start() wMsg.Content = "已启动通知!" case strings.ToLower(rMsg.Content) == "lst": codes := u.Codes(false) stks, err := stock.GetStocks(codes...) if err != nil { wMsg.Content = "查询错误:\n" + err.Error() } else { msg := stks.Msg() if msg == "" { wMsg.Content = "您未订阅任何股票!" } else { wMsg.Content = "所有订阅股票信息:\n" + msg } } case strings.ToLower(rMsg.Content) == "lfd": codes := u.Codes(true) msg := fund.FundsMsg(codes...) if msg == "" { wMsg.Content = "您未订阅任何基金!" } else { wMsg.Content = "所有订阅基金信息:\n" + msg } case len(rMsg.Content) < 9: break case strings.HasPrefix(rMsg.Content, "="): code := rMsg.Content[3:] isFund := rMsg.Content[1:3] == "fd" var im IMsg if isFund { im, err = fund.NewFund(code) } else { im, err = stock.GetStock(code) } if err != nil { wMsg.Content = "查询出错:\n" + err.Error() } else { wMsg.Content = "查询成功:\n" + im.Msg() } case strings.HasPrefix(rMsg.Content, "+"): code := rMsg.Content[3:] isFund := rMsg.Content[1:3] == "fd" var im IMsg if isFund { im, err = fund.NewFund(code) } else { im, err = stock.GetStock(code) } if err != nil { wMsg.Content = "订阅出错:\n" + err.Error() } else { u.Subscribe(isFund, code) wMsg.Content = "订阅成功:\n" + im.Msg() } case strings.HasPrefix(rMsg.Content, "-"): code := rMsg.Content[3:] isFund := rMsg.Content[1:3] == "fd" var im IMsg if isFund { im, err = fund.NewFund(code) } else { im, err = stock.GetStock(code) } if err != nil { wMsg.Content = "取消订阅:\n" + err.Error() } else { wMsg.Content = "成功取消订阅:" + im.Name() } u.UnSubscribe(isFund, code) } } if rMsg.MsgType == "event" { switch rMsg.Event { case "subscribe": logx.Infof("user=%s subscribe!", u.OpenID()) u.Start() case "unsubscribe": logx.Infof("user=%s unsubscribe!", u.OpenID()) u.Stop() c.String(http.StatusOK, "success") c.Abort() return } } c.XML(http.StatusOK, wMsg) }