|
|
|
|
/**
|
|
|
|
|
* @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/module"
|
|
|
|
|
"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
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
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 errcode.New(1, "arg == 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 module.IUser) 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"`
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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)",
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if rMsg.MsgType == "text" {
|
|
|
|
|
u, err := user.GetUser(rMsg.FromUserName)
|
|
|
|
|
if err != nil {
|
|
|
|
|
c.String(http.StatusOK, err.Error())
|
|
|
|
|
c.Abort()
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch {
|
|
|
|
|
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)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
c.XML(http.StatusOK, wMsg)
|
|
|
|
|
}
|