wangchuanjin 2 anos atrás
pai
commit
959228d76c

+ 2 - 0
go-xweb/httpsession/IsRedisStore.go

@@ -4,4 +4,6 @@ package httpsession
 var (
 	IsRedisSessionStore  = false
 	RedisSessionLockSize = 20
+	RedisNotLoginKey     = ""   //是否登录是标识
+	RedisNotLoginExpire  = 1800 //未登录用户session的失效时间为30分钟
 )

+ 1 - 1
go-xweb/httpsession/manager.go

@@ -67,7 +67,6 @@ func (manager *Manager) Session(req *http.Request, rw http.ResponseWriter) *Sess
 		println("error:", err.Error())
 		return nil
 	}
-
 	if !manager.generator.IsValid(id) {
 		id = manager.generator.Gen(req)
 		manager.transfer.Set(req, rw, id)
@@ -82,6 +81,7 @@ func (manager *Manager) Session(req *http.Request, rw http.ResponseWriter) *Sess
 		cookie, _ := req.Cookie(manager.transfer.(*CookieTransfer).Name)
 		cookie.Path = "/"
 		cookie.Secure = false
+		cookie.Domain = manager.transfer.(*CookieTransfer).Domain
 		cookie.MaxAge = int(manager.transfer.(*CookieTransfer).MaxAge / time.Second)
 		http.SetCookie(rw, cookie)
 	}

+ 21 - 5
go-xweb/httpsession/redissessionstore.go

@@ -44,10 +44,14 @@ func (store *redisStore) GetMultiple(id Id) map[string]interface{} {
 		lock(id).Unlock()
 		return m
 	}
-	redis.SetExpire("session", string(id), int(store.maxAge.Seconds()))
+	json.Unmarshal(*bs, &m)
+	timeout := int(store.maxAge.Seconds())
+	if RedisNotLoginKey != "" && m[RedisNotLoginKey] == nil {
+		timeout = RedisNotLoginExpire
+	}
+	redis.SetExpire("session", string(id), timeout)
 	store.last = time.Now()
 	lock(id).Unlock()
-	json.Unmarshal(*bs, &m)
 	return m
 }
 
@@ -70,8 +74,12 @@ func (store *redisStore) SetMultiple(id Id, m map[string]interface{}) {
 	for k, v := range m {
 		userdata[k] = v
 	}
+	timeout := int(store.maxAge.Seconds())
+	if RedisNotLoginKey != "" && userdata[RedisNotLoginKey] == nil {
+		timeout = RedisNotLoginExpire
+	}
 	putdata, _ := json.Marshal(userdata)
-	redis.PutBytes("session", string(id), &putdata, int(store.maxAge.Seconds()))
+	redis.PutBytes("session", string(id), &putdata, timeout)
 }
 
 func (store *redisStore) Add(id Id) {
@@ -88,8 +96,12 @@ func (store *redisStore) Del(id Id, key string) bool {
 	var userdata map[string]interface{}
 	json.Unmarshal(*bs, &userdata)
 	delete(userdata, key)
+	timeout := int(store.maxAge.Seconds())
+	if RedisNotLoginKey != "" && userdata[RedisNotLoginKey] == nil {
+		timeout = RedisNotLoginExpire
+	}
 	putdata, _ := json.Marshal(userdata)
-	redis.PutBytes("session", string(id), &putdata, int(store.maxAge.Seconds()))
+	redis.PutBytes("session", string(id), &putdata, timeout)
 	return true
 }
 
@@ -103,9 +115,13 @@ func (store *redisStore) UpdateByCustomField(findkey string, findvalue interface
 	}
 	var data map[string]interface{}
 	json.Unmarshal(*bs, &data)
+	timeout := int(store.maxAge.Seconds())
+	if RedisNotLoginKey != "" && data[RedisNotLoginKey] == nil {
+		timeout = RedisNotLoginExpire
+	}
 	data[setkey] = setvalue
 	putdata, _ := json.Marshal(data)
-	redis.PutBytes("session", findkey, &putdata, int(store.maxAge.Seconds()))
+	redis.PutBytes("session", findkey, &putdata, timeout)
 	return true
 }
 

+ 1 - 0
go-xweb/httpsession/transfer.go

@@ -80,6 +80,7 @@ func (transfer *CookieTransfer) Set(req *http.Request, rw http.ResponseWriter, i
 			cookie.MaxAge = int(transfer.MaxAge / time.Second)
 			//cookie.Expires = time.Now().Add(transfer.maxAge)
 		}
+		cookie.Domain = transfer.Domain
 	}
 	http.SetCookie(rw, cookie)
 }

+ 1 - 1
go-xweb/xweb/action.go

@@ -709,7 +709,7 @@ func (c *Action) Render(tmpl string, params ...*T) error {
 }
 
 //仅生成网页内容
-var regInclude = regexp.MustCompile(`\{\{\s*include\s*"(.*?\.html)"\}\}`)
+var regInclude = regexp.MustCompile(`\{\{\s*include\s*"(.*?\.html)".*\}\}`)
 
 func (c *Action) NamedRender4Cache(name, content string, params ...*T) ([]byte, error) {
 	c.f["oinclude"] = c.Include

+ 3 - 0
go-xweb/xweb/template.go

@@ -366,6 +366,9 @@ func newIncludeIntmpl(rootDir string, content []byte) []byte {
 			b = true
 			tpl := regInclude.FindSubmatch(m)[1]
 			fpath := filepath.Join(rootDir, string(tpl))
+			if strings.Contains(string(m), "OUTSIDE") {
+				fpath = string(tpl)
+			}
 			c, err := ioutil.ReadFile(fpath)
 			if err != nil {
 				return []byte{}

+ 41 - 0
rpc/credit.go

@@ -0,0 +1,41 @@
+// credit
+package rpc
+
+import (
+	"net/rpc"
+)
+
+//客户端远程调用封装
+type RpcCall struct {
+	Addr string //rpc服务地址
+}
+
+type CreditData struct {
+	Code       string //积分代码
+	Uid        string //用户ID
+	Umid       string //用户m_open_id
+	Num        int    //积分值
+	OtherParam map[string]interface{}
+}
+
+//增加积分
+func (rc *RpcCall) InCreadit(param *CreditData, replay *int) error {
+	client, err := rpc.DialHTTP("tcp", rc.Addr)
+	defer client.Close()
+	if err != nil {
+		return err
+	}
+	err = client.Call("CreditRpc.InCreadit", param, replay)
+	return err
+}
+
+//消费积分
+func (rc *RpcCall) OutCreadit(param *CreditData, replay *int) error {
+	client, err := rpc.DialHTTP("tcp", rc.Addr)
+	defer client.Close()
+	if err != nil {
+		return err
+	}
+	err = client.Call("CreditRpc.OutCreadit", param, replay)
+	return err
+}

+ 8 - 0
rpc/follow.go

@@ -0,0 +1,8 @@
+// follow
+package rpc
+
+type FollowData struct {
+	UserId      string `json:"userId"`
+	Server      string `json:"server"`
+	Projectname string `json:"projectname"`
+}

+ 17 - 0
rpc/log.go

@@ -0,0 +1,17 @@
+// credit
+package rpc
+
+import (
+	"net/rpc"
+)
+
+//rpc日志采集
+func (rc *RpcCall) AccessLog(json string) error {
+	client, err := rpc.DialHTTP("tcp", rc.Addr)
+	defer client.Close()
+	if err != nil {
+		return err
+	}
+	err = client.Call("RpcAccessLog.Log", json, nil)
+	return err
+}

+ 102 - 0
rpc/options.go

@@ -0,0 +1,102 @@
+package rpc
+import (
+	"errors"
+	"math/rand"
+	"sync"
+	"time"
+)
+
+var (
+	errClosed   = errors.New("pool is closed")
+	errInvalid  = errors.New("invalid config")
+	errRejected = errors.New("connection is nil. rejecting")
+	errTargets  = errors.New("targets server is empty")
+)
+
+func init() {
+	rand.NewSource(time.Now().UnixNano())
+}
+
+//Options pool options
+type Options struct {
+	lock sync.RWMutex
+	//targets node
+	Targets *[]string
+	//targets channel
+	input chan *[]string
+
+	//InitTargets init targets
+	InitTargets []string
+	// init connection
+	InitCap int
+	// max connections
+	MaxCap       int
+	DialTimeout  time.Duration
+	IdleTimeout  time.Duration
+	ReadTimeout  time.Duration
+	WriteTimeout time.Duration
+}
+
+// Input is the input channel
+func (o *Options) Input() chan<- *[]string {
+	return o.input
+}
+
+// update targets
+func (o *Options) update() {
+	//init targets
+	o.Targets = &o.InitTargets
+
+	go func() {
+		for targets := range o.input {
+			if targets == nil {
+				continue
+			}
+
+			o.lock.Lock()
+			o.Targets = targets
+			o.lock.Unlock()
+		}
+	}()
+
+}
+
+// NewOptions returns a new newOptions instance with sane defaults.
+func NewOptions() *Options {
+	o := &Options{}
+	o.InitCap = 5
+	o.MaxCap = 100
+	o.DialTimeout = 5 * time.Second
+	o.ReadTimeout = 5 * time.Second
+	o.WriteTimeout = 5 * time.Second
+	o.IdleTimeout = 60 * time.Second
+	return o
+}
+
+// validate checks a Config instance.
+func (o *Options) validate() error {
+	if o.InitTargets == nil ||
+		o.InitCap <= 0 ||
+		o.MaxCap <= 0 ||
+		o.InitCap > o.MaxCap ||
+		o.DialTimeout == 0 ||
+		o.ReadTimeout == 0 ||
+		o.WriteTimeout == 0 {
+		return errInvalid
+	}
+	return nil
+}
+
+//nextTarget next target implement load balance
+func (o *Options) nextTarget() string {
+	o.lock.RLock()
+	defer o.lock.RUnlock()
+
+	tlen := len(*o.Targets)
+	if tlen <= 0 {
+		return ""
+	}
+
+	//rand server
+	return (*o.Targets)[rand.Int()%tlen]
+}

+ 84 - 0
rpc/order.go

@@ -0,0 +1,84 @@
+package rpc
+
+//数据导出线下支付
+type DateExportData struct {
+	ImgSrc    string `json:"imgSrc"`
+	OrderCode string `json:"orderCode"`
+}
+
+//对公转账完成回调参数
+type TransferAccountsParam struct {
+	ImgSrc    string `json:"imgSrc"`
+	OrderCode string `json:"orderCode"`
+}
+
+//创建订单
+type JyPayOrderParam struct {
+	Price       int                    `json:"price"`
+	ProductType string                 `json:"productType"`
+	Ip          string                 `json:"ip"`
+	Openid      string                 `json:"openid"`
+	PayWay      string                 `json:"payWay"`
+	Userid      string                 `json:"userid"`
+	Phone       string                 `json:"phone"`
+	Detail      map[string]interface{} `json:"detail"`
+	LotteryId   string                 `json:"lotteryId"`  //卡券id
+	UseProduct  string                 `json:"useProduct"` //产品id
+}
+
+//修改订单
+type JyPayOrderChangeParam struct {
+	ProductType string `json:"productType"`
+	OrderCode   string `json:"orderCode"`
+	PayWay      string `json:"payWay"`
+	Openid      string `json:"openid"`
+	Ip          string `json:"ip"`
+}
+
+//关闭订单
+type JyPayOrderCloseParam struct {
+	ProductType string `json:"productType"`
+	OrderCode   string `json:"orderCode"`
+}
+
+/*
+code -1:失败
+err  错误信息
+*/
+type JyPayOrderResult struct {
+	Status    int    `json:"status"`
+	Err       string `json:"err"`
+	OrderCode string `json:"orderCode"`
+	PayStr    string `json:"payStr"`
+}
+
+type CreateEntReq struct {
+	Name        string
+	Phone       string
+	OrderCode   string
+}
+
+type CreateEntRes struct {
+	Status int    `json:"status"`
+	Err    string `json:"err"`
+	Id     int `json:"id"`
+}
+
+//分享完成 订单处理
+type JYShareUserIdsRes struct {
+	ShareUserInfo []shareUserInfo //被分享者+分享者等用户信息
+}
+
+// shareUserInfo
+type shareUserInfo struct {
+	UserId     string `json:"userId"`     //用户id
+	TimeExpand int    `json:"timeExpand"` //延长时间
+	Remark     string `json:"remark"`     //备注
+}
+
+//分享完成 订单处理结果
+type JYShareResp struct {
+	Error_code int64       `json:"error_code"`
+	Error_msg  string      `json:"error_msg"`
+	Data       interface{} `json:"data"`
+}

+ 23 - 0
rpc/push.go

@@ -0,0 +1,23 @@
+package rpc
+
+type PushData struct {
+	Mopenid  string
+	PushType map[string]string
+	Words    string
+}
+type FollowPush struct {
+	ProjectName string
+	ProjectCode string
+	InfoId      string
+	FollowId    string
+	UserId      string
+	OpenId      string
+	Flag        int
+}
+type FollowPushEnt struct {
+	Entname  string
+	InfoId   string
+	FollowId string
+	OpenId   string
+	Flag     int
+}

+ 28 - 0
rpc/rpc_test.go

@@ -0,0 +1,28 @@
+// rpc_test
+package rpc
+
+import (
+	"log"
+	"testing"
+)
+
+func Test_InCreadit(t *testing.T) {
+	rc := new(RpcCall)
+	rc.Addr = "127.0.0.1:8765"
+	otherParam := make(map[string]interface{})
+	otherParam["name"] = "zhangsan"
+	otherParam["age"] = 18
+	err := rc.InCreadit(&CreditData{Code: "1", Uid: "2", Num: 3, OtherParam: otherParam}, 0)
+	log.Println("err:", err)
+}
+
+func Test_OutCreadit(t *testing.T) {
+	rc := new(RpcCall)
+	rc.Addr = "127.0.0.1:8765"
+	otherParam := make(map[string]interface{})
+	otherParam["name"] = "zhangsan"
+	otherParam["age"] = 18
+	replay := 0
+	err := rc.OutCreadit(&CreditData{Code: "1", Uid: "2", Num: 3, OtherParam: otherParam}, &replay)
+	log.Println("err:", err)
+}

+ 21 - 13
rpc/rpccall.go

@@ -8,24 +8,12 @@ import (
 	util "app.yhyue.com/moapp/jybase/common"
 )
 
-type TmplItem struct {
-	Value string `json:"value,omitempty"`
-	Color string `json:"color,omitempty"`
-}
-
-type WxTmplMsg struct {
-	OpenId   string //用户id
-	Url      string
-	TplId    string
-	TmplData map[string]*TmplItem
-}
-
 /*通用的微信发模板消息方法
  *成功:repl=="Y"
  */
 func WxSendTmplMsg(address string, p *WxTmplMsg) (bool, error) {
 	defer util.Catch()
-	var repl string
+	var repl RpcResult
 	client, err := rpc.DialHTTP("tcp", address)
 	if err != nil {
 		log.Println(p.OpenId, err)
@@ -40,6 +28,26 @@ func WxSendTmplMsg(address string, p *WxTmplMsg) (bool, error) {
 	return repl == "Y", nil
 }
 
+/*微信推送消息rpc接口
+ *成功:repl=="Y"
+ */
+func WxPush(address, serviceMethod string, p *NotifyMsg) (bool, string) {
+	defer util.Catch()
+	var repl RpcResult
+	client, err := rpc.DialHTTP("tcp", address)
+	if err != nil {
+		log.Println(p.Openid, err.Error())
+		return false, ""
+	}
+	defer client.Close()
+	err = client.Call(serviceMethod, p, &repl)
+	if err != nil {
+		log.Println(p.Openid, err.Error())
+		return false, ""
+	}
+	return repl == "Y", string(repl)
+}
+
 //app推送消息rpc接口
 func AppPush(address string, m map[string]interface{}) bool {
 	defer util.Catch()

+ 214 - 0
rpc/rpcpool.go

@@ -0,0 +1,214 @@
+package rpc
+
+import (
+	"bufio"
+	"encoding/gob"
+	"fmt"
+	"io"
+	"net"
+	"net/rpc"
+	"sync"
+	"time"
+)
+
+//RPCPool pool info
+type RPCPool struct {
+	Mu          sync.Mutex
+	IdleTimeout time.Duration
+	conns       chan *rpcIdleConn
+	factory     func() (*rpc.Client, error)
+	close       func(*rpc.Client) error
+}
+
+type rpcIdleConn struct {
+	conn *rpc.Client
+	t    time.Time
+}
+
+//Get get from pool
+func (c *RPCPool) Get() (*rpc.Client, error) {
+	c.Mu.Lock()
+	conns := c.conns
+	c.Mu.Unlock()
+
+	if conns == nil {
+		return nil, errClosed
+	}
+	for {
+		select {
+		case wrapConn := <-conns:
+			if wrapConn == nil {
+				return nil, errClosed
+			}
+			//判断是否超时,超时则丢弃
+			if timeout := c.IdleTimeout; timeout > 0 {
+				if wrapConn.t.Add(timeout).Before(time.Now()) {
+					//丢弃并关闭该链接
+					c.close(wrapConn.conn)
+					continue
+				}
+			}
+			return wrapConn.conn, nil
+		case <-time.After(50 * time.Millisecond):
+			conn, err := c.factory()
+			if err != nil {
+				return nil, err
+			}
+			return conn, nil
+		}
+	}
+}
+
+//Put put back to pool
+func (c *RPCPool) Put(conn *rpc.Client) error {
+	if conn == nil {
+		return errRejected
+	}
+
+	c.Mu.Lock()
+	defer c.Mu.Unlock()
+
+	if c.conns == nil {
+		return c.close(conn)
+	}
+
+	select {
+	case c.conns <- &rpcIdleConn{conn: conn, t: time.Now()}:
+		return nil
+	default:
+		//连接池已满,直接关闭该链接
+		return c.close(conn)
+	}
+}
+
+//Close close all connection
+func (c *RPCPool) Close() {
+	c.Mu.Lock()
+	conns := c.conns
+	c.conns = nil
+	c.factory = nil
+	closeFun := c.close
+	c.close = nil
+	c.Mu.Unlock()
+
+	if conns == nil {
+		return
+	}
+
+	close(conns)
+	for wrapConn := range conns {
+		closeFun(wrapConn.conn)
+	}
+}
+
+//IdleCount idle connection count
+func (c *RPCPool) IdleCount() int {
+	c.Mu.Lock()
+	conns := c.conns
+	c.Mu.Unlock()
+	return len(conns)
+}
+
+//Codec ...
+type Codec struct {
+	Timeout time.Duration
+	Closer  io.ReadWriteCloser
+	Decoder *gob.Decoder
+	Encoder *gob.Encoder
+	EncBuf  *bufio.Writer
+}
+
+//WriteRequest ...
+func (c *Codec) WriteRequest(r *rpc.Request, body interface{}) (err error) {
+	if err = c.timeoutCoder(r, "write request"); err != nil {
+		return
+	}
+
+	if err = c.timeoutCoder(body, "write request body"); err != nil {
+		return
+	}
+
+	return c.EncBuf.Flush()
+}
+
+//ReadResponseHeader ...
+func (c *Codec) ReadResponseHeader(r *rpc.Response) error {
+	return c.Decoder.Decode(r)
+}
+
+//ReadResponseBody ...
+func (c *Codec) ReadResponseBody(body interface{}) error {
+	return c.Decoder.Decode(body)
+}
+
+//Close ...
+func (c *Codec) Close() error {
+	return c.Closer.Close()
+}
+
+func (c *Codec) timeoutCoder(e interface{}, msg string) error {
+	if c.Timeout < 0 {
+		c.Timeout = time.Second * 5
+	}
+
+	echan := make(chan error, 1)
+	go func() { echan <- c.Encoder.Encode(e) }()
+
+	select {
+	case e := <-echan:
+		return e
+	case <-time.After(c.Timeout):
+		return fmt.Errorf("Timeout %s", msg)
+	}
+}
+
+//NewRPCPool init rpc pool
+func NewRPCPool(o *Options) (*RPCPool, error) {
+	if err := o.validate(); err != nil {
+		return nil, err
+	}
+
+	//init pool
+	pool := &RPCPool{
+		conns: make(chan *rpcIdleConn, o.MaxCap),
+		factory: func() (*rpc.Client, error) {
+			target := o.nextTarget()
+			if target == "" {
+				return nil, errTargets
+			}
+
+			conn, err := net.DialTimeout("tcp", target, o.DialTimeout)
+			if err != nil {
+				return nil, err
+			}
+
+			encBuf := bufio.NewWriter(conn)
+			p := rpc.NewClientWithCodec(&Codec{
+				Closer:  conn,
+				Decoder: gob.NewDecoder(conn),
+				Encoder: gob.NewEncoder(encBuf),
+				EncBuf:  encBuf,
+				Timeout: o.WriteTimeout,
+			})
+
+			return p, err
+		},
+		close:       func(v *rpc.Client) error { return v.Close() },
+		IdleTimeout: o.IdleTimeout,
+	}
+
+	//danamic update targets
+	o.update()
+
+	//init make conns
+	for i := 0; i < o.InitCap; i++ {
+		conn, err := pool.factory()
+		if err != nil {
+			pool.Close()
+			return nil, err
+		}
+		pool.conns <- &rpcIdleConn{conn: conn, t: time.Now()}
+	}
+
+	return pool, nil
+}

+ 55 - 0
rpc/weixin.go

@@ -0,0 +1,55 @@
+package rpc
+
+type NotifyMsg struct {
+	Openid      string //用户id
+	Remark      string //消息内容,其他属性待加
+	Result      string //
+	Detail      string //
+	Title       string
+	Url         string
+	Date        string
+	Service     string
+	Color       string
+	DetailColor string
+	TplId       string
+}
+
+type RpcResult string
+
+//红包
+type BonusMsg struct {
+	Mchbillno   string `json:"mch_billno"`   //订单号
+	Sendname    string `json:"send_name"`    //红包发送者名称
+	Reopenid    string `json:"re_openid"`    //接受人openid
+	Totalamount int    `json:"total_amount"` //金额,单位分
+	Totalnum    int    `json:"total_num"`    //发放总人数
+	Wishing     string `json:"wishing"`      //祝福语128字以内
+	Actname     string `json:"act_name"`     //活动名称
+	Remark      string `json:"remark"`       //说明
+}
+type Article struct {
+	Title       string `json:"title"`
+	Description string `json:"description"`
+	PicUrl      string `json:"picurl"`
+	Url         string `json:"url"`
+}
+type News struct {
+	ToUser   string //用户id
+	Articles []Article
+}
+type CustomMsg struct {
+	Url  string
+	Data map[string]interface{}
+}
+
+type TmplItem struct {
+	Value string `json:"value,omitempty"`
+	Color string `json:"color,omitempty"`
+}
+
+type WxTmplMsg struct {
+	OpenId   string //用户id
+	Url      string
+	TplId    string
+	TmplData map[string]*TmplItem
+}