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

280 lines
6.4 KiB
Go

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

/**
* @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(true)
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)
}