wxgzh
parent
179c6a3afa
commit
0df3603ef2
@ -0,0 +1,84 @@
|
|||||||
|
/**
|
||||||
|
* @Author: jager
|
||||||
|
* @Email: lhj168os@gmail.com
|
||||||
|
* @File: main
|
||||||
|
* @Date: 2021/12/20 2:24 下午
|
||||||
|
* @package: ss
|
||||||
|
* @Version: v1.0.0
|
||||||
|
*
|
||||||
|
* @Description:
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/jageros/hawox/contextx"
|
||||||
|
"github.com/jageros/hawox/httpx"
|
||||||
|
"github.com/jageros/hawox/logx"
|
||||||
|
"net/http"
|
||||||
|
"stock/msg"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
ctx, cancel := contextx.Default()
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
logx.Init(logx.DebugLevel, logx.SetCaller(), logx.SetRequest())
|
||||||
|
defer logx.Sync()
|
||||||
|
|
||||||
|
httpx.InitializeHttpServer(ctx, func(engine *gin.Engine) {
|
||||||
|
r := engine.Group("/api")
|
||||||
|
r.GET("/sayhello", func(c *gin.Context) {
|
||||||
|
httpx.PkgMsgWrite(c, map[string]interface{}{"say": "hello world!"})
|
||||||
|
})
|
||||||
|
r.POST("/receive", func(c *gin.Context) {
|
||||||
|
rMsg := &msg.RData{}
|
||||||
|
err := c.BindXML(rMsg)
|
||||||
|
if err != nil {
|
||||||
|
logx.Error(err)
|
||||||
|
} else {
|
||||||
|
logx.Info(rMsg)
|
||||||
|
}
|
||||||
|
|
||||||
|
wMsg := &xml{
|
||||||
|
ToUserName: rMsg.FromUserName,
|
||||||
|
FromUserName: rMsg.ToUserName,
|
||||||
|
CreateTime: int(time.Now().Unix()),
|
||||||
|
MsgType: "text",
|
||||||
|
Content: "收到,谢谢!",
|
||||||
|
}
|
||||||
|
c.XML(http.StatusOK, wMsg)
|
||||||
|
|
||||||
|
//c.XML(http.StatusOK, wMsg)
|
||||||
|
|
||||||
|
//err = msg.Rcv(rMsg.FromUserName)
|
||||||
|
//if err != nil {
|
||||||
|
// logx.Error(err)
|
||||||
|
//}
|
||||||
|
|
||||||
|
//c.String(http.StatusOK, "success")
|
||||||
|
})
|
||||||
|
|
||||||
|
r.GET("/receive", func(c *gin.Context) {
|
||||||
|
echostr := c.Query("echostr")
|
||||||
|
logx.Infof("=== %s ===", echostr)
|
||||||
|
c.String(http.StatusOK, echostr)
|
||||||
|
})
|
||||||
|
}, func(s *httpx.Server) {
|
||||||
|
s.Mode = "debug"
|
||||||
|
s.Port = 8567
|
||||||
|
})
|
||||||
|
err := ctx.Wait()
|
||||||
|
logx.Infof("Stop With: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
type xml struct {
|
||||||
|
ToUserName string `xml:"ToUserName"`
|
||||||
|
FromUserName string `xml:"FromUserName"`
|
||||||
|
CreateTime int `xml:"CreateTime"`
|
||||||
|
MsgType string `xml:"MsgType"`
|
||||||
|
Content string `xml:"Content"`
|
||||||
|
}
|
@ -0,0 +1,45 @@
|
|||||||
|
/**
|
||||||
|
* @Author: jager
|
||||||
|
* @Email: lhj168os@gmail.com
|
||||||
|
* @File: cache
|
||||||
|
* @Date: 2021/12/20 6:39 下午
|
||||||
|
* @package: user
|
||||||
|
* @Version: v1.0.0
|
||||||
|
*
|
||||||
|
* @Description:
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package user
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/jageros/hawox/attribute"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
var users sync.Map
|
||||||
|
|
||||||
|
func LoadAllUserIntoCache() error {
|
||||||
|
attrs, err := attribute.LoadAll("user")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
for _, attr := range attrs {
|
||||||
|
u := &User{attr: attr}
|
||||||
|
users.Store(attr.GetAttrID(), u)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetUser(openId string) (*User, error) {
|
||||||
|
u, ok := users.Load(openId)
|
||||||
|
if ok {
|
||||||
|
return u.(*User), nil
|
||||||
|
}
|
||||||
|
us, err := newUser(openId)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
users.Store(openId, us)
|
||||||
|
return us, nil
|
||||||
|
}
|
@ -0,0 +1,114 @@
|
|||||||
|
/**
|
||||||
|
* @Author: jager
|
||||||
|
* @Email: lhj168os@gmail.com
|
||||||
|
* @File: user
|
||||||
|
* @Date: 2021/12/20 4:54 下午
|
||||||
|
* @package: user
|
||||||
|
* @Version: v1.0.0
|
||||||
|
*
|
||||||
|
* @Description:
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package user
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/jageros/hawox/attribute"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type User struct {
|
||||||
|
attr *attribute.AttrMgr
|
||||||
|
}
|
||||||
|
|
||||||
|
func newUser(openId string) (*User, error) {
|
||||||
|
u := &User{
|
||||||
|
attr: attribute.NewAttrMgr("user", openId),
|
||||||
|
}
|
||||||
|
err := u.attr.Load(true)
|
||||||
|
if err == attribute.NotExistsErr {
|
||||||
|
u.attr.SetInt64("create_time", time.Now().Unix())
|
||||||
|
err = u.attr.Save(false)
|
||||||
|
}
|
||||||
|
return u, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *User) OpenID() string {
|
||||||
|
return u.attr.GetAttrID().(string)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *User) Codes(isFund bool) []string {
|
||||||
|
key := "stock"
|
||||||
|
if isFund {
|
||||||
|
key = "fund"
|
||||||
|
}
|
||||||
|
attr := u.attr.GetMapAttr(key)
|
||||||
|
if attr == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
var codes []string
|
||||||
|
attr.ForEachKey(func(key string) bool {
|
||||||
|
codes = append(codes, key)
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
return codes
|
||||||
|
}
|
||||||
|
|
||||||
|
// HasSubscribed 查询用户是否订阅此票
|
||||||
|
func (u *User) HasSubscribed(isFund bool, code string) bool {
|
||||||
|
key := "stock"
|
||||||
|
if isFund {
|
||||||
|
key = "fund"
|
||||||
|
}
|
||||||
|
attr := u.attr.GetMapAttr(key)
|
||||||
|
if attr == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
sAttr := attr.GetMapAttr(code)
|
||||||
|
if sAttr == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return sAttr.GetBool("notify")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Subscribe 订阅股票或基金
|
||||||
|
func (u *User) Subscribe(isFund bool, codes ...string) {
|
||||||
|
key := "stock"
|
||||||
|
if isFund {
|
||||||
|
key = "fund"
|
||||||
|
}
|
||||||
|
attr := u.attr.GetMapAttr(key)
|
||||||
|
if attr == nil {
|
||||||
|
attr = attribute.NewMapAttr()
|
||||||
|
u.attr.SetMapAttr(key, attr)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, code := range codes {
|
||||||
|
sAttr := attr.GetMapAttr(code)
|
||||||
|
if sAttr == nil {
|
||||||
|
sAttr = attribute.NewMapAttr()
|
||||||
|
attr.SetMapAttr(code, sAttr)
|
||||||
|
}
|
||||||
|
sAttr.SetBool("notify", true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnSubscribe 取消订阅股票或基金
|
||||||
|
func (u *User) UnSubscribe(isFund bool, codes ...string) {
|
||||||
|
key := "stock"
|
||||||
|
if isFund {
|
||||||
|
key = "fund"
|
||||||
|
}
|
||||||
|
attr := u.attr.GetMapAttr(key)
|
||||||
|
if attr == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, code := range codes {
|
||||||
|
sAttr := attr.GetMapAttr(code)
|
||||||
|
if sAttr == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
sAttr.SetBool("notify", false)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,110 @@
|
|||||||
|
/**
|
||||||
|
* @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/jageros/hawox/errcode"
|
||||||
|
"github.com/jageros/hawox/httpc"
|
||||||
|
"stock/stock"
|
||||||
|
"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 RData struct {
|
||||||
|
ToUserName string `xml:"ToUserName"`
|
||||||
|
FromUserName string `xml:"FromUserName"`
|
||||||
|
CreateTime int `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 int `xml:"CreateTime"`
|
||||||
|
MsgType string `xml:"MsgType"`
|
||||||
|
Content string `xml:"Content"`
|
||||||
|
}
|
||||||
|
|
||||||
|
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, stk stock.IArg, recall bool) error {
|
||||||
|
token, err := getAccessToken(false)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
url := fmt.Sprintf(sendUrl, token)
|
||||||
|
|
||||||
|
arg := stk.Arg(openID)
|
||||||
|
resp := &Resp{}
|
||||||
|
err = httpc.RequestWithInterface(httpc.POST, url, httpc.JSON, arg, 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, stk, false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return errcode.New(int32(resp.Errcode), resp.Errmsg)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func Send(openId string, stk stock.IArg) error {
|
||||||
|
return send(openId, stk, true)
|
||||||
|
}
|
Loading…
Reference in New Issue