Create & Init Project...

This commit is contained in:
2019-04-22 18:49:16 +08:00
commit fc4fa37393
25440 changed files with 4054998 additions and 0 deletions

View File

@@ -0,0 +1,53 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = ["mobile_test.go"],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/interface/main/app-wall/conf:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"mobile.go",
"service.go",
],
importpath = "go-common/app/interface/main/app-wall/service/mobile",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/interface/main/app-wall/conf:go_default_library",
"//app/interface/main/app-wall/dao/mobile:go_default_library",
"//app/interface/main/app-wall/model:go_default_library",
"//app/interface/main/app-wall/model/mobile:go_default_library",
"//library/ecode:go_default_library",
"//library/log:go_default_library",
"//library/stat/prom:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,167 @@
package mobile
import (
"context"
"time"
"go-common/app/interface/main/app-wall/model"
"go-common/app/interface/main/app-wall/model/mobile"
"go-common/library/ecode"
"go-common/library/log"
)
const (
_mobileKey = "mobile"
)
// InOrdersSync insert OrdersSync
func (s *Service) InOrdersSync(c context.Context, ip string, u *mobile.MobileXML, now time.Time) (err error) {
if !s.iplimit(_mobileKey, ip) {
err = ecode.AccessDenied
return
}
var result int64
if result, err = s.dao.InOrdersSync(c, u); err != nil || result == 0 {
log.Error("mobile_s.dao.OrdersSync (%v) error(%v) or result==0", u, err)
}
return
}
// FlowSync update OrdersSync
func (s *Service) FlowSync(c context.Context, u *mobile.MobileXML, ip string) (err error) {
if !s.iplimit(_mobileKey, ip) {
err = ecode.AccessDenied
return
}
var result int64
if result, err = s.dao.FlowSync(c, u); err != nil || result == 0 {
log.Error("mobile_s.dao.OrdersSync(%v) error(%v) or result==0", u, err)
}
return
}
// Activation
func (s *Service) Activation(c context.Context, usermob string, now time.Time) (msg string, err error) {
rows := s.mobileInfo(c, usermob, now)
res, ok := rows[usermob]
if !ok {
err = ecode.NothingFound
msg = "该卡号尚未开通哔哩哔哩专属免流服务"
return
}
for _, u := range res {
if u.Actionid == 1 || (u.Actionid == 2 && now.Unix() <= int64(u.Expiretime)) {
return
}
}
err = ecode.NotModified
msg = "该卡号哔哩哔哩专属免流服务已退订且已过期"
return
}
// Activation
func (s *Service) MobileState(c context.Context, usermob string, now time.Time) (res *mobile.Mobile) {
data := s.mobileInfo(c, usermob, now)
res = s.userState(data, usermob, now)
return
}
// UserFlowState
func (s *Service) UserMobileState(c context.Context, usermob string, now time.Time) (res *mobile.Mobile) {
data := s.mobileInfo(c, usermob, now)
if rows, ok := data[usermob]; ok {
for _, res = range rows {
if res.Actionid == 1 || (res.Actionid == 2 && now.Unix() <= int64(res.Expiretime)) {
res.MobileType = 2
return
}
}
res = &mobile.Mobile{MobileType: 1}
}
res = &mobile.Mobile{MobileType: 1}
return
}
// userState
func (s *Service) userState(user map[string][]*mobile.Mobile, usermob string, now time.Time) (res *mobile.Mobile) {
if rows, ok := user[usermob]; !ok {
res = &mobile.Mobile{MobileType: 1}
} else {
for _, res = range rows {
if res.Actionid == 2 && now.Unix() <= int64(res.Expiretime) {
res.MobileType = 4
break
} else if res.Actionid == 1 {
res.MobileType = 2
break
}
}
if res.MobileType == 0 {
res.MobileType = 3
}
}
log.Info("mobile_state_type:%v mobile_state_usermob:%v", res.MobileType, usermob)
return
}
// mobileInfo
func (s *Service) mobileInfo(c context.Context, usermob string, now time.Time) (res map[string][]*mobile.Mobile) {
var (
err error
m []*mobile.Mobile
tmps []*mobile.Mobile
row = map[string][]*mobile.Mobile{}
)
res = map[string][]*mobile.Mobile{}
if m, err = s.dao.MobileCache(c, usermob); err == nil && len(m) > 0 {
row[usermob] = m
s.pHit.Incr("mobile_cache")
} else {
row, err = s.dao.OrdersUserFlow(c, usermob, now)
if err != nil {
log.Error("mobile_s.dao.OrdersUserFlow error(%v)", err)
return
}
s.pMiss.Incr("mobile_cache")
if user, ok := row[usermob]; ok && len(user) > 0 {
if err = s.dao.AddMobileCache(c, usermob, user); err != nil {
log.Error("s.dao.AddMobileCache error(%v)", err)
return
}
}
}
if ms, ok := row[usermob]; ok && len(ms) > 0 {
for _, m := range ms {
tmp := &mobile.Mobile{}
*tmp = *m
tmp.Productid = ""
tmps = append(tmps, tmp)
}
res[usermob] = tmps
}
return
}
// IsMobileIP is mobile ip
func (s *Service) IsMobileIP(ipUint uint32, ipStr, usermob string) (res *mobile.MobileUserIP) {
res = &mobile.MobileUserIP{
IPStr: ipStr,
IsValide: false,
}
if !model.IsIPv4(ipStr) {
return
}
for _, u := range s.mobileIpCache {
if u.IPStartUint <= ipUint && u.IPEndUint >= ipUint {
res.IsValide = true
return
}
}
log.Error("mobile_user_ip:%v mobile_ip_usermob:%v", ipStr, usermob)
return
}
// mobileIp ip limit
func (s *Service) iplimit(k, ip string) bool {
return true
}

View File

@@ -0,0 +1,60 @@
package mobile
import (
"context"
"flag"
"path/filepath"
"testing"
"time"
"go-common/app/interface/main/app-wall/conf"
. "github.com/smartystreets/goconvey/convey"
)
var (
s *Service
)
func WithService(f func(s *Service)) func() {
return func() {
f(s)
}
}
func init() {
dir, _ := filepath.Abs("../../cmd/app-wall-test.toml")
flag.Set("conf", dir)
conf.Init()
s = New(conf.Conf)
time.Sleep(time.Second)
}
func TestActivation(t *testing.T) {
Convey("Unicom Activation", t, WithService(func(s *Service) {
res, err := s.Activation(context.TODO(), "", time.Now())
So(res, ShouldNotBeEmpty)
So(err, ShouldBeNil)
}))
}
func TestMobileState(t *testing.T) {
Convey("Unicom MobileState", t, WithService(func(s *Service) {
res := s.MobileState(context.TODO(), "", time.Now())
So(res, ShouldNotBeEmpty)
}))
}
func TestUserMobileState(t *testing.T) {
Convey("Unicom UserMobileState", t, WithService(func(s *Service) {
res := s.UserMobileState(context.TODO(), "", time.Now())
So(res, ShouldNotBeEmpty)
}))
}
func TestIsMobileIP(t *testing.T) {
Convey("Unicom IsMobileIP", t, WithService(func(s *Service) {
res := s.IsMobileIP(1, "", "")
So(res, ShouldNotBeEmpty)
}))
}

View File

@@ -0,0 +1,78 @@
package mobile
import (
"bufio"
"io"
"os"
"strings"
"time"
"go-common/app/interface/main/app-wall/conf"
mobileDao "go-common/app/interface/main/app-wall/dao/mobile"
"go-common/app/interface/main/app-wall/model"
"go-common/app/interface/main/app-wall/model/mobile"
"go-common/library/log"
"go-common/library/stat/prom"
)
type Service struct {
c *conf.Config
dao *mobileDao.Dao
tick time.Duration
mobileIpCache []*mobile.MobileIP
ipPath string
// prom
pHit *prom.Prom
pMiss *prom.Prom
}
func New(c *conf.Config) (s *Service) {
s = &Service{
c: c,
dao: mobileDao.New(c),
tick: time.Duration(c.Tick),
mobileIpCache: []*mobile.MobileIP{},
ipPath: c.IPLimit.MobileIPFile,
// prom
pHit: prom.CacheHit,
pMiss: prom.CacheMiss,
}
s.loadIP()
return
}
func (s *Service) loadIP() {
var (
ip *mobile.MobileIP
file *os.File
line string
err error
ips []*mobile.MobileIP
)
if file, err = os.Open(s.ipPath); err != nil {
log.Error("mobileIPFile is null")
return
}
defer file.Close()
reader := bufio.NewReader(file)
for {
if line, err = reader.ReadString('\n'); err != nil {
if err == io.EOF {
err = nil
break
}
continue
}
lines := strings.Fields(line)
if len(lines) < 3 {
continue
}
ip = &mobile.MobileIP{
IPStartUint: model.InetAtoN(lines[1]),
IPEndUint: model.InetAtoN(lines[2]),
}
ips = append(ips, ip)
}
s.mobileIpCache = ips
log.Info("loadMobileIPCache success")
}

View File

@@ -0,0 +1,50 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = ["offer_test.go"],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/interface/main/app-wall/conf:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = ["offer.go"],
importpath = "go-common/app/interface/main/app-wall/service/offer",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/interface/main/app-wall/conf:go_default_library",
"//app/interface/main/app-wall/dao/callback:go_default_library",
"//app/interface/main/app-wall/dao/offer:go_default_library",
"//app/interface/main/app-wall/dao/padding:go_default_library",
"//app/interface/main/app-wall/model:go_default_library",
"//library/log:go_default_library",
"//vendor/github.com/pkg/errors:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,224 @@
package offer
import (
"context"
iaes "crypto/aes"
icipher "crypto/cipher"
"crypto/md5"
"encoding/hex"
"time"
"go-common/app/interface/main/app-wall/conf"
callbackdao "go-common/app/interface/main/app-wall/dao/callback"
offerdao "go-common/app/interface/main/app-wall/dao/offer"
"go-common/app/interface/main/app-wall/dao/padding"
"go-common/app/interface/main/app-wall/model"
"go-common/library/log"
"github.com/pkg/errors"
)
type Service struct {
c *conf.Config
dao *offerdao.Dao
cbdao *callbackdao.Dao
}
func New(c *conf.Config) (s *Service) {
s = &Service{
c: c,
dao: offerdao.New(c),
cbdao: callbackdao.New(c),
}
return
}
// Click
func (s *Service) Click(c context.Context, ip uint32, cid, mac, idfa, cb string, now time.Time) (err error) {
res, err := s.dao.InClick(c, ip, cid, mac, idfa, cb, now)
if err != nil || res == 0 {
log.Error("s.dao.InClick(%d, %s, %s, %s, %s) error(%v) or row==0", ip, cid, mac, idfa, cb, now, err)
}
return
}
// ANClick
func (s *Service) ANClick(c context.Context, channel, imei, androidid, mac, cb string, ip uint32, now time.Time) (err error) {
res, err := s.dao.InANClick(c, channel, imei, androidid, mac, cb, ip, now)
if err != nil {
return
}
if res == 0 {
log.Error("s.dao.InANClick(%s, %s, %s, %s, %s, %d, %s) row==0", channel, imei, androidid, mac, cb, ip, now, err)
}
return
}
func (s *Service) ANActive(c context.Context, imei, androidid, mac string, now time.Time) (err error) {
const (
_typeUnactive = 0
_typeActive = 1
)
//gdt
gdtImei := model.GdtIMEI(imei)
count, err := s.dao.ANActive(c, androidid, imei, gdtImei)
if err != nil {
return
}
if count > 0 {
log.Warn("ANActive androidid(%s) imei(%s) gdtImei(%s) already count(%d) activated", androidid, imei, gdtImei, count)
return
}
id, channel, cb, typ, err := s.dao.ANCallback(c, androidid, imei, gdtImei)
if err != nil {
return
}
if id == 0 {
log.Warn("ANActive androidid(%s) imei(%s) gdtImei(%s) not exist", androidid, imei, gdtImei)
return
}
if typ != _typeUnactive {
log.Warn("ANActive androidid(%s) imei(%s) gdtImei(%s) already activated", androidid, imei, gdtImei)
return
}
if err = s.newCallback(c, model.TypeAndriod, channel, imei, gdtImei, cb, now); err != nil {
err = errors.Wrapf(err, "%d", id)
return
}
if _, err = s.dao.ANClickAct(c, id, _typeActive); err != nil {
return
}
return
}
func (s *Service) newCallback(c context.Context, appType, channel string, imei, gdtImei, cb string, now time.Time) (err error) {
const (
_eventActive = "0"
)
switch channel {
case model.ChannelToutiao:
err = s.cbdao.ToutiaoCallback(c, cb, _eventActive)
// gdt
case model.ChannelShike:
err = s.cbdao.ShikeCallback(c, imei, cb, now)
case model.ChannelDontin:
err = s.cbdao.DontinCallback(c, imei, cb)
default:
if _, ok := model.ChannelGdt[channel]; ok {
if appID, ok := model.AppIDGdt[appType]; ok {
err = s.cbdao.GdtCallback(c, appID, appType, channel, gdtImei, cb, now)
}
} else {
log.Warn("channel(%s) undefined", channel)
}
}
return
}
func (s *Service) Active(c context.Context, ip uint32, mid, rmac, mac, idfa, device string, now time.Time) (err error) {
var (
count int
)
res, err := s.dao.InActive(c, ip, mid, rmac, mac, idfa, device, now)
if err != nil {
log.Error("s.dao.InActive(%d, %s, %s, %s, %s, %s) error(%v) or row==0", ip, mid, rmac, mac, idfa, device, err)
return
}
if res == 0 {
log.Warn("wall active(%s) exist", idfa)
return
}
if rmac != "" {
count, err = s.dao.RMacCount(c, rmac)
if err != nil {
log.Error("s.dao.RMacCount(%s) error(%d)", rmac, err)
return
}
if count > 10 {
log.Warn("wallService.RMacCount(%s) count(%d) more than 10", rmac, count)
return
}
}
return s.callback(c, model.TypeIOS, idfa, now)
}
func (s *Service) Exists(c context.Context, idfa string) (exist bool, err error) {
exist, err = s.dao.Exists(c, idfa)
if err != nil {
log.Error("s.dao.Exists(%s) error(%v)", idfa, err)
}
return
}
// callback
func (s *Service) callback(c context.Context, appType, idfa string, now time.Time) (err error) {
if len(idfa) <= 20 {
return
}
// only gdt
allIdfa := idfa[0:8] + "-" + idfa[8:12] + "-" + idfa[12:16] + "-" + idfa[16:20] + "-" + idfa[20:]
bs := md5.Sum([]byte(allIdfa))
gdtIdfa := hex.EncodeToString(bs[:])
// get callback
channel, cb, err := s.dao.Callback(c, idfa, gdtIdfa, now)
if err != nil {
log.Error("s.dao.Callback(%s) error(%v)", idfa, err)
return
}
if cb == "" {
log.Info("callback idfa(%s) callback url is not exists", idfa)
return
}
switch channel {
case model.ChannelShike:
s.cbdao.ShikeCallback(c, idfa, cb, now)
s.dao.UpIdfaActive(c, allIdfa, idfa, now)
case model.ChannelDontin:
s.cbdao.DontinCallback(c, idfa, cb)
s.dao.UpIdfaActive(c, allIdfa, idfa, now)
default:
if _, ok := model.ChannelGdt[channel]; ok {
if appID, ok := model.AppIDGdt[appType]; ok {
if err = s.cbdao.GdtCallback(c, appID, appType, channel, gdtIdfa, cb, now); err != nil {
s.dao.UpIdfaActive(c, allIdfa, gdtIdfa, now)
}
}
} else {
log.Warn("channel(%s) undefined", channel)
}
}
return
}
// CBCDecrypt aes cbc decrypt.
func (s *Service) CBCDecrypt(src, key, iv []byte, p padding.Padding) ([]byte, error) {
var (
ErrAesSrcSize = errors.New("ciphertext too short")
ErrAesIVSize = errors.New("iv size is not a block size")
)
// check src
if len(src) < iaes.BlockSize || len(src)%iaes.BlockSize != 0 {
log.Info("check src src(%v) blockSize (%v)", src, iaes.BlockSize)
log.Info("len(src) < iaes.BlockSize (%v)", len(src) < iaes.BlockSize)
log.Info("len(src)%iaes.BlockSize != 0 (%v)", len(src)%iaes.BlockSize != 0)
return nil, ErrAesSrcSize
}
// check iv
if len(iv) != iaes.BlockSize {
log.Info("check iv iv(%v) blockSize (%v)", iv, iaes.BlockSize)
return nil, ErrAesIVSize
}
block, err := iaes.NewCipher(key)
if err != nil {
log.Error("iaes.NewCipher err(%v)", err)
return nil, err
}
mode := icipher.NewCBCDecrypter(block, iv)
decryptText := make([]byte, len(src))
mode.CryptBlocks(decryptText, src)
if p == nil {
return decryptText, nil
} else {
return p.Unpadding(decryptText, iaes.BlockSize)
}
}

View File

@@ -0,0 +1,58 @@
package offer
import (
"context"
"flag"
"path/filepath"
"testing"
"time"
"go-common/app/interface/main/app-wall/conf"
. "github.com/smartystreets/goconvey/convey"
)
var (
s *Service
)
func init() {
dir, _ := filepath.Abs("../../cmd/app-wall-test.toml")
flag.Set("conf", dir)
conf.Init()
s = New(conf.Conf)
}
func WithService(f func(s *Service)) func() {
return func() {
f(s)
}
}
func TestTelecomPay(t *testing.T) {
Convey("TelecomPay", t, WithService(func(s *Service) {
err := s.Click(context.TODO(), 1, "", "", "", "", time.Now())
So(err, ShouldBeNil)
}))
}
func TestANClick(t *testing.T) {
Convey("ANClick", t, WithService(func(s *Service) {
err := s.ANClick(context.TODO(), "", "", "", "", "", 1, time.Now())
So(err, ShouldBeNil)
}))
}
func TestANActive(t *testing.T) {
Convey("ANActive", t, WithService(func(s *Service) {
err := s.ANActive(context.TODO(), "", "", "", time.Now())
So(err, ShouldBeNil)
}))
}
func TestActive(t *testing.T) {
Convey("Active", t, WithService(func(s *Service) {
err := s.Active(context.TODO(), 1, "", "", "", "", "", time.Now())
So(err, ShouldBeNil)
}))
}

View File

@@ -0,0 +1,45 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = ["operator_test.go"],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/interface/main/app-wall/conf:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = ["operator.go"],
importpath = "go-common/app/interface/main/app-wall/service/operator",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/interface/main/app-wall/conf:go_default_library",
"//app/interface/main/app-wall/model/operator:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,42 @@
package operator
import (
"time"
"go-common/app/interface/main/app-wall/conf"
"go-common/app/interface/main/app-wall/model/operator"
)
// Service reddot service
type Service struct {
c *conf.Config
cache *operator.Reddot
}
// New reddot new
func New(c *conf.Config) (s *Service) {
s = &Service{
c: c,
cache: &operator.Reddot{},
}
s.loadCache(c)
return
}
// Reddot get reddot
func (s *Service) Reddot(now time.Time) (res *operator.Reddot) {
res = s.cache
if res != nil {
current := now.Unix()
if current > int64(res.EndTime) || current < int64(res.StartTime) {
res = &operator.Reddot{}
}
}
return
}
func (s *Service) loadCache(c *conf.Config) {
tmp := &operator.Reddot{}
tmp.ReddotChange(c.Reddot.StartTime, c.Reddot.EndTime)
s.cache = tmp
}

View File

@@ -0,0 +1,37 @@
package operator
import (
"flag"
"path/filepath"
"testing"
"time"
"go-common/app/interface/main/app-wall/conf"
. "github.com/smartystreets/goconvey/convey"
)
var (
s *Service
)
func WithService(f func(s *Service)) func() {
return func() {
f(s)
}
}
func init() {
dir, _ := filepath.Abs("../../cmd/app-wall-test.toml")
flag.Set("conf", dir)
conf.Init()
s = New(conf.Conf)
time.Sleep(time.Second)
}
func TestReddot(t *testing.T) {
Convey("operator Reddot", t, WithService(func(s *Service) {
res := s.Reddot(time.Now())
So(res, ShouldNotBeEmpty)
}))
}

View File

@@ -0,0 +1,45 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = ["ping_test.go"],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/interface/main/app-wall/conf:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = ["ping.go"],
importpath = "go-common/app/interface/main/app-wall/service/ping",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/interface/main/app-wall/conf:go_default_library",
"//app/interface/main/app-wall/dao/wall:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,24 @@
package ping
import (
"context"
"go-common/app/interface/main/app-wall/conf"
walldao "go-common/app/interface/main/app-wall/dao/wall"
)
type Service struct {
wallDao *walldao.Dao
}
func New(c *conf.Config) (s *Service) {
s = &Service{
wallDao: walldao.New(c),
}
return
}
// Ping is check server ping.
func (s *Service) Ping(c context.Context) (err error) {
return s.wallDao.Ping(c)
}

View File

@@ -0,0 +1,38 @@
package ping
import (
"context"
"flag"
"path/filepath"
"testing"
"time"
"go-common/app/interface/main/app-wall/conf"
. "github.com/smartystreets/goconvey/convey"
)
var (
s *Service
)
func WithService(f func(s *Service)) func() {
return func() {
f(s)
}
}
func init() {
dir, _ := filepath.Abs("../../cmd/app-wall-test.toml")
flag.Set("conf", dir)
conf.Init()
s = New(conf.Conf)
time.Sleep(time.Second)
}
func TestPing(t *testing.T) {
Convey("Unicom Ping", t, WithService(func(s *Service) {
err := s.Ping(context.TODO())
So(err, ShouldBeNil)
}))
}

View File

@@ -0,0 +1,54 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = ["telecom_test.go"],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/interface/main/app-wall/conf:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"service.go",
"telecom.go",
],
importpath = "go-common/app/interface/main/app-wall/service/telecom",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/interface/main/app-wall/conf:go_default_library",
"//app/interface/main/app-wall/dao/seq:go_default_library",
"//app/interface/main/app-wall/dao/telecom:go_default_library",
"//app/interface/main/app-wall/model/telecom:go_default_library",
"//library/ecode:go_default_library",
"//library/log:go_default_library",
"//library/stat/prom:go_default_library",
"//library/sync/errgroup:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,80 @@
package telecom
import (
"fmt"
"go-common/app/interface/main/app-wall/conf"
seqDao "go-common/app/interface/main/app-wall/dao/seq"
telecomDao "go-common/app/interface/main/app-wall/dao/telecom"
"go-common/library/log"
"go-common/library/stat/prom"
)
const (
_initIPlimitKey = "iplimit_%v_%v"
_telecomKey = "telecom"
)
type Service struct {
c *conf.Config
dao *telecomDao.Dao
seqdao *seqDao.Dao
flowPercentage int
smsTemplate string
smsMsgTemplate string
smsFlowTemplate string
smsOrderTemplateOK string
operationIPlimit map[string]struct{}
telecomArea map[string]struct{}
// prom
pHit *prom.Prom
pMiss *prom.Prom
}
func New(c *conf.Config) (s *Service) {
s = &Service{
c: c,
dao: telecomDao.New(c),
seqdao: seqDao.New(c),
flowPercentage: c.Telecom.FlowPercentage,
smsTemplate: c.Telecom.SMSTemplate,
smsMsgTemplate: c.Telecom.SMSMsgTemplate,
smsFlowTemplate: c.Telecom.SMSFlowTemplate,
smsOrderTemplateOK: c.Telecom.SMSOrderTemplateOK,
operationIPlimit: map[string]struct{}{},
telecomArea: map[string]struct{}{},
// prom
pHit: prom.CacheHit,
pMiss: prom.CacheMiss,
}
go s.loadIPlimit(c)
go s.loadTelecomArea(c)
return
}
func (s *Service) loadIPlimit(c *conf.Config) {
hosts := make(map[string]struct{}, len(c.IPLimit.Addrs))
for k, v := range c.IPLimit.Addrs {
for _, ipStr := range v {
key := fmt.Sprintf(_initIPlimitKey, k, ipStr)
if _, ok := hosts[key]; !ok {
hosts[key] = struct{}{}
}
}
}
s.operationIPlimit = hosts
log.Info("loadTelecomIPCache success")
}
func (s *Service) loadTelecomArea(c *conf.Config) {
areas := make(map[string]struct{}, len(c.Telecom.Area))
for _, v := range c.Telecom.Area {
for _, area := range v {
if _, ok := areas[area]; !ok {
areas[area] = struct{}{}
}
}
}
s.telecomArea = areas
log.Info("loadTelecomArea success")
}

View File

@@ -0,0 +1,488 @@
package telecom
import (
"bytes"
"context"
"crypto/des"
"errors"
"fmt"
"math/rand"
"strconv"
"time"
"go-common/app/interface/main/app-wall/model/telecom"
"go-common/library/ecode"
"go-common/library/log"
"go-common/library/sync/errgroup"
)
const (
_sendSMSCaptcha = `{"captcha":"%v"}`
_sendSMSFlow = `{"flow":"%v"}`
_flowPackageID = 279
)
// InOrdersSync insert OrdersSync
func (s *Service) InOrdersSync(c context.Context, ip string, u *telecom.TelecomOrderJson) (err error) {
if !s.iplimit(_telecomKey, ip) {
err = ecode.AccessDenied
return
}
if u == nil || u.Detail == nil {
err = ecode.NothingFound
return
}
var (
result int64
requestNo int
phoneStr string
detail = u.Detail
)
detail.TelecomJSONChange()
requestNo, _ = strconv.Atoi(u.RequestNo)
if detail.PhoneID == "" {
if phoneStr, err = s.dao.PayPhone(c, int64(requestNo)); err != nil {
log.Error("telecom_s.dao.PayPhone error(%v)", err)
return
}
} else {
phoneStr = detail.PhoneID
}
if result, err = s.dao.InOrderSync(c, requestNo, u.ResultType, phoneStr, detail); err != nil || result == 0 {
log.Error("telecom_s.dao.OrdersSync (%v) error(%v) or result==0", u, err)
return
}
if detail.OrderStatus == 3 {
phoneInt, _ := strconv.Atoi(phoneStr)
if err = s.dao.SendTelecomSMS(c, phoneInt, s.smsOrderTemplateOK); err != nil {
log.Error("telecom_s.dao.SendTelecomSMS error(%v)", err)
return
}
}
return
}
// InRechargeSync insert RechargeSync
func (s *Service) InRechargeSync(c context.Context, ip string, u *telecom.RechargeJSON) (err error) {
if !s.iplimit(_telecomKey, ip) {
err = ecode.AccessDenied
return
}
var result int64
if result, err = s.dao.InRechargeSync(c, u); err != nil || result == 0 {
log.Error("telecom_s.dao.InRechargeSync (%v) error(%v) or result==0", u, err)
return
}
return
}
// telecomMessageOrder
func (s *Service) TelecomMessageSync(c context.Context, ip string, u *telecom.TelecomMessageJSON) (err error) {
if !s.iplimit(_telecomKey, ip) {
err = ecode.AccessDenied
return
}
if u == nil {
err = ecode.ServerErr
return
}
phoneInt, _ := strconv.Atoi(u.PhoneID)
if err = s.dao.SendTelecomSMS(c, phoneInt, s.smsMsgTemplate); err != nil {
log.Error("telecom_s.dao.SendTelecomSMS error(%v)", err)
return
}
return
}
// telecomInfo
func (s *Service) telecomInfo(c context.Context, phone int) (res map[int]*telecom.OrderInfo, err error) {
var (
row *telecom.OrderInfo
)
res = map[int]*telecom.OrderInfo{}
if row, err = s.dao.TelecomCache(c, phone); err == nil && row != nil {
res[phone] = row
s.pHit.Incr("telecom_cache")
return
}
if res, err = s.dao.OrdersUserFlow(c, phone); err != nil {
log.Error("telecom_s.dao.OrdersUserFlow phone (%v) error(%v)", phone, err)
return
}
s.pMiss.Incr("telecom_cache")
if user, ok := res[phone]; ok {
if err = s.dao.AddTelecomCache(c, phone, user); err != nil {
log.Error("telecom_s.dao.AddTelecomCache error(%v)", err)
return
}
}
return
}
// telecomInfoByOrderID
func (s *Service) telecomInfoByOrderID(c context.Context, orderID int64) (res map[int64]*telecom.OrderInfo, err error) {
var (
row *telecom.OrderInfo
)
res = map[int64]*telecom.OrderInfo{}
if row, err = s.dao.TelecomOrderIDCache(c, orderID); err == nil && row != nil {
res[orderID] = row
s.pHit.Incr("telecom_orderid_cache")
return
}
if res, err = s.dao.OrdersUserByOrderID(c, orderID); err != nil {
log.Error("telecom_s.dao.OrdersUserByOrderID phone (%v) error(%v)", orderID, err)
return
}
s.pMiss.Incr("telecom_orderid_cache")
if user, ok := res[orderID]; ok {
if err = s.dao.AddTelecomOrderIDCache(c, orderID, user); err != nil {
log.Error("telecom_s.dao.AddTelecomOrderIDCache error(%v)", err)
return
}
}
return
}
// TelecomPay
func (s *Service) TelecomPay(c context.Context, phone, isRepeatOrder, payChannel, payAction int, orderID int64, ipStr string) (res *telecom.Pay, msg string, err error) {
var (
requestNo int64
t map[int]*telecom.OrderInfo
rcode int
beginTime time.Time
firstOrderEndtime time.Time
)
if requestNo, err = s.seqdao.SeqID(c); err != nil {
log.Error("telecom_s.seqdao.SeqID error (%v)", err)
return
}
if t, err = s.telecomInfo(c, phone); err != nil {
log.Error("telecom_s.telecomInfo phone(%v) error (%v)", phone, err)
return
}
if user, ok := t[phone]; ok {
beginTime = user.Begintime.Time()
firstOrderEndtime = user.Endtime.Time()
}
if res, err, msg = s.dao.PayInfo(c, requestNo, phone, isRepeatOrder, payChannel, payAction, orderID, ipStr, beginTime, firstOrderEndtime); err != nil || res == nil {
log.Error("telecom_s.dao.PayInfo requestNo (%v) phone (%v) isRepeatOrder (%v) payChannel (%v) payAction (%v) t.OrderID (%v) ipStr (%v) error (%v)",
requestNo, phone, isRepeatOrder, payChannel, payAction, orderID, ipStr, err)
return
}
phoneStr := strconv.Itoa(phone)
if rcode, err = s.dao.AddPayPhone(c, requestNo, phoneStr); err != nil || rcode != 1 {
log.Error("telecom_s.dao.AddPayPhone error (%v)", err)
return
}
return
}
// CancelRepeatOrder
func (s *Service) CancelRepeatOrder(c context.Context, phone int) (msg string, err error) {
var (
res map[int]*telecom.OrderInfo
)
res, err = s.telecomInfo(c, phone)
if err != nil {
log.Error("telecom_s.telecomInfo phone(%v) error (%v)", phone, err)
return
}
user, ok := res[phone]
if !ok {
err = ecode.NothingFound
msg = "订单不存在"
return
}
if msg, err = s.dao.CancelRepeatOrder(c, phone, user.SignNo); err != nil {
log.Error("telecom_s.dao.CancelRepeatOrder phone(%v) signNo(%v) error (%v)", phone, user.SignNo, err)
return
}
return
}
// OrderList user order list
func (s *Service) OrderList(c context.Context, orderID int64, phone int) (res *telecom.SucOrder, msg string, err error) {
if res, err, msg = s.dao.SucOrderList(c, phone); err != nil || res == nil {
log.Error("telecom_s.dao.SucOrderList orderID (%v) phone (%v) error (%v)", orderID, phone, err)
return
}
return
}
// PhoneFlow user flow
func (s *Service) PhoneFlow(c context.Context, orderID int64, phone int) (res *telecom.OrderFlow, msg string, err error) {
var t *telecom.SucOrder
if t, err, msg = s.dao.SucOrderList(c, phone); err != nil || t == nil {
log.Error("telecom_s.dao.SucOrderList orderID (%v) phone (%v) error (%v)", orderID, phone, err)
return
}
res = &telecom.OrderFlow{
FlowBalance: t.FlowBalance,
}
if (t.FlowBalance/t.FlowPackageSize)*100 < s.flowPercentage {
flow := strconv.Itoa(t.FlowBalance)
dataJSON := fmt.Sprintf(_sendSMSFlow, flow)
if err = s.dao.SendSMS(c, phone, s.smsFlowTemplate, dataJSON); err != nil {
log.Error("telecom_s.dao.SendSMS phone(%v) error (%v)", phone, err)
return
}
msg = "免流量量剩余不不⾜足10%,超出部分会按正常流量量资费计费"
return
}
return
}
// OrderConsent user orderConsent
func (s *Service) OrderConsent(c context.Context, phone int, orderID int64, captcha string) (res *telecom.PhoneConsent, msg string, err error) {
var (
area string
t *telecom.SucOrder
captchaStr string
order *telecom.OrderPhoneState
)
captchaStr, err = s.dao.PhoneCode(c, phone)
if err != nil {
log.Error("telecom_s.dao.PhoneCode error (%v)", err)
msg = "验证码已过期"
return
}
if captchaStr == "" || captchaStr != captcha {
err = ecode.NotModified
msg = "验证码错误"
return
}
res = &telecom.PhoneConsent{
Consent: 0,
}
g, ctx := errgroup.WithContext(c)
g.Go(func() error {
if area, err, msg = s.dao.PhoneArea(ctx, phone); err != nil {
log.Error("telecom_s.dao.PhoneArea phone(%v) error (%v)", phone, err)
return err
}
return nil
})
g.Go(func() error {
if t, err, _ = s.dao.SucOrderList(ctx, phone); err != nil {
if err == ecode.NothingFound {
err = nil
} else {
log.Error("telecom_s.dao.SucOrderList sphone (%v) error (%v)", phone, err)
}
return err
}
return nil
})
if orderID > 0 {
g.Go(func() error {
if order, err = s.dao.OrderState(ctx, orderID); err != nil {
log.Error("telecom_s.dao.OrderState phone(%v) orderID(%v) error(%v)", phone, orderID, err)
return err
}
return nil
})
}
if err = g.Wait(); err != nil {
log.Error("telecom_errgroup.WithContext error(%v)", err)
return
}
if len(area) >= 4 {
a := area[:4]
if _, ok := s.telecomArea[a]; !ok {
return
}
}
if order != nil && order.OrderState == 2 && order.FlowPackageID == _flowPackageID {
res.Consent = 3
return
}
if t != nil && t.OrderID > 0 {
res.Consent = 2
return
}
res.Consent = 1
return
}
// PhoneCode
func (s *Service) PhoneCode(c context.Context, phone int, captcha string, now time.Time) (res *telecom.Pay, err error, msg string) {
var (
captchaStr string
order map[int]*telecom.OrderInfo
)
captchaStr, err = s.dao.PhoneCode(c, phone)
if err != nil {
log.Error("telecom_s.dao.PhoneCode error (%v)", err)
msg = "验证码已过期"
return
}
if captchaStr == "" || captchaStr != captcha {
err = ecode.NotModified
msg = "验证码错误"
return
}
if order, err = s.telecomInfo(c, phone); err != nil {
log.Error("telecom_s.telecomInfo phone(%v) error (%v)", phone, err)
return
}
user, ok := order[phone]
if !ok {
err = ecode.NothingFound
msg = "订单不存在"
return
}
switch user.OrderState {
case 2:
err = ecode.NotModified
msg = "订购中"
case 3:
if now.Unix() > int64(user.Endtime) {
err = ecode.NotModified
msg = "订单已过期"
} else {
res = &telecom.Pay{
OrderID: user.OrderID,
}
msg = "激活成功,麻麻再也不不⽤用担⼼心我的流量量了了(/≧▽≦)/"
}
case 4:
err = ecode.NotModified
msg = "订单失败"
case 5:
err = ecode.NotModified
msg = "订单已过期"
}
return
}
// PhoneSendSMS
func (s *Service) PhoneSendSMS(c context.Context, phone int) (err error) {
var (
captcha string
rcode int
)
r := rand.New(rand.NewSource(time.Now().UnixNano()))
for i := 0; i < 6; i++ {
captcha = captcha + strconv.Itoa(r.Intn(10))
}
dataJSON := fmt.Sprintf(_sendSMSCaptcha, captcha)
if err = s.dao.SendSMS(c, phone, s.smsTemplate, dataJSON); err != nil {
log.Error("telecom_s.dao.SendSMS error (%v)", err)
return
}
if rcode, err = s.dao.AddPhoneCode(c, phone, captcha); err != nil || rcode != 1 {
log.Error("telecom_s.dao.AddPhoneCode error (%v)", err)
return
}
return
}
// OrderState
func (s *Service) OrderState(c context.Context, orderid int64) (t *telecom.OrderState, msg string, err error) {
var (
orderState *telecom.OrderPhoneState
torder map[int64]*telecom.OrderInfo
userOrder *telecom.OrderInfo
tSucOrder *telecom.SucOrder
ok bool
)
g, ctx := errgroup.WithContext(c)
log.Error("userOrder.PhoneID_test")
g.Go(func() error {
if orderState, err = s.dao.OrderState(ctx, orderid); err != nil {
log.Error("telecom_s.dao.OrderState orderID error(%v)", orderid, err)
return err
}
return nil
})
g.Go(func() error {
if torder, err = s.telecomInfoByOrderID(c, orderid); err != nil {
log.Error("telecom_s.telecomInfoByOrderID error(%v)", orderid, err)
return err
}
if userOrder, ok = torder[orderid]; ok {
if tSucOrder, err, _ = s.dao.SucOrderList(ctx, userOrder.PhoneID); err != nil {
if err == ecode.NothingFound {
err = nil
} else {
log.Error("telecom_s.dao.SucOrderList sphone (%v) error (%v)", userOrder.PhoneID, err)
}
return err
}
}
return nil
})
if err = g.Wait(); err != nil {
log.Error("telecom_errgroup.WithContext error(%v)", err)
return
}
if orderState == nil {
t = &telecom.OrderState{
OrderState: 1,
}
return
}
t = &telecom.OrderState{
OrderState: orderState.OrderState,
FlowSize: orderState.FlowSize,
}
if tSucOrder != nil && tSucOrder.OrderID > 0 {
t.FlowBalance = tSucOrder.FlowBalance
t.FlowSize = tSucOrder.FlowPackageSize
}
if ok {
t.IsRepeatorder = userOrder.IsRepeatorder
if userOrder.IsRepeatorder == 0 {
t.Endtime = userOrder.Endtime
}
}
switch t.OrderState {
case 6:
if !ok {
err = ecode.NothingFound
msg = "订单不存在"
return
}
t.Endtime = userOrder.Endtime
}
return
}
// telecomIp ip limit
func (s *Service) iplimit(k, ip string) bool {
key := fmt.Sprintf(_initIPlimitKey, k, ip)
if _, ok := s.operationIPlimit[key]; ok {
return true
}
return false
}
// DesDecrypt
func (s *Service) DesDecrypt(src, key []byte) ([]byte, error) {
block, err := des.NewCipher(key)
if err != nil {
return nil, err
}
out := make([]byte, len(src))
dst := out
bs := block.BlockSize()
if len(src)%bs != 0 {
return nil, errors.New("crypto/cipher: input not full blocks")
}
for len(src) > 0 {
block.Decrypt(dst, src[:bs])
src = src[bs:]
dst = dst[bs:]
}
out = s.zeroUnPadding(out)
return out, nil
}
// zeroUnPadding
func (s *Service) zeroUnPadding(origData []byte) []byte {
return bytes.TrimFunc(origData,
func(r rune) bool {
return r == rune(0)
})
}

View File

@@ -0,0 +1,94 @@
package telecom
import (
"context"
"flag"
"path/filepath"
"testing"
"time"
"go-common/app/interface/main/app-wall/conf"
. "github.com/smartystreets/goconvey/convey"
)
var (
s *Service
)
func WithService(f func(s *Service)) func() {
return func() {
f(s)
}
}
func init() {
dir, _ := filepath.Abs("../../cmd/app-wall-test.toml")
flag.Set("conf", dir)
conf.Init()
s = New(conf.Conf)
time.Sleep(time.Second)
}
func TestTelecomPay(t *testing.T) {
Convey("TelecomPay", t, WithService(func(s *Service) {
res, _, err := s.TelecomPay(context.TODO(), 1, 1, 1, 1, 1, "")
So(res, ShouldNotBeEmpty)
So(err, ShouldBeNil)
}))
}
func TestCancelRepeatOrder(t *testing.T) {
Convey("CancelRepeatOrder", t, WithService(func(s *Service) {
res, err := s.CancelRepeatOrder(context.TODO(), 1)
So(res, ShouldNotBeEmpty)
So(err, ShouldBeNil)
}))
}
func TestOrderList(t *testing.T) {
Convey("OrderList", t, WithService(func(s *Service) {
res, _, err := s.OrderList(context.TODO(), 1, 1)
So(res, ShouldNotBeEmpty)
So(err, ShouldBeNil)
}))
}
func TestPhoneFlow(t *testing.T) {
Convey("PhoneFlow", t, WithService(func(s *Service) {
res, _, err := s.PhoneFlow(context.TODO(), 1, 1)
So(res, ShouldNotBeEmpty)
So(err, ShouldBeNil)
}))
}
func TestOrderConsent(t *testing.T) {
Convey("OrderConsent", t, WithService(func(s *Service) {
res, _, err := s.OrderConsent(context.TODO(), 1, 1, "")
So(res, ShouldNotBeEmpty)
So(err, ShouldBeNil)
}))
}
func TestPhoneCode(t *testing.T) {
Convey("PhoneCode", t, WithService(func(s *Service) {
res, _, err := s.PhoneCode(context.TODO(), 1, "", time.Now())
So(res, ShouldNotBeEmpty)
So(err, ShouldBeNil)
}))
}
func TestPhoneSendSMS(t *testing.T) {
Convey("PhoneSendSMS", t, WithService(func(s *Service) {
err := s.PhoneSendSMS(context.TODO(), 1)
So(err, ShouldBeNil)
}))
}
func TestOrderState(t *testing.T) {
Convey("OrderState", t, WithService(func(s *Service) {
res, _, err := s.OrderState(context.TODO(), 1)
So(res, ShouldNotBeEmpty)
So(err, ShouldBeNil)
}))
}

View File

@@ -0,0 +1,66 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = ["unicom_test.go"],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/interface/main/app-wall/conf:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"cache.go",
"databus.go",
"infoc.go",
"pack.go",
"service.go",
"unicom.go",
],
importpath = "go-common/app/interface/main/app-wall/service/unicom",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/interface/main/app-wall/conf:go_default_library",
"//app/interface/main/app-wall/dao/account:go_default_library",
"//app/interface/main/app-wall/dao/live:go_default_library",
"//app/interface/main/app-wall/dao/seq:go_default_library",
"//app/interface/main/app-wall/dao/shopping:go_default_library",
"//app/interface/main/app-wall/dao/unicom:go_default_library",
"//app/interface/main/app-wall/model:go_default_library",
"//app/interface/main/app-wall/model/unicom:go_default_library",
"//app/service/main/account/model:go_default_library",
"//library/cache/memcache:go_default_library",
"//library/ecode:go_default_library",
"//library/log:go_default_library",
"//library/log/infoc:go_default_library",
"//library/queue/databus:go_default_library",
"//library/queue/databus/report:go_default_library",
"//library/stat/prom:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,203 @@
package unicom
import (
"context"
"fmt"
"time"
"go-common/app/interface/main/app-wall/conf"
"go-common/app/interface/main/app-wall/model/unicom"
"go-common/library/cache/memcache"
"go-common/library/ecode"
log "go-common/library/log"
)
const (
_initIPUnicomKey = "ipunicom_%v_%v"
)
// loadUnicomIP load unicom ip
func (s *Service) loadUnicomIP() {
unicomIP, err := s.dao.IPSync(context.TODO())
if err != nil {
log.Error("s.dao.IPSync error(%v)", err)
return
}
s.unicomIpCache = unicomIP
tmp := map[string]*unicom.UnicomIP{}
for _, u := range s.unicomIpCache {
key := fmt.Sprintf(_initIPUnicomKey, u.Ipbegin, u.Ipend)
tmp[key] = u
}
s.unicomIpSQLCache = tmp
log.Info("loadUnicomIPCache success")
}
// loadIPlimit ip limit
func (s *Service) loadIPlimit(c *conf.Config) {
hosts := make(map[string]struct{}, len(c.IPLimit.Addrs))
for k, v := range c.IPLimit.Addrs {
for _, ipStr := range v {
key := fmt.Sprintf(_initIPlimitKey, k, ipStr)
if _, ok := hosts[key]; !ok {
hosts[key] = struct{}{}
}
}
}
s.operationIPlimit = hosts
log.Info("load operationIPlimit success")
}
// loadUnicomIPOrder load unciom ip order update
func (s *Service) loadUnicomIPOrder(now time.Time) {
unicomIP, err := s.dao.UnicomIP(context.TODO(), now)
if err != nil {
log.Error("s.dao.UnicomIP(%v)", err)
return
}
if len(unicomIP) == 0 {
log.Info("unicom ip orders is null")
return
}
tx, err := s.dao.BeginTran(context.TODO())
if err != nil {
log.Error("s.dao.BeginTran error(%v)", err)
return
}
for _, uip := range unicomIP {
key := fmt.Sprintf(_initIPUnicomKey, uip.Ipbegin, uip.Ipend)
if _, ok := s.unicomIpSQLCache[key]; ok {
delete(s.unicomIpSQLCache, key)
continue
}
var (
result int64
)
if result, err = s.dao.InUnicomIPSync(tx, uip, time.Now()); err != nil || result == 0 {
tx.Rollback()
log.Error("s.dao.InUnicomIPSync error(%v)", err)
return
}
}
for _, uold := range s.unicomIpSQLCache {
var (
result int64
)
if result, err = s.dao.UpUnicomIP(tx, uold.Ipbegin, uold.Ipend, 0, time.Now()); err != nil || result == 0 {
tx.Rollback()
log.Error("s.dao.UpUnicomIP error(%v)", err)
return
}
}
if err = tx.Commit(); err != nil {
log.Error("tx.Commit error(%v)", err)
return
}
log.Info("update unicom ip success")
}
func (s *Service) loadUnicomPacks() {
pack, err := s.dao.UserPacks(context.TODO())
if err != nil {
log.Error("s.dao.UserPacks error(%v)", err)
return
}
s.unicomPackCache = pack
}
func (s *Service) loadUnicomFlow() {
var (
list map[string]*unicom.UnicomUserFlow
err error
)
if list, err = s.dao.UserFlowListCache(context.TODO()); err != nil {
log.Error("load unicom s.dao.UserFlowListCache error(%v)", err)
return
}
for key, u := range list {
var (
c = context.TODO()
requestNo int64
orderstatus string
msg string
)
if err = s.dao.UserFlowCache(c, key); err != nil {
if err == memcache.ErrNotFound {
if err = s.returnPoints(c, u); err != nil {
if err != ecode.NothingFound {
log.Error("load unicom s.returnPoints error(%v)", err)
continue
}
err = nil
}
log.Info("load unicom userbind timeout flow(%v)", u)
} else {
log.Error("load unicom s.dao.UserFlowCache error(%v)", err)
continue
}
} else {
if requestNo, err = s.seqdao.SeqID(c); err != nil {
log.Error("load unicom s.seqdao.SeqID error(%v)", err)
continue
}
if orderstatus, msg, err = s.dao.FlowQry(c, u.Phone, requestNo, u.Outorderid, u.Orderid, time.Now()); err != nil {
log.Error("load unicom s.dao.FlowQry error(%v) msg(%s)", err, msg)
continue
}
log.Info("load unicom userbind flow(%v) orderstatus(%s)", u, orderstatus)
if orderstatus == "00" {
continue
} else if orderstatus != "01" {
if err = s.returnPoints(c, u); err != nil {
if err != ecode.NothingFound {
log.Error("load unicom s.returnPoints error(%v)", err)
continue
}
err = nil
}
}
}
delete(list, key)
if err = s.dao.DeleteUserFlowCache(c, key); err != nil {
log.Error("load unicom s.dao.DeleteUserFlowCache error(%v)", err)
continue
}
}
if err = s.dao.AddUserFlowListCache(context.TODO(), list); err != nil {
log.Error("load unicom s.dao.AddUserFlowListCache error(%v)", err)
return
}
log.Info("load unicom flow success")
}
// returnPoints retutn user integral and flow
func (s *Service) returnPoints(c context.Context, u *unicom.UnicomUserFlow) (err error) {
var (
userbind *unicom.UserBind
result int64
)
if userbind, err = s.unicomBindInfo(c, u.Mid); err != nil {
return
}
ub := &unicom.UserBind{}
*ub = *userbind
ub.Flow = ub.Flow + u.Flow
ub.Integral = ub.Integral + u.Integral
if err = s.dao.AddUserBindCache(c, ub.Mid, ub); err != nil {
log.Error("unicom s.dao.AddUserBindCache error(%v)", err)
return
}
if result, err = s.dao.UpUserIntegral(c, ub); err != nil || result == 0 {
log.Error("unicom s.dao.UpUserIntegral error(%v) or result==0", err)
return
}
var packInt int
if u.Integral > 0 {
packInt = u.Integral
} else {
packInt = u.Flow
}
log.Info("unicom_pack(%v) mid(%v)", u.Desc+",领取失败并返还", userbind.Mid)
s.unicomPackInfoc(userbind.Usermob, u.Desc+",领取失败并返还", u.Orderid, userbind.Phone, packInt, 0, userbind.Mid, time.Now())
return
}

View File

@@ -0,0 +1,38 @@
package unicom
import (
"context"
"strconv"
"go-common/app/interface/main/app-wall/model/unicom"
log "go-common/library/log"
)
func (s *Service) addUserBindState(u *unicom.UserBindInfo) {
select {
case s.userBindCh <- u:
default:
log.Warn("add user bind state buffer is full")
}
}
func (s *Service) userbindConsumer() {
defer s.waiter.Done()
for {
i, ok := <-s.userBindCh
if !ok {
return
}
var (
err error
)
switch v := i.(type) {
case *unicom.UserBindInfo:
if err = s.userbindPub.Send(context.TODO(), strconv.FormatInt(v.MID, 10), v); err != nil {
log.Error("s.userbindSub.Send error(%v)", err)
continue
}
log.Info("s.userbindSub.Send(%+v) success", v)
}
}
}

View File

@@ -0,0 +1,104 @@
package unicom
import (
"strconv"
"time"
"go-common/app/interface/main/app-wall/conf"
log "go-common/library/log"
binfoc "go-common/library/log/infoc"
)
type orderInfoc struct {
usermob string
orderType string
ip string
mobiApp string
build string
now string
}
type ipInfoc struct {
usermob string
isValide string
ip string
mobiApp string
build string
now string
}
type packInfoc struct {
usermob string
phone string
mid string
requestNo string
packName string
packIntegral string
packType string
now string
}
// Infoc write data for Hadoop do analytics
func (s *Service) unicomInfoc(mobiApp, usermob, ip string, build, orderType int, now time.Time) {
select {
case s.logCh <- orderInfoc{usermob, strconv.Itoa(orderType), ip, mobiApp, strconv.Itoa(build), strconv.FormatInt(now.Unix(), 10)}:
default:
log.Warn("unicomInfoc log buffer is full")
}
}
// Infoc write data for Hadoop do analytics
func (s *Service) ipInfoc(mobiApp, usermob, ip string, build int, isValide bool, now time.Time) {
select {
case s.logCh <- ipInfoc{usermob, strconv.FormatBool(isValide), ip, mobiApp, strconv.Itoa(build), strconv.FormatInt(now.Unix(), 10)}:
default:
log.Warn("ipInfoc log buffer is full")
}
}
func (s *Service) unicomInfocproc() {
var (
unicominf2 = binfoc.New(conf.Conf.UnicomUserInfoc2)
ipinf2 = binfoc.New(conf.Conf.UnicomIpInfoc2)
)
for {
i, ok := <-s.logCh
if !ok {
log.Warn("infoc proc exit")
return
}
switch v := i.(type) {
case orderInfoc:
unicominf2.Info(v.now, "0", v.usermob, v.orderType, v.ip, v.mobiApp, v.build)
case ipInfoc:
ipinf2.Info(v.now, "0", v.isValide, v.ip, v.usermob, v.mobiApp, v.build)
}
}
}
// unicomPackInfoc unicom pack infoc
func (s *Service) unicomPackInfoc(usermob, packName, orderNumber string, phone, packIntegral, packType int, mid int64, now time.Time) {
select {
case s.packCh <- packInfoc{usermob, strconv.Itoa(phone), strconv.FormatInt(mid, 10),
orderNumber, packName, strconv.Itoa(packIntegral), strconv.Itoa(packType), strconv.FormatInt(now.Unix(), 10)}:
default:
log.Warn("unicomPackInfoc log buffer is full")
}
}
func (s *Service) unicomPackInfocproc() {
var (
packinf = binfoc.New(conf.Conf.UnicomPackInfoc)
)
for {
i, ok := <-s.packCh
if !ok {
log.Warn("infoc proc exit")
return
}
switch v := i.(type) {
case packInfoc:
packinf.Info(v.now, "0", v.usermob, v.phone, v.mid, v.requestNo, v.packName, v.packIntegral, v.packType)
}
}
}

View File

@@ -0,0 +1,69 @@
package unicom
import (
"context"
"time"
"go-common/library/ecode"
"go-common/library/log"
)
// PrivilegePack
func (s *Service) Pack(c context.Context, usermob string, mid int64, now time.Time) (msg string, err error) {
row := s.unicomInfo(c, usermob, now)
u, ok := row[usermob]
if !ok || u == nil {
err = ecode.NothingFound
msg = "该卡号尚未开通哔哩哔哩专属免流服务"
return
}
var (
result int64
)
userpacke, err := s.userPack(c, usermob)
if err != nil {
log.Error("s.userPack error(%v)", err)
msg = "特权礼包领取失败"
return
}
var (
unicomPackOk bool
userPackOk bool
user map[int64]struct{}
)
if user, unicomPackOk = userpacke[usermob]; unicomPackOk {
_, userPackOk = user[mid]
}
if !unicomPackOk && !userPackOk {
result, err = s.dao.InPack(c, usermob, mid)
if err != nil {
log.Error("s.pack.InPack(%s, %s) error(%v)", usermob, mid, err)
} else if result == 0 {
err = ecode.RequestErr
msg = "每张卡只能领取一次特权礼包哦"
log.Error("s.pack.InPackc(%s,%s) error(%v) result==0", usermob, mid, err)
} else {
if err = s.live.Pack(c, mid, u.CardType); err != nil {
msg = "礼包领取失败"
log.Error("s.live.Pack mid error(%v)", mid, err)
}
}
} else if unicomPackOk {
err = ecode.NotModified
msg = "每张卡只能领取一次特权礼包哦"
} else if userPackOk {
err = ecode.NotModified
msg = "每个账号只能领取一次哦"
} else {
msg = "领取成功特权礼包将在1~3个⼯工作⽇日内发放到您的账号"
}
return
}
func (s *Service) userPack(c context.Context, usermob string) (pack map[string]map[int64]struct{}, err error) {
if pack, err = s.dao.Pack(c, usermob); err != nil {
log.Error("s.pack.Pack usermob:%v error(%v)", usermob, err)
return
}
return
}

View File

@@ -0,0 +1,97 @@
package unicom
import (
"sync"
"time"
"go-common/app/interface/main/app-wall/conf"
accdao "go-common/app/interface/main/app-wall/dao/account"
liveDao "go-common/app/interface/main/app-wall/dao/live"
seqDao "go-common/app/interface/main/app-wall/dao/seq"
shopDao "go-common/app/interface/main/app-wall/dao/shopping"
unicomDao "go-common/app/interface/main/app-wall/dao/unicom"
"go-common/app/interface/main/app-wall/model/unicom"
"go-common/library/queue/databus"
"go-common/library/stat/prom"
)
const (
_initIPlimitKey = "iplimit_%v_%v"
)
type Service struct {
c *conf.Config
dao *unicomDao.Dao
live *liveDao.Dao
seqdao *seqDao.Dao
accd *accdao.Dao
shop *shopDao.Dao
tick time.Duration
unicomIpCache []*unicom.UnicomIP
unicomIpSQLCache map[string]*unicom.UnicomIP
operationIPlimit map[string]struct{}
unicomPackCache []*unicom.UserPack
// infoc
logCh chan interface{}
packCh chan interface{}
packLogCh chan interface{}
userBindCh chan interface{}
// waiter
waiter sync.WaitGroup
// databus
userbindPub *databus.Databus
// prom
pHit *prom.Prom
pMiss *prom.Prom
}
func New(c *conf.Config) (s *Service) {
s = &Service{
c: c,
dao: unicomDao.New(c),
live: liveDao.New(c),
seqdao: seqDao.New(c),
accd: accdao.New(c),
shop: shopDao.New(c),
tick: time.Duration(c.Tick),
unicomIpCache: []*unicom.UnicomIP{},
unicomIpSQLCache: map[string]*unicom.UnicomIP{},
operationIPlimit: map[string]struct{}{},
unicomPackCache: []*unicom.UserPack{},
// databus
userbindPub: databus.New(c.UnicomDatabus),
// infoc
logCh: make(chan interface{}, 1024),
packCh: make(chan interface{}, 1024),
packLogCh: make(chan interface{}, 1024),
userBindCh: make(chan interface{}, 1024),
// prom
pHit: prom.CacheHit,
pMiss: prom.CacheMiss,
}
// now := time.Now()
s.loadIPlimit(c)
s.loadUnicomIP()
// s.loadUnicomIPOrder(now)
s.loadUnicomPacks()
// s.loadUnicomFlow()
go s.loadproc()
go s.unicomInfocproc()
go s.unicomPackInfocproc()
go s.addUserPackLogproc()
s.waiter.Add(1)
go s.userbindConsumer()
return
}
// cacheproc load cache
func (s *Service) loadproc() {
for {
time.Sleep(s.tick)
// now := time.Now()
s.loadUnicomIP()
// s.loadUnicomIPOrder(now)
s.loadUnicomPacks()
// s.loadUnicomFlow()
}
}

View File

@@ -0,0 +1,961 @@
package unicom
import (
"bytes"
"context"
"crypto/des"
"encoding/base64"
"errors"
"fmt"
"strconv"
"time"
"go-common/app/interface/main/app-wall/model"
"go-common/app/interface/main/app-wall/model/unicom"
account "go-common/app/service/main/account/model"
"go-common/library/ecode"
log "go-common/library/log"
"go-common/library/queue/databus/report"
)
const (
_unicomKey = "unicom"
_unicomPackKey = "unicom_pack"
)
// InOrdersSync insert OrdersSync
func (s *Service) InOrdersSync(c context.Context, usermob, ip string, u *unicom.UnicomJson, now time.Time) (err error) {
if !s.iplimit(_unicomKey, ip) {
err = ecode.AccessDenied
return
}
var result int64
if result, err = s.dao.InOrdersSync(c, usermob, u, now); err != nil || result == 0 {
log.Error("unicom_s.dao.OrdersSync (%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%v) error(%v) or result==0",
usermob, u.Cpid, u.Spid, u.TypeInt, u.Ordertypes, u.Channelcode, u.Ordertime, u.Canceltime, u.Endtime, u.Province, u.Area, u.Videoid, err)
}
return
}
// InAdvanceSync insert AdvanceSync
func (s *Service) InAdvanceSync(c context.Context, usermob, ip string, u *unicom.UnicomJson, now time.Time) (err error) {
if !s.iplimit(_unicomKey, ip) {
err = ecode.AccessDenied
return
}
var result int64
if result, err = s.dao.InAdvanceSync(c, usermob, u, now); err != nil || result == 0 {
log.Error("unicom_s.dao.InAdvanceSync (%s,%s,%s,%s,%s,%s,%s,%s,%v) error(%v) or result==0",
usermob, u.Userphone, u.Cpid, u.Spid, u.Ordertypes, u.Channelcode, u.Province, u.Area, err)
}
return
}
// FlowSync update OrdersSync
func (s *Service) FlowSync(c context.Context, flowbyte int, usermob, time, ip string, now time.Time) (err error) {
if !s.iplimit(_unicomKey, ip) {
err = ecode.AccessDenied
return
}
var result int64
if result, err = s.dao.FlowSync(c, flowbyte, usermob, time, now); err != nil || result == 0 {
log.Error("unicom_s.dao.OrdersSync(%s, %s, %s) error(%v) or result==0", usermob, time, flowbyte, err)
}
return
}
// InIPSync
func (s *Service) InIPSync(c context.Context, ip string, u *unicom.UnicomIpJson, now time.Time) (err error) {
if !s.iplimit(_unicomKey, ip) {
err = ecode.AccessDenied
return
}
var result int64
if result, err = s.dao.InIPSync(c, u, now); err != nil {
log.Error("s.dao.InIpSync(%s,%s) error(%v)", u.Ipbegin, u.Ipend, err)
} else if result == 0 {
err = ecode.RequestErr
log.Error("unicom_s.dao.InIpSync(%s,%s) error(%v) result==0", u.Ipbegin, u.Ipend, err)
}
return
}
// UserFlow
func (s *Service) UserFlow(c context.Context, usermob, mobiApp, ip string, build int, now time.Time) (res *unicom.Unicom, msg string, err error) {
var (
row map[string]*unicom.Unicom
orderType int
)
row = s.unicomInfo(c, usermob, now)
res, msg, err = s.uState(row, usermob, now)
switch err {
case ecode.NothingFound:
orderType = 1
case ecode.NotModified:
orderType = 3
default:
orderType = 2
}
s.unicomInfoc(mobiApp, usermob, ip, build, orderType, now)
return
}
// unicomInfo
func (s *Service) unicomInfo(c context.Context, usermob string, now time.Time) (res map[string]*unicom.Unicom) {
var (
err error
us []*unicom.Unicom
)
res = map[string]*unicom.Unicom{}
if us, err = s.dao.UnicomCache(c, usermob); err == nil && len(us) > 0 {
s.pHit.Incr("unicoms_cache")
} else {
if us, err = s.dao.OrdersUserFlow(context.TODO(), usermob); err != nil {
log.Error("unicom_s.dao.OrdersUserFlow error(%v)", err)
return
}
s.pMiss.Incr("unicoms_cache")
if len(us) > 0 {
if err = s.dao.AddUnicomCache(c, usermob, us); err != nil {
log.Error("s.dao.AddUnicomCache usermob(%v) error(%v)", usermob, err)
return
}
}
}
if len(us) > 0 {
row := &unicom.Unicom{}
channel := &unicom.Unicom{}
for _, u := range us {
if u.TypeInt == 1 && now.Unix() <= int64(u.Endtime) {
*row = *u
continue
} else if u.TypeInt == 0 {
if int64(row.Ordertime) == 0 {
*row = *u
} else if int64(row.Ordertime) < int64(u.Ordertime) {
continue
}
*row = *u
continue
} else if u.TypeInt == 1 {
if int64(row.Ordertime) > int64(u.Ordertime) {
continue
}
*channel = *u
}
}
if row.Spid == 0 && channel.Spid == 0 {
return
} else if row.Spid == 0 && channel.Spid > 0 {
row = channel
}
res[usermob] = row
}
return
}
// UserState
func (s *Service) UserState(c context.Context, usermob, mobiApp, ip string, build int, now time.Time) (res *unicom.Unicom, msg string, err error) {
var (
orderType int
)
row := s.unicomInfo(c, usermob, now)
res, msg, err = s.uState(row, usermob, now)
switch err {
case ecode.NothingFound:
orderType = 1
case ecode.NotModified:
orderType = 3
default:
orderType = 2
}
s.unicomInfoc(mobiApp, usermob, ip, build, orderType, now)
return
}
// UnicomState
func (s *Service) UnicomState(c context.Context, usermob, mobiApp, ip string, build int, now time.Time) (res *unicom.Unicom, err error) {
var (
ok bool
)
row := s.unicomInfo(c, usermob, now)
if res, ok = row[usermob]; !ok {
res = &unicom.Unicom{Unicomtype: 1}
} else if res.TypeInt == 1 && now.Unix() > int64(res.Endtime) {
res.Unicomtype = 3
} else if res.TypeInt == 1 {
res.Unicomtype = 4
} else if res.TypeInt == 0 {
res.Unicomtype = 2
}
log.Info("unicomstate_type:%v unicomstate_type_usermob:%v", res.Unicomtype, usermob)
s.unicomInfoc(mobiApp, usermob, ip, build, res.Unicomtype, now)
return
}
// UserFlowState
func (s *Service) UserFlowState(c context.Context, usermob string, now time.Time) (res *unicom.Unicom, err error) {
row := s.unicomInfo(c, usermob, now)
var ok bool
if res, ok = row[usermob]; !ok {
res = &unicom.Unicom{Unicomtype: 1}
} else if res.TypeInt == 1 {
res.Unicomtype = 3
} else if res.TypeInt == 0 {
res.Unicomtype = 2
}
return
}
// uState
func (s *Service) uState(unicom map[string]*unicom.Unicom, usermob string, now time.Time) (res *unicom.Unicom, msg string, err error) {
var ok bool
if res, ok = unicom[usermob]; !ok {
err = ecode.NothingFound
msg = "该卡号尚未开通哔哩哔哩专属免流服务"
} else if res.TypeInt == 1 && now.Unix() > int64(res.Endtime) {
err = ecode.NotModified
msg = "该卡号哔哩哔哩专属免流服务已退订且已过期"
}
return
}
// IsUnciomIP is unicom ip
func (s *Service) IsUnciomIP(ipUint uint32, ipStr, mobiApp string, build int, now time.Time) (err error) {
if !model.IsIPv4(ipStr) {
err = ecode.NothingFound
return
}
isValide := s.unciomIPState(ipUint)
s.ipInfoc(mobiApp, "", ipStr, build, isValide, now)
if isValide {
return
}
err = ecode.NothingFound
return
}
// UserUnciomIP
func (s *Service) UserUnciomIP(ipUint uint32, ipStr, usermob, mobiApp string, build int, now time.Time) (res *unicom.UnicomUserIP) {
res = &unicom.UnicomUserIP{
IPStr: ipStr,
IsValide: false,
}
if !model.IsIPv4(ipStr) {
return
}
if res.IsValide = s.unciomIPState(ipUint); !res.IsValide {
log.Error("unicom_user_ip:%v unicom_ip_usermob:%v", ipStr, usermob)
}
s.ipInfoc(mobiApp, usermob, ipStr, build, res.IsValide, now)
return
}
// Order unicom user order
func (s *Service) Order(c context.Context, usermobDes, channel string, ordertype int, now time.Time) (res *unicom.BroadbandOrder, msg string, err error) {
var (
usermob string
)
var (
_aesKey = []byte("9ed226d9")
)
bs, err := base64.StdEncoding.DecodeString(usermobDes)
if err != nil {
log.Error("base64.StdEncoding.DecodeString(%s) error(%v)", usermobDes, err)
return
}
bs, err = s.DesDecrypt(bs, _aesKey)
if err != nil {
log.Error("unicomSvc.DesDecrypt error(%v)", err)
return
}
if len(bs) > 32 {
usermob = string(bs[:32])
} else {
usermob = string(bs)
}
row := s.unicomInfo(c, usermob, now)
if u, ok := row[usermob]; ok {
if u.Spid != 979 && u.Spid != 0 && u.TypeInt == 0 {
err = ecode.NotModified
msg = "您当前是流量卡并且已生效无法再订购流量包"
return
}
}
if res, msg, err = s.dao.Order(c, usermobDes, channel, ordertype); err != nil {
log.Error("s.dao.Order usermobDes(%v) error(%v)", usermobDes, err)
return
}
return
}
// CancelOrder unicom user cancel order
func (s *Service) CancelOrder(c context.Context, usermob string) (res *unicom.BroadbandOrder, msg string, err error) {
if res, msg, err = s.dao.CancelOrder(c, usermob); err != nil {
log.Error("s.dao.CancelOrder usermob(%v) error(%v)", usermob, err)
return
}
return
}
// UnicomSMSCode unicom sms code
func (s *Service) UnicomSMSCode(c context.Context, phone string, now time.Time) (msg string, err error) {
if msg, err = s.dao.SendSmsCode(c, phone); err != nil {
log.Error("s.dao.SendSmsCode phone(%v) error(%v)", phone, err)
return
}
return
}
// AddUnicomBind unicom user bind
func (s *Service) AddUnicomBind(c context.Context, phone string, code int, mid int64, now time.Time) (msg string, err error) {
var (
usermobDes string
usermob string
ub *unicom.UserBind
result int64
res *unicom.Unicom
)
if usermobDes, msg, err = s.dao.SmsNumber(c, phone, code); err != nil {
log.Error("s.dao.SmsNumber error(%v)", err)
return
}
if usermobDes == "" {
err = ecode.NotModified
msg = "激活失败,请重新输入验证码激活"
return
}
var (
_aesKey = []byte("9ed226d9")
)
bs, err := base64.StdEncoding.DecodeString(usermobDes)
if err != nil {
log.Error("base64.StdEncoding.DecodeString(%s) error(%v)", usermobDes, err)
return
}
bs, err = s.DesDecrypt(bs, _aesKey)
if err != nil {
log.Error("unicomSvc.DesDecrypt error(%v)", err)
return
}
if len(bs) > 32 {
usermob = string(bs[:32])
} else {
usermob = string(bs)
}
row := s.unicomInfo(c, usermob, now)
if res, msg, err = s.uState(row, usermob, now); err != nil {
return
}
if res.Spid == 979 {
err = ecode.NotModified
msg = "该业务只支持哔哩哔哩免流卡"
return
}
if _, err = s.unicomBindInfo(c, mid); err == nil {
err = ecode.NotModified
msg = "该账户已绑定过手机号"
return
}
if midtmp := s.unicomBindMIdByPhone(c, phone); midtmp > 0 {
err = ecode.NotModified
msg = "该手机号已被注册"
return
}
if ub, err = s.dao.UserBindOld(c, phone); err != nil || ub == nil {
phoneInt, _ := strconv.Atoi(phone)
ub = &unicom.UserBind{
Usermob: usermob,
Phone: phoneInt,
Mid: mid,
State: 1,
}
} else {
ub.Mid = mid
ub.State = 1
}
if result, err = s.dao.InUserBind(c, ub); err != nil || result == 0 {
log.Error("s.dao.InUserBind ub(%v) error(%v) or result==0", ub, err)
return
}
if err = s.dao.AddUserBindCache(c, mid, ub); err != nil {
log.Error("s.dao.AddUserBindCache error(%v)", err)
return
}
// databus
s.addUserBindState(&unicom.UserBindInfo{MID: ub.Mid, Phone: ub.Phone, Action: "unicom_welfare_bind"})
return
}
// ReleaseUnicomBind release unicom bind
func (s *Service) ReleaseUnicomBind(c context.Context, mid int64, phone int) (msg string, err error) {
var (
result int64
ub *unicom.UserBind
)
if ub, err = s.unicomBindInfo(c, mid); err != nil {
msg = "用户未绑定手机号"
return
}
ub.State = 0
if err = s.dao.DeleteUserBindCache(c, mid); err != nil {
log.Error("s.dao.DeleteUserBindCache error(%v)", err)
return
}
if result, err = s.dao.InUserBind(c, ub); err != nil || result == 0 {
log.Error("s.dao.InUserBind ub(%v) error(%v) or result==0", ub, err)
return
}
// databus
s.addUserBindState(&unicom.UserBindInfo{MID: ub.Mid, Phone: ub.Phone, Action: "unicom_welfare_untied"})
return
}
// unicomBindInfo unicom bind info
func (s *Service) unicomBindInfo(c context.Context, mid int64) (res *unicom.UserBind, err error) {
if res, err = s.dao.UserBindCache(c, mid); err == nil {
s.pHit.Incr("unicoms_userbind_cache")
} else {
if res, err = s.dao.UserBind(c, mid); err != nil {
log.Error("s.dao.UserBind error(%v)", err)
return
}
s.pMiss.Incr("unicoms_userbind_cache")
if res == nil {
err = ecode.NothingFound
return
}
if err = s.dao.AddUserBindCache(c, mid, res); err != nil {
log.Error("s.dao.AddUserBindCache mid(%d) error(%v)", mid, err)
return
}
}
return
}
func (s *Service) unicomBindMIdByPhone(c context.Context, phone string) (mid int64) {
var err error
if mid, err = s.dao.UserBindPhoneMid(c, phone); err != nil {
log.Error("s.dao.UserBindPhoneMid error(%v)", phone)
return
}
return
}
// UserBind user bind
func (s *Service) UserBind(c context.Context, mid int64) (res *unicom.UserBind, msg string, err error) {
var (
acc *account.Info
ub *unicom.UserBind
)
if acc, err = s.accd.Info(c, mid); err != nil {
log.Error("s.accd.info error(%v)", err)
return
}
res = &unicom.UserBind{
Name: acc.Name,
Mid: acc.Mid,
}
if ub, err = s.unicomBindInfo(c, mid); err != nil {
log.Error("s.userBindInfo error(%v)", err)
err = nil
}
if ub != nil {
res.Phone = ub.Phone
res.Integral = ub.Integral
res.Flow = ub.Flow
}
return
}
// UnicomPackList unicom pack list
func (s *Service) UnicomPackList() (res []*unicom.UserPack) {
res = s.unicomPackCache
return
}
// UnicomPackReceive unicom pack receive
func (s *Service) UnicomPackReceive(c context.Context, mid int64, packID int64, now time.Time) (msg string, err error) {
var (
pack *unicom.UserPack
userbind *unicom.UserBind
requestNo int64
unicomOrderID string
unicomOutorderID string
u *unicom.Unicom
)
if userbind, err = s.unicomBindInfo(c, mid); err != nil {
err = ecode.NotModified
msg = "用户未绑定手机号"
return
}
row := s.unicomInfo(c, userbind.Usermob, now)
if u, msg, err = s.uState(row, userbind.Usermob, now); err != nil {
return
}
if u.Spid == 979 {
err = ecode.NotModified
msg = "该业务只支持哔哩哔哩免流卡"
return
}
if pack, err = s.unicomPackInfos(c, packID); err != nil {
err = ecode.NotModified
msg = "该礼包不存在"
return
}
if pack.Capped != 0 && pack.Amount == 0 {
err = ecode.NotModified
msg = "该礼包不存在"
return
}
if userbind.Integral < pack.Integral {
err = ecode.NotModified
msg = "福利点不足"
return
}
if requestNo, err = s.seqdao.SeqID(c); err != nil {
log.Error("unicom_s.seqdao.SeqID error (%v)", err)
return
}
switch pack.Type {
case 0:
if err = s.dao.UserFlowWaitCache(c, userbind.Phone); err == nil {
err = ecode.NotModified
msg = "请间隔一分钟之后再领取流量包"
return
}
if msg, err = s.dao.FlowPre(c, userbind.Phone, requestNo, now); err != nil {
log.Error("s.dao.FlowPre error(%v)", err)
return
}
if unicomOrderID, unicomOutorderID, msg, err = s.dao.FlowExchange(c, userbind.Phone, pack.Param, requestNo, now); err != nil {
log.Error("s.dao.FlowExchange error(%v)", err)
return
}
uf := &unicom.UnicomUserFlow{
Phone: userbind.Phone,
Mid: mid,
Integral: pack.Integral,
Flow: 0,
Orderid: unicomOrderID,
Outorderid: unicomOutorderID,
Desc: pack.Desc,
}
key := strconv.Itoa(userbind.Phone) + unicomOutorderID
if err = s.addUserFlowCache(c, key, uf); err != nil {
log.Error("s.addUserFlowCache error(%v)", err)
return
}
if err = s.dao.AddUserFlowWaitCache(c, userbind.Phone); err != nil {
log.Error("s.dao.AddUserFlowWaitCache error(%v)", err)
return
}
case 1:
var batchID int
if batchID, err = strconv.Atoi(pack.Param); err != nil {
log.Error("batchID(%v) strconv.Atoi error(%v)", pack.Param, err)
msg = "礼包参数错误"
err = ecode.RequestErr
return msg, err
}
if msg, err = s.accd.AddVIP(c, mid, requestNo, batchID, pack.Desc); err != nil {
log.Error("s.accd.AddVIP error(%v)", err)
return msg, err
}
case 2:
var day int
if day, err = strconv.Atoi(pack.Param); err != nil {
log.Error("day(%v) strconv.Atoi error(%v)", pack.Param, err)
msg = "礼包参数错误"
err = ecode.RequestErr
return msg, err
}
if msg, err = s.live.AddVip(c, mid, day); err != nil {
log.Error("s.live.AddVip error(%v)", err)
return "", err
}
case 3:
var acc *account.Info
if acc, err = s.accd.Info(c, mid); err != nil {
log.Error("s.accd.info error(%v)", err)
return
}
if msg, err = s.shop.Coupon(c, pack.Param, mid, acc.Name); err != nil {
log.Error("s.shop.Coupon error(%v)", err)
return
}
}
var (
p = &unicom.UserPack{}
ub = &unicom.UserBind{}
requestNoStr string
result int64
)
if pack.Capped != 0 {
*p = *pack
p.Amount = p.Amount - 1
if p.Amount == 0 {
if err = s.dao.DeleteUserPackCache(c, p.ID); err != nil {
log.Error("s.dao.DeleteUserPackCache error(%v)", err)
return
}
p.State = 0
} else {
if err = s.dao.AddUserPackCache(c, p.ID, p); err != nil {
log.Error("s.dao.AddUserPackCache error(%v)", err)
return
}
}
if result, err = s.dao.UpUserPacks(c, p, p.ID); err != nil || result == 0 {
log.Error("s.dao.UpUserPacks error(%v) or result==0", err)
return
}
}
*ub = *userbind
ub.Integral = ub.Integral - pack.Integral
if err = s.updateUserIntegral(c, mid, ub); err != nil {
log.Error("s.updateUserIntegral error(%v)", err)
return
}
msg = pack.Desc + ",领取成功"
if unicomOrderID != "" {
requestNoStr = unicomOrderID
} else {
requestNoStr = strconv.FormatInt(requestNo, 10)
}
log.Info("unicom_pack(%v) mid(%v)", pack.Desc+",领取成功", userbind.Mid)
s.unicomPackInfoc(userbind.Usermob, pack.Desc, requestNoStr, userbind.Phone, pack.Integral, int(pack.Capped), userbind.Mid, now)
ul := &unicom.UserPackLog{
Phone: userbind.Phone,
Usermob: userbind.Usermob,
Mid: userbind.Mid,
RequestNo: requestNoStr,
Type: pack.Type,
Desc: pack.Desc,
UserDesc: ("您当前已领取" + pack.Desc + ",扣除" + strconv.Itoa(pack.Integral) + "福利点"),
Integral: pack.Integral,
}
s.addUserPackLog(ul)
return
}
// UnicomFlowPack unicom flow pack
func (s *Service) UnicomFlowPack(c context.Context, mid int64, flowID string, now time.Time) (msg string, err error) {
var (
userbind *unicom.UserBind
ub = &unicom.UserBind{}
requestNo int64
flowDesc string
flow int
unicomOrderID string
unicomOutorderID string
u *unicom.Unicom
)
if userbind, err = s.unicomBindInfo(c, mid); err != nil {
err = ecode.NotModified
msg = "用户未绑定手机号"
return
}
row := s.unicomInfo(c, userbind.Usermob, now)
if u, msg, err = s.uState(row, userbind.Usermob, now); err != nil {
return
}
if u.Spid == 979 {
err = ecode.NotModified
msg = "该业务只支持哔哩哔哩免流卡"
return
}
switch flowID {
case "01":
flow = 100
flowDesc = "100MB流量包"
case "02":
flow = 200
flowDesc = "200MB流量包"
case "03":
flow = 300
flowDesc = "300MB流量包"
case "04":
flow = 500
flowDesc = "500MB流量包"
case "05":
flow = 1024
flowDesc = "1024MB流量包"
case "06":
flow = 2048
flowDesc = "2048MB流量包"
default:
err = ecode.RequestErr
msg = "流量包参数错误"
return
}
if userbind.Flow < flow {
err = ecode.NotModified
msg = "可用流量不足"
return
}
if err = s.dao.UserFlowWaitCache(c, userbind.Phone); err == nil {
err = ecode.NotModified
msg = "请间隔一分钟之后再领取流量包"
return
}
if requestNo, err = s.seqdao.SeqID(c); err != nil {
log.Error("unicom_s.seqdao.SeqID error (%v)", err)
return
}
if unicomOrderID, unicomOutorderID, msg, err = s.dao.FlowExchange(c, userbind.Phone, flowID, requestNo, now); err != nil {
log.Error("s.dao.FlowExchange error(%v)", err)
return
}
uf := &unicom.UnicomUserFlow{
Phone: userbind.Phone,
Mid: mid,
Integral: 0,
Flow: flow,
Orderid: unicomOrderID,
Outorderid: unicomOutorderID,
Desc: flowDesc,
}
key := strconv.Itoa(userbind.Phone) + unicomOutorderID
if err = s.addUserFlowCache(c, key, uf); err != nil {
log.Error("s.addUserFlowCache error(%v)", err)
return
}
*ub = *userbind
ub.Flow = ub.Flow - flow
if err = s.updateUserIntegral(c, mid, ub); err != nil {
log.Error("s.updateUserIntegral error(%v)", err)
return
}
msg = flowDesc + ",领取成功"
log.Info("unicom_pack(%v) mid(%v)", flowDesc+",领取成功", userbind.Mid)
s.unicomPackInfoc(userbind.Usermob, flowDesc, unicomOrderID, userbind.Phone, flow, 0, userbind.Mid, now)
ul := &unicom.UserPackLog{
Phone: userbind.Phone,
Usermob: userbind.Usermob,
Mid: userbind.Mid,
RequestNo: unicomOrderID,
Type: 0,
Desc: flowDesc,
UserDesc: ("您当前已领取" + flowDesc + ",扣除" + strconv.Itoa(flow) + "MB流量"),
Integral: flow,
}
s.addUserPackLog(ul)
if err = s.dao.AddUserFlowWaitCache(c, userbind.Phone); err != nil {
log.Error("s.dao.AddUserFlowWaitCache error(%v)", err)
return
}
return
}
// UserBindLog user bind week log
func (s *Service) UserBindLog(c context.Context, mid int64, now time.Time) (res []*unicom.UserLog, err error) {
if res, err = s.dao.SearchUserBindLog(c, mid, now); err != nil {
log.Error("unicom s.dao.SearchUserBindLog error(%v)", err)
return
}
return
}
// WelfareBindState welfare user bind state
func (s *Service) WelfareBindState(c context.Context, mid int64) (res int) {
if ub, err := s.dao.UserBindCache(c, mid); err == nil && ub != nil {
res = 1
}
return
}
func (s *Service) updateUserIntegral(c context.Context, mid int64, ub *unicom.UserBind) (err error) {
var result int64
if err = s.dao.AddUserBindCache(c, mid, ub); err != nil {
log.Error("s.dao.AddUserBindCache error(%v)", err)
return
}
if result, err = s.dao.UpUserIntegral(c, ub); err != nil {
log.Error("s.dao.UpUserIntegral error(%v) ", err)
return
}
if result == 0 {
log.Error("s.dao.UpUserIntegral result==0")
err = ecode.NotModified
return
}
return
}
// unicomPackInfos unicom pack infos
func (s *Service) unicomPackInfos(c context.Context, id int64) (res *unicom.UserPack, err error) {
var (
ub *unicom.UserPack
row = map[int64]*unicom.UserPack{}
ok bool
)
if ub, err = s.dao.UserPackCache(c, id); err == nil {
res = ub
s.pHit.Incr("unicoms_pack_cache")
} else {
if row, err = s.dao.UserPackByID(c, id); err != nil {
log.Error("s.dao.UserBind error(%v)", err)
return
}
s.pMiss.Incr("unicoms_pack_cache")
ub, ok = row[id]
if !ok {
err = ecode.NothingFound
return
}
if err = s.dao.AddUserPackCache(c, id, ub); err != nil {
log.Error("s.dao.AddUserPackCache id(%d) error(%v)", id, err)
return
}
res = ub
}
return
}
// unciomIPState
func (s *Service) unciomIPState(ipUint uint32) (isValide bool) {
for _, u := range s.unicomIpCache {
if u.IPStartUint <= ipUint && u.IPEndUint >= ipUint {
isValide = true
return
}
}
isValide = false
return
}
// unicomIp ip limit
func (s *Service) iplimit(k, ip string) bool {
key := fmt.Sprintf(_initIPlimitKey, k, ip)
if _, ok := s.operationIPlimit[key]; ok {
return true
}
return false
}
// DesDecrypt
func (s *Service) DesDecrypt(src, key []byte) ([]byte, error) {
block, err := des.NewCipher(key)
if err != nil {
return nil, err
}
out := make([]byte, len(src))
dst := out
bs := block.BlockSize()
if len(src)%bs != 0 {
return nil, errors.New("crypto/cipher: input not full blocks")
}
for len(src) > 0 {
block.Decrypt(dst, src[:bs])
src = src[bs:]
dst = dst[bs:]
}
out = s.zeroUnPadding(out)
return out, nil
}
// zeroUnPadding
func (s *Service) zeroUnPadding(origData []byte) []byte {
return bytes.TrimFunc(origData,
func(r rune) bool {
return r == rune(0)
})
}
func (s *Service) addUserFlowCache(c context.Context, key string, uf *unicom.UnicomUserFlow) (err error) {
if err = s.dao.AddUserFlowCache(c, key); err != nil {
log.Error("s.dao.AddUserFlowCache error(%v)", err)
return
}
var flowList map[string]*unicom.UnicomUserFlow
if flowList, err = s.dao.UserFlowListCache(c); err != nil {
log.Error("s.dao.UserFlowListCache error(%v)", err)
return
}
if flowList == nil {
flowList = map[string]*unicom.UnicomUserFlow{
key: uf,
}
} else {
flowList[key] = uf
}
if err = s.dao.AddUserFlowListCache(c, flowList); err != nil {
log.Error("s.dao.AddUserFlowListCache error(%v)", err)
return
}
return
}
// UserPacksLog user pack logs
func (s *Service) UserPacksLog(c context.Context, starttime, now time.Time, start int, ip string) (res []*unicom.UserPackLog, err error) {
if !s.iplimit(_unicomPackKey, ip) {
err = ecode.AccessDenied
return
}
var (
endday time.Time
)
if starttime.Month() >= now.Month() && starttime.Year() >= now.Year() {
res = []*unicom.UserPackLog{}
return
}
if endInt := starttime.AddDate(0, 1, -1).Day(); start > endInt {
res = []*unicom.UserPackLog{}
return
} else if start == endInt {
endday = starttime.AddDate(0, 1, 0)
} else {
endday = starttime.AddDate(0, 0, start)
}
if res, err = s.dao.UserPacksLog(c, endday.AddDate(0, 0, -1), endday); err != nil {
log.Error("user pack logs s.dao.UserPacksLog error(%v)", err)
return
}
if len(res) == 0 {
res = []*unicom.UserPackLog{}
}
return
}
func (s *Service) addUserPackLog(u *unicom.UserPackLog) {
select {
case s.packLogCh <- u:
default:
log.Warn("user pack log buffer is full")
}
}
func (s *Service) addUserPackLogproc() {
for {
i, ok := <-s.packLogCh
if !ok {
log.Warn("user pack log proc exit")
return
}
var (
c = context.TODO()
result int64
err error
logID = 91
)
switch v := i.(type) {
case *unicom.UserPackLog:
if result, err = s.dao.InUserPackLog(c, v); err != nil || result == 0 {
log.Error("s.dao.UpUserIntegral error(%v) or result==0", err)
continue
}
report.User(&report.UserInfo{
Mid: v.Mid,
Business: logID,
Action: "unicom_userpack_deduct",
Ctime: time.Now(),
Content: map[string]interface{}{
"phone": v.Phone,
"pack_desc": v.UserDesc,
"integral": (0 - v.Integral),
},
})
}
}
}

View File

@@ -0,0 +1,158 @@
package unicom
import (
"context"
"flag"
"path/filepath"
"testing"
"time"
"go-common/app/interface/main/app-wall/conf"
. "github.com/smartystreets/goconvey/convey"
)
var (
s *Service
)
func WithService(f func(s *Service)) func() {
return func() {
f(s)
}
}
func init() {
dir, _ := filepath.Abs("../../cmd/app-wall-test.toml")
flag.Set("conf", dir)
conf.Init()
s = New(conf.Conf)
time.Sleep(time.Second)
}
func TestUserFlow(t *testing.T) {
Convey("Unicom UserFlow", t, WithService(func(s *Service) {
res, _, err := s.UserFlow(context.TODO(), "", "iphone", "127.0.0.1", 111, time.Now())
So(res, ShouldNotBeEmpty)
So(err, ShouldBeNil)
}))
}
func TestUserState(t *testing.T) {
Convey("Unicom UserState", t, WithService(func(s *Service) {
res, _, err := s.UserState(context.TODO(), "", "iphone", "127.0.0.1", 111, time.Now())
So(res, ShouldNotBeEmpty)
So(err, ShouldBeNil)
}))
}
func TestUnicomState(t *testing.T) {
Convey("Unicom UnicomState", t, WithService(func(s *Service) {
res, err := s.UnicomState(context.TODO(), "", "iphone", "127.0.0.1", 111, time.Now())
So(res, ShouldNotBeEmpty)
So(err, ShouldBeNil)
}))
}
func TestUserFlowState(t *testing.T) {
Convey("Unicom UserFlowState", t, WithService(func(s *Service) {
res, err := s.UserFlowState(context.TODO(), "", time.Now())
So(res, ShouldNotBeEmpty)
So(err, ShouldBeNil)
}))
}
func TestIsUnciomIP(t *testing.T) {
Convey("Unicom IsUnciomIP", t, WithService(func(s *Service) {
err := s.IsUnciomIP(0, "127.0.0.1", "iphone", 0, time.Now())
So(err, ShouldBeNil)
}))
}
func TestUserUnciomIP(t *testing.T) {
Convey("Unicom UserUnciomIP", t, WithService(func(s *Service) {
err := s.UserUnciomIP(0, "127.0.0.1", "", "iphone", 0, time.Now())
So(err, ShouldBeNil)
}))
}
func TestOrder(t *testing.T) {
Convey("Unicom Order", t, WithService(func(s *Service) {
res, _, err := s.Order(context.TODO(), "", "", 0, time.Now())
So(res, ShouldNotBeEmpty)
So(err, ShouldBeNil)
}))
}
func TestCancelOrder(t *testing.T) {
Convey("Unicom CancelOrder", t, WithService(func(s *Service) {
res, _, err := s.CancelOrder(context.TODO(), "")
So(res, ShouldNotBeEmpty)
So(err, ShouldBeNil)
}))
}
func TestUnicomSMSCode(t *testing.T) {
Convey("Unicom UnicomSMSCode", t, WithService(func(s *Service) {
res, err := s.UnicomSMSCode(context.TODO(), "", time.Now())
So(res, ShouldNotBeEmpty)
So(err, ShouldBeNil)
}))
}
func TestAddUnicomBind(t *testing.T) {
Convey("Unicom AddUnicomBind", t, WithService(func(s *Service) {
res, err := s.AddUnicomBind(context.TODO(), "", 1, 1, time.Now())
So(res, ShouldNotBeEmpty)
So(err, ShouldBeNil)
}))
}
func TestReleaseUnicomBind(t *testing.T) {
Convey("Unicom ReleaseUnicomBind", t, WithService(func(s *Service) {
res, err := s.ReleaseUnicomBind(context.TODO(), 1, 1)
So(res, ShouldNotBeEmpty)
So(err, ShouldBeNil)
}))
}
func TestUserBind(t *testing.T) {
Convey("Unicom UserBind", t, WithService(func(s *Service) {
res, _, err := s.UserBind(context.TODO(), 1)
So(res, ShouldNotBeEmpty)
So(err, ShouldBeNil)
}))
}
func TestUnicomPackList(t *testing.T) {
Convey("Unicom UnicomPackList", t, WithService(func(s *Service) {
res := s.UnicomPackList()
So(res, ShouldNotBeEmpty)
}))
}
func TestUnicomPackReceive(t *testing.T) {
Convey("Unicom UnicomPackReceive", t, WithService(func(s *Service) {
res, _ := s.UnicomPackReceive(context.TODO(), 1, 1, time.Now())
So(res, ShouldNotBeEmpty)
}))
}
func TestUnicomUnicomFlowPack(t *testing.T) {
Convey("Unicom UnicomFlowPack", t, WithService(func(s *Service) {
res, _ := s.UnicomFlowPack(context.TODO(), 1, "", time.Now())
So(res, ShouldNotBeEmpty)
}))
}
func TestUnicomloadUnicomFlow(t *testing.T) {
Convey("Unicom loadUnicomFlow", t, WithService(func(s *Service) {
s.loadUnicomFlow()
}))
}
func TestUnicomloadUnicomIPOrder(t *testing.T) {
Convey("Unicom loadUnicomIPOrder", t, WithService(func(s *Service) {
s.loadUnicomIPOrder(time.Now())
}))
}

View File

@@ -0,0 +1,48 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = ["wall_test.go"],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/interface/main/app-wall/conf:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = ["wall.go"],
importpath = "go-common/app/interface/main/app-wall/service/wall",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/interface/main/app-wall/conf:go_default_library",
"//app/interface/main/app-wall/dao/wall:go_default_library",
"//app/interface/main/app-wall/model/wall:go_default_library",
"//library/log:go_default_library",
"//library/net/http/blademaster:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,59 @@
package wall
import (
"context"
"time"
"go-common/app/interface/main/app-wall/conf"
walldao "go-common/app/interface/main/app-wall/dao/wall"
"go-common/app/interface/main/app-wall/model/wall"
log "go-common/library/log"
httpx "go-common/library/net/http/blademaster"
)
type Service struct {
c *conf.Config
client *httpx.Client
dao *walldao.Dao
tick time.Duration
cache []*wall.Wall
testCache []*wall.Wall
}
func New(c *conf.Config) (s *Service) {
s = &Service{
c: c,
client: httpx.NewClient(c.HTTPClient),
dao: walldao.New(c),
tick: time.Duration(c.Tick),
}
s.load()
go s.loadproc()
return
}
// GetWall All
func (s *Service) Wall() (res []*wall.Wall) {
res = s.cache
return
}
// load WallAll
func (s *Service) load() {
res, err := s.dao.WallAll(context.TODO())
if err != nil {
log.Error("s.dao.wallAll error(%v)", err)
return
}
s.cache = res
s.testCache = res
log.Info("loadWallsCache success")
}
// cacheproc load cache
func (s *Service) loadproc() {
for {
time.Sleep(s.tick)
s.load()
}
}

View File

@@ -0,0 +1,37 @@
package wall
import (
"flag"
"path/filepath"
"testing"
"time"
"go-common/app/interface/main/app-wall/conf"
. "github.com/smartystreets/goconvey/convey"
)
var (
s *Service
)
func WithService(f func(s *Service)) func() {
return func() {
f(s)
}
}
func init() {
dir, _ := filepath.Abs("../../cmd/app-wall-test.toml")
flag.Set("conf", dir)
conf.Init()
s = New(conf.Conf)
time.Sleep(time.Second)
}
func TestWall(t *testing.T) {
Convey("Wall", t, WithService(func(s *Service) {
res := s.Wall()
So(res, ShouldNotBeEmpty)
}))
}