Browse Source

init

master
guzeng 3 years ago
commit
78929abeac
16 changed files with 805 additions and 0 deletions
  1. +86
    -0
      cache.go
  2. +26
    -0
      cache_test.go
  3. +63
    -0
      header.go
  4. +73
    -0
      master.go
  5. +15
    -0
      master_test.go
  6. +41
    -0
      order_sign.go
  7. +69
    -0
      order_sn.go
  8. +30
    -0
      order_sn_test.go
  9. +176
    -0
      order_status.go
  10. +14
    -0
      redis.go
  11. +43
    -0
      sendmsg.go
  12. +101
    -0
      site.go
  13. +23
    -0
      site_test.go
  14. +25
    -0
      user.go
  15. +14
    -0
      user_test.go
  16. +6
    -0
      var.go

+ 86
- 0
cache.go View File

@ -0,0 +1,86 @@
package site
import (
"encoding/json"
"errors"
"git.tetele.net/ttlpkg/tgo/redis"
)
/**
* 从redis获取分站数据库及ID信息
* 2020/06/08
* gz
*/
func GetSiteFromRedis(host string) (map[string]string, error) {
var site map[string]string = make(map[string]string)
info, err := redis.HGetString(SITE_KEY, host)
if err != nil {
return site, err
}
type siteStruct struct {
Database string `json:"database"`
SiteId string `json:"site_id"`
}
var siteInfo siteStruct
err = json.Unmarshal([]byte(info), &siteInfo)
if err != nil {
return site, err
}
if siteInfo.Database != "" {
site["database"] = siteInfo.Database
}
if siteInfo.SiteId != "" {
site["site_id"] = siteInfo.SiteId
}
return site, nil
}
/**
* 分站数据库及ID信息保存及redis
* 2020/06/08
* gz
*/
func SetToRedis(host string, site map[string]string) error {
if host == "" {
return errors.New("没有域名")
}
if len(site) < 1 {
return errors.New("没有站点信息")
}
siteStr, err := json.Marshal(site)
if err != nil {
return err
}
_, err = redis.HMSet(SITE_KEY, host, siteStr)
return err
}
func GetAll() ([]map[string]string, error) {
list, err := redis.HGetAll(SITE_KEY)
if err != nil {
return nil, err
}
var siteInfo map[string]string
var all []map[string]string
if len(list) > 0 {
for key, item := range list {
if (key+1)%2 == 0 { //只处理偶数位
siteInfo = make(map[string]string)
err = json.Unmarshal(item, &siteInfo)
if err != nil {
continue
}
siteInfo["domainname"] = string(list[key-1])
all = append(all, siteInfo)
}
}
}
return all, err
}

+ 26
- 0
cache_test.go View File

@ -0,0 +1,26 @@
package site
import (
"testing"
)
func Test_GetSiteFromRedis(t *testing.T) {
host := "dev.tetele.net"
ret, err := GetSiteFromRedis(host)
t.Log(ret)
t.Log(err)
// site := map[string]string{"database": "dev_testing", "site_id": "2000"}
// err = SetToRedis(host, site)
// t.Log(err)
ret2, err := GetAll()
t.Log(ret2)
t.Log(len(ret2))
}

+ 63
- 0
header.go View File

@ -0,0 +1,63 @@
package site
import (
"net/http"
"strings"
)
/**
* 取访问主机名
*/
func GetHost(req *http.Request) string {
var hostlist []string = req.Header.Values("X-Forwarded-Host")
var host string
if len(hostlist) > 1 {
host = hostlist[len(hostlist)-1] //取最后一次转发的
} else if len(hostlist) == 1 {
host = hostlist[0]
} else {
host = ""
}
if host != "" {
hosts := strings.Split(host, ",")
host = strings.Trim(hosts[len(hosts)-1], " ")
}
if host == "" {
host = req.Host
}
return host
}
/**
* 取域名
*/
func GetDomain(req *http.Request) string {
scheme := "http://"
if req.TLS != nil {
scheme = "https://"
}
if strings.Contains(req.Referer(), "https://") {
scheme = "https://"
}
var host string = GetHost(req)
host = strings.Split(host, ":")[0]
var w strings.Builder
w.WriteString(scheme)
w.WriteString(host)
return w.String()
}
func SetHeader(w http.ResponseWriter, resp *http.Request) {
w.Header().Set("Access-Control-Allow-Origin", "*") //允许访问所有域
w.Header().Add("Access-Control-Allow-Headers", "Content-Type,x-csrf-token,x-requested-with,token") //header的类型
w.Header().Set("Access-Control-Allow-Methods", "POST,GET,OPTIONS")
w.Header().Set("content-type", "application/json") //返回数据格式是json
// w.Header().Set("Content-Length", resp.Header.Get("Content-Length"))
}

+ 73
- 0
master.go View File

@ -0,0 +1,73 @@
package site
import (
"encoding/json"
"errors"
"io/ioutil"
"net/http"
"strings"
"git.tetele.net/ttlpkg/tgo/helper"
)
/**
* 从总站获取数据库信息
* master 总站域名带协议
* host 分站域名带协议
* 2020/06/05
* gz
*/
/**
* 从总站获取分站数据库及ID信息
* 2020/06/06
* gz
*/
func GetSiteFromMaster(master, host string) (map[string]string, error) {
url := helper.StringJoin(master, "/api/gethostdb")
var site map[string]string = make(map[string]string)
resp, err := http.Post(url, "application/x-www-form-urlencoded", strings.NewReader("host="+host))
if err != nil {
return site, errors.New("获取站点数据失败," + err.Error())
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return site, errors.New("获取站点数据失败," + err.Error())
}
type D struct {
Database interface{} `json:"database"`
SiteId interface{} `json:"site_id"`
}
type Reply struct {
Code interface{} `json:"code"`
Data D `json:"data"`
Msg string `json:"msg"`
}
var data Reply
err = json.Unmarshal(body, &data)
if err != nil {
return site, errors.New("站点数据格式错误," + err.Error())
}
if helper.ToStr(data.Code) != "1" {
return site, errors.New(data.Msg)
}
if data.Data.Database != "" {
site["database"] = helper.ToStr(data.Data.Database)
}
if data.Data.SiteId != "" {
site["site_id"] = helper.ToStr(data.Data.SiteId)
}
return site, nil
}

+ 15
- 0
master_test.go View File

@ -0,0 +1,15 @@
package site
import (
"testing"
)
func Test_GetSiteFromMaster(t *testing.T) {
master := "https://devmaster.tetele.net"
host := "https://dev.tetele.net"
ret, err := GetSiteFromMaster(master, host)
t.Log(ret)
t.Log(err)
}

+ 41
- 0
order_sign.go View File

@ -0,0 +1,41 @@
package orderattr
import (
"crypto/md5"
"encoding/hex"
"strings"
)
/**
* 通知订单状态时签名
* 签名方式md5(order_sn-status--time---appid)
* 2020/08/21
*gz
*/
func Sign(order_sn, status, time, appid string) string {
return Md5Password(StringJoin(order_sn, "--", status, "--", time, "--", appid))
}
//密码加密
func Md5Password(password string) string {
h := md5.New()
h.Write([]byte(password)) // 需要加密的字符串
cipher2Str := h.Sum(nil)
sMd5 := hex.EncodeToString(cipher2Str) // 输出加密结果
return sMd5
}
/*
* 连接多个字符串
* 2019/05/05
*/
func StringJoin(s ...string) string {
var build strings.Builder
if len(s) > 0 {
for _, v := range s {
build.WriteString(v)
}
}
return build.String()
}

+ 69
- 0
order_sn.go View File

@ -0,0 +1,69 @@
package orderattr
import (
"math/rand"
"strconv"
"strings"
"time"
)
/**
* 订单号规则
* id后4位随机4位+当前时间10
* 2020/08/10
*/
func NewOrderSn(user_id string) string {
var prefix string
if user_id != "" {
if len(user_id) > 4 {
prefix = user_id[len(user_id)-4:] //截取后4位
} else {
prefix = user_id
}
} else {
//随机4位
str := "123456789"
bytes := []byte(str)
result := []byte{}
r := rand.New(rand.NewSource(time.Now().UnixNano()))
for i := 0; i < 4; i++ {
result = append(result, bytes[r.Intn(len(bytes))])
}
prefix = string(result)
}
//拼接
var build strings.Builder
build.WriteString(prefix)
build.WriteString(strconv.FormatInt(time.Now().Unix(), 10)) //当前时间
return build.String()
}
/**
* 核销码规则
* 随机2位+当前时间6
* 2020/08/10
*/
func VerifyNumber() string {
var prefix string
//随机4位
str := "123456789"
bytes := []byte(str)
result := []byte{}
r := rand.New(rand.NewSource(time.Now().UnixNano()))
for i := 0; i < 1; i++ {
result = append(result, bytes[r.Intn(len(bytes))])
}
prefix = string(result)
//拼接
var build strings.Builder
build.WriteString(prefix)
build.WriteString(strconv.FormatInt(time.Now().UnixNano(), 10)[10:17]) //当前时间
return build.String()
}

+ 30
- 0
order_sn_test.go View File

@ -0,0 +1,30 @@
package orderattr
import (
"testing"
"time"
)
func Test_NewNumber(t *testing.T) {
t.Log(time.Now().UnixNano())
var set map[string]int
set = make(map[string]int)
var i, reply int = 0, 0
var num string
for i < 100000 {
i++
num = VerifyNumber()
if _, ok := set[num]; ok {
reply++
} else {
set[num] = i
}
}
t.Log("reply:", reply)
// t.Log(set)
}

+ 176
- 0
order_status.go View File

@ -0,0 +1,176 @@
package site
/**
'0': 待支付 下单尚未支付 created
'1':已支付 付款成功此状态可退款 payed
'5'已验证 虚拟订单验证核销码 using
'6'已完成 与供应商结算后订单结束配送订单配送完成 finished
'7'已取消 订单取消 canceled
'8'自动取消 到期未支付自动取消此状态可由管理员手动延期取消 autocanceled
'9'申请退款 用户自助申请退订单此状态可退款
'13'已退款 订单完成退款 refunded
'15'自动完成 使用时间过期自动完成 finished
cancel,received,payed,created,finished,using
## 发货
is_delivery 是否发货 '1': 已发货
delivery 发货时间
## 收货
is_received 是否收货 '1': 已收货
received 收货时间
*/
var statusList map[string]string = map[string]string{
"0": "created",
"1": "payed",
"5": "using",
"6": "finished",
"7": "canceled",
"8": "autocanceled",
"9": "askForRefund",
"13": "refunded",
"15": "autofinished",
}
var statusExtendList map[string]string = map[string]string{
"6": "received", //已收货归入已完成,
}
/*串货订单,供应商系统订单状态*/
var channelOrderStatusList map[string]string = map[string]string{
"1": "nosend",
"2": "created",
"3": "payed",
"4": "askForRefund",
"5": "refunded",
"6": "canceled",
"7": "finished",
"8": "payFailed", //支付失败
"9": "breakoff", //断开
"10": "fullRefund", //全额退款
"14": "autocanceled",
"15": "autofinished",
"16": "delivered",
}
func GetOrderStatusKey(status string) (key string) {
for k, val := range statusList {
if val == status {
key = k
break
}
}
if key == "" { //再找扩展的状态
for k, val := range statusExtendList {
if val == status {
key = k
break
}
}
}
return
}
func GetOrderStatusText(key string) (text string) {
for k, val := range statusList {
if k == key {
text = val
break
}
}
if text == "" { //再找扩展的状态
for k, val := range statusExtendList {
if k == key {
text = val
break
}
}
}
return
}
/**
* 返回订单状态描述
* 2021/01/28
*/
func GetOrderStatusDescByFlag(flag string) (text string) {
status := GetStatusText(flag)
return GetStatusDesc(status)
}
/**
* 返回订单状态描述
* 2020/10/22
*/
func GetOrderStatusDesc(key string) (text string) {
var statusDesc map[string]string = map[string]string{
"created": "已创建",
"payed": "已支付",
"askForRefund": "请求退款",
"using": "使用中",
"finished": "已完成",
"canceled": "已取消",
"autocanceled": "自动取消",
"refunded": "已退款",
"autofinished": "自动完成",
"received": "已收货",
}
for k, val := range statusDesc {
if k == key {
text = val
break
}
}
return
}
func GetChannelOrderStatusKey(status string) (key string) {
for k, val := range channelOrderStatusList {
if val == status {
key = k
break
}
}
return
}
func GetChannelOrderStatusText(key string) (text string) {
for k, val := range channelOrderStatusList {
if k == key {
text = val
break
}
}
return
}
/**
* 返回订单状态描述
* 2020/10/22
*/
func GetChannelOrderStatusDesc(key string) (text string) {
var statusDesc map[string]string = map[string]string{
"nosend": "未发送",
"created": "已创建",
"payed": "已支付",
"askForRefund": "请求退款",
"refunded": "已退款",
"canceled": "已取消",
"finished": "已完成",
"payFailed": "支付失败",
"breakoff": "断开",
"fullRefund": "全额退款",
"autocanceled": "自动取消",
"autofinished": "自动取消",
"delivered": "已发货",
}
for k, val := range statusDesc {
if k == key {
text = val
break
}
}
return
}

+ 14
- 0
redis.go View File

@ -0,0 +1,14 @@
package site
import (
"strings"
)
func GetConfigRedisKey(site_id string) string {
var build strings.Builder
build.WriteString(site_id)
build.WriteString("_config")
return build.String()
}

+ 43
- 0
sendmsg.go View File

@ -0,0 +1,43 @@
package site
/*
* 串货接口请求及通知订单状态
*/
var MsgTypeList map[string]string = map[string]string{
"1": "order_create", // 请求创建订单
"2": "order_created_notify", //订单已创建通知
"3": "order_refund", //请求订单退款
"4": "order_refunded_notify",
"5": "order_pay", //请求支付订单
"6": "order_payed_notify",
"7": "order_cancel", // 发送取消订单请求
"8": "order_canceled_notify",
"9": "order_receive", //向被串货方发送订单已收货请求
"10": "order_received_notify",
"11": "order_finished_notify", //订单已完成通知
"12": "send_sms", //短信
"13": "order_delivered_notify", //订单已发货通知
"14": "order_autocanceled_notify", //订单自动取消通知
"15": "order_askforrefund_notify", //订单已申请退款通知
"16": "order_pay_by_master", //订单请求总站支付
}
func GetMsgTypeText(key string) (text string) {
for k, val := range MsgTypeList {
if k == key {
text = val
break
}
}
return
}
func GetMsgTypeKey(text string) (key string) {
for k, val := range MsgTypeList {
if val == text {
key = k
break
}
}
return
}

+ 101
- 0
site.go View File

@ -0,0 +1,101 @@
package site
import (
"errors"
"log"
"net/http"
"strings"
)
func GetSiteInfo(master, host string) (map[string]string, error) {
if master == "" || host == "" {
errors.New("params error")
}
host = strings.Replace(host, "https://", "", 1)
host = strings.Replace(host, "http://", "", 1)
//去掉端口
if strings.Contains(host, ":") {
index := strings.Index(host, ":")
host = host[:index]
}
host = strings.Split(host, ":")[0]
site, err := GetSiteFromRedis(host) //从redis获取
if err != nil {
log.Println("从redis获取分站失败", err)
}
if err == nil && len(site) > 0 {
return site, nil
}
log.Println("从总站", master, "获取分站信息", host)
site, err = GetSiteFromMaster(master, host) //从总站获取
if err != nil {
log.Println("从总站获取分站信息失败", err)
return site, err
}
if len(site) > 0 {
if _, ok := site["database"]; !ok { //检查是否有database
log.Println("站点数据没有database", site)
return site, errors.New("站点数据错误,缺少必要参数")
}
if _, ok := site["site_id"]; !ok { //检查是否有site_id
log.Println("站点数据没有site_id", site)
return site, errors.New("站点数据错误,缺少必要参数")
}
SetToRedis(host, site) //存入redis
return site, nil
} else {
return site, errors.New("数据错误")
}
}
/**
* 取完整数据库名
* 2020/06/15
* gz
*/
func GetDbName(master, host string) (string, error) {
siteInfo, err := GetSiteInfo(master, host)
if err != nil {
return "", err
}
return siteInfo["database"], nil
}
/**
* 取站点ID
* 2020/06/15
* gz
*/
func GetSiteId(master, domain string) (string, error) {
siteInfo, err := GetSiteInfo(master, domain)
if err != nil {
return "", err
}
if _, ok := siteInfo["site_id"]; !ok {
return "", errors.New("没有找到站点ID")
}
return siteInfo["site_id"], nil
}
func GetSiteInfoFromReq(master string, req *http.Request) (map[string]string, error) {
log.Println("header:", req.Header, ";", "body:", req.Body)
host := GetHost(req)
siteInfo, err := GetSiteInfo(master, host)
if err != nil {
return siteInfo, err
}
if len(siteInfo) > 0 {
siteInfo["host"] = host
}
return siteInfo, nil
}

+ 23
- 0
site_test.go View File

@ -0,0 +1,23 @@
package site
import (
"strings"
"testing"
)
func Test_GetSiteInfo(t *testing.T) {
master := "https://devmaster.tetele.net"
host := "dev.tetele.net:80"
ret, err := GetSiteInfo(master, host)
t.Log(ret)
t.Log(err)
str := " dev.tetele.net"
trim := strings.Trim(str, " ")
t.Log(str)
t.Log(trim)
}

+ 25
- 0
user.go View File

@ -0,0 +1,25 @@
package site
import (
"crypto/hmac"
"fmt"
"golang.org/x/crypto/ripemd160"
)
func EncryptedUserToken(token string, key ...string) string {
var token_key string = USER_TOKEN_KEY
if len(key) > 0 {
token_key = key[0]
}
h2 := hmac.New(ripemd160.New, []byte(token_key))
h2.Write([]byte(token))
hashBytes := h2.Sum(nil)
hashString := fmt.Sprintf("%x", hashBytes)
return hashString
}

+ 14
- 0
user_test.go View File

@ -0,0 +1,14 @@
package site
import (
// "fmt"
"testing"
)
func Test_EncryptedUserToken(t *testing.T) {
//2a12d5373e04a96c2e1862f786e9d054464fc13d
// fmt.Println([]byte("2a12d5373e04a96c2e1862f786e9d054464fc13d"))
token := "5536827c-36a5-4ec7-946d-49e4380c5103"
ret := EncryptedUserToken(token)
t.Log(ret)
}

+ 6
- 0
var.go View File

@ -0,0 +1,6 @@
package site
const SITE_KEY = "allSitesInfo" // 所有站点的信息
//用户TOKEN加密转换key
var USER_TOKEN_KEY = "i3d6o32wo8fvs1fvdpwens"

Loading…
Cancel
Save