Browse Source

first commit

qiaozhi 1 year ago
commit
d624acb45e
100 changed files with 618983 additions and 0 deletions
  1. 34 0
      .gitignore
  2. 2 0
      .idea/.gitignore
  3. 5 0
      .idea/codeStyles/codeStyleConfig.xml
  4. 9 0
      .idea/gobackend_hb1.iml
  5. 6 0
      .idea/misc.xml
  6. 8 0
      .idea/modules.xml
  7. 7 0
      .idea/vcs.xml
  8. 5 0
      Dockerfile
  9. 10 0
      Makefile
  10. 36 0
      cerror/error.go
  11. 193 0
      cmd/search_index.go
  12. 158 0
      cmd/task.go
  13. 50 0
      config/config.go
  14. 42 0
      constants/constants.go
  15. 13 0
      constants/constants_test.go
  16. 14 0
      constants/error.go
  17. 48 0
      constants/smscode_type.go
  18. 17 0
      credentials/token_credential.go
  19. 82 0
      dal/cart_dal.go
  20. 40 0
      dal/cart_dal_test.go
  21. 58 0
      dal/city_dal.go
  22. 8 0
      dal/constants.go
  23. 142 0
      dal/coupon_dal.go
  24. 16 0
      dal/coupon_dal_test.go
  25. 72 0
      dal/dal.go
  26. 46 0
      dal/dal_test.go
  27. 514 0
      dal/deliver_userdal.go
  28. 12 0
      dal/icart_dal.go
  29. 12 0
      dal/icity_dal.go
  30. 13 0
      dal/icoupon_dal.go
  31. 18 0
      dal/ideliver_userdal.go
  32. 9 0
      dal/ifcode_dal.go
  33. 16 0
      dal/iorder_dal.go
  34. 18 0
      dal/iproduct_dal.go
  35. 11 0
      dal/ismscode_dal.go
  36. 16 0
      dal/iuser_dal.go
  37. 13 0
      dal/iuserlinker_dal.go
  38. 525 0
      dal/order_dal.go
  39. 24 0
      dal/order_dal_test.go
  40. 7 0
      dal/pager.go
  41. 396 0
      dal/product_dal.go
  42. 164 0
      dal/result.go
  43. 41 0
      dal/smscode_dal.go
  44. 147 0
      dal/user_dal.go
  45. 99 0
      dal/userlinker_dal.go
  46. 34 0
      dict/hmm_model.utf8
  47. 258826 0
      dict/idf.utf8
  48. 348982 0
      dict/jieba.dict.utf8
  49. 1534 0
      dict/stop_words.utf8
  50. 5 0
      dict/user.dict.utf8
  51. 17 0
      docker-compose.yml
  52. 2808 0
      endpoint.go
  53. 19 0
      entity/act_jd_uinfo.go
  54. 11 0
      entity/act_reporter.go
  55. 20 0
      entity/act_tvshop.go
  56. 9 0
      entity/cart.go
  57. 58 0
      entity/city.go
  58. 11 0
      entity/consumer_gene_sign.go
  59. 134 0
      entity/custom_file.go
  60. 25 0
      entity/deliver_bill.go
  61. 38 0
      entity/deliver_exam.go
  62. 19 0
      entity/deliver_msg.go
  63. 17 0
      entity/deliver_study.go
  64. 36 0
      entity/deliver_user.go
  65. 15 0
      entity/detect_item.go
  66. 6 0
      entity/detect_product.go
  67. 13 0
      entity/dict_item.go
  68. 47 0
      entity/discount_ticket.go
  69. 30 0
      entity/discount_ticket_type.go
  70. 38 0
      entity/fcode.go
  71. 13 0
      entity/gp_param.go
  72. 31 0
      entity/jdl_entity.go
  73. 173 0
      entity/order.go
  74. 12 0
      entity/order_callback_info.go
  75. 19 0
      entity/order_product.go
  76. 12 0
      entity/order_sign.go
  77. 11 0
      entity/order_survey.go
  78. 94 0
      entity/product.go
  79. 16 0
      entity/product_category.go
  80. 8 0
      entity/product_picture.go
  81. 11 0
      entity/productivity.go
  82. 9 0
      entity/productivity_config.go
  83. 16 0
      entity/queue_notice.go
  84. 17 0
      entity/sms_code.go
  85. 8 0
      entity/tag.go
  86. 40 0
      entity/user.go
  87. 52 0
      entity/user_linker.go
  88. 10 0
      entity/user_linker_rel.go
  89. 40 0
      go.mod
  90. 526 0
      go.sum
  91. 623 0
      logging_middleware.go
  92. 434 0
      main.go
  93. 171 0
      params.go
  94. 50 0
      pay/ali/client.go
  95. 85 0
      pay/wx/cache.go
  96. 24 0
      pay/wx/config.go
  97. 130 0
      pay/wx/jssdk.go
  98. 129 0
      pay/wx/request_response.go
  99. 291 0
      pay/wx/weixin.go
  100. 0 0
      retry/retry.go

+ 34 - 0
.gitignore

@@ -0,0 +1,34 @@
+auth.db
+client/
+config.ini
+cpbackend.sh
+data/
+grpc_binding.go_test
+log.txt
+#logging_middleware.go
+backend
+nbackend
+nbackend_bak
+ntask
+pb/
+root
+search_index
+storage/
+templetes/
+test.go.bak1
+test.go.txt
+test.*
+*.ini
+# Binaries for programs and plugins
+*.exe
+*.exe~
+*.dll
+*.so
+*.dylib
+
+# Test binary, build with `go test -c`
+*.test
+
+# Output of the go coverage tool, specifically when used with LiteIDE
+*.out
+docker_build

+ 2 - 0
.idea/.gitignore

@@ -0,0 +1,2 @@
+# Default ignored files
+/workspace.xml

+ 5 - 0
.idea/codeStyles/codeStyleConfig.xml

@@ -0,0 +1,5 @@
+<component name="ProjectCodeStyleConfiguration">
+  <state>
+    <option name="PREFERRED_PROJECT_CODE_STYLE" value="Default" />
+  </state>
+</component>

+ 9 - 0
.idea/gobackend_hb1.iml

@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module type="WEB_MODULE" version="4">
+  <component name="Go" enabled="true" />
+  <component name="NewModuleRootManager">
+    <content url="file://$MODULE_DIR$" />
+    <orderEntry type="inheritedJdk" />
+    <orderEntry type="sourceFolder" forTests="false" />
+  </component>
+</module>

+ 6 - 0
.idea/misc.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="JavaScriptSettings">
+    <option name="languageLevel" value="ES6" />
+  </component>
+</project>

+ 8 - 0
.idea/modules.xml

@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="ProjectModuleManager">
+    <modules>
+      <module fileurl="file://$PROJECT_DIR$/.idea/gobackend_hb1.iml" filepath="$PROJECT_DIR$/.idea/gobackend_hb1.iml" />
+    </modules>
+  </component>
+</project>

+ 7 - 0
.idea/vcs.xml

@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="VcsDirectoryMappings">
+    <mapping directory="$PROJECT_DIR$" vcs="Git" />
+    <mapping directory="$PROJECT_DIR$/gobackend" vcs="Git" />
+  </component>
+</project>

+ 5 - 0
Dockerfile

@@ -0,0 +1,5 @@
+FROM test.xiaoniaokuaiyan.com:5000/xiaoniao/goruntimeenv:0.1
+COPY ./docker_build /go
+WORKDIR /go
+ENTRYPOINT ./nbackend -f $APP_CONFIG_FILE > /data/xiaoniao/server/log.docker
+#if have more condition logic, then write bash script file

+ 10 - 0
Makefile

@@ -0,0 +1,10 @@
+outdir=docker_build
+.PHONY: docker_build
+build:
+	if [ ! -d $(outdir) ]; then mkdir $(outdir); fi
+#	cp -r data $(outdir)/ && cp docker_config.ini $(outdir)/config.ini && cp -r cmd/xn_product.bleve $(outdir)/ 
+	cp -r dict $(outdir)/
+	go build -ldflags "-X main.Version=`git rev-parse HEAD`" -o $(outdir)/nbackend
+
+build_docker: build
+	docker build -t xiaoniao/backend:0.1 .

+ 36 - 0
cerror/error.go

@@ -0,0 +1,36 @@
+package cerror
+
+import (
+	"xiaoniaokuaiyan.com/xiaoniao/constants"
+)
+
+import "fmt"
+
+type CError interface {
+	error
+	CError() string
+	GetErrno() int
+}
+type customError struct {
+	Errno  constants.ErrorCode `json:"errno"`
+	Errmsg string              `json:"error"`
+}
+
+func (err *customError) Error() string {
+	return err.Errmsg
+}
+
+func (err *customError) GetErrno() int {
+	return int(err.Errno)
+}
+
+func (err *customError) CError() string {
+	return fmt.Sprintf("%d:%s", err.Errno, err.Errmsg)
+}
+
+func New(errno constants.ErrorCode, msg string) *customError {
+	return &customError{
+		Errno:  errno,
+		Errmsg: msg,
+	}
+}

+ 193 - 0
cmd/search_index.go

@@ -0,0 +1,193 @@
+package main
+
+import (
+	"flag"
+	"fmt"
+	"log"
+	"os"
+	"strings"
+
+	"gopkg.in/guregu/null.v3"
+
+	"github.com/blevesearch/bleve"
+	"github.com/blevesearch/bleve/mapping"
+	_ "xiaoniaokuaiyan.com/xiaoniao/search/analyzer"
+	"xiaoniaokuaiyan.com/xiaoniao/util"
+)
+
+type DetectItem struct {
+	Name string `db:"name" json:"name"`
+	//MarketPrice float32 `db:"market_price" json:"marketPrice"`
+}
+
+type ProductDB struct {
+	Id           string      `db:"id" json:"id"`
+	Name         string      `db:"name" json:"name"`
+	Price        int         `db:"price" json:"price"`
+	IsRecommend  int         `db:"is_recommend" json:"isRecommend"`
+	TKeywords    null.String `db:"keywords" json:"tkeywords"`
+	Keywords     string      `db:"-" json:"keywords"`
+	Picture      string      `db:"picture" json:"picture"`
+	Items        string      `db:"-" json:"items"`
+	CityIds      []string    `db:"-" json:"cityIds"`
+	Pinyin       string      `db:"-" json:"py"`
+	JP           string      `db:"-" json:"jp"`
+	Cates        []string    `db:"-" json:"cates"`
+	SaleNum      int         `db:"sale_num" json:"sale_num"`
+	SortNo       int         `db:"sort_no" json:"sort_no"`
+	CreatedAt    string      `db:"created_at" json:"created_at"`
+	TPutawayTime null.String `db:"putaway_time" json:"-"`
+	PutawayTime  string      `db:"-" json:"putaway_time"`
+	MarketPrice  int         `db:"market_price" json:"market_price"`
+}
+
+func buildIndexMapping() (*mapping.IndexMappingImpl, error) {
+	indexMapping := bleve.NewIndexMapping()
+	err := indexMapping.AddCustomTokenizer("gojieba",
+		map[string]interface{}{
+			"dictpath":     "dict/jieba.dict.utf8", //gojieba.DICT_PATH,
+			"hmmpath":      "dict/hmm_model.utf8",  //gojieba.HMM_PATH,
+			"userdictpath": "dict/user.dict.utf8",  //gojieba.USER_DICT_PATH,
+			"idf":          "dict/idf.utf8",        //gojieba.IDF_PATH,
+			"stop_words":   "dict/stop_words.utf8", //gojieba.STOP_WORDS_PATH,
+			"type":         "gojieba",
+		},
+	)
+	if err != nil {
+		panic(err)
+	}
+	err = indexMapping.AddCustomAnalyzer("gojieba",
+		map[string]interface{}{
+			"type":      "gojieba",
+			"tokenizer": "gojieba",
+		},
+	)
+	if err != nil {
+		panic(err)
+	}
+	indexMapping.DefaultAnalyzer = "gojieba"
+	pyFieldMapping := mapping.NewTextFieldMapping()
+	pyFieldMapping.Name = "py"
+	pyFieldMapping.Analyzer = "standard"
+	jpFieldMapping := mapping.NewTextFieldMapping()
+	jpFieldMapping.Name = "jp"
+	jpFieldMapping.Analyzer = "standard"
+	cityFieldMapping := mapping.NewTextFieldMapping()
+	cityFieldMapping.Name = "cityIds"
+	cityFieldMapping.Analyzer = "standard"
+	catesMapping := mapping.NewTextFieldMapping()
+	catesMapping.Name = "cates"
+	catesMapping.Analyzer = "standard"
+	pyMapping := mapping.NewDocumentMapping()
+	pyMapping.AddFieldMappingsAt("py", pyFieldMapping)
+	pyMapping.AddFieldMappingsAt("jp", jpFieldMapping)
+	pyMapping.AddFieldMappingsAt("cityIds", cityFieldMapping)
+	pyMapping.AddFieldMappingsAt("cates", catesMapping)
+	pictureFieldMapping := bleve.NewTextFieldMapping()
+	pictureFieldMapping.Index = false
+	pyMapping.AddFieldMappingsAt("picture", pictureFieldMapping)
+	//pyMapping.AddSubDocumentMapping("picture", bleve.NewDocumentStaticMapping())
+	//pyMapping.AddSubDocumentMapping("picture", bleve.NewDocumentDisabledMapping())
+	pyMapping.AddSubDocumentMapping("tkeywords", bleve.NewDocumentDisabledMapping())
+	//indexMapping.AddDocumentMapping("pinyin", pyMapping)
+	indexMapping.DefaultMapping = pyMapping
+	return indexMapping, nil
+}
+
+func dump(idx bleve.Index) {
+	ma := bleve.NewMatchAllQuery()
+	request := bleve.NewSearchRequest(ma)
+	request.Fields = []string{"id", "price"}
+	request.SortBy([]string{"_id"})
+
+	request.Size = 1000
+	dc, _ := idx.DocCount()
+	fmt.Println(dc)
+
+	sr, err := idx.Search(request)
+	if err != nil {
+		log.Fatal(err)
+	}
+	//fmt.Println(sr)
+
+	for _, hit := range sr.Hits {
+		fmt.Printf("%s\t,%v\n", hit.Fields["id"], hit.Fields["price"])
+	}
+}
+
+func main() {
+	isDump := flag.Bool("dump", false, "--dump")
+	flag.Parse()
+	mapping, err := buildIndexMapping()
+	if err != nil {
+		log.Fatal(err)
+	}
+	/*docMapping := mapping.DefaultMapping
+	docMapping.AddSubDocumentMapping("isRecommend", bleve.NewDocumentStaticMapping())
+	docMapping.AddSubDocumentMapping("picture", bleve.NewDocumentStaticMapping())
+	*/
+	indexName := "xn_product.bleve"
+	var productIndex bleve.Index
+
+	var ierr error
+	if _, err := os.Stat(indexName); os.IsNotExist(err) {
+		productIndex, ierr = bleve.New(indexName, mapping)
+	} else if err == nil {
+		if *isDump {
+			productIndex, ierr = bleve.OpenUsing(indexName, map[string]interface{}{
+				"read_only": true,
+			})
+		} else {
+			productIndex, ierr = bleve.Open(indexName)
+		}
+	}
+	if ierr != nil {
+		log.Fatal(ierr)
+	}
+	defer productIndex.Close()
+	if *isDump {
+		dump(productIndex)
+		return
+	}
+	/*p := Product{
+		Id:   "200817010121",
+		No:   "sdsdfsjosdifkids",
+		Name: "空腹血糖",
+		Tags: "血糖",
+		Tips: "需要空腹测试",
+	}
+	productIndex.Index(p.Id, p)
+	*/
+	strSql := "select id, name,price, is_recommend, picture, keywords,sale_num,putaway_time,sort_no,created_at,market_price from t_product  where is_putaway = 0 and is_delete = 0;"
+	db := util.GetSqlDB()
+	productList := []ProductDB{}
+	err = db.Select(&productList, strSql)
+	if err != nil {
+		log.Fatal(err)
+	}
+	for _, product := range productList {
+		strSql := "select t1.name from t_detect_product t1 left join t_product_detect_product t2 on t1.id = t2.detect_product_id where t2.product_id = " + product.Id
+		itemList := []string{}
+		db.Select(&itemList, strSql)
+		//strSql = "select tag_name from t_product_tag t1 left join t_tag t2 on t1.tag_id = t2.id where t1.product_id = ?"
+		//tagList := []string{}
+		//db.Select(&tagList, strSql, product.Id)
+		strSql = "select city_id from v_product_city where product_id = ?"
+		cityIds := []string{}
+		db.Select(&cityIds, strSql, product.Id)
+		product.Items = strings.Join(itemList, " ")
+		//product.Tags = strings.Join(tagList, " ")
+		product.CityIds = cityIds
+		product.Pinyin, product.JP, _ = util.GetPinyin(product.Name)
+		product.Keywords = product.TKeywords.String
+		product.PutawayTime = product.TPutawayTime.String
+		strSql = "SELECT cat_id from t_product_category_product where product_id = ?"
+		var cateIds = []string{}
+		db.Select(&cateIds, strSql, product.Id)
+		product.Cates = cateIds
+		productIndex.Index(product.Id, product)
+	}
+	//bytes, _ := json.Marshal(&productList)
+	//fmt.Println(string(bytes))
+
+}

+ 158 - 0
cmd/task.go

@@ -0,0 +1,158 @@
+package main
+
+import (
+	"encoding/json"
+	"flag"
+	"fmt"
+	"log"
+	"strconv"
+	"strings"
+	"xiaoniaokuaiyan.com/xiaoniao/config"
+	"xiaoniaokuaiyan.com/xiaoniao/constants"
+
+	"time"
+
+	"xiaoniaokuaiyan.com/xiaoniao/entity"
+	"xiaoniaokuaiyan.com/xiaoniao/util"
+
+	"github.com/jmoiron/sqlx"
+	"gopkg.in/redis.v2"
+)
+
+//type DetectItem struct {
+//	Name string `db:"name" json:"name"`
+//	//MarketPrice float32 `db:"market_price" json:"marketPrice"`
+//}
+//
+//type ProductDB struct {
+//	Id          string   `db:"id" json:"id"`
+//	Name        string   `db:"name" json:"name"`
+//	Price       int      `db:"price" json:"price"`
+//	IsRecommend int      `db:"is_recommend" json:"isRecommend"`
+//	Tags        string   `db:"tags" json:"tags"`
+//	Picture     string   `db:"picture" json:"picture"`
+//	Items       []string `db:"-" json:"items"`
+//}
+
+func main() {
+	var (
+		client      *redis.Client
+		nowStr      string
+		orderPayKey = "order_unpay"
+		ticker      = time.NewTicker(time.Second)
+		db          *sqlx.DB
+		oid         string
+		timeStr     string
+		mId         int64
+		delaySec    int
+	)
+	fs := flag.NewFlagSet("", flag.ExitOnError)
+	configFile := fs.String("f", "config.ini", "app config file")
+	config.Reload(*configFile)
+	defer ticker.Stop()
+
+	db = util.GetWriteSqlDB()
+	strSql := "select id, created_at, m_id, delay_deadtime from t_order where status = 1"
+	rows, err := db.Query(strSql)
+	if err != nil {
+		log.Fatal(err)
+	}
+	client = util.GetRedis()
+	client.Select(2)
+	for rows.Next() {
+		rows.Scan(&oid, &timeStr, &mId, &delaySec)
+		client.HSet(orderPayKey, oid, fmt.Sprintf("%s;%d;%d", timeStr, mId, delaySec))
+	}
+	var delayTimeSecs int64
+	for {
+		select {
+		case <-ticker.C:
+			client = util.GetRedis()
+			client.Select(2)
+			msCmd := client.HGetAllMap(orderPayKey)
+			if err := msCmd.Err(); err != nil {
+				log.Panicln(err)
+			}
+			kvs := msCmd.Val()
+			for key, val := range kvs {
+				temp := strings.Split(val, ";")
+				if len(temp) < 2 {
+					continue
+				}
+				delayTimeSecs = int64(time.Second) * 30 * 60
+				if len(temp) == 3 {
+					delaySec, err = strconv.Atoi(temp[2])
+					if err != nil {
+						log.Println(err, val)
+						continue
+					}
+					delayTimeSecs = int64(time.Second) * int64(delaySec)
+				}
+
+				nowStr = time.Now().Add(-time.Duration(delayTimeSecs)).Format("2006-01-02 15:04:05")
+				if temp[0] < nowStr {
+					tx, _ := db.Begin()
+					//todo set order status to unused
+					sr, _ := tx.Exec("update t_order set status = 9, m_id = 0 where id = ? and status = 1", key)
+					if er, _ := sr.RowsAffected(); er <= 0 {
+						log.Println("update order status of ", key, " failed")
+						client.HDel(orderPayKey, key)
+						tx.Rollback()
+						continue
+					}
+					if temp[1] != "0" {
+						sr, _ = tx.Exec("update t_producer_info set remain_num = remain_num + 1 where id = ?", temp[1])
+						if er, _ := sr.RowsAffected(); er <= 0 {
+							log.Println("failed to update producer info of ", key, temp[1])
+							client.HDel(orderPayKey, key)
+							tx.Rollback()
+							continue
+						}
+					}
+					orderItem := entity.OrderDB{}
+					err1 := db.Get(&orderItem, "select * FROM t_order WHERE id = ?", key)
+
+					//回滚库存
+					var ops = []entity.OrderProduct{}
+					db.Select(&ops, "select t1.*, t2.stock_switch from t_order_product t1 left join t_product t2 on t1.product_id = t2.id where order_id = ?", key)
+					for _, op := range ops {
+						if op.StockSwitch == "ON" {
+							sql := "update t_product set stock = stock + ? where id = ?"
+							if orderItem.Source == "sp_zfb" {
+								sql = "update t_product set zfb_stock = zfb_stock + ? where id = ?"
+							}
+							result, _ := tx.Exec(sql, op.Quantity, op.ProductId)
+							if ra, _ := result.RowsAffected(); ra <= 0 {
+								tx.Rollback()
+								log.Println(key + "更新库存失败")
+							}
+						}
+					}
+					db.Exec("update t_discount_ticket set order_id = null, status = 0 where order_id = ?;", key)
+					intCmd := client.HDel(orderPayKey, key)
+					if err := intCmd.Err(); err != nil {
+						tx.Rollback()
+						log.Println(err)
+						continue
+					}
+					tx.Commit()
+
+					if err1 == nil {
+						//20210303 添加状态通知
+						if util.SourceCheck(orderItem.Source) {
+							log.Printf("%s,send status 9", key)
+							msg := map[string]interface{}{
+								"user":    "system",
+								"orderid": orderItem.Id,
+								"source":  orderItem.Source,
+								"status":  constants.ORDERSTATUS_UNUSED,
+							}
+							buf, _ := json.Marshal(msg)
+							client.Publish("order-status-change", string(buf))
+						}
+					}
+				}
+			}
+		}
+	}
+}

+ 50 - 0
config/config.go

@@ -0,0 +1,50 @@
+package config
+
+import (
+	"github.com/go-ini/ini"
+	"log"
+)
+
+var IniConf *ini.File
+var ipath string
+
+type changeCallback func()
+
+var changeCallbackList = []changeCallback{}
+
+/*func init() {
+pwd, _ := os.Getwd()
+ipath = filepath.Join(pwd, "config.ini")
+var err error
+/*fs := flag.NewFlagSet("", flag.ContinueOnError)
+fp := fs.String("f", "", "config file path")
+fs.Parse(os.Args[1:])
+if *fp != "" {
+	ipath = *fp
+}
+IniConf, err = ini.Load(ipath)
+if err != nil {
+	log.Fatal(err)
+}
+*/
+
+func Reload(cpath string) {
+	if cpath == "" {
+		cpath = ipath
+	}
+	iniConf, err := ini.Load(cpath)
+	if err != nil {
+		log.Println(err)
+		return
+	} else {
+		IniConf = iniConf
+	}
+	for _, cb := range changeCallbackList {
+		cb()
+	}
+	ipath = cpath
+}
+
+func RegistChangeCallback(cb changeCallback) {
+	changeCallbackList = append(changeCallbackList, cb)
+}

+ 42 - 0
constants/constants.go

@@ -0,0 +1,42 @@
+package constants
+
+// go:generate stringer -type=PaymentType
+// go:generate jsonenums -type=PaymentType
+type PaymentType int
+
+const (
+	PAYMENTTYPE_UNKNOW PaymentType = iota
+	PAYMENTTYPE_WEIXIN
+	PAYMENTTYPE_ALIPAY
+	PAYMENTTYPE_UNION
+	PAYMENTTYPE_CASH
+	PAYMENTTYPE_COUPON
+	PAYMENTTYPE_TRANSFER
+	PAYMENTTYPE_NONE
+)
+
+type OrderStatus int
+
+const (
+	ORDERSTATUS_INVALID   OrderStatus = iota
+	ORDERSTATUS_UNPAY                 //待支付
+	ORDERSTATUS_UNRECEIVE             //待接单
+	ORDERSTATUS_UNGO                  //待上门
+	ORDERSTATUS_ALREADYGO             //上门完成
+	ORDERSTATUS_UNREPORT              //待上传检测报告
+	ORDERSTATUS_COMPLETE              //完成
+	ORDERSTATUS_CANCELED              //已取消
+	ORDERSTATUS_DELETED               //已删除
+	ORDERSTATUS_UNUSED                //超时未支付失效
+)
+
+type CouponType int
+
+const (
+	COUPONTYPE_INVALID     CouponType = iota
+	COUPONTYPE_NORMAL                 //普通代金券
+	COUPONTYPE_LIMIT                  //满减券
+	COUPONTYPE_SERVICE                //服务费券
+	COUPONTYPE_COMPOSITION            //组合券
+	COUPONTYPE_DISCOUNT               //折扣券
+)

+ 13 - 0
constants/constants_test.go

@@ -0,0 +1,13 @@
+package constants
+
+import (
+	"encoding/json"
+	"fmt"
+	"testing"
+)
+
+func TestPayTypeString(t *testing.T) {
+	pt := PaymentType(1)
+	buf, _ := json.Marshal(pt)
+	fmt.Println(string(buf))
+}

+ 14 - 0
constants/error.go

@@ -0,0 +1,14 @@
+package constants
+
+type ErrorCode int
+
+const (
+	ERRORCODE_API_TOKEN ErrorCode = iota + 10000
+)
+
+const (
+	ERRORCODE_FCODE_INVILID ErrorCode = iota + 10200
+	ERRORCODE_FCODE_EXPIRED
+	ERRORCODE_FCODE_UPEXCEED
+	ERRORCODE_FCODE_ALREADY_GOT
+)

+ 48 - 0
constants/smscode_type.go

@@ -0,0 +1,48 @@
+package constants
+
+type SMSType int
+
+const (
+	SMS_REGIST                SMSType = iota + 1 //用户注册获取短信验证码
+	SMS_FORGOT_PASSWORD                          //用户忘记密码,获取短信验证码以重置密码
+	SMS_ORDER_PAID_INFORM                        //用户支付成功提醒
+	SMS_RESULT_TURNOUT                           //出化验结果之后给用户推送
+	SMS_CHECK_RESULT                             //用户获取短信验证码查看化验结果报告
+	SMS_LOGIN                                    //登录随机密码短信
+	SMS_ORDER_PAID_INFORM_MBH                    //梦百合
+	SMS_HOUSEKEEPING_QUERY                       //家政套餐查询验证码
+	SMS_ORDER_PAID_INFORM_JIYIN
+	SMS_CHECKMOBILE //验证手机号
+	SMS_JDBOOK
+)
+
+const (
+	SMS_ACT_YOUKE_LOGIN SMSType = iota + 101
+)
+
+type SMSCodeType int
+
+const (
+	SMSCODE_REGIST SMSCodeType = iota + 1
+	SMSCODE_FORGOT_PASSWORD
+	SMSCODE_CHECK_RESULT
+	SMSCODE_LOGIN
+	SMSCODE_HOUSEKEEPING_QUERY
+	SMSCODE_CHECKMOBILE
+)
+const (
+	SMSCODE_ACT_YOUKE_LOGIN = iota + 101
+)
+
+const SMSCONTENT_REGIST = "您的注册验证码为[{code}]"
+const SMSCONTENT_PAYSUCCESS = "尊敬的客户,您已成功购买[{products}]产品服务,小鸟会尽快为您处理订单,如您需要修改订单信息请及时拨打4001-365-360(服务时间为周一至周日8:30-18:00),或在小鸟快验微信公众号上留言,小鸟客服竭诚为您服务。"
+const SMSCONTENT_CHECKRESULT = "您正在申请查看化验单的结果,为保证用户隐私,您的验证码为[{code}]"
+const SMSCONTENT_RESULT_TURNOUT = "快报!快报!您的体检快报送到,查询码为[{code}],戳链接查看吧!http://m.xiaoniaokuaiyan.com"
+const SMSCONTENT_FORGOT_PASSWORD = "您正在使用找回密码功能,请确认您的验证码 [{code}]"
+const SMSCONTENT_LOGIN = "您的登录验证码为[{code}]"
+const SMSCONTENT_CHECKMOBILE = "您的手机验证码为[{code}]"
+const SMSCONTENT_MBH_PAYSUCCESS = "亲,您好,您的订单【{OrderId}】已经支付成功,请您保持电话畅通,我们会在一周之内与您电话联系哦,如有疑问可致电4001365360,祝您生活愉快!"
+const SMSCONTENT_HOUSEKEEPING = "您正在申请查看家政报告,您的验证码为[{code}]"
+const SMSCONTENT_JIYIN_PAYSUCCESS = "您已成功购买订单({products})产品服务,小鸟会尽快为您发出包裹,如果您需要修改订单信息请及时拨打400-1365-360小鸟客服竭诚为您服务。客服服务时间为周一至周日9:00-18:00。"
+const SMSCONTENT_ACT_YOUKE_LOGIN = "您的验证码为[{code}]"
+const SMSCONTENT_JDBOOK_SUCCESS = "您的体检预约已经成功,体检时间{time},地址:{address}。如需修改时间,请使用京ME搜索“员工健康关怀--福利体检”"

+ 17 - 0
credentials/token_credential.go

@@ -0,0 +1,17 @@
+package credentials
+
+import "golang.org/x/net/context"
+
+type TokenCredential struct {
+	Token string
+}
+
+func (cred *TokenCredential) GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error) {
+	return map[string]string{
+		"token": cred.Token,
+	}, nil
+}
+
+func (cred *TokenCredential) RequireTransportSecurity() bool {
+	return false
+}

+ 82 - 0
dal/cart_dal.go

@@ -0,0 +1,82 @@
+package dal
+
+import (
+	"errors"
+	"fmt"
+
+	"xiaoniaokuaiyan.com/xiaoniao/entity"
+	"xiaoniaokuaiyan.com/xiaoniao/util"
+)
+
+type Cart struct{}
+
+func (c *Cart) Get(customId int) ([]entity.ProductDB, error) {
+	db := util.GetSqlDB()
+	strSql := "select t1.quantity, t2.* from t_cart t1 left join t_product t2 on t1.pid = t2.id where cid = ?"
+	plist := []entity.ProductDB{}
+	err := db.Select(&plist, strSql, customId)
+	if err != nil {
+		return nil, err
+	}
+	return plist, nil
+}
+
+func (c *Cart) Update(customId, productId, quantity int, isAdd bool) (bool, error) {
+	var strSql string = "select quantity from t_cart where cid = ? and pid =?"
+	db := util.GetWriteSqlDB()
+	var (
+		quan int
+		err  error
+	)
+	db.Get(&quan, strSql, customId, productId)
+
+	if quan <= 0 {
+		if quantity < 1 {
+			return false, errors.New("wrong param quantity")
+		}
+		strSql = "insert into t_cart(cid, pid, quantity) values(?,?,?);"
+		_, err = db.Exec(strSql, customId, productId, quantity)
+	} else {
+		if isAdd {
+			quantity = quan + quantity
+		}
+		if quantity < 1 {
+			return false, errors.New("wrong param quantity")
+		}
+		strSql = "update t_cart set quantity = ? where cid = ? and pid = ?"
+		_, err = db.Exec(strSql, quantity, customId, productId)
+	}
+	if err != nil {
+		return false, err
+	}
+	return true, nil
+}
+
+func (c *Cart) Del(customId int, productIds []int) (bool, error) {
+	if len(productIds) == 0 {
+		return false, errors.New("wrong product id param")
+	}
+	var strSql = fmt.Sprintf("delete from t_cart where cid = %d and pid in(", customId)
+	for _, pid := range productIds {
+		strSql += fmt.Sprintf("%d,", pid)
+	}
+	strSql = strSql[0:len(strSql)-1] + ");"
+	db := util.GetWriteSqlDB()
+	_, err := db.Exec(strSql)
+	if err != nil {
+		return false, err
+	}
+	return true, nil
+}
+
+func (c *Cart) Clear(customId int) (bool, error) {
+	strSql := "delete from t_cart where cid = ?"
+	db := util.GetWriteSqlDB()
+	_, err := db.Exec(strSql, customId)
+	if err != nil {
+		return false, err
+	}
+	return true, nil
+}
+
+var DefaultCartDal = &Cart{}

+ 40 - 0
dal/cart_dal_test.go

@@ -0,0 +1,40 @@
+package dal
+
+import (
+	"fmt"
+	"os"
+	"testing"
+)
+
+var cartDal ICart
+
+func setup() {
+	cartDal = &Cart{}
+}
+
+func TestMain(m *testing.M) {
+	setup()
+	code := m.Run()
+	//teardown
+	os.Exit(code)
+}
+
+func TestAddCart(t *testing.T) {
+	var (
+		customId  = 1
+		productId = 1
+	)
+	sucess, err := cartDal.Update(customId, productId, 1,true)
+	if err != nil {
+		t.Fatal(err)
+	}
+	t.Log(sucess)
+}
+
+func TestGetCart(t *testing.T) {
+	plist, err := cartDal.Get(1)
+	if err != nil {
+		t.Fatal(err)
+	}
+	fmt.Println(plist)
+}

+ 58 - 0
dal/city_dal.go

@@ -0,0 +1,58 @@
+package dal
+
+import (
+	"xiaoniaokuaiyan.com/xiaoniao/entity"
+	"xiaoniaokuaiyan.com/xiaoniao/util"
+)
+
+type City struct{}
+
+func (c *City) GetOpenList() ([]entity.City, error) {
+	db := util.GetSqlDB()
+	strSql := "select * from t_city where is_open = 1"
+	var cityList = []entity.City{}
+	err := db.Select(&cityList, strSql)
+	if err != nil {
+		return nil, err
+	}
+	return cityList, nil
+}
+
+func (c *City) GetCityListById(ids []int) ([]entity.City, error) {
+	strIds := util.IntJoin(ids, ",")
+	db := util.GetSqlDB()
+	strSql := "select * from t_city where id in(" + strIds + ");"
+	var cityList = []entity.City{}
+	err := db.Select(&cityList, strSql)
+	return cityList, err
+}
+
+func (c *City) GetCountyByCityId(cityId int) ([]entity.County, error) {
+	db := util.GetSqlDB()
+	strSql := "select * from t_county where city_id = ? and flag = 'Y';"
+	var countyList = []entity.County{}
+	err := db.Select(&countyList, strSql, cityId)
+	return countyList, err
+}
+
+func (c *City) GetCityAllList() ([]entity.CityAll, error) {
+	db := util.GetSqlDB()
+	strSql := `SELECT
+	t1.id AS province_id,
+	t1.name AS province,
+	t2.id AS city_id,
+	t2.NAME AS city,
+	t3.id AS country_id,
+	t3.name AS country 
+FROM
+	t_province t1
+	LEFT JOIN t_city t2 ON t1.id = t2.province_id
+	LEFT JOIN t_county t3 ON t3.city_id = t2.id
+	where t3.flag = 'Y'`
+	var cityAll = []entity.CityAll{}
+	err := db.Select(&cityAll, strSql)
+
+	return cityAll, err
+}
+
+var DefaultCityDal = &City{}

+ 8 - 0
dal/constants.go

@@ -0,0 +1,8 @@
+package dal
+
+import "errors"
+
+var (
+	DBRECORD_NOT_EXISTS_ERROR     = errors.New("can not find record from db")
+	DBRECORD_ALREADY_EXISTS_ERROR = errors.New("record already exists")
+)

+ 142 - 0
dal/coupon_dal.go

@@ -0,0 +1,142 @@
+package dal
+
+import (
+	"database/sql"
+	"encoding/json"
+	"errors"
+	"time"
+
+	"xiaoniaokuaiyan.com/xiaoniao/cerror"
+	"xiaoniaokuaiyan.com/xiaoniao/constants"
+	"xiaoniaokuaiyan.com/xiaoniao/entity"
+	"xiaoniaokuaiyan.com/xiaoniao/util"
+)
+
+type Coupon struct {
+}
+
+func (cdal *Coupon) Get(id int, orderId string) (*entity.DiscountTicketDB, error) {
+	db := util.GetSqlDB()
+	var (
+		strSql     string
+		paramValue interface{}
+	)
+	if id > 0 {
+		strSql = "select * from t_discount_ticket where id = ?"
+		paramValue = id
+	} else {
+		strSql = "select * from t_discount_ticket where order_id = ?"
+		paramValue = orderId
+	}
+	citem := entity.DiscountTicketDB{}
+	err := db.Get(&citem, strSql, paramValue)
+	if err != nil {
+		if err == sql.ErrNoRows {
+			return nil, nil
+		}
+		return nil, err
+	}
+	return &citem, nil
+}
+
+func (cdal *Coupon) Save(item *entity.DiscountTicket) (*entity.DiscountTicket, error) {
+	db := util.GetWriteSqlDB()
+	sqlStr, kvm := util.GenerateInsertSqlFromStruct("t_discount_ticket", item)
+	result, err := db.NamedExec(sqlStr, kvm)
+	if err != nil {
+		return nil, errors.New("db error")
+	}
+	cid, err := result.LastInsertId()
+	if err != nil {
+		return nil, err
+	}
+	item.Id = int(cid)
+	return item, nil
+}
+
+func (cdal *Coupon) Update(item *entity.DiscountTicket) (*entity.DiscountTicket, error) {
+	db := util.GetWriteSqlDB()
+	sqlStr, kvm := util.GenerateUpdateSqlFromStruct("t_discount_ticket", item, " where id = :id")
+	_, err := db.NamedExec(sqlStr, kvm)
+	if err != nil {
+		return nil, err
+	}
+	return item, nil
+}
+
+func (cdal *Coupon) Exchange(codeStr string, customId int, mobile string) (interface{}, cerror.CError) {
+	db := util.GetWriteSqlDB()
+	strSql := "select * from t_fcode where code_str = ?"
+	codeItem := &entity.Fcode{}
+	err := db.Get(codeItem, strSql, codeStr)
+	if err != nil {
+		return nil, cerror.New(constants.ERRORCODE_FCODE_INVILID, "F码无效")
+	}
+	if err := codeItem.Valid(); err != nil {
+		return nil, err
+	}
+	strSql = "select count(*) as num from t_fcode_custom where cid = ? and fid = ?"
+	var num int
+	db.Get(&num, strSql, customId, codeItem.Id)
+	if num > 0 {
+		return nil, cerror.New(constants.ERRORCODE_FCODE_ALREADY_GOT, "该用户已经使用此码兑换过优惠券")
+	}
+	var tlist = []*entity.DiscountTicket{}
+	ctype := constants.CouponType(codeItem.TypeId)
+	var ticketDeadline = codeItem.TicketDeadline
+	if codeItem.TicketValidDays.Valid && codeItem.TicketValidDays.Int64 > 0 {
+		ticketDeadline = time.Now().Add(time.Hour * 24 * time.Duration(codeItem.TicketValidDays.Int64)).Format("2006-01-02 15:04:05")
+	}
+	if ctype == constants.COUPONTYPE_COMPOSITION {
+		tt := []struct {
+			TypeId       int    `json:"type_id"`
+			Value        int    `json:"ticket_value"`
+			UseMaxValue  int    `json:"use_max_value"`
+			BindProducts string `json:"bind_products"`
+		}{}
+		err = json.Unmarshal([]byte(codeItem.Remark.String), &tt)
+		if err != nil {
+			return nil, cerror.New(101, "unmarshal error")
+		}
+		for _, t := range tt {
+			ticket := &entity.DiscountTicket{
+				TypeId:       t.TypeId,
+				Mobile:       mobile,
+				Value:        t.Value,
+				Deadline:     ticketDeadline,
+				UseMaxValue:  t.UseMaxValue,
+				BindProducts: codeItem.BindProducts.String,
+			}
+			if t.BindProducts != "" {
+				ticket.BindProducts = t.BindProducts
+			}
+			tlist = append(tlist, ticket)
+		}
+
+	} else {
+		ticket := &entity.DiscountTicket{
+			TypeId:       codeItem.TypeId,
+			Mobile:       mobile,
+			Value:        codeItem.TicketValue,
+			Deadline:     ticketDeadline,
+			UseMaxValue:  codeItem.UseMaxValue,
+			BindProducts: codeItem.BindProducts.String,
+		}
+		tlist = append(tlist, ticket)
+	}
+	for _, titem := range tlist {
+		_, err = cdal.Save(titem)
+		if err != nil {
+			return nil, cerror.New(500, err.Error())
+		}
+		strSql = "insert into t_fcode_custom(cid, fid, qid) values(?,?,?)"
+		_, err = db.Exec(strSql, customId, codeItem.Id, titem.Id)
+		if err != nil {
+			return nil, cerror.New(500, err.Error())
+		}
+	}
+	db.Exec("update t_fcode set already_use_num = already_use_num + 1 where code_str = ?", codeStr)
+	return tlist, nil
+}
+
+var DefaultCouponDal = &Coupon{}

+ 16 - 0
dal/coupon_dal_test.go

@@ -0,0 +1,16 @@
+package dal
+
+import (
+	"fmt"
+	"testing"
+)
+
+func TestGetCoupon(t *testing.T) {
+	cid := 2
+	citem, err := DefaultCouponDal.Get(cid,"")
+	if err != nil {
+		t.Fatal(err)
+	}
+	fmt.Println(citem)
+
+}

+ 72 - 0
dal/dal.go

@@ -0,0 +1,72 @@
+package dal
+
+import (
+	"fmt"
+
+	"xiaoniaokuaiyan.com/xiaoniao/util"
+)
+
+type SortParam struct {
+	SortBy  string
+	SortDir int
+}
+
+type ListResult struct {
+	Totoal    int         `json:"total"`
+	PageIndex int         `json:"pi"`
+	PageSize  int         `json:"ps"`
+	Data      interface{} `json:"data"`
+}
+
+func List(result interface{}, tableName, strSql, orderStr, whereStr string, whereValue []interface{}, pinfo Pager) (*ListResult, error) {
+	count, err := Count("select count(*) as total from "+tableName+" "+whereStr, whereValue)
+	if err != nil {
+		return nil, err
+	}
+	if count == 0 {
+		return &ListResult{
+			Totoal:    0,
+			PageIndex: pinfo.PageIndex,
+			PageSize:  pinfo.PageSize,
+		}, nil
+	}
+	db := util.GetSqlDB()
+
+	if pinfo.PageIndex < 1 {
+		pinfo.PageIndex = 1
+	}
+	if pinfo.PageSize == 0 {
+		pinfo.PageSize = 10
+	}
+	strSql += " " + whereStr + " " + orderStr
+	strSql += fmt.Sprintf(" limit %d,%d ", (pinfo.PageIndex-1)*pinfo.PageSize, pinfo.PageSize)
+	//rows, err := db.Queryx(strSql, whereValue...)
+	err = db.Select(result, strSql, whereValue...)
+	if err != nil {
+		return nil, err
+	}
+	/*err = util.ScanStructOld(rows.Rows, result)
+	if err != nil {
+		return nil, err
+	}*/
+	return &ListResult{
+		Totoal:    count,
+		PageSize:  pinfo.PageSize,
+		PageIndex: pinfo.PageIndex,
+		Data:      result,
+	}, nil
+}
+
+func Count(strSql string, params []interface{}) (int, error) {
+	db := util.GetSqlDB()
+	//rows, err := db.NamedQuery(strSql, params)
+	rows, err := db.Queryx(strSql, params...)
+	if err != nil {
+		return 0, err
+	}
+	var count int
+	for rows.Rows.Next() {
+		rows.Rows.Scan(&count)
+	}
+	return count, nil
+}

File diff suppressed because it is too large
+ 46 - 0
dal/dal_test.go


+ 514 - 0
dal/deliver_userdal.go

@@ -0,0 +1,514 @@
+package dal
+
+import (
+	"database/sql"
+	"encoding/json"
+	"errors"
+	"fmt"
+	"github.com/leeqvip/gophp/serialize"
+	"gopkg.in/mgo.v2/bson"
+	"sort"
+	"strconv"
+	"time"
+
+	"github.com/jmoiron/sqlx"
+	_ "github.com/leeqvip/gophp"
+	"gopkg.in/guregu/null.v3"
+	"xiaoniaokuaiyan.com/xiaoniao/entity"
+	"xiaoniaokuaiyan.com/xiaoniao/util"
+)
+
+type DeliverUserDal struct {
+}
+
+type DUOrderItem struct {
+	OrderId         string      `db:"id" json:"order_id"`
+	CustomName      string      `db:"name" json:"name"`
+	Gender          string      `db:"gender" json:"gender"`
+	Age             uint8       `db:"age" json:"age"`
+	Birthday        string      `db:"birthday" json:"birthday"`
+	CustomMobile    string      `db:"mobile" json:"mobile"`
+	Address         string      `db:"address" json:"address"`
+	BookTime        null.String `db:"book_time" json:"book_time"`
+	OrderStatus     int         `db:"status" json:"order_status"`
+	Products        []DUProduct `db:"-" json:"products"`
+	NeedEmptiness   null.Int    `db:"need_emptiness" json:"need_emptiness"`
+	ReportPeriod    null.String `db:"report_period" json:"report_period"`
+	PressurePipe    null.String `db:"pressure_pipe" json:"pressure_pipe"`
+	BloodAddress    null.String `db:"blood_address" json:"blood_address"`
+	Notice          null.String `db:"notice" json:"notice"`
+	Remark1         null.String `db:"remark1" json:"remark1"`
+	GetType         null.String `db:"get_type" json:"get_type"`
+	DeliverUsers    []DU        `db:"-" json:"deliver_users"`
+	EVisitDate      null.String `db:"e_visit_date" json:"EVisitDate"`
+	EVisitTimeRange null.String `db:"e_visit_time_range" json:"EVisitTimeRange"`
+	IdNum           null.String `db:"id_num" json:"IdNum"`
+	NucleinType     uint8       `db:"nuclein_type" json:"nuclein_type"`
+}
+
+type DUOrderItemV2 struct {
+	DUOrderItem
+	IsDone bool `json:"is_done"`
+}
+
+type DU struct {
+	Name   string `db:"name" json:"name"`
+	Tel    string `db:"tel" json:"tel"`
+	Career string `db:"career" json:"career"`
+}
+type DUProduct struct {
+	Name      string `db:"name" json:"name"`
+	ItemNames string `db:"item_names" json:"item_names"`
+	Searchs   string `db:"searchs" json:"searchs"`
+}
+
+func (dud *DeliverUserDal) GetOrderList(openid string, status, pageIndex, pageSize int) (interface{}, error) {
+	//20230403 只查100 去掉110
+	strStatus := " status in (3,4, 6, 11) and t3.retype in ('100') "
+	whereStr := " where t1.openid = ? and" + strStatus
+	params := []interface{}{
+		openid,
+	}
+	strSql := `select t3.id, t3.name, t3.gender, t3.birthday, t3.age, t3.mobile,t3.status, concat(t3.address, t3.detail_address) as address, concat(t3.visit_date, ' ', t3.visit_time_range) as book_time, t4.need_emptiness, t4.report_period, pressure_pipe,
+	blood_address, notice, t4.remark1,t4.e_visit_date,t4.e_visit_time_range,t2.get_type,t3.id_num,t3.nuclein_type
+	from t_deliver_user t1 left join t_order_deliver_user t2 on t1.id = t2.deliver_user_id
+	right join t_order t3 on t2.order_id = t3.id
+	left join t_order_extra t4 on t3.id = t4.order_id `
+	dataList := &[]*DUOrderItem{}
+	result, err := List(dataList, "("+strSql+whereStr+") t5", strSql+whereStr, " order by t3.visit_date desc , t3.nuclein_type ,t3.visit_time_range", "", params, Pager{PageIndex: pageIndex, PageSize: pageSize})
+	if err != nil {
+		return nil, err
+	}
+
+	strSql = `select t3.*, group_concat(dp.name) as item_names from t_product_detect_product pdp left join t_detect_product dp on pdp.detect_product_id = dp.id right join 
+		(select t2.id, t2.name,t2.searchs from t_order_product t1 left join t_product t2 on t1.product_id = t2.id where t1.order_id = ?) t3 on pdp.product_id = t3.id`
+	strSqlDu := "select t1.name, t1.tel, t2.career from t_deliver_user t1 left join t_order_deliver_user t2 on t1.id = t2.deliver_user_id right join t_order t3 on t2.order_id = t3.id where t3.id = ?"
+	db := util.GetSqlDB()
+	for _, item := range *dataList {
+		pitems := []DUProduct{}
+		err = db.Select(&pitems, strSql, item.OrderId)
+		if err != nil {
+			return nil, err
+		}
+		item.Products = pitems
+
+		//fetch deliver user info
+		duList := []DU{}
+		err = db.Select(&duList, strSqlDu, item.OrderId)
+		if err != nil {
+			return nil, err
+		}
+		item.DeliverUsers = duList
+	}
+	return result, nil
+}
+
+// 20220225
+func (dud *DeliverUserDal) GetOrderListV2(openid string, pageIndex, pageSize int) (interface{}, error) {
+	//20230403 只查100 去掉110
+	strStatus := " status = 3 and t3.retype in ('100') "
+	whereStr := " where t1.openid = ? and" + strStatus
+
+	db := util.GetSqlDB()
+	strSql := `select t3.id, t3.name, t3.gender, t3.birthday, t3.age, t3.mobile,t3.status, concat(t3.address, t3.detail_address) as address, concat(t3.visit_date, ' ', t3.visit_time_range) as book_time, t4.need_emptiness, t4.report_period, pressure_pipe,
+	blood_address, notice, t4.remark1,t4.e_visit_date,t4.e_visit_time_range,t2.get_type,t3.id_num,t3.nuclein_type
+	from t_deliver_user t1 left join t_order_deliver_user t2 on t1.id = t2.deliver_user_id
+	right join t_order t3 on t2.order_id = t3.id
+	left join t_order_extra t4 on t3.id = t4.order_id `
+	dataList := []*DUOrderItemV2{}
+	err := db.Select(&dataList, strSql+whereStr+" order by t3.visit_date desc , t3.nuclein_type ,t3.visit_time_range limit 100", openid)
+	if err != nil {
+		return nil, err
+	}
+
+	strSql = `select t3.*, group_concat(dp.name) as item_names from t_product_detect_product pdp left join t_detect_product dp on pdp.detect_product_id = dp.id right join 
+		(select t2.id, t2.name,t2.searchs from t_order_product t1 left join t_product t2 on t1.product_id = t2.id where t1.order_id = ?) t3 on pdp.product_id = t3.id`
+	strSqlDu := "select t1.name, t1.tel, t2.career from t_deliver_user t1 left join t_order_deliver_user t2 on t1.id = t2.deliver_user_id right join t_order t3 on t2.order_id = t3.id where t3.id = ?"
+
+	strSqlSign := "select count(1) from t_order_sign where order_id = ? and flag='200' and status = '300'"
+	done := []*DUOrderItemV2{}
+	notDone := []*DUOrderItemV2{}
+	for _, item := range dataList {
+		pitems := []DUProduct{}
+		err = db.Select(&pitems, strSql, item.OrderId)
+		if err != nil {
+			return nil, err
+		}
+		item.Products = pitems
+
+		//fetch deliver user info
+		duList := []DU{}
+		err = db.Select(&duList, strSqlDu, item.OrderId)
+		if err != nil {
+			return nil, err
+		}
+		item.DeliverUsers = duList
+		count := 0
+		db.Get(&count, strSqlSign, item.OrderId)
+		item.IsDone = count > 0
+		if count > 0 {
+			done = append(done, item)
+		} else {
+			notDone = append(notDone, item)
+		}
+	}
+	return map[string]interface{}{
+		"not_done": notDone,
+		"done":     done,
+	}, nil
+}
+
+func (dud *DeliverUserDal) GetOrderSign(orderId string) (interface{}, error) {
+	db := util.GetSqlDB()
+	strSql := "select t2.openid,t1.career from t_order_deliver_user t1 inner join t_deliver_user t2 on t1.deliver_user_id = t2.id where t1.order_id = ?"
+	deliverUserlist := []struct {
+		Openid string `json:"openid"`
+		Career string `json:"career"`
+	}{}
+	err := db.Select(&deliverUserlist, strSql, orderId)
+	if err != nil {
+		return nil, err
+	}
+	if len(deliverUserlist) == 0 {
+		return map[string]interface{}{
+			"deliver_user_list": deliverUserlist,
+			"sign_list":         nil,
+		}, nil
+	}
+	strSql = "select * from t_order_sign where order_id = ? and flag='200' order by id desc"
+	signList := &[]entity.OrderSign{}
+	err = db.Select(signList, strSql, orderId)
+	if err != nil {
+		return nil, err
+	}
+	orderInfo, _ := DefaultOrderDal.Get(orderId)
+	return map[string]interface{}{
+		"deliver_user_list": deliverUserlist,
+		"sign_list":         signList,
+		"order_info":        orderInfo,
+	}, nil
+}
+
+func (dud *DeliverUserDal) SaveOrderSign(signItem *entity.OrderSign) (interface{}, error) {
+	var (
+		strSql string
+		kv     map[string]interface{}
+	)
+	db := util.GetWriteSqlDB()
+	tx := db.MustBegin()
+	strSql, kv = util.GenerateInsertSqlFromStruct("t_order_sign", signItem)
+	sqlResult, err := tx.NamedExec(strSql, kv)
+	if err != nil {
+		tx.Rollback()
+		return false, err
+	}
+	if ra, _ := sqlResult.RowsAffected(); ra <= 0 {
+		tx.Rollback()
+		return false, errors.New("failed to sign")
+	}
+	if signItem.Status == "400" {
+		var mj = struct {
+			Code      string `json:"code"`
+			IsXueYang string `json:"isxieyang"`
+		}{}
+		err := json.Unmarshal([]byte(signItem.Remark), &mj)
+		if err != nil {
+			tx.Rollback()
+			return nil, err
+		}
+		//20210927 如果血样是0 则是核酸类,血检条码必须唯一
+		if mj.IsXueYang == "0" {
+			var count int
+			db.Get(&count, "select count(1) from t_order where blood_codes=? and id != ? ", mj.Code, signItem.OrderId)
+			if count > 0 {
+				tx.Rollback()
+				return nil, fmt.Errorf("2::已存在的blood_codes %s", mj.Code)
+			}
+		}
+		tx.Exec("update t_order set blood_codes = ? where id = ?", mj.Code, signItem.OrderId)
+		go util.InsertMongo(signItem.OrderId, "护士系统400", 1, map[string]interface{}{"blood_codes": mj.Code, "url": "/duser/saveordersign/400"})
+	} else if signItem.Status == "700" {
+		//20210218 增加 700 护士修改 订单name gender birthday idnum age 字段 只有在状态3 待上门才可以修改
+		//20210223 增加 mobile
+		var item = struct {
+			Name   string `json:"name"`
+			Gender string `json:"gender"`
+			Birth  string `json:"birth"`
+			IdNum  string `json:"idnum"`
+			Mobile string `json:"mobile"`
+		}{}
+
+		err := json.Unmarshal([]byte(signItem.Remark), &item)
+		if err != nil {
+			tx.Rollback()
+			return nil, err
+		}
+		//if len(item.Birth) >= 7 {
+		//	item.Birth = item.Birth[0:7]
+		//}
+		birth, err := time.Parse("2006-01-02", item.Birth)
+		if err != nil {
+			tx.Rollback()
+			return nil, err
+		}
+		age := time.Now().Year() - birth.Year()
+		sqlResult, err := tx.Exec("update t_order set name = ?,age = ?,birthday = ?,gender = ?,id_num = ?,mobile = ?,updated_at = ? where id = ? and status = 3", item.Name, age, item.Birth, item.Gender, item.IdNum, item.Mobile, time.Now().Format("2006-01-02 15:04:05"), signItem.OrderId)
+		if err != nil {
+			tx.Rollback()
+			return nil, err
+		}
+		if ra, _ := sqlResult.RowsAffected(); ra <= 0 {
+			tx.Rollback()
+			return nil, fmt.Errorf("7::name:%s,age:%d,birth:%s,gender:%s,idnum:%s,orderid:%s", item.Name, age, item.Birth, item.Gender, item.IdNum, signItem.OrderId)
+		}
+		go util.InsertMongo(signItem.OrderId, "护士系统700", 1, map[string]interface{}{"name": item.Name, "age": age, "birthday": item.Birth, "gender": item.Gender, "id_num": item.IdNum, "mobile": item.Mobile, "url": "/duser/saveordersign/700"})
+	}
+	tx.Commit()
+	return true, nil
+}
+
+var DefaultDeliverUserDal = &DeliverUserDal{}
+
+func (dud *DeliverUserDal) Get(openid string) (*entity.DeliverUser, error) {
+	db := util.GetSqlDB()
+	strSql := "select * from t_deliver_user where openid = ? and is_delete = 1;"
+	var du = entity.DeliverUser{}
+	err := db.Get(&du, strSql, openid)
+	if err != nil {
+		if err == sql.ErrNoRows {
+			return nil, errors.New("1::not exists")
+		}
+		return nil, err
+	}
+
+	du.Qualifiction, _ = getDeliverUserPic(du.Id, "qualifiction")
+	du.License, _ = getDeliverUserPic(du.Id, "license")
+	du.Photo, _ = getDeliverUserPic(du.Id, "photo")
+	return &du, nil
+}
+
+func getDeliverUserPic(id uint64, pType string) ([]string, error) {
+	db := util.GetSqlDB()
+	strSql := "select pic from t_deliver_user_pic where delever_uer_id = ? and type = ? and is_delete = 'N' "
+	var list = []string{}
+	err := db.Select(&list, strSql, id, pType)
+	if err != nil {
+		if err == sql.ErrNoRows {
+			return nil, errors.New("1::not exists")
+		}
+		return nil, err
+	}
+	return list, nil
+}
+
+func (dud *DeliverUserDal) SaveDU(duItem *entity.DeliverUser) (bool, error) {
+	db := util.GetWriteSqlDB()
+	if len(duItem.Openid) > 0 {
+		strSql := "select tel from t_deliver_user where openid =? and is_delete <>2 limit 1;"
+		var tel null.String
+		err := db.Get(&tel, strSql, duItem.Openid)
+		if err == nil {
+			if !tel.Valid || (tel.Valid && len(tel.String) == 0) {
+				//todo 更新 tel
+				db.Exec("update t_deliver_user set tel = ? where openid = ?", duItem.Tel, duItem.Openid)
+				return true, nil
+			} else if tel.String != duItem.Tel {
+				return false, errors.New("2:: already bind another tel")
+			}
+		}
+	}
+
+	strSql := "select id from t_deliver_user where tel = ? and is_delete <> 2;"
+	var eid int
+	db.Get(&eid, strSql, duItem.Tel)
+	if eid > 0 {
+		return false, errors.New("1::already regist")
+	}
+	strSql, kvs := util.GenerateInsertSqlFromStruct("t_deliver_user", duItem)
+	sqlResult, err := db.NamedExec(strSql, kvs)
+	if err != nil {
+		return false, err
+	}
+	if ra, _ := sqlResult.RowsAffected(); ra <= 0 {
+		return false, errors.New("failed to regist")
+	}
+	did, _ := sqlResult.LastInsertId()
+	//todo 20210312 保存到mongo t_log
+	jsonbyte, err := serialize.Marshal(_map2map(kvs))
+	if err != nil {
+		//return false ,err
+		fmt.Println(err.Error())
+	} else {
+		_insertMongo(strconv.FormatInt(did, 10), string(jsonbyte), 15)
+	}
+
+	strSql = "insert into t_deliver_user_pic(delever_uer_id, type,pic,create_time) values(?,?,?,?);"
+	var ctime = time.Now().Format("2006-01-02 15:05:05")
+	for _, ql := range duItem.Qualifiction {
+		db.Exec(strSql, did, "qualifiction", ql, ctime)
+	}
+	for _, lc := range duItem.License {
+		db.Exec(strSql, did, "license", lc, ctime)
+	}
+	for _, pt := range duItem.Photo {
+		db.Exec(strSql, did, "photo", pt, ctime)
+	}
+	db.Exec("insert into t_deliver_account(deliver_user_id, created_at) values(?,?);", did, ctime)
+	return true, nil
+}
+
+func (dud *DeliverUserDal) UpdateDU(duItem *entity.DeliverUser) (interface{}, error) {
+	db := util.GetWriteSqlDB()
+	tx := db.MustBegin()
+	strSql, kvs := util.GenerateUpdateSqlFromStruct("t_deliver_user", duItem, " where id=:id")
+	sqlResult, err := tx.NamedExec(strSql, kvs)
+	if err != nil {
+		tx.Tx.Rollback()
+		return false, err
+	}
+	if ra, _ := sqlResult.RowsAffected(); ra <= 0 {
+		tx.Tx.Rollback()
+		return false, errors.New("1::failed to update")
+	}
+
+	//todo 20210312 保存到mongo t_log
+	jsonbyte, err := serialize.Marshal(_map2map(kvs))
+	if err != nil {
+		//tx.Tx.Rollback()
+		//return false ,err
+		fmt.Println(err.Error())
+	} else {
+		_insertMongo(strconv.FormatUint(duItem.Id, 10), string(jsonbyte), 17)
+	}
+
+	if err = _updatePic(tx, duItem.Id, "qualifiction", duItem.Qualifiction); err != nil {
+		return nil, err
+	}
+	if err = _updatePic(tx, duItem.Id, "license", duItem.License); err != nil {
+		return nil, err
+	}
+	if err = _updatePic(tx, duItem.Id, "photo", duItem.Photo); err != nil {
+		return nil, err
+	}
+	tx.Commit()
+	return true, nil
+}
+
+func _insertMongo(name, data string, dbtype int) {
+	db := util.GetMgoDB()
+	if db == nil {
+		return
+	}
+	defer db.Session.Close()
+	err := db.C("t_log").Insert(bson.M{
+		"name":     name,
+		"type":     dbtype,
+		"data":     data,
+		"createby": "go",
+		"create":   time.Now().Format("2006-01-02 15:04:05"),
+	})
+	if err != nil {
+		fmt.Println(err)
+		return
+	}
+}
+
+// null 转换成 普通类型,否则php 序列化过不去
+func _map2map(kvs map[string]interface{}) map[string]interface{} {
+	resultMap := map[string]interface{}{}
+	for k, v := range kvs {
+		//t := reflect.TypeOf(v)
+		//switch t.Kind() {
+		//case reflect.TypeOf(null.String{}).Kind():
+		//	if v.(null.String).Valid{
+		//		resultMap[k]=v.(null.String).String
+		//	}
+		//case reflect.TypeOf(null.Int{}).Kind():
+		//	if v.(null.Int).Valid{
+		//		resultMap[k]=v.(null.Int).Int64
+		//	}
+		//default:
+		//			resultMap[k]=v
+		//		}
+		if nullString, ok := v.(null.String); ok {
+			resultMap[k] = nullString.String
+		} else if nullInt, ok := v.(null.Int); ok {
+			resultMap[k] = nullInt.Int64
+		} else {
+			resultMap[k] = v
+		}
+
+	}
+	return resultMap
+}
+
+func _updatePic(tx *sqlx.Tx, duId uint64, typ string, pics []string) error {
+	if len(pics) > 0 {
+		strSql := "delete from t_deliver_user_pic where delever_uer_id = ? and type = ?;"
+		tx.MustExec(strSql, duId, typ)
+		strSql = ""
+		var ctime = time.Now().Format("2006-01-02 15:05:05")
+		for i, ql := range pics {
+			strSql += fmt.Sprintf("(%d,'%s','%s','%s')", duId, typ, ql, ctime)
+			if i < len(pics)-1 {
+				strSql += ","
+			}
+		}
+		strSql = "insert into t_deliver_user_pic(delever_uer_id, type,pic,create_time) values" + strSql
+		sqlResult := tx.MustExec(strSql)
+		if ra, _ := sqlResult.RowsAffected(); ra <= 0 {
+			tx.Tx.Rollback()
+			return errors.New("2::failed to update " + typ)
+		}
+	}
+	return nil
+}
+
+func (dud *DeliverUserDal) GetBills(duId int, pageIndex, pageSize int) (interface{}, error) {
+	per := Pager{PageIndex: pageIndex, PageSize: pageSize}
+	var bills = []entity.DeliverBill{}
+	result, err := List(&bills, "t_deliver_bill", "select * from t_deliver_bill", " order by created_at desc", "where deliver_user_id = ? and status = '300' ", []interface{}{duId}, per)
+	return result, err
+}
+
+func (dud *DeliverUserDal) GetMsg(duId int, pageIndex, pageSize int, cityId int) (interface{}, error) {
+	per := Pager{PageIndex: pageIndex, PageSize: pageSize}
+	var msgList = []entity.DeliverMsg{}
+	result, err := List(&msgList, "t_deliver_msg", "select * from t_deliver_msg", " order by created_at desc", "where deliver_user_id = ? ", []interface{}{duId}, per)
+
+	var pubMsglist = []entity.DeliverMsg{}
+	strSql := fmt.Sprintf("SELECT t1.*,t2.is_read from t_deliver_pubmsg t1 left join t_deliver_msg t2 on t1.id = t2.ref_id  where city_ids REGEXP ',?%d,?' order by created_at desc limit 10", cityId)
+	db := util.GetWriteSqlDB()
+	err = db.Select(&pubMsglist, strSql)
+	if err != nil {
+		return nil, err
+	}
+	strSql = "insert into t_deliver_msg(deliver_user_id, title, content,created_at, ref_id) values"
+	for _, msg := range pubMsglist {
+		if !msg.IsRead.Valid {
+			strSql += fmt.Sprintf("(%d,'%s','%s', '%s', %d),", duId, msg.Title, msg.Content, msg.CreatedAt, msg.Id)
+			msgList = append(msgList, msg)
+		}
+	}
+	strSql = strSql[0 : len(strSql)-1]
+	db.Exec(strSql)
+	sort.Slice(msgList, func(i, j int) bool {
+		return msgList[i].CreatedAt > msgList[j].CreatedAt
+	})
+	return result, err
+
+}
+
+func (dud *DeliverUserDal) GetScoreBill(duId int, pageIndex, pageSize int, typ string) (interface{}, error) {
+	per := Pager{PageIndex: pageIndex, PageSize: pageSize}
+	var bills = []entity.DeliverScoreBill{}
+	params := []interface{}{duId}
+	var whereStr = "where deliver_user_id = ? "
+	if typ == "score" {
+		whereStr += "and type in('SIGNIN', 'ORDER', 'INVITE_F', 'STUDY_DATA','AUTOTRANS', 'INVITE_F_EXAM', 'DAILY_QUESTION','CHECK','INVITE_EXAM','CHECK_F') "
+	} else if typ == "cash" {
+		whereStr += "and type in('WITHDRAW','SCORECHSH') "
+	}
+	result, err := List(&bills, "t_deliver_score_bill", "select * from t_deliver_score_bill", " order by created_at desc", whereStr, params, per)
+	return result, err
+}

+ 12 - 0
dal/icart_dal.go

@@ -0,0 +1,12 @@
+package dal
+
+import (
+	"xiaoniaokuaiyan.com/xiaoniao/entity"
+)
+
+type ICart interface {
+	Get(customId int) ([]entity.ProductDB, error)
+	Update(customId int, productId, quantity int, isAdd bool) (bool, error)
+	Clear(customId int) (bool, error)
+	Del(customId int, productIds []int) (bool, error)
+}

+ 12 - 0
dal/icity_dal.go

@@ -0,0 +1,12 @@
+package dal
+
+import (
+	"xiaoniaokuaiyan.com/xiaoniao/entity"
+)
+
+type ICity interface {
+	GetOpenList() ([]entity.City, error)
+	GetCountyByCityId(int) ([]entity.County, error)
+	GetCityListById([]int) ([]entity.City, error)
+	GetCityAllList() ([]entity.CityAll, error)
+}

+ 13 - 0
dal/icoupon_dal.go

@@ -0,0 +1,13 @@
+package dal
+
+import (
+	"xiaoniaokuaiyan.com/xiaoniao/cerror"
+	"xiaoniaokuaiyan.com/xiaoniao/entity"
+)
+
+type ICoupon interface {
+	Get(id int, orderId string) (*entity.DiscountTicketDB, error)
+	Save(item *entity.DiscountTicket) (*entity.DiscountTicket, error)
+	Update(item *entity.DiscountTicket) (*entity.DiscountTicket, error)
+	Exchange(codeStr string, customId int, mobile string) (interface{}, cerror.CError)
+}

+ 18 - 0
dal/ideliver_userdal.go

@@ -0,0 +1,18 @@
+package dal
+
+import (
+	"xiaoniaokuaiyan.com/xiaoniao/entity"
+)
+
+type IDeliverUserDal interface {
+	GetOrderList(openid string, status, pageIndex, pageSize int) (interface{}, error)
+	GetOrderListV2(openid string, pageIndex, pageSize int) (interface{}, error)
+	GetOrderSign(orderId string) (interface{}, error)
+	SaveOrderSign(signItem *entity.OrderSign) (interface{}, error)
+	SaveDU(duItem *entity.DeliverUser) (bool, error)
+	UpdateDU(duItem *entity.DeliverUser) (interface{}, error)
+	Get(openid string) (*entity.DeliverUser, error)
+	GetBills(int, int, int) (interface{}, error)
+	GetMsg(duId int, pageIndex, pageSize, cityId int) (interface{}, error)
+	GetScoreBill(int, int, int, string) (interface{}, error)
+}

+ 9 - 0
dal/ifcode_dal.go

@@ -0,0 +1,9 @@
+package dal
+
+import (
+	"xiaoniaokuaiyan.com/xiaoniao/entity"
+)
+
+type IFcode interface {
+	Exchange(codeStr string) (*entity.DiscountTicket, error)
+}

+ 16 - 0
dal/iorder_dal.go

@@ -0,0 +1,16 @@
+package dal
+
+import "xiaoniaokuaiyan.com/xiaoniao/entity"
+
+type IOrder interface {
+	Update(oitem *entity.Order) (interface{}, error)
+	Get(id string) (*entity.OrderDB, error)
+	GetByCode(code string) (interface{}, error)
+	List(cid int, pageIndex, pageSize int, status int, mobile string, isZFB bool, isHis bool) (interface{}, error)
+	Detail(oid string) (interface{}, error)
+	CheckAndSplitOrder(oid string) (bool, error)
+	CommitSurvey(osItem *entity.OrderSurvey) (bool, error)
+	IsFirst(mobile string) (bool, error)
+	SplitOrderV3(oid string, productId int)
+	ListCustomFile(cid int, pageIndex, pageSize int, status int, mobile string, isZFB, isHis bool) (interface{}, error)
+}

+ 18 - 0
dal/iproduct_dal.go

@@ -0,0 +1,18 @@
+package dal
+
+import (
+	"xiaoniaokuaiyan.com/xiaoniao/entity"
+)
+
+type IProduct interface {
+	Get(pids []int) ([]*entity.ProductDB, error)
+	GetByCateId(cids []int, pager Pager, cityId int, sp SortParam) ([]*entity.ProductDB, error)
+	GetCate(posType int) ([]entity.ProductCategory, error)
+	GetRecommend(pager Pager, cityId int, sp SortParam) ([]*entity.ProductDB, error)
+	GetTags(level, cityId int) ([]entity.Tag, error)
+	GetByTags(tags []string, pageIndex, pageSize uint, cityId int) ([]*entity.ProductDB, error)
+	GetProductAddingCate() (interface{}, error)
+	GetProductByAddingCate(cid int) (interface{}, error)
+	AddProductByDpIds([]int) (interface{}, error)
+	GetTop(int, int) ([]entity.ProductDB, error)
+}

+ 11 - 0
dal/ismscode_dal.go

@@ -0,0 +1,11 @@
+package dal
+
+import (
+	"xiaoniaokuaiyan.com/xiaoniao/entity"
+)
+
+type ISMSCode interface {
+	Add(code *entity.SMSCode) (*entity.SMSCode, error)
+	Update(code *entity.SMSCode) (*entity.SMSCode, error)
+	Get(mobile, code string, codeType int) (*entity.SMSCode, error)
+}

+ 16 - 0
dal/iuser_dal.go

@@ -0,0 +1,16 @@
+package dal
+
+import (
+	"xiaoniaokuaiyan.com/xiaoniao/entity"
+)
+
+type IUser interface {
+	Get(account string) (*entity.UserDB, error)
+	Save(map[string]interface{}) (interface{}, error)
+	Update(user *entity.User) (*entity.User, error)
+	GetNotice(mobile string) ([]entity.QueueNotice, error)
+	UpdateNotice(notice *entity.QueueNotice) (bool, error)
+	GetUserByOpenid(openid string) (*entity.UserDB, error)
+	GetUserByUnionid(unionid string) (*entity.UserDB, error)
+	GetUserByUserId(zfbUserId string) (*entity.UserDB, error)
+}

+ 13 - 0
dal/iuserlinker_dal.go

@@ -0,0 +1,13 @@
+package dal
+
+import (
+	"xiaoniaokuaiyan.com/xiaoniao/entity"
+)
+
+type IUserLinker interface {
+	Save(linker *entity.UserLinker) (*entity.UserLinker, error)
+	List(customId int, isDefault bool) ([]entity.UserLinkerDB, error)
+	Get(id, cid int) (*entity.UserLinkerDB, error)
+	Update(linker *entity.UserLinker) (*entity.UserLinker, error)
+	Remove(linker *entity.UserLinker) (interface{}, error)
+}

File diff suppressed because it is too large
+ 525 - 0
dal/order_dal.go


+ 24 - 0
dal/order_dal_test.go

@@ -0,0 +1,24 @@
+package dal
+
+import (
+	"encoding/json"
+	"fmt"
+	"testing"
+)
+
+func TestGetOrder(t *testing.T) {
+	var oid string = "BJ16050415050900582"
+	odal := Order{}
+	oitem, err := odal.Get(oid)
+	if err != nil {
+		t.Fatal(err)
+	}
+	buf, _ := json.Marshal(oitem)
+	fmt.Println(string(buf))
+}
+
+func TestCheckAndSplitOrder(t *testing.T){
+	odal:=Order{}
+	f,err:=odal.CheckAndSplitOrder("BJ22122915541127540")
+	fmt.Println(f,err)
+}

+ 7 - 0
dal/pager.go

@@ -0,0 +1,7 @@
+package dal
+
+type Pager struct {
+	PageSize  int `json:"pz"`
+	PageIndex int `json:"pi"`
+	Total     int `json:"total"`
+}

+ 396 - 0
dal/product_dal.go

@@ -0,0 +1,396 @@
+package dal
+
+import (
+	"crypto/md5"
+	"database/sql"
+	"errors"
+	"fmt"
+	"sort"
+	"time"
+
+	"gopkg.in/guregu/null.v3"
+
+	"xiaoniaokuaiyan.com/xiaoniao/entity"
+	"xiaoniaokuaiyan.com/xiaoniao/util"
+)
+
+type Product struct{}
+
+func (pdal *Product) Get(productIds []int) ([]*entity.ProductDB, error) {
+	if len(productIds) == 0 {
+		return nil, errors.New("wrong param prooduct id")
+	}
+	strSql := ""
+	for _, pid := range productIds {
+		strSql += fmt.Sprintf("%d,", pid)
+	}
+	//strSql = "select t1.*, group_concat(city_id) as cityIds, group_concat(county_id separator '-') as countyIds from t_product t1 left join t_product_city t2 on t1.id = t2.product_id where id in(" + strSql[0:len(strSql)-1] + ") and is_delete = 0 group by id;"
+	strSql = "select t1.*, group_concat(city_id) as cityIds from t_product t1 left join v_product_city t2 on t1.id = t2.product_id where id in(" + strSql[0:len(strSql)-1] + ") and is_delete = 0 group by id;"
+	db := util.GetSqlDB()
+	plist := []*entity.ProductDB{}
+	err := db.Select(&plist, strSql)
+	if err != nil {
+		return nil, err
+	}
+	for _, pitem := range plist {
+		dps := []entity.DetectProduct{}
+		db.Select(&dps, "select t1.* from t_detect_product t1 left join t_product_detect_product t2 on t1.id = t2.detect_product_id where t2.product_id = ?", pitem.Id)
+		picList := []entity.ProductPicture{}
+		db.Select(&picList, "select * from t_product_picture where product_id = ? order by pic_type desc", pitem.Id)
+		attrList := []struct {
+			ProductId int         `db:"product_id" json:"product_id"`
+			Name      null.String `db:"name" json:"name"`
+			Value     null.String `db:"value" json:"value"`
+			Pic       string      `db:"picture" json:"picture"`
+		}{}
+		//db.Select(&attrList, "select * from t_product_attribute where product_id = ?", pitem.Id)
+		db.Select(&attrList, "select a.*,p.picture from t_product_attribute a left join t_product p on a.value = p.id where a.product_id = ?", pitem.Id)
+		pitem.Pictures = picList
+		pitem.Items = dps
+		pitem.Attributes = attrList
+		//query add attach city info
+		cityList := []entity.City{}
+		db.Select(&cityList, "select * from t_city where id in("+pitem.CityIds.String+");")
+		//strCountyIds := pitem.CountyIds.String
+		//countyIds := strings.Split(strCountyIds, "-")
+		//cityIds := strings.Split(pitem.CityIds.String, ",")
+		//countyMap := map[string]string{}
+		//for i, cid := range cityIds {
+		//	for j, ctid := range countyIds {
+		//		if j != i {
+		//			continue
+		//		}
+		//		subCountyIds := strings.Split(ctid, ",")
+		//		for _, sctid := range subCountyIds {
+		//			countyMap[sctid] = cid
+		//		}
+		//	}
+		//}
+		//cityMap := map[string]int{}
+		//for i, cityItem := range cityList {
+		//	cityMap[fmt.Sprintf("%d", cityItem.Id)] = i
+		//}
+		//strCountyIds = strings.Replace(strCountyIds, "-", ",", -1)
+		//countys := []entity.County{}
+		//db.Select(&countys, "select * from t_county where id in("+strCountyIds+");")
+		//for _, ct := range countys {
+		//	if cid, ok := countyMap[fmt.Sprintf("%d", ct.Id)]; ok {
+		//		if idx, sok := cityMap[cid]; sok {
+		//			cityList[idx].Countys = append(cityList[idx].Countys, ct)
+		//		}
+		//	}
+		//}
+		pitem.Citys = cityList
+		//pitem.CountyIds.SetValid(strings.Replace(pitem.CountyIds.String, "-", ",", -1))
+	}
+	return plist, nil
+}
+
+func (pdal *Product) GetByCateId(cids []int, pager Pager, cityId int, sp SortParam) ([]*entity.ProductDB, error) {
+	if pager.PageIndex < 1 {
+		pager.PageIndex = 1
+	}
+	var skip = (pager.PageIndex - 1) * pager.PageSize
+	var (
+		sortDir = "desc"
+		sortBy  = "is_recommend"
+	)
+	if sp.SortDir == 1 {
+		sortDir = "asc"
+	}
+	switch sp.SortBy {
+	case "SALE_NUM":
+		sortBy = "sale_num"
+	case "NEW":
+		sortBy = "t2.created_at"
+	case "SUM_UP":
+		sortBy = "sort_no"
+	case "PRICE":
+		sortBy = "price"
+	}
+	var strCity = "and city_id =" + fmt.Sprintf("%d", cityId)
+	if cityId == 0 {
+		strCity = ""
+	}
+	db := util.GetSqlDB()
+	if len(cids) > 0 && cids[0] == -3 {
+		var childCids = []int{}
+		db.Select(&childCids, "SELECT id from t_product_category WHERE parent_id in(?);", util.IntJoin(cids[1:], ","))
+		cids = childCids
+	}
+	//strSql := "select t2.*,group_concat(city_id) as cityIds from t_product t2 left join t_product_category_product t1 on t1.product_id = t2.id join t_product_city t3 on t2.id = t3.product_id where t1.cat_id in(?) " + strCity + " and t2.is_putaway = 0 and t2.is_delete = 0 group by t2.id order by " + sortBy + " " + sortDir + ", t2.id desc limit ?,?;"
+	strSql := "select t2.*,group_concat(city_id) as cityIds from t_product t2 left join t_product_category_product t1 on t1.product_id = t2.id join v_product_city t3 on t2.id = t3.product_id where t1.cat_id in(?) " + strCity + " and t2.is_putaway = 0 and t2.is_delete = 0 group by t2.id order by " + sortBy + " " + sortDir + ", t2.id desc limit ?,?;"
+	var firstParam interface{} = util.IntJoin(cids, ",")
+	if len(cids) > 0 {
+		if cids[0] == -1 { //促销产品
+			//strSql = "select t1.*, group_concat(city_id) as cityIds from t_product t1 left join t_product_city t2 on t1.id = t2.product_id where t1.id > ? and price <> market_price and market_price > 0 " + strCity + " and t1.is_putaway = 0 and t1.is_delete = 0 group by t1.id order by " + sortBy + " " + sortDir + ", t1.id desc limit ?,?;"
+			strSql = "select t1.*, group_concat(city_id) as cityIds from t_product t1 left join v_product_city t2 on t1.id = t2.product_id where t1.id > ? and price <> market_price and market_price > 0 " + strCity + " and t1.is_putaway = 0 and t1.is_delete = 0 group by t1.id order by " + sortBy + " " + sortDir + ", t1.id desc limit ?,?;"
+			firstParam = 0
+		} else if cids[0] == -2 {
+			//strSql = "select t1.*, group_concat(city_id) as cityIds from t_product t1 left join t_product_city t2 on t1.id = t2.product_id where t1.id > ? " + strCity + "  and t1.is_putaway = 0 and t1.is_delete = 0 group by t1.id order by " + sortBy + " " + sortDir + ",t1.id desc limit ?,?"
+			strSql = "select t1.*, group_concat(city_id) as cityIds from t_product t1 left join v_product_city t2 on t1.id = t2.product_id where t1.id > ? " + strCity + "  and t1.is_putaway = 0 and t1.is_delete = 0 group by t1.id order by " + sortBy + " " + sortDir + ",t1.id desc limit ?,?"
+			firstParam = 0
+		}
+	}
+	plist := []*entity.ProductDB{}
+	err := db.Select(&plist, strSql, firstParam, skip, pager.PageSize)
+	if err != nil {
+		return nil, err
+	}
+	for _, pitem := range plist {
+		dps := []entity.DetectProduct{}
+		db.Select(&dps, "select t1.* from t_detect_product t1 left join t_product_detect_product t2 on t1.id = t2.detect_product_id where t2.product_id = ?", pitem.Id)
+		pitem.Items = dps
+	}
+	return plist, nil
+}
+func (pdal *Product) GetByTags(tags []string, pageIndex, pageSize uint, cityId int) ([]*entity.ProductDB, error) {
+	if pageIndex < 1 {
+		pageIndex = 1
+	}
+	if pageSize < 5 {
+		pageSize = 5
+	}
+	var skip = pageSize * (pageIndex - 1)
+	var strTag = ""
+	for _, tag := range tags {
+		strTag += "'" + tag + "',"
+	}
+	strTag = strTag[0 : len(strTag)-1]
+	//strSql := "select distinct t3.* from t_tag t1 inner join t_product_tag t2 on t1.id = t2.tag_id inner join t_product t3 on t2.product_id = t3.id left join t_product_city t4 on t3.id = t4.product_id where t4.city_id = ? and t3.is_putaway = 0 and is_delete = 0 and t1.tag_name in (" + strTag + ") order by sort_no desc limit ?,?;"
+	strSql := "select distinct t3.* from t_tag t1 inner join t_product_tag t2 on t1.id = t2.tag_id inner join t_product t3 on t2.product_id = t3.id left join v_product_city t4 on t3.id = t4.product_id where t4.city_id = ? and t3.is_putaway = 0 and is_delete = 0 and t1.tag_name in (" + strTag + ") order by sort_no desc limit ?,?;"
+	db := util.GetSqlDB()
+	plist := []*entity.ProductDB{}
+	err := db.Select(&plist, strSql, cityId, skip, pageSize)
+	if err != nil {
+		return nil, err
+	}
+	for _, pitem := range plist {
+		dps := []entity.DetectProduct{}
+		db.Select(&dps, "select t1.* from t_detect_product t1 left join t_product_detect_product t2 on t1.id = t2.detect_product_id where t2.product_id = ?", pitem.Id)
+		pitem.Items = dps
+	}
+	return plist, nil
+}
+func (pdal *Product) GetRecommend(pager Pager, cityId int, sp SortParam) ([]*entity.ProductDB, error) {
+	if pager.PageIndex < 1 {
+		pager.PageIndex = 1
+	}
+	if pager.PageSize < 5 {
+		pager.PageSize = 5
+	}
+	var skip = (pager.PageIndex - 1) * pager.PageSize
+	var (
+		sortDir = "desc"
+		sortBy  = "sort_no"
+	)
+	if sp.SortDir == 1 {
+		sortDir = "asc"
+	}
+	switch sp.SortBy {
+	case "SALE_NUM":
+		sortBy = "sale_num"
+	case "NEW":
+		sortBy = "t1.created_at"
+	case "PRICE":
+		sortBy = "price"
+	}
+	//strSql := "select * from t_product t1 left join t_product_city t2 on t1.id = t2.product_id where city_id = ? and is_recommend = 1 and is_putaway = 0 and is_delete = 0 order by " + sortBy + " " + sortDir + ", t1.id desc limit ?,?;"
+	strSql := "select * from t_product t1 left join v_product_city t2 on t1.id = t2.product_id where city_id = ? and is_recommend = 1 and is_putaway = 0 and is_delete = 0 order by " + sortBy + " " + sortDir + ", t1.id desc limit ?,?;"
+	db := util.GetSqlDB()
+	plist := []*entity.ProductDB{}
+	err := db.Select(&plist, strSql, cityId, skip, pager.PageSize)
+	if err != nil {
+		return nil, err
+	}
+	for _, pitem := range plist {
+		dps := []entity.DetectProduct{}
+		db.Select(&dps, "select t1.* from t_detect_product t1 left join t_product_detect_product t2 on t1.id = t2.detect_product_id where t2.product_id = ?", pitem.Id)
+		pitem.Items = dps
+	}
+	return plist, nil
+}
+
+func (pdal *Product) GetCate(pid int) ([]entity.ProductCategory, error) {
+	strSql := "select * from t_product_category where is_leaf = 1 and pos_type = ? order by sort_no desc"
+	var firstParam interface{} = pid
+	switch pid {
+	case -1:
+		strSql = "select * from t_product_category where id > ? order by sort_no asc;"
+		firstParam = 0
+	case -2:
+		strSql = "select * from t_product_category where id > ? and is_leaf = 1;"
+		firstParam = 0
+	default:
+		strSql = "select * from t_product_category where parent_id = ? order by sort_no asc;"
+	}
+	db := util.GetSqlDB()
+	cateList := []entity.ProductCategory{}
+	err := db.Select(&cateList, strSql, firstParam)
+	return cateList, err
+}
+
+func (pdal *Product) GetTags(level, cityId int) ([]entity.Tag, error) {
+	strSql := "select id, tag_name from t_tag where parent_id = ?;"
+	db := util.GetSqlDB()
+	tagList := []entity.Tag{}
+	err := db.Select(&tagList, strSql, level)
+	return tagList, err
+}
+
+func (pdal *Product) GetProductAddingCate() (interface{}, error) {
+	strSql := "select id, name, picture from t_product_add_classify;"
+	db := util.GetSqlDB()
+	cateList := []struct {
+		Id      int         `db:"id" json:"cate_id"`
+		Name    string      `db:"name" json:"name"`
+		Picture null.String `db:"picture" json:"picture"`
+	}{}
+	err := db.Select(&cateList, strSql)
+	return cateList, err
+}
+
+func (pdal *Product) GetProductByAddingCate(cid int) (interface{}, error) {
+	strSql := `select t2.id, t2.name, t2.price, GROUP_CONCAT(t5.name) as items from t_product_add t1 LEFT JOIN t_product t2 on t1.product_id = t2.id 
+	LEFT JOIN t_product_detect_product t3 on t2.id = t3.product_id left JOIN t_detect_product_item t4 on t3.detect_product_id = t4.detect_product_id
+	left join t_detect_item t5 on t4.detect_item_id = t5.id  where t1.classify_id = ? GROUP BY(t2.id);`
+	db := util.GetSqlDB()
+	plist := []struct {
+		Id    int         `db:"id" json:"id"`
+		Name  string      `db:"name" json:"name"`
+		Price int         `db:"price" json:"price"`
+		Items null.String `db:"items" json:"items"`
+	}{}
+	err := db.Select(&plist, strSql, cid)
+	return plist, err
+}
+
+func (pdal *Product) AddProductByDpIds(dpids []int) (interface{}, error) {
+	sort.Ints(dpids)
+	strDpids := util.IntJoin(dpids, ",")
+	strSql := "select id, price from t_detect_product where id  in(" + strDpids + ");"
+	db := util.GetWriteSqlDB()
+	var dpItems = []struct {
+		Id    int `db:"id"`
+		Price int `db:"price"`
+	}{}
+	err := db.Select(&dpItems, strSql)
+	if err != nil {
+		return nil, err
+	}
+	if len(dpItems) != len(dpids) {
+		return nil, errors.New("数据错误")
+	}
+	var pPrice int
+	for _, dpItem := range dpItems {
+		pPrice += dpItem.Price
+	}
+	buf := md5.Sum([]byte(strDpids))
+	strDpids = fmt.Sprintf("%x", buf[:])
+	strSql = "select id,price from t_product where dpid_str = ? limit 1;"
+	var pitem = struct {
+		Id    int `db:"id"`
+		Price int `db:"price"`
+	}{}
+	err = db.Get(&pitem, strSql, strDpids)
+	if err != nil {
+		if err == sql.ErrNoRows {
+			//TODO create new product
+			tx := db.MustBegin()
+			newPitem := entity.Product{
+				Name:          "专属产品",
+				IsPutAway:     1,
+				Picture:       "",
+				CreatedAt:     time.Now().Format("2006-01-02 15:04:05"),
+				Price:         pPrice,
+				MarketPrice:   pPrice,
+				Tube:          `{"yellow":2,"green":0,"purple":1,"breathcard":0,"breathbagpowder":0,"breathbaggree":0,"swab":0,"other":""}`,
+				SaleMode:      100,
+				Collection:    "成人",
+				Notice:        "电子报告,1-2工作日",
+				Report:        "建议空腹",
+				IsDrawBlood:   1,
+				Sampling:      "静脉血",
+				TipReportDays: 2,
+				DpidStr:       strDpids,
+			}
+			strSql, mkv := util.GenerateInsertSqlFromStruct("t_product", &newPitem)
+			sqlResult, err := tx.NamedExec(strSql, mkv)
+			if err != nil {
+				tx.Tx.Rollback()
+				return nil, err
+			}
+			if ra, _ := sqlResult.RowsAffected(); ra <= 0 {
+				tx.Tx.Rollback()
+				return nil, errors.New("failed to generate new product")
+			}
+			newPid, _ := sqlResult.LastInsertId()
+			var strValues string = "insert into t_product_detect_product(product_id,detect_product_id) values"
+			for _, dpid := range dpids {
+				strValues += fmt.Sprintf("(%d,%d),", newPid, dpid)
+			}
+			strValues = strValues[0 : len(strValues)-1]
+			sqlResult = tx.MustExec(strValues)
+			if ra, _ := sqlResult.RowsAffected(); ra <= 0 {
+				tx.Tx.Rollback()
+				return nil, errors.New("failed to generate detect_product")
+			}
+			strValues = "insert into t_product_city(city_id,county_id,product_id) values"
+			strValues += fmt.Sprintf("(1,'1,2,5,6,8,11,12,13,14',%d),", newPid)
+			strValues += fmt.Sprintf("(73,'747,748,749,750,751,752,753,754,755',%d),", newPid)
+			strValues += fmt.Sprintf("(237,'2156,2157,2158,2159,2160,2175,2176',%d),", newPid)
+			strValues += fmt.Sprintf("(198,'1812,1813,1814,1815,1816,1817,1818,1819,1820,1821,1822,1823',%d),", newPid)
+			strValues += fmt.Sprintf("(170,'1591,1593,1592,1588,1590,1589',%d),", newPid)
+			strValues += fmt.Sprintf("(74,'766,768,769,770,774',%d)", newPid)
+			sqlResult = tx.MustExec(strValues)
+			if ra, _ := sqlResult.RowsAffected(); ra <= 0 {
+				tx.Tx.Rollback()
+				return nil, errors.New("failed to generate new product_city")
+			}
+			strSql = fmt.Sprintf("insert into t_product_picture(product_id, picture,pic_type) values(%d, %s,1", newPid, "")
+			sqlResult = tx.MustExec(strSql)
+			if ra, _ := sqlResult.RowsAffected(); ra <= 0 {
+				tx.Tx.Rollback()
+				return nil, errors.New("failed to generate new product picture")
+			}
+			tx.Commit()
+			return newPid, nil
+		} else {
+			return nil, err
+		}
+	}
+
+	if pPrice != pitem.Price {
+		strSql = "update t_product set price = ? where id = ?;"
+		db.Exec(strSql, pPrice, pitem.Id)
+	}
+	return pitem.Id, nil
+}
+
+func (pdal *Product) GetTop(n int, cityId int) ([]entity.ProductDB, error) {
+	var (
+		now       = time.Now()
+		startDate = now.Add(-time.Hour * 24 * 90).Format("2006-01-02")
+		endDate   = now.Add(time.Hour * 24).Format("2006-01-02")
+	)
+	/*strSql := `select * from t_product t1 right join(
+		select tp.* from (
+		    SELECT product_id, count(*) as num from t_order_product where order_id in(
+				SELECT id from t_order where actual_payment >0 and (created_at BETWEEN ? and ?) and status not in(1,7,8,9,14)
+			) GROUP BY product_id
+		)tp left JOIN t_product_city tc on tp.product_id = tc.product_id where tc.city_id = ?
+	) t2 on t1.id = t2.product_id  where is_delete = 0 and is_putaway =0 order by num desc LIMIT ?;`*/
+	strSql := `select * from t_product t1 right join(
+					select tp.* from (
+					    SELECT product_id, count(*) as num from t_order_product where order_id in(
+							SELECT id from t_order where actual_payment >0 and (created_at BETWEEN ? and ?) and status not in(1,7,8,9,14) and retype in ('100','110') and is_delete='N'
+						) GROUP BY product_id 
+					)tp left JOIN v_product_city tc on tp.product_id = tc.product_id where tc.city_id = ?
+				) t2 on t1.id = t2.product_id  where is_delete = 0 and is_putaway =0 order by num desc LIMIT ?;`
+	db := util.GetSqlDB()
+	plist := []entity.ProductDB{}
+	err := db.Select(&plist, strSql, startDate, endDate, cityId, n)
+	return plist, err
+}
+
+var DefaultProductDal = &Product{}

+ 164 - 0
dal/result.go

@@ -0,0 +1,164 @@
+package dal
+
+import (
+	"fmt"
+
+	"gopkg.in/guregu/null.v3"
+	"xiaoniaokuaiyan.com/xiaoniao/entity"
+	"xiaoniaokuaiyan.com/xiaoniao/util"
+)
+
+type OrderResult struct {
+	Id              string                `db:"id"`     //订单编号
+	Name            string                `db:"name"`   //客户姓名
+	Gender          int                   `db:"gender"` //姓名
+	Age             int                   `db:"age"`    //年龄
+	Birthday        string                `db:"birthday"`
+	Address         string                `db:"address"`                //上门地址
+	DetailAddress   string                `db:"detail_address"`         //详细地址
+	VisitDate       null.String           `db:"visit_date"`             //上门日期
+	VisitTimeRange  null.String           `db:"visit_time_range"`       //上门时间段
+	Status          int                   `db:"status"`                 //订单状态(1待支付,2待接单-匹配客户经理以及护士,3待上门,4待上传化验结果,5已完成)
+	WorkFee         null.Int              `db:"work_fee"`               //上门费
+	FreeFee         int                   `db:"free_fee"`               //优惠费用
+	RepeatItemFee   int                   `db:"repeat_item_fee"`        //重复项减免费用
+	Payment         int                   `db:"payment,omitempty"`      //订单需支付金额
+	ActualPayment   null.Int              `db:"actual_payment"`         //实际支付金额
+	PaymentTime     null.String           `db:"payment_time,omitempty"` //支付时间
+	PayType         null.Int              `db:"pay_type,omitempty"`     //支付类型
+	PayNo           null.String           `db:"pay_no"`                 //支付流水号
+	CustomMobile    string                `db:"custom_mobile"`          //下单人电话
+	Mobile          string                `db:"mobile"`                 //被下单人电话
+	CreatedAt       string                `db:"created_at"`             //下单时间*/
+	Products        []entity.OrderProduct `db:"-"`
+	DeliverUsers    []entity.DeliverUser  `db:"-"`
+	IsViewReport    string                `db:"is_view_report"`
+	ReportPicture   string                `db:"report_picture"`
+	IsNotice        null.String           `db:"is_notice"`
+	Express         null.String           `db:"express"`
+	ExpressNumber   null.String           `db:"expressnumber"`
+	DelayDeadtime   uint                  `db:"delay_deadtime" json:"delay_deadtime"` //订单失效时间延迟时长
+	LinkerId        int                   `db:"linker_id"`
+	RelId           int                   `db:"-"`
+	Source          string                `db:"source"`
+	NeedEmptiness   null.Int              `db:"need_emptiness"`
+	ReportPeriod    null.String           `db:"report_period"`
+	PressurePipe    null.String           `db:"pressure_pipe"`
+	BloodAddress    null.String           `db:"blood_address"`
+	Notice          null.String           `db:"notice"`
+	Remark1         null.String           `db:"remark1"`
+	Remark          null.String           `db:"remark"`
+	IdNum           null.String           `db:"id_num"`
+	EVisitDate      null.String           `db:"e_visit_date",json:"EVisitDate"`
+	EVisitTimeRange null.String           `db:"e_visit_time_range",json:"EVisitTimeRange"`
+	Zone            null.String           `db:"zone" json:"zone"`
+	VCode           null.String           `db:"vcode" json:"vcode"`
+	JDOrderID       null.String           `db:"jd_order_id" json:"jd_order_id"`
+	PreOrderId      null.String           `db:"pre_order_id" json:"PreOrderId"`     //20211112 主单id,订单变为服务单
+	CompleteTime    null.String           `db:"complete_time" json:"complete_time"` //20230904 完成时间
+	ShareSource     null.String           `db:"share_source" json:"share_source"`
+}
+
+func (oitem *OrderResult) FetchProduct() error {
+	db := util.GetSqlDB()
+	plist := []entity.OrderProduct{}
+	strSql := "select order_id, product_id,t2.sale_mode, t1.product_name,cast(t1.price as signed) as price, t1.picture,t1.quantity,t2.discount_switch, t2.is_tip, t2.tip_content, t2.is_jiyin,t2.searchs from t_order_product t1 left join t_product t2 on t1.product_id = t2.id where order_id = ?"
+	err := db.Select(&plist, strSql, oitem.Id)
+	if err != nil {
+		return err
+	}
+	oitem.Products = plist
+	oitem.DeliverUsers = []entity.DeliverUser{}
+	// fetch deliveruser
+	strSql = "select t3.id, t3.name, t3.age, t3.gender, t3.head_pic, t3.tel, t3.remark, t2.career,t3.qualifiction from t_order t1 inner join t_order_deliver_user t2 on t1.id = t2.order_id inner join t_deliver_user t3 on t2.deliver_user_id = t3.id where t1.id = ?"
+	err = db.Select(&oitem.DeliverUsers, strSql, oitem.Id)
+	if err != nil {
+		return err
+	}
+	if len(oitem.DeliverUsers) > 0 {
+		strduids := ""
+		for _, du := range oitem.DeliverUsers {
+			strduids += fmt.Sprintf("%d,", du.Id)
+		}
+		strduids = strduids[0 : len(strduids)-1]
+		strSql = "select delever_uer_id, pic from t_deliver_user_pic where delever_uer_id in(" + strduids + ") and type='qualifiction' and is_delete='N'"
+		var tempPicList = []struct {
+			DuId int    `db:"delever_uer_id"`
+			Pic  string `db:"pic"`
+		}{}
+		db.Select(&tempPicList, strSql)
+		for i, du := range oitem.DeliverUsers {
+			for _, pic := range tempPicList {
+				if pic.DuId == int(du.Id) {
+					oitem.DeliverUsers[i].Qualifiction = append(oitem.DeliverUsers[i].Qualifiction, pic.Pic)
+				}
+			}
+		}
+	}
+	strSql = "select rel_id from t_custom_linker_rel where id = ?;"
+	var relIds = []int{}
+	db.Select(&relIds, strSql, oitem.LinkerId)
+	if len(relIds) > 0 {
+		oitem.RelId = relIds[0]
+	}
+	return nil
+}
+
+type OrderListResult []*OrderResult
+
+func (olr OrderListResult) FetchProduct() error {
+	var ids string = ""
+	length := len(olr)
+	if length <= 0 {
+		return nil
+	}
+	var lids string
+	for i, oitem := range olr {
+		if i < length-1 {
+			ids += "'" + oitem.Id + "'" + ","
+			lids += fmt.Sprintf("'%d',", oitem.LinkerId)
+		} else {
+			ids += "'" + oitem.Id + "'"
+			lids += fmt.Sprintf("'%d'", oitem.LinkerId)
+		}
+	}
+	db := util.GetSqlDB()
+	//strSql := "select order_id, product_id, product_name, price, picture,quantity from t_order_product where order_id in (" + ids + ");"
+	strSql := "select order_id, product_id, product_name, t1.price, t1.picture,quantity,t2.sale_mode from t_order_product t1 left join t_product t2 on t1.product_id = t2.id where order_id in (" + ids + ");"
+	plist := []entity.OrderProduct{}
+	err := db.Select(&plist, strSql)
+	if err != nil {
+		return err
+	}
+	if len(plist) == 0 {
+		return nil
+	}
+	grpPitems := map[string][]entity.OrderProduct{}
+	for _, pitem := range plist {
+		/*if _, ok := grpPitems[pitem.OrderId]; !ok {
+			grpPitems[pitem.OrderId] = []entity.OrderProduct{}
+		}*/
+		grpPitems[pitem.OrderId] = append(grpPitems[pitem.OrderId], pitem)
+	}
+	for _, oitem := range olr {
+		oitem.Products = append(oitem.Products, grpPitems[oitem.Id]...)
+	}
+	//attach rel_id
+	strSql = fmt.Sprintf("select id, rel_id from t_custom_linker where id in (%s)", lids)
+	var relIds = []struct {
+		LID   int `db:"id"`
+		RelId int `db:"rel_id"`
+	}{}
+	err = db.Select(&relIds, strSql)
+	if err != nil {
+		return err
+	}
+	for _, oitem := range olr {
+		for _, rt := range relIds {
+			if oitem.LinkerId == rt.LID {
+				oitem.RelId = rt.RelId
+			}
+		}
+	}
+	return nil
+}

+ 41 - 0
dal/smscode_dal.go

@@ -0,0 +1,41 @@
+package dal
+
+import (
+	"xiaoniaokuaiyan.com/xiaoniao/entity"
+	"xiaoniaokuaiyan.com/xiaoniao/util"
+)
+
+type SMSCode struct{}
+
+func (sdal *SMSCode) Add(code *entity.SMSCode) (*entity.SMSCode, error) {
+	db := util.GetWriteSqlDB()
+	strSql, kvm := util.GenerateInsertSqlFromStruct("t_sms_code", code)
+	_, err := db.NamedExec(strSql, kvm)
+	if err != nil {
+		return nil, err
+	}
+	return code, nil
+}
+
+func (sdal *SMSCode) Update(code *entity.SMSCode) (*entity.SMSCode, error) {
+	db := util.GetWriteSqlDB()
+	strSql, kvm := util.GenerateUpdateSqlFromStruct("t_sms_code", code, "where mobile = :mobile and code = :code")
+	_, err := db.NamedExec(strSql, kvm)
+	if err != nil {
+		return nil, err
+	}
+	return code, nil
+}
+
+func (sdal *SMSCode) Get(mobile, code string, codeType int) (*entity.SMSCode, error) {
+	db := util.GetSqlDB()
+	var codeItem = entity.SMSCode{}
+	err := db.Get(&codeItem, "select * from t_sms_code where mobile = ? and code = ? and code_type = ? and is_used = 0", mobile, code, codeType)
+	if err != nil {
+		return nil, err
+	}
+
+	return &codeItem, nil
+}
+
+var DefaultSMSCodeDal = &SMSCode{}

+ 147 - 0
dal/user_dal.go

@@ -0,0 +1,147 @@
+package dal
+
+import (
+	"database/sql"
+	"errors"
+	"fmt"
+	"xiaoniaokuaiyan.com/xiaoniao/entity"
+	"xiaoniaokuaiyan.com/xiaoniao/util"
+)
+
+type User struct {
+}
+
+func (u *User) Get(account string) (*entity.UserDB, error) {
+	db := util.GetSqlDB()
+	strSql := "select id, mobile, password, password_salt, extra, account_type,avatar from t_custom where mobile = ? limit 1"
+	var user entity.UserDB
+	err := db.Get(&user, strSql, account)
+	if err != nil {
+		if err == sql.ErrNoRows {
+			return nil, DBRECORD_NOT_EXISTS_ERROR
+		}
+		return nil, err
+	}
+	return &user, nil
+
+}
+
+func (u *User) Save(params map[string]interface{}) (interface{}, error) {
+	db := util.GetWriteSqlDB()
+	var sqlStr = util.GenerateInsertSql("t_custom", params)
+	result, err := db.NamedExec(sqlStr, params)
+	if err != nil {
+		return nil, errors.New("db error")
+	}
+	aid, err := result.LastInsertId()
+	if err != nil {
+		if id, ok := params["id"]; ok {
+			return id, nil
+		} else {
+			return nil, nil
+		}
+	}
+	return aid, nil
+}
+
+func (u *User) Update(user *entity.User) (*entity.User, error) {
+	if user.Id == 0 && user.Mobile == "" {
+		return nil, errors.New("错误的请求")
+	}
+	db := util.GetWriteSqlDB()
+	var whereStr string
+	if user.Id == 0 {
+		whereStr = " where mobile = :mobile"
+	} else {
+		whereStr = " where id = :id"
+	}
+	sqlStr, kvm := util.GenerateUpdateSqlFromStruct("t_custom", user, whereStr)
+	result, err := db.NamedExec(sqlStr, kvm)
+	if err != nil {
+		return nil, err
+	}
+	_, err = result.RowsAffected()
+	if err != nil {
+		return nil, err
+	}
+	/*if ra <= 0 {
+		return nil, errors.New("404::update failed(can not found user)")
+	}*/
+	return user, nil
+}
+
+func (u *User) GetNotice(mobile string) ([]entity.QueueNotice, error) {
+	db := util.GetSqlDB()
+	qlist := []entity.QueueNotice{}
+	err := db.Select(&qlist, "select * from t_custom_queue where custom_mobile = ? and isallnotice = 'N'", mobile)
+	return qlist, err
+}
+
+func (u *User) UpdateNotice(notice *entity.QueueNotice) (bool, error) {
+	if notice.Id == 0 {
+		return false, errors.New("can not find info")
+	}
+	db := util.GetWriteSqlDB()
+	sqlStr, kvm := util.GenerateUpdateSqlFromStruct("t_custom_queue", notice, " where id = :id")
+	result, err := db.NamedExec(sqlStr, kvm)
+	if err != nil {
+		return false, err
+	}
+	ra, err := result.RowsAffected()
+	if err != nil {
+		return false, err
+	}
+	if ra <= 0 {
+		return false, errors.New("404::update failed(can not found info)")
+	}
+	return true, nil
+}
+
+// 根据openid 查询用户
+func (u *User) GetUserByOpenid(openid string) (*entity.UserDB, error) {
+	db := util.GetSqlDB()
+	strSql := "select id, mobile, password, password_salt, extra, account_type,avatar from t_custom where instr(extra,?)>0 limit 1"
+	var user entity.UserDB
+	err := db.Get(&user, strSql, openid)
+	if err != nil {
+		if err == sql.ErrNoRows {
+			return nil, DBRECORD_NOT_EXISTS_ERROR
+		}
+		return nil, err
+	}
+	return &user, nil
+
+}
+
+func (u *User) GetUserByUnionid(unionid string) (*entity.UserDB, error) {
+	if unionid == "" {
+		return nil, fmt.Errorf("unionid is empty")
+	}
+	db := util.GetSqlDB()
+	strSql := "select id, mobile, password, password_salt, extra, account_type,avatar from t_custom where unionid = ? limit 1"
+	var user entity.UserDB
+	err := db.Get(&user, strSql, unionid)
+	if err != nil {
+		if err == sql.ErrNoRows {
+			return nil, DBRECORD_NOT_EXISTS_ERROR
+		}
+		return nil, err
+	}
+	return &user, nil
+}
+
+func (u *User) GetUserByUserId(zfbUserId string) (*entity.UserDB, error) {
+	db := util.GetSqlDB()
+	strSql := "select id, mobile, password, password_salt, extra, account_type,avatar from t_custom where extra like ? limit 1"
+	var user entity.UserDB
+	err := db.Get(&user, strSql, "%"+zfbUserId+"%")
+	if err != nil {
+		if err == sql.ErrNoRows {
+			return nil, DBRECORD_NOT_EXISTS_ERROR
+		}
+		return nil, err
+	}
+	return &user, nil
+}
+
+var DefaultUserDal = &User{}

+ 99 - 0
dal/userlinker_dal.go

@@ -0,0 +1,99 @@
+package dal
+
+import (
+	"errors"
+	"time"
+
+	"xiaoniaokuaiyan.com/xiaoniao/entity"
+	"xiaoniaokuaiyan.com/xiaoniao/util"
+)
+
+type UserLinker struct{}
+
+func (ul *UserLinker) Save(linker *entity.UserLinker) (*entity.UserLinker, error) {
+	db := util.GetWriteSqlDB()
+	linker.CreatedAt = time.Now().Format("2006-01-02 15:04:05")
+	strSql, kvm := util.GenerateInsertSqlFromStruct("t_custom_linker", linker)
+	result, err := db.NamedExec(strSql, kvm)
+	if err != nil {
+		return nil, err
+	}
+	ar, _ := result.RowsAffected()
+	if ar > 0 && linker.IsDefault == 1 {
+		_, err = db.Exec("update t_custom_linker set is_default = 0 where custom_id = ? and id <> ?")
+		if err != nil {
+			return nil, err
+		}
+	}
+	aid, _ := result.LastInsertId()
+	linker.Id = int(aid)
+	return linker, nil
+}
+
+func (ul *UserLinker) List(customId int, isDefault bool) ([]entity.UserLinkerDB, error) {
+	db := util.GetSqlDB()
+	var linkerList = []entity.UserLinkerDB{}
+	strSql := "select * from t_custom_linker where custom_id = ?"
+	if isDefault {
+		strSql += " order by is_default desc limit 1"
+	}
+	err := db.Select(&linkerList, strSql, customId)
+	if err != nil {
+		return nil, err
+	}
+	return linkerList, nil
+}
+
+func (ul *UserLinker) Get(id, cid int) (*entity.UserLinkerDB, error) {
+	db := util.GetSqlDB()
+	var userLinker = &entity.UserLinkerDB{}
+	err := db.Get(userLinker, "select * from t_custom_linker where id = ? and custom_id = ?", id, cid)
+	if err != nil {
+		return nil, err
+	}
+	return userLinker, nil
+}
+
+func (ul *UserLinker) Update(linker *entity.UserLinker) (*entity.UserLinker, error) {
+	db := util.GetWriteSqlDB()
+	if linker.County != "" {
+		var countyId int
+		db.Get(&countyId, "select id from t_county where name = ?;", linker.County)
+		if countyId <= 0 {
+			return nil, errors.New("can not find county: " + linker.County)
+		}
+		//linker.CountyId = countyId
+	}
+	strSql, kvm := util.GenerateUpdateSqlFromStruct("t_custom_linker", linker, " where id = :id")
+	_, err := db.NamedExec(strSql, kvm)
+	if err != nil {
+		return nil, err
+	}
+	/*ra, _ := result.RowsAffected()
+	if ra <= 0 {
+		return nil, errors.New("update failed")
+	}*/
+	if linker.IsDefault == 1 {
+		_, err = db.Exec("update t_custom_linker set is_default = 0 where custom_id = ? and id <> ?", linker.CustomId, linker.Id)
+		if err != nil {
+			return nil, err
+		}
+	}
+	return linker, nil
+}
+
+func (ul *UserLinker) Remove(linker *entity.UserLinker) (interface{}, error) {
+	db := util.GetWriteSqlDB()
+	strSql := "delete from t_custom_linker where id = ? and custom_id = ?"
+	result, err := db.Exec(strSql, linker.Id, linker.CustomId)
+	if err != nil {
+		return nil, err
+	}
+	ra, _ := result.RowsAffected()
+	if ra <= 0 {
+		return nil, errors.New("remove failed(can not find record)")
+	}
+	return true, nil
+}
+
+var DefaultUserLinkerDal = &UserLinker{}

File diff suppressed because it is too large
+ 34 - 0
dict/hmm_model.utf8


File diff suppressed because it is too large
+ 258826 - 0
dict/idf.utf8


File diff suppressed because it is too large
+ 348982 - 0
dict/jieba.dict.utf8


File diff suppressed because it is too large
+ 1534 - 0
dict/stop_words.utf8


+ 5 - 0
dict/user.dict.utf8

@@ -0,0 +1,5 @@
+云计算
+韩玉鉴赏
+蓝翔 nz
+区块链 10 nz
+酸 nz

+ 17 - 0
docker-compose.yml

@@ -0,0 +1,17 @@
+version: '3'
+
+services:
+  backend:
+    image: test.xiaoniaokuaiyan.com:5000/xiaoniao/gobackend
+    container_name: gobackend
+    environment:
+      - APP_CONFIG_FILE=/xn/config.ini 
+    ports:
+      - 8000:8000
+    networks:
+      - xiaoniao
+    volumes:
+      - /data/xiaoniao/server:/xn
+
+networks:
+  xiaoniao:

File diff suppressed because it is too large
+ 2808 - 0
endpoint.go


+ 19 - 0
entity/act_jd_uinfo.go

@@ -0,0 +1,19 @@
+package entity
+
+type JDUserInfo struct {
+	Name              string `json:"name" db:"name"`
+	Erp               string `json:"erp" db:"erp"`
+	Gender            string `json:"gender" db:"gender"`
+	Type              string `json:"type" db:"product_name"`
+	Birthday          string `json:"bithday" db:"birthday"`
+	Address           string `json:"address" db:"address"`
+	AddrId            int    `json:"addr_id" db:"addr_id"`
+	Mobile            string `json:"mobile" db:"mobile"`
+	IsMarried         string `json:"is_married" db:"is_married"`
+	IsAdmin           string `json:"is_admin" db:"is_admin"`
+	IsOlderThanThirty string `json:"is_older_than_thirty" db:"age"`
+	HasBooked         string `json:"has_booked" db:"-"`
+	OrderStatus       int    `json:"order_status" db:"-"`
+	OrderId           string `json:"order_id" db:"-"`
+	IsViewReport      string `json:"is_view_report" db:"-"`
+}

+ 11 - 0
entity/act_reporter.go

@@ -0,0 +1,11 @@
+package entity
+
+type ActReporter struct {
+	Name      string `db:"name" json:"name"`
+	Gender    uint8  `db:"gender" json:"gender"`
+	Mobile    string `db:"mobile" json:"mobile"`
+	Picture   string `db:"pic" json:"picture"`
+	Age       uint8  `db:"age" json:"age"`
+	Company   string `db:"company" json:"company"`
+	CreatedAt string `db:"create_time" json:"create_time"`
+}

+ 20 - 0
entity/act_tvshop.go

@@ -0,0 +1,20 @@
+package entity
+
+import "gopkg.in/guregu/null.v3"
+
+type ActInfo struct {
+	Id         int         `db:"id" json:"id"`
+	CustomName null.String `db:"custom_name" json:"custom_name"`
+	Age        null.Int    `db:"age" json:"age"`
+	Gender     null.String `db:"gender" json:"gender"`
+	Mobile     null.String `db:"mobile" json:"mobile"`
+	Address    null.String `db:"address" json:"address"`
+	ExCode     null.String `db:"ex_code" json:"ex_code"`
+	PayType    string      `db:"pay_type" json:"pay_type"`
+	Payment    null.Int    `db:"payment" json:"payment"`
+	CreatedAt  string      `db:"created_at" json:"created_at"`
+	Extra      null.String `db:"extra" json:"extra"`
+	Source     string      `db:"source" json:"source"`
+	Status     string      `db:"status" json:"status"`
+	Remark     null.String `db:"remark" json:"remark"`
+}

+ 9 - 0
entity/cart.go

@@ -0,0 +1,9 @@
+package entity
+
+type Cart struct {
+	CustomId  int    `db:"cid"`
+	ProductId int    `db:"pid"`
+	Quantity  int    `db:"quantity"`
+	CreatedAt string `db:"created_at"`
+	IsAdd     bool   `db:"-" json:"is_add"`
+}

+ 58 - 0
entity/city.go

@@ -0,0 +1,58 @@
+package entity
+
+import "gopkg.in/guregu/null.v3"
+
+type City struct {
+	Id       int      `db:"id"`
+	Name     string   `db:"name"`
+	AreaCode string   `db:"area_code"`
+	IsOpen   int      `db:"is_open"`
+	Countys  []County `db:"-"`
+}
+
+type County struct {
+	Id       int    `db:"id" json:"id"`
+	CityId   int    `db:"city_id" json:"city_id"`
+	Name     string `db:"name" json:"name"`
+	PostCode string `db:"post_code" json:"post_code"`
+}
+
+type City2 struct {
+	Id       int       `db:"id"`
+	Name     string    `db:"name"`
+	Counties []County2 `db:"-" json:"children"`
+}
+
+type CityNode struct {
+	Id       int          `db:"id" json:"id"`
+	Name     string       `db:"name" json:"name"`
+	PId      int          `db:"province_id" json:"pid"`
+	PName    null.String  `db:"province" json:"pname"`
+	Counties []CountyNode `db:"-" json:"children"`
+}
+
+type CountyNode struct {
+	Id    int         `db:"id" json:"id"`
+	Name  string      `db:"name" json:"name"`
+	PId   int         `db:"_" json:"pid"`
+	PName null.String `db:"_" json:"pname"`
+}
+type County2 struct {
+	Id   int    `db:"id" json:"id"`
+	Name string `db:"name" json:"name"`
+}
+
+type Province struct {
+	Id     int     `db:"id"`
+	Name   string  `db:"name"`
+	Cities []City2 `db:"-" json:"children"`
+}
+
+type CityAll struct {
+	ProvinceId int    `db:"province_id"`
+	Province   string `db:"province"`
+	CityId     int    `db:"city_id"`
+	City       string `db:"city"`
+	CountryId  int    `db:"country_id"`
+	Country    string `db:"country"`
+}

+ 11 - 0
entity/consumer_gene_sign.go

@@ -0,0 +1,11 @@
+package entity
+
+type ConsumerGeneSign struct {
+	Mobile  string `db:"mobile" json:"mobile"`
+	Name    string `db:"name" json:"name"`
+	Age     int    `db:"age" json:"age"`
+	Gender  string `db:"gender" json:"gender"`
+	Barcode string `db:"barcode" json:"barcode"`
+	Extra   string `db:"extra" json:"extra"`
+	Source  string `db:"source" json:"source"`
+}

+ 134 - 0
entity/custom_file.go

@@ -0,0 +1,134 @@
+package entity
+
+import "gopkg.in/guregu/null.v3"
+
+/**
+* @Author: qz
+* @Date: 2021/12/13 18:46
+* @Description:
+ */
+
+type CustomInfoLabelsDto struct {
+	CustomFileId int               `json:"custom_file_id"`
+	List         []CustomInfoLabel `json:"custom_file_info"`
+}
+
+//custom_file 标签字段(酗酒,睡眠)
+type CustomInfoLabel struct {
+	Key   string `json:"key"`
+	Value string `json:"value"`
+	Other string `json:"other"`
+}
+
+type CustomFileInfoDB struct {
+	Id                        int         `db:"id" json:"id"`
+	Name                      null.String `db:"name" json:"name"`
+	Mobile                    null.String `db:"mobile" json:"mobile"`
+	Birthday                  null.String `db:"birthday" json:"birthday"` //生日
+	CustomId                  int         `db:"custom_id" json:"custom_id"`
+	RelId                     int         `db:"rel_id" json:"rel_id"`
+	RelStr                    string      `json:"rel_str"`
+	IdType                    null.Int    `db:"id_type" json:"id_type"`
+	Gender                    int         `db:"gender" json:"gender"`
+	IdNum                     null.String `db:"id_num" json:"id_num"`
+	Height                    null.Int    `db:"height" json:"height"`                                 //身高
+	Weight                    null.Int    `db:"weight" json:"weight"`                                 //体重
+	BloodType                 null.String `db:"blood_type" json:"blood_type"`                         //血型
+	SmokeLevel                null.Int    `db:"smoke_level" json:"smoke_level"`                       //吸烟程度
+	SmokeLevelStr             string      `json:"smoke_level_str"`                                    //吸烟程度文字
+	AlcoholLevel              null.Int    `db:"alcohol_level" json:"alcohol_level"`                   //饮酒程度
+	AlcoholLevelStr           string      `json:"alcohol_level_str"`                                  //饮酒程度文字
+	ExerciseLevel             null.Int    `db:"exercise_level" json:"exercise_level"`                 //锻炼程度
+	ExerciseLevelStr          string      `json:"exercise_level_str"`                                 //锻炼程度文字
+	SleepLevel                null.Int    `db:"sleep_level" json:"sleep_level"`                       //睡眠质量
+	SleepLevelStr             string      `json:"sleep_level_str"`                                    //睡眠质量文字
+	SelfMedicalHistory        null.String `db:"self_medical_history" json:"self_medical_history"`     //既往病史
+	SelfMedicalHistoryStr     string      `json:"self_medical_history_str"`                           //既往病史文字
+	FamilyMedicalHistory      null.String `db:"family_medical_history" json:"family_medical_history"` //家族病史
+	FamilyMedicalHistoryStr   string      `json:"family_medical_history_str"`                         //家族病史文字
+	DrugAllergy               null.String `db:"drug_allergy" json:"drug_allergy"`                     //过敏用药
+	DrugAllergyStr            string      `json:"drug_allergy_str"`                                   //过敏用药文字
+	DietaryHabit              null.String `db:"dietary_habit" json:"dietary_habit"`                   //饮食习惯
+	DietaryHabitStr           string      `json:"dietary_habit_str"`                                  //饮食习惯文字
+	HealthNeeds               null.String `db:"health_needs" json:"health_needs"`                     //健康需求
+	HealthNeedsStr            string      `json:"health_needs_str"`                                   //健康需求文字
+	SmokeLevelOther           null.String `db:"smoke_level_other" json:"smoke_level_other"`
+	AlcoholLevelOther         null.String `db:"alcohol_level_other" json:"alcohol_level_other"`
+	ExerciseLevelOther        null.String `db:"exercise_level_other" json:"exercise_level_other"`
+	SleepLevelOther           null.String `db:"sleep_level_other" json:"sleep_level_other"`
+	SelfMedicalHistoryOther   null.String `db:"self_medical_history_other" json:"self_medical_history_other"`
+	FamilyMedicalHistoryOther null.String `db:"family_medical_history_other" json:"family_medical_history_other"`
+	DrugAllergyOther          null.String `db:"drug_allergy_other" json:"drug_allergy_other"`
+	DietaryHabitOther         null.String `db:"dietary_habit_other" json:"dietary_habit_other"`
+	HealthNeedsOther          null.String `db:"health_needs_other" json:"health_needs_other"`
+}
+
+type CustomFile struct {
+	Id                        int    `db:"id" json:"id"`
+	Name                      string `db:"name" json:"name"`
+	Mobile                    string `db:"mobile" json:"mobile"`
+	Birthday                  string `db:"birthday" json:"birthday"` //生日
+	CustomId                  int    `db:"custom_id" json:"custom_id"`
+	RelId                     int    `db:"rel_id" json:"rel_id"`
+	IdNum                     string `db:"id_num" json:"id_num"`
+	IdType                    int    `db:"id_type" json:"id_type"`
+	Gender                    int    `db:"gender" json:"gender"`
+	Height                    int    `db:"height" json:"height"`                                 //身高
+	Weight                    int    `db:"weight" json:"weight"`                                 //体重
+	BloodType                 string `db:"blood_type" json:"blood_type"`                         //血型
+	SmokeLevel                int    `db:"smoke_level" json:"smoke_level"`                       //吸烟程度
+	AlcoholLevel              int    `db:"alcohol_level" json:"alcohol_level"`                   //饮酒程度
+	ExerciseLevel             int    `db:"exercise_level" json:"exercise_level"`                 //锻炼程度
+	SleepLevel                int    `db:"sleep_level" json:"sleep_level"`                       //睡眠质量
+	SelfMedicalHistory        string `db:"self_medical_history" json:"self_medical_history"`     //既往病史
+	FamilyMedicalHistory      string `db:"family_medical_history" json:"family_medical_history"` //家族病史
+	DrugAllergy               string `db:"drug_allergy" json:"drug_allergy"`                     //过敏用药
+	DietaryHabit              string `db:"dietary_habit" json:"dietary_habit"`                   //饮食习惯
+	HealthNeeds               string `db:"health_needs" json:"health_needs"`                     //健康需求
+	SmokeLevelOther           string `db:"smoke_level_other" json:"smoke_level_other"`
+	AlcoholLevelOther         string `db:"alcohol_level_other" json:"alcohol_level_other"`
+	ExerciseLevelOther        string `db:"exercise_level_other" json:"exercise_level_other"`
+	SleepLevelOther           string `db:"sleep_level_other" json:"sleep_level_other"`
+	SelfMedicalHistoryOther   string `db:"self_medical_history_other" json:"self_medical_history_other"`
+	FamilyMedicalHistoryOther string `db:"family_medical_history_other" json:"family_medical_history_other"`
+	DrugAllergyOther          string `db:"drug_allergy_other" json:"drug_allergy_other"`
+	DietaryHabitOther         string `db:"dietary_habit_other" json:"dietary_habit_other"`
+	HealthNeedsOther          string `db:"health_needs_other" json:"health_needs_other"`
+	VCode                     string `json:"vcode"`
+}
+
+type CustomAttachment struct {
+	Id           int    `json:"id"`
+	CustomId     int    `json:"custom_id" db:"custom_id"`
+	CustomFileId int    `json:"custom_file_id" db:"custom_file_id"`
+	Path         string `json:"path" db:"path"`
+	UpLoadType   string `json:"upload_type" db:"upload_type"` //JZ 就诊 JYD 检验单 CF 处方
+	CustomRemark string `json:"custom_remark" db:"custom_remark"`
+	DoctorRemark string `json:"doctor_remark" db:"doctor_remark"`
+	UploadAt     string `json:"upload_at" db:"upload_at"`
+	CheckDate    string `json:"check_date" db:"check_date"`
+	Title        string `json:"title" db:"title"`
+}
+type CustomAttachmentDB struct {
+	Id           int         `db:"id" json:"id"`
+	CustomId     int         `db:"custom_id" json:"custom_id"`
+	CustomFileId int         `db:"custom_file_id" json:"custom_file_id"`
+	Path         string      `db:"path" json:"path"`
+	UpLoadType   string      `db:"upload_type" json:"upload_type"`
+	CustomRemark null.String `db:"custom_remark" json:"custom_remark"`
+	DoctorRemark null.String `db:"doctor_remark" json:"doctor_remark"`
+	UploadAt     null.String `db:"upload_at" json:"upload_at"`
+	CheckDate    null.String `db:"check_date" json:"check_date"`
+	Title        null.String `db:"title" json:"title"`
+}
+
+type CustomFileParam struct {
+	CustomFileId int    `json:"custom_file_id"`
+	Mobile       string `json:"mobile"`
+	CustomMobile string `json:"custom_mobile"`
+}
+
+func (c *CustomFileParam) IsCustomSelf() bool {
+	flag := c.CustomMobile == c.Mobile
+	return flag
+}

+ 25 - 0
entity/deliver_bill.go

@@ -0,0 +1,25 @@
+package entity
+
+type DeliverBill struct {
+	DeliverUserId int    `db:"deliver_user_id" json:"deliver_user_id"`
+	Fee           int    `db:"fee" json:"fee"`
+	Type          string `db:"type" json:"type"`
+	CreatedAt     string `db:"created_at" json:"created_at"`
+}
+
+type DeliverAccount struct {
+	DeliverUserId int `db:"deliver_user_id" json:"deliver_user_id"`
+	Remain        int `db:"remain" json:"remain"`
+	Withdrawed    int `db:"withdrawed" json:"withdrawed"`
+	ValidWithdraw int `db:"valid_withdraw" json:"valid_withdraw"`
+	Score         int `db:"score" json:"score"`
+	ScoreCash     int `db:"score_cash" json:"score_cash"`
+	ScoreCashed   int `db:"score_cashed" json:"score_cashed"`
+}
+
+type DeliverScoreBill struct {
+	DeliverUserId int    `db:"deliver_user_id" json:"deliver_user_id"`
+	Score         int    `db:"score" json:"score"`
+	Type          string `db:"type" json:"type"`
+	CreatedAt     string `db:"created_at" json:"created_at"`
+}

+ 38 - 0
entity/deliver_exam.go

@@ -0,0 +1,38 @@
+package entity
+
+type ExamQuestion struct {
+	Id       int          `db:"id" json:"id"`
+	Name     string       `db:"name" json:"name"`
+	Type     string       `db:"type" json:"type"`
+	Flag     string       `db:"flag" json:"flag"`
+	SortNo   int          `db:"sortno" json:"sortno"`
+	Answer   string       `db:"answer" json:"-"`
+	InAnswer string       `db:"-" json:"answer"`
+	Options  []ExamOption `db:"-" json:"options"`
+}
+
+type ExamOption struct {
+	Id     int    `db:"id" json:"id"`
+	ExamId int    `db:"exam_id" json:"exam_id"`
+	Name   string `db:"name" json:"name"`
+	Flag   string `db:"flag" json:"flag"`
+}
+
+// 20221009 护士加项产品考试 试题
+type ProductQuestion struct {
+	ID            int             `db:"id" json:"title_id"`
+	TitleName     string          `db:"name" json:"title_name"`
+	AnswerValue   int             `db:"answer_value" json:"-"`
+	PaperId       int             `db:"paper_id" json:"-"`
+	SortNo        int             `db:"sort_no" json:"sort_no"`
+	InAnswerValue int             `db:"-" json:"answer"`
+	Options       []ProductOption `json:"options"`
+}
+
+// 20221009 护士加项产品考试 选项
+type ProductOption struct {
+	ID         int    `db:"id" json:"-"`
+	OptionName string `db:"name" json:"option_name"`
+	Value      int    `db:"value" json:"value"`
+	TitleId    int    `db:"title_id" json:"-"`
+}

+ 19 - 0
entity/deliver_msg.go

@@ -0,0 +1,19 @@
+package entity
+
+import "gopkg.in/guregu/null.v3"
+
+type DeliverMsg struct {
+	Id            int         `db:"id" json:"id"`
+	DeliverUserId int         `db:"deliver_user_id" json:"deliver_user_id"`
+	Title         string      `db:"title" json:"title"`
+	Content       string      `db:"content" json:"content"`
+	IsRead        null.String `db:"is_read" json:"is_read"`
+	CreatedAt     string      `db:"created_at" json:"created_at"`
+}
+
+type DeliverChatMsg struct {
+	From      int    `db:"fu" json:"from"`
+	To        int    `db:"tu" json:"to"`
+	Message   string `db:"message" json:"message"`
+	CreatedAt string `db:"created_at" json:"created_at"`
+}

+ 17 - 0
entity/deliver_study.go

@@ -0,0 +1,17 @@
+package entity
+
+type DeliverStudy struct {
+	Id      int    `db:"id" json:"id"`
+	Title   string `db:"title" json:"title"`
+	Desc    string `db:"desc" json:"desc"`
+	Content string `db:"content" json:"content"`
+	Flag    string `db:"flag" json:"flag"`
+	Sortno  int    `db:"sortno" json:"sortno"`
+	Type    string `db:"typ" json:"type"`
+}
+
+type DeliverStudyLog struct {
+	Openid         string `db:"openid" json:"openid"`
+	DeliverStudyId int    `db:"deliver_study_id" json:"deliver_study_id"`
+	DeliverUserId  int    `db:"-" json:"deliver_user_id"`
+}

+ 36 - 0
entity/deliver_user.go

@@ -0,0 +1,36 @@
+package entity
+
+import "gopkg.in/guregu/null.v3"
+
+type DeliverUser struct {
+	Id            uint64      `db:"id"`     //json:"id"`
+	Name          string      `db:"name"`   //json:"name"`
+	Age           uint8       `db:"age"`    //json:"age"`
+	Gender        string      `db:"gender"` //json:"gender"`
+	Tel           string      `db:"tel"`    //json:"tel"`
+	Career        string      `db:"career"` //json:"career"`
+	Openid        string      `db:"openid"`
+	HeadPic       string      `db:"head_pic"` //json:"head_pic"`
+	Remark        string      `db:"remark"`   //json:"remark"`
+	Qualifiction  []string    `db:"-"`        //json:"qualifiction"`
+	License       []string    `db:"-"`
+	Photo         []string    `db:"-"`
+	Address       string      `db:"address"`   // json:"address"`
+	Education     string      `db:"education"` // json:"education"`
+	IdFront       string      `db:"id_front"`  //json:"id_front"`
+	IdBack        string      `db:"id_back"`   //json:"id_back"`
+	Company       string      `db:"company"`   //json:"company"`
+	Birthday      string      `db:"birthday"`
+	CreateAt      string      `db:"create_at"`
+	Vcode         string      `db:"-"`
+	ProcessState  string      `db:"process_staus"`
+	Grade         string      `db:"grade"`
+	Reason        null.String `db:"reason"`
+	InviteBy      string      `db:"invite_by"`
+	IsFetch       string      `db:"is_fetch"`
+	ProvinceId    null.Int    `db:"province_id" json:"province_id"`
+	CityId        null.Int    `db:"city_id" json:"city_id"`
+	CountyId      null.Int    `db:"county_id" json:"county_id"`
+	IsSkip        string      `db:"is_skip"`
+	CertificateNo string      `db:"certificate_no" json:"certificate_no"`
+}

+ 15 - 0
entity/detect_item.go

@@ -0,0 +1,15 @@
+package entity
+
+type DetectItem struct {
+	Id             int     `db:"id"`
+	Name           string  `db:"name" json:"name"`
+	Code           string  `db:"code"`
+	Price          float32 `db:"price"`
+	MarketPrice    float32 `db:"market_price"`
+	Description    string  `db:"description"`
+	Unit           string  `db:"unit"`
+	RefValue       string  `db:"refValue"`
+	AdviceOfHigh   string  `db:"adviceOfHigh"`
+	AdviceOfLow    string  `db:"adviceOfLow"`
+	AdviceOfNormal string  `db:"adviceOfNormal"`
+}

+ 6 - 0
entity/detect_product.go

@@ -0,0 +1,6 @@
+package entity
+
+type DetectProduct struct {
+	Id   int    `db:"id"`
+	Name string `db:"name"`
+}

+ 13 - 0
entity/dict_item.go

@@ -0,0 +1,13 @@
+package entity
+
+import "gopkg.in/guregu/null.v3"
+
+type DictItem struct {
+	Id       int         `db:"id" json:"id"`
+	Class    string      `db:"class" json:"class"`
+	Title    string      `db:"title" json:"title"`
+	Value    string      `db:"value" json:"value"`
+	Flag     string      `db:"flag" json:"flag"`
+	OrderNum int         `db:"ordernum" json:"ordernum"`
+	Extra    null.String `db:"extra" json:"extra"`
+}

+ 47 - 0
entity/discount_ticket.go

@@ -0,0 +1,47 @@
+package entity
+
+import (
+	"time"
+
+	"xiaoniaokuaiyan.com/xiaoniao/constants"
+
+	"gopkg.in/guregu/null.v3"
+)
+
+type DiscountTicket struct {
+	Id           int    `db:"id" json:"id"`
+	TypeId       int    `db:"type_id" json:"type_id"`
+	Mobile       string `db:"mobile",validate:"regexp=^1\d{10,10}$" json:"mobile"`
+	Value        int    `db:"value" json:"value"`
+	UseMaxValue  int    `db:"use_max_value" json:"use_max_value"`
+	Deadline     string `db:"deadline" json:"deadline"`
+	Status       int    `db:"status" json:"status"`
+	OrderId      string `db:"order_id" json:"order_id"`
+	CreatedAt    string `db:"created_at" json:"created_at"`
+	BindProducts string `db:"bind_products" json:"bind_products"`
+}
+type DiscountTicketDB struct {
+	Id           int         `db:"id"`
+	TypeId       int         `db:"type_id"`
+	Mobile       string      `db:"mobile"`
+	Value        int         `db:"value"`
+	UseMaxValue  null.Int    `db:"use_max_value"`
+	Deadline     string      `db:"deadline"`
+	Status       int         `db:"status"`
+	OrderId      null.String `db:"order_id"`
+	CreatedAt    string      `db:"created_at"`
+	BindProducts null.String `db:"bind_products"`
+	LianrenId    null.Int    `db:"lianren_id"`
+}
+
+func (ticket *DiscountTicketDB) IsValid(useMaxVal int) bool {
+	if ticket.TypeId == int(constants.COUPONTYPE_LIMIT) && ticket.UseMaxValue.Int64 > int64(useMaxVal) {
+		return false
+	}
+	return ticket.Status == 0 && !ticket.IsExpired() //&& !ticket.OrderId.Valid
+}
+
+func (ticket *DiscountTicketDB) IsExpired() bool {
+	deadline, _ := time.Parse("2006-01-02", ticket.Deadline)
+	return deadline.Before(time.Now().AddDate(0, 0, -1))
+}

+ 30 - 0
entity/discount_ticket_type.go

@@ -0,0 +1,30 @@
+package entity
+
+import "gopkg.in/guregu/null.v3"
+
+type DiscountTicketType struct {
+	Id       int    `db:"id"`
+	TypeName string `db:"type_name"`
+}
+
+type DiscountActParams struct {
+	Mobile string `json:"mobile"`
+	Pid    int    `json:"pid"`
+}
+
+type DiscountReceiveParams struct {
+	Mobile string `json:"mobile"`
+	Id     int    `json:"id"`
+}
+
+// 20230215 t_dicount_activity 表
+type DiscountActDB struct {
+	Id           int         `db:"id" json:"id"`
+	Name         string      `db:"name" json:"name"`
+	EndTime      string      `db:"end_time" json:"end_time"`
+	Value        int         `db:"value" json:"value"`
+	TypeId       int         `db:"type_id" json:"type_id"`
+	UseMaxValue  null.Int    `db:"use_max_value" json:"use_max_value"`
+	BindProducts null.String `db:"bind_products" json:"bind_products"`
+	Count        int         `db:"count" json:"count"`
+}

+ 38 - 0
entity/fcode.go

@@ -0,0 +1,38 @@
+package entity
+
+import (
+	"time"
+
+	"gopkg.in/guregu/null.v3"
+
+	"xiaoniaokuaiyan.com/xiaoniao/cerror"
+	"xiaoniaokuaiyan.com/xiaoniao/constants"
+)
+
+type Fcode struct {
+	Id              int         `db:"id"`
+	TypeId          int         `db:"type_id"`
+	CodeStr         string      `db:"code_str"`
+	TicketValue     int         `db:"ticket_value"`
+	UseMaxValue     int         `db:"use_max_value"`
+	UseNum          int         `db:"use_num"`
+	AlreadyUseNum   int         `db:"already_use_num"`
+	Deadline        string      `db:"deadline"`
+	TicketDeadline  string      `db:"ticket_deadline"`
+	CreatedAt       string      `db:"createdAt"`
+	Remark          null.String `db:"remark" json:"remark"`
+	BindProducts    null.String `db:"bind_products"`
+	Usefor          null.String `db:"usefor" json:"usefor"`
+	TicketValidDays null.Int    `db:"ticket_valid_days" json:"ticket_valid_days"`
+}
+
+func (codeItem *Fcode) Valid() cerror.CError {
+	deadline, _ := time.Parse("2006-01-02", codeItem.Deadline)
+	if deadline.Before(time.Now().AddDate(0, 0, -1)) {
+		return cerror.New(constants.ERRORCODE_FCODE_EXPIRED, "code has expired|"+codeItem.Deadline)
+	}
+	if codeItem.AlreadyUseNum >= codeItem.UseNum {
+		return cerror.New(constants.ERRORCODE_FCODE_UPEXCEED, "码的使用次数已达到上限")
+	}
+	return nil
+}

+ 13 - 0
entity/gp_param.go

@@ -0,0 +1,13 @@
+package entity
+
+type GBPDPItem struct {
+	DetectProductId int    `json:"detect_product_id"`
+	Name            string `json:"keshi_name"`
+	DetectItemIds   []int  `json:"detect_item_ids"`
+}
+
+type GPParam struct {
+	Mobile  string      `json:"mobile"`
+	DPItems []GBPDPItem `json:"dp_items"`
+	Oper    string      `json:"oper"`
+}

+ 31 - 0
entity/jdl_entity.go

@@ -0,0 +1,31 @@
+package entity
+
+/**
+* @Author: qz
+* @Date: 2022/6/23 18:58
+* @Description:
+ */
+type JDLParams struct {
+	SenderProvince        string `json:"sender_province"`
+	SenderCity            string `json:"sender_city"`
+	SenderDistrict        string `json:"sender_district"`
+	SenderDetailAddress   string `json:"sender_detailAddress"`
+	SenderName            string `json:"sender_name"`
+	SenderMobile          string `json:"sender_mobile"`
+	ReceiverProvince      string `json:"receiver_province"`
+	ReceiverCity          string `json:"receiver_city"`
+	ReceiverDistrict      string `json:"receiver_district"`
+	ReceiverDetailAddress string `json:"receiver_detailAddress"`
+	ReceiverName          string `json:"receiver_name"`
+	ReceiverMobile        string `json:"receiver_mobile"`
+	XnCode                string `json:"order_id"`
+	SendStart             string `json:"send_start"`
+	SendEnd               string `json:"send_end"`
+	Remark                string `json:"remark"`
+	CustomerCode          string `json:"customer_code"`
+}
+
+type JDLCheck struct {
+	PickUpCode   string `json:"pick_up_code"`
+	CustomerCode string `json:"customer_code"`
+}

+ 173 - 0
entity/order.go

@@ -0,0 +1,173 @@
+package entity
+
+import "gopkg.in/guregu/null.v3"
+
+type Order struct {
+	Id              string         `db:"id"`     //订单编号
+	Name            string         `db:"name"`   //客户姓名
+	Gender          int            `db:"gender"` //姓名
+	Age             int            `db:"age"`    //年龄
+	Birthday        string         `db:"birthday"`
+	Address         string         `db:"address"`           //上门地址
+	DetailAddress   string         `db:"detail_address"`    //详细地址
+	VisitDate       string         `db:"visit_date"`        //上门日期
+	VisitTimeRange  string         `db:"visit_time_range"`  //上门时间段
+	Source          string         `db:"source"`            //订单来源
+	Status          int            `db:"status"`            //订单状态(1待支付,2待接单-匹配客户经理以及护士,3待上门,4待上传化验结果,5已完成)
+	WorkFee         int            `db:"work_fee,positive"` //上门费
+	FreeFee         int            `db:"free_fee"`          //优惠费用
+	RepeatItemFee   int            `db:"repeat_item_fee"`   //重复项减免费用
+	Payment         int            `db:"payment,positive"`  //订单需支付金额
+	OnlinePayment   int            `db:"online_payment,positive"`
+	ActualPayment   int            `db:"actual_payment"` //实际支付金额
+	VActualPayment  int            `db:"v_actual_payment"`
+	PaymentTime     string         `db:"payment_time,omitempty"`      //支付时间
+	PayType         int            `db:"pay_type,omitempty"`          //支付类型
+	PayNo           string         `db:"pay_no,omitempty"`            //支付流水号
+	CustomManagerId string         `db:"cm_id,omitempty" json:"CmId"` //客户经理id 20210331 用于保存json 字段,查看是否点击扣减活动
+	NourseId        string         `db:"nurse_id,omitempty"`          //护士id
+	IsOthers        int            `db:"is_others"`                   //是否为替他人下单
+	IsMerged        int            `db:"is_merged"`                   //是否被合并
+	BloodCodes      string         `db:"blood_codes,omitempty"`       //血检条码
+	AssayTime       string         `db:"assay_time,omitempty"`        //上门时间
+	CustomId        int            `db:"custom_id"`
+	CustomMobile    string         `db:"custom_mobile"` //下单人电话
+	Mobile          string         `db:"mobile"`        //被下单人电话
+	MaterialId      int            `db:"m_id"`          //占用产能id
+	Remark          string         `db:"remark,omitempty"`
+	AdminRemark     string         `db:"admin_remark"`
+	UpdatedAt       string         `db:"updated_at"`
+	CreatedAt       string         `db:"created_at"`
+	IsViewReport    string         `db:"is_view_report"`
+	ShareCode       string         `db:"share_code"`
+	IsAgent         uint           `db:"isagent"`
+	Type            string         `db:"type"` //集采类型
+	BloodTestId     string         `db:"null"`
+	OpenId          string         `db:"null"`
+	Relationship    string         `db:"null"`
+	IsYunxue        int            `db:"null"`
+	IsDfguomin      int            `db:"null"`
+	ProductIds      []OrderProduct `db:"null"`
+	ItemIds         []int          `db:"null"`
+	Coupons         []int          `db:"null"`
+	IsNeedPay       string         `db:"null"`
+	LinkerId        int            `db:"linker_id"`
+	CreatedBy       string         `db:"created_by"`
+	PTId            int            `db:"null"`
+	ToOpenID        string         `db:"null",json:"toopenid"`
+	IdNum           string         `db:"id_num",json:"IdNum"`
+	NurseId         string         `db:"null",json:"NurseId"`
+	ServiceRemark   string         `db:"service_remark"`
+	JdOrderId       string         `db:"jd_order_id",json:"JdOrderId"`    //20210225 微医 扩展字段,占用 京东订单号
+	Zone            string         `db:"zone" json:"zone"`                //20210324 增加json存储省市区字段
+	Coordinates     string         `db:"coordinates" json:"Coordinates"`  //20210922 添加订单坐标
+	PreOrderId      string         `db:"pre_order_id" json:"PreOrderId"`  //20211112 主单id,订单变为服务单
+	ShareSource     string         `db:"share_source" json:"ShareSource"` //20220428 增加保存json 字段
+	IsZFB           bool           `db:"null"`
+	AccountType     string         `db:"account_type" json:"AccountType"` //20230904 增加微信支付账户类型  主要分博德,云动脉等
+}
+
+type OrderDB struct {
+	Id              string      `db:"id"`     //订单编号
+	Name            string      `db:"name"`   //客户姓名
+	Gender          int         `db:"gender"` //姓名
+	Age             int         `db:"age"`    //年龄
+	Birthday        string      `db:"birthday"`
+	Address         string      `db:"address"`          //上门地址
+	DetailAddress   string      `db:"detail_address"`   //详细地址
+	VisitDate       null.String `db:"visit_date"`       //上门日期
+	VisitTimeRange  null.String `db:"visit_time_range"` //上门时间段
+	Source          string      `db:"source"`           //订单来源
+	Status          int         `db:"status"`           //订单状态(1待支付,2待接单-匹配客户经理以及护士,3待上门,4待上传化验结果,5已完成)
+	WorkFee         null.Int    `db:"work_fee"`         //上门费
+	FreeFee         int         `db:"free_fee"`         //优惠费用
+	RepeatItemFee   int         `db:"repeat_item_fee"`  //重复项减免费用
+	Payment         int         `db:"payment"`          //订单需支付金额
+	OnlinePayment   int         `db:"online_payment"`
+	ActualPayment   null.Int    `db:"actual_payment"`   //实际支付金额
+	VActualPayment  int         `db:"v_actual_payment"` //拆单时用
+	PaymentTime     null.String `db:"payment_time"`     //支付时间
+	PayType         null.Int    `db:"pay_type"`         //支付类型
+	PayNo           null.String `db:"pay_no"`
+	CustomManagerId null.String `db:"cm_id"`       //客户经理id
+	NourseId        null.String `db:"nurse_id"`    //护士id
+	IsOthers        int         `db:"is_others"`   //是否为替他人下单
+	IsMerged        int         `db:"is_merged"`   //是否被合并
+	BloodCodes      null.String `db:"blood_codes"` //血检条码
+	AssayTime       null.String `db:"assay_time"`  //上门时间
+	CustomId        null.Int    `db:"custom_id"`
+	CustomMobile    string      `db:"custom_mobile"` //下单人电话
+	Mobile          string      `db:"mobile"`        //被下单人电话
+	MaterialId      int         `db:"m_id"`          //占用产能id
+	ReportPicture   string      `db:"report_picture"`
+	IsViewReport    string      `db:"is_view_report"`
+	Remark          null.String `db:"remark"`
+	UpdatedAt       string      `db:"updated_at"`
+	CreatedAt       string      `db:"created_at,omitempty"`
+	IsNotice        string      `db:"is_notice"`
+	ThirdPayNo      null.String `db:"third_pay_no" json:"-"`
+	DelayDeadtime   uint        `db:"delay_deadtime" json:"delay_deadtime"` //订单失效时间延迟时长
+	Relationship    null.String `db:"relationship"`
+	RelId           null.Int    `db:"rel_id"`
+	IsYunxue        null.Int    `db:"is_yunxue"`
+	IsDfguomin      null.Int    `db:"is_dfguomin"`
+	Type            string      `db:"type" json:"type"` //订单类型
+	BloodTestId     null.String `db:"bloodtest_id" json:"bloodtest_id"`
+	NeedEmptiness   null.Int    `db:"need_emptiness"`
+	ReportPeriod    null.String `db:"report_period"`
+	PressurePipe    null.String `db:"pressure_pipe"`
+	BloodAddress    null.String `db:"blood_address"`
+	Notice          null.String `db:"notice"`
+	IsFetchData     int         `db:"is_fetch_data"`
+	NurseRemark     null.String `db:"nurse_remark"`
+	ServiceRemark   null.String `db:"service_remark"`
+	OriginalReport  null.String `db:"original_report"`
+	JdOrderId       null.String `db:"jd_order_id"`
+	Zone            null.String `db:"zone" json:"zone"`               //20210324 增加json存储省市区字段
+	Coordinates     null.String `db:"coordinates" json:"coordinates"` //20210324 增加json存储省市区字段
+	IdNum           null.String `db:"id_num",json:"IdNum"`            //20220208 增加身份证id
+	PreOrderId      string      `db:"pre_order_id" json:"PreOrderId"` //20211112 主单id,订单变为服务单
+	ShareSource     null.String `db:"share_source" `                  //20220428 增加保存json 字段
+}
+
+// order/add 用 20200814 qz add
+type AgentEntity struct {
+	Id           string      `db:"id"`
+	OpenId       string      `db:"openid"`
+	CreateTime   string      `db:"createtime"`
+	UpdateTime   string      `db:"updatetime"`
+	UserParentId null.String `db:"userparentid"`
+	AgentType    null.Int    `db:"type"`
+	RedPacket    null.Int    `db:"redpacket"`
+}
+
+// qz 检测项录入 传参 20200826
+type DetectInfoParam struct {
+	OrderId      string `json:"order_no"`
+	DetectItemID int    `json:"detect_item_id"`
+	Final        string `json:"final"`
+	Unit         string `json:"unit"`
+	RefValue     string `json:"refValue"`
+	Status       int    `json:"final_status"`
+	CreatedAt    string `json:"createdAt"`
+	IsSelf       int    `json:"is_self"`
+}
+
+// qz 检测项录入 DB数据 20200826
+type DetectInfoDB struct {
+	OrderId      string      `db:"order_no"`
+	DetectItemID int         `db:"detect_item_id"`
+	Final        string      `db:"final"`
+	Unit         string      `db:"unit"`
+	RefValue     null.String `db:"refValue"`
+	Age          null.String `db:"age"`
+	Gender       null.String `db:"gender"`
+	Checker      null.String `db:"checker"`
+	Approver     null.String `db:"approver"`
+	CheckTime    null.String `db:"checkTime"`
+	CreatedAt    string      `db:"createdAt"`
+	IsSelf       int         `db:"is_self"`
+	FinalStatus  int         `db:"final_status"`
+	FinalTip     null.String `db:"final_tip"`
+	Extra        null.String `db:"extra"`
+}

+ 12 - 0
entity/order_callback_info.go

@@ -0,0 +1,12 @@
+package entity
+
+type OrderCallbackInfo struct {
+	OrderId        string `db:"order_id" json:"order_id"`
+	IsOwnDate      string `db:"is_own_date" json:"is_own_date"`
+	CreateTime     string `db:"create_time" json:"create_time"`
+	CreateBy       string `db:"create_by" json:"create_by"`
+	VisitEndtime   string `db:"visit_end_time" json:"visit_end_time"`
+	CustomId       int    `db:"null" json:"custom_id"`
+	VisitTimeRange string `db:"visit_time_range" json:"visit_time_range"`
+	ReviewDate     string `db:"review_date" json:"review_date"`
+}

+ 19 - 0
entity/order_product.go

@@ -0,0 +1,19 @@
+package entity
+
+import "gopkg.in/guregu/null.v3"
+
+type OrderProduct struct {
+	OrderId        string      `db:"order_id"`
+	ProductId      int         `db:"product_id"`
+	ProductName    string      `db:"product_name"`
+	ProductPrice   int         `db:"price"`
+	Picture        string      `db:"picture"`
+	IsTip          null.Int    `db:"is_tip"`
+	Quantity       int         `db:"quantity"`
+	TipContent     null.String `db:"tip_content"`
+	IsJinyin       int         `db:"is_jiyin"`
+	SaleMode       int         `db:"sale_mode"`
+	DiscountSwitch string      `db:"discount_switch"`
+	StockSwitch    string      `db:"stock_switch"`
+	Searchs        string      `db:"searchs"`
+}

+ 12 - 0
entity/order_sign.go

@@ -0,0 +1,12 @@
+package entity
+
+type OrderSign struct {
+	Id        int    `json:"id" db:"id"`
+	OrderId   string `json:"order_id" db:"order_id"`
+	Status    string `json:"status" db:"status"` //护士签到状态100:出门签到 200:到达客户签到 600:一般检查 300:离开签到 400:保存条码号 500:上传图片 700:修改信息 201:签到 601:其他检测(20221229 增加)
+	SignTime  string `json:"sign_time" db:"signtime"`
+	Address   string `json:"address" db:"address"`
+	Picture   string `json:"picture" db:"picture"`
+	Remark    string `json:"remark" db:"remark"`
+	CreatedBy string `json:"create_by" db:"create_by"`
+}

+ 11 - 0
entity/order_survey.go

@@ -0,0 +1,11 @@
+package entity
+
+import "gopkg.in/guregu/null.v3"
+
+type OrderSurvey struct {
+	OrderId              string      `db:"order_id" json:"order_id"`
+	ServiceScore         string      `db:"service_score" json:"service_score"`
+	CustomerServiceScore null.String `db:"customer_service_score" json:"customer_service_score"`
+	NurseScore           string      `db:"nurse_score" json:"nurse_score"`
+	Advice               null.String `db:"advice" json:"advice"`
+}

+ 94 - 0
entity/product.go

@@ -0,0 +1,94 @@
+package entity
+
+import "gopkg.in/guregu/null.v3"
+
+type Product struct {
+	Id            int    `db:"id" json:"id"`
+	No            string `db:"no" json:"no"`
+	Name          string `db:"name" json: "name"`
+	MarketPrice   int    `db:"market_price" json:"market_price"`
+	Price         int    `db:"price" json:"price"`
+	IsPutAway     int    `db:"is_putaway"`
+	IsRecommend   int    `db:"is_recommend"`
+	Tips          string `db:"tips"`
+	Tags          string `db:"tags"`
+	Picture       string `db:"picture"`
+	CreatedAt     string `db:"created_at"`
+	UpdatedAt     string `db:"updated_at"`
+	Tube          string `db:"tube"`
+	SaleMode      int    `db:"sale_mode"`
+	Collection    string `db:"collection"`
+	Notice        string `db:"notice"`
+	Report        string `db:"report"`
+	IsDrawBlood   int    `db:"is_draw_blood"`
+	Sampling      string `db:"sampling"`
+	TipReportDays int    `db:"tip_report_days"`
+	DpidStr       string `db:"dpid_str"`
+}
+type ProductDB struct {
+	Id                int              `db:"id" json:"id"`
+	No                null.String      `db:"no" json:"no"`
+	Name              string           `db:"name" json:"name"`
+	Price             int              `db:"price" json:"price"`
+	MarketPrice       int              `db:"market_price" json:"market_price"`
+	IsPutAway         int              `db:"is_putaway" json:"isPutaway"`
+	IsRecomment       int              `db:"is_recommend" json:"isRecommend"`
+	Tips              null.String      `db:"tips" json:"tips"`
+	Tags              null.String      `db:"tags" json:"tags"`
+	Picture           string           `db:"picture"`
+	CreatedAt         string           `db:"created_at" json:"createdAt"`
+	UpdatedAt         string           `db:"updated_at" json:"updatedAt"`
+	Items             []DetectProduct  `db:"-" json:"items"`
+	Pictures          []ProductPicture `db:"-" json:"pictures"`
+	Attributes        interface{}      `db:"-" json:"attributes"`
+	CityIds           null.String      `db:"cityIds" json:"CityIds"`
+	CountyIds         null.String      `db:"countyIds" json:"CountyIds"`
+	Citys             []City           `db:"-" json:"citys"`
+	Tube              null.String      `db:"tube"`
+	SaleMode          int              `db:"sale_mode"`
+	Collection        string           `db:"collection" json:"collection"`
+	Notice            string           `db:"notice" json:"notice"`
+	Report            string           `db:"report" json:"report"`
+	InstructionsTitle string           `db:"instructionstitle" json:"instructionstitle"`
+	Instructions      string           `db:"instructions" json:"instructions"`
+	IsNoBooktime      int              `db:"is_no_booktime" json:"is_no_booktime"`
+	IsDrawBlood       int              `db:"is_draw_blood" json:"is_draw_blood"`
+	IsWorkFee         int              `db:"is_work_fee" json:"is_work_fee"`
+	IsTip             null.Int         `db:"is_tip" json:"is_tip"`
+	TipContent        null.String      `db:"tip_content" json:"tip_content"`
+	Quantity          int              `db:"quantity" json:"quantity"`
+	Sampling          null.String      `db:"sampling" json:"sampling"`
+	IsJiyin           null.Int         `db:"is_jiyin" json:"is_jiyin"`
+	Stock             int              `db:"stock" json:"stock"`
+	StockSwitch       string           `db:"stock_switch" json:"stock_switch"`
+	Pstock            int              `db:"pstock" json:"pstock"`
+	PstockSwitch      string           `db:"pstock_switch" json:"pstock_switch"`
+	BoughtNum         null.Int         `db:"bought_num" json:"-"`
+	Searchs           string           `db:"searchs" json:"searchs"`
+	TopNum            int              `db:"num" json:"top_num"`
+	IsEmptyStomach    int              `db:"is_empty_stomach" json:"is_empty_stomach"`
+	ZFBStock          int              `db:"zfb_stock" json:"-"`
+	ZFBPStock         int              `db:"zfb_pstock" json:"-"`
+	ZFBPrice          int              `db:"zfb_price" json:"-"`
+	IsZFB             int              `db:"is_zfb" json:"-"`
+}
+
+func ZFBWash(l []*ProductDB) {
+	for k := range l {
+		l[k].Stock = l[k].ZFBStock
+		l[k].Pstock = l[k].ZFBPStock
+		l[k].Price = l[k].ZFBPrice
+	}
+}
+
+/*type PicturePath struct {
+	sql.NullString
+}
+
+func (s PicturePath) MarshalJSON() ([]byte, error) {
+	if !s.Valid {
+		return []byte("null"), nil
+	}
+
+	return json.Marshal(util.EncryptPath([]byte(s.String), []byte(util.PATH_SECRET)))
+}*/

+ 16 - 0
entity/product_category.go

@@ -0,0 +1,16 @@
+package entity
+
+import "gopkg.in/guregu/null.v3"
+
+type ProductCategory struct {
+	Id        int         `db:"id"`
+	ParentId  int         `db:"parent_id"`
+	Name      string      `db:"name"`
+	IsLeaf    int         `db:"is_leaf"`
+	SortNo    int         `db:"sort_no"`
+	Pictrue   string      `db:"picture"`
+	SubTitle  null.String `db:"sub_title"`
+	CreatedAt string      `db:"created_at"`
+	Link      string      `db:"link"`
+	Icon      string      `db:"icon"`
+}

+ 8 - 0
entity/product_picture.go

@@ -0,0 +1,8 @@
+package entity
+
+type ProductPicture struct {
+	Id        int    `db:"id"`
+	ProductId int    `db:"product_id"`
+	Picture   string `db:"picture"`
+	PicType   int    `db:"pic_type"`
+}

+ 11 - 0
entity/productivity.go

@@ -0,0 +1,11 @@
+package entity
+
+type ProductivityInfo struct {
+	Id        int    `db:"id"`
+	GlobalId  int    `db:""global_id`
+	PDate     string `db:"pdate"`
+	TimeRange string `db:"time_range"`
+	Num       int    `db:"num"`
+	RemainNum int    `db:"remain_num"`
+	UpdatedAt string `db:"updated_at"`
+}

+ 9 - 0
entity/productivity_config.go

@@ -0,0 +1,9 @@
+package entity
+
+type ProductivityConfig struct {
+	Id        int    `db:"id"`
+	Name      string `db:"name"`
+	City      string `db:"city"`
+	Num       int    `db:"num"`
+	UpdatedAt string `db:"updated_at"`
+}

+ 16 - 0
entity/queue_notice.go

@@ -0,0 +1,16 @@
+package entity
+
+import "gopkg.in/guregu/null.v3"
+
+type QueueNotice struct {
+	Id           uint        `db:"id" json:"id"`
+	OrderId      string      `db:"order_id" json:"order_id"`
+	Company      string      `db:"company" json:"company"`
+	Name         string      `db:"name" json:"name"`
+	CustomMobile string      `db:"custom_mobile" json:"custom_mobile"`
+	Product      string      `db:"product" json:"product"`
+	OnSiteDate   string      `db:"onsitedate" json:"on_site_date"`
+	IsAllNotice  string      `db:"isallnotice" json:"is_all_notice"`
+	AllSentTime  null.String `db:"all_sent_time" json:"all_sent_time"`
+	Address      null.String `db:"address" json:"address"`
+}

+ 17 - 0
entity/sms_code.go

@@ -0,0 +1,17 @@
+package entity
+
+import "time"
+
+type SMSCode struct {
+	Code      string `db:"code"`
+	Mobile    string `db:"mobile"`
+	CodeType  int    `db:"code_type"`
+	IsUsed    int    `db:"is_used"`
+	CreatedAt string `db:"created_at"`
+	UpdatedAt string `db:"updated_at"`
+}
+
+func (code *SMSCode) IsExpired(period time.Duration) bool {
+	cat, _ := time.Parse("2006-01-02 15:04:05", code.CreatedAt)
+	return cat.Add(period).Format("2006-01-02 15:04:05") < time.Now().Format("2006-01-02 15:04:05")
+}

+ 8 - 0
entity/tag.go

@@ -0,0 +1,8 @@
+package entity
+
+type Tag struct {
+	Name      string `db:"tag_name" json:"name"`
+	Id        int    `db:"id" json:"id"`
+	ParentId  int    `db:"parent_id" json:"pid"`
+	CreatedAt string `db:"created_at" json"-"`
+}

+ 40 - 0
entity/user.go

@@ -0,0 +1,40 @@
+package entity
+
+import "gopkg.in/guregu/null.v3"
+
+type User struct {
+	Id            int64  `db:"id"`                     //编号:w
+	Gender        int    `db:"gender"`                 //性别
+	Mobile        string `db:"mobile"`                 //手机号
+	Name          string `db:"name"`                   //昵称
+	Age           int    `db:"age"`                    //真实姓名
+	Password      string `db:"password" json:"-"`      //用户密码
+	PasswordSalt  string `db:"password_salt" json:"-"` //密码盐值
+	Status        int    `db:"status"`                 //用户状态
+	CreatedAt     string `db:"created_at"`             //创建日期
+	Extra         string `db:"extra"`                  //普通账户时按需存储,或存储第三方账户信息
+	AccountType   uint   `db:"account_type"`           //账户类型
+	Avatar        string `db:"avatar"`
+	IsAcceptProto string `db:"is_accept_up"`
+	IsNew         bool   `json:"is_new"`
+	Height        int    `db:"height"`   //身高
+	Weight        int    `db:"weight"`   //体重
+	BirthDay      string `db:"birthday"` //生日
+	Hobby         string `db:"hobby"`    //喜好
+}
+type UserDB struct {
+	Id            int64       `db:"id"`                     //编号:w
+	Gender        null.Int    `db:"gender"`                 //性别
+	Mobile        string      `db:"mobile"`                 //手机号
+	Name          null.String `db:"name"`                   //昵称
+	Age           null.Int    `db:"age"`                    //真实姓名
+	Password      string      `db:"password" json:"-"`      //用户密码
+	PasswordSalt  string      `db:"password_salt" json:"-"` //密码盐值
+	Status        int         `db:"status"`                 //用户状态
+	CreatedAt     string      `db:"created_at"`             //创建日期
+	Extra         null.String `db:"extra"`
+	AccountType   uint        `db:"account_type"`
+	Avatar        string      `db:"avatar"`
+	IsAcceptProto string      `db:"is_accept_up"`
+	IsNew         bool        `json:"is_new"`
+}

+ 52 - 0
entity/user_linker.go

@@ -0,0 +1,52 @@
+package entity
+
+import "gopkg.in/guregu/null.v3"
+
+type UserLinker struct {
+	Id            int     `db:"id"`
+	CustomId      int     `db:"custom_id"`
+	Name          string  `db:"name"` //联系人姓名
+	Gender        int     `db:"gender"`
+	Mobile        string  `db:"mobile"`
+	Age           int     `db:"age"`
+	Birthday      string  `db:"birthday"`
+	Province      string  `db:"province"`
+	CityId        int     `db:"city_id"`
+	City          string  `db:"city"`
+	County        string  `db:"county"`
+	CountyId      int     `db:"county_id"`
+	Address       string  `db:"address"`
+	DetailAddress string  `db:"detail_address"`
+	Long          float32 `db:"longitude"`
+	Lat           float32 `db:"latitude"`
+	IsDefault     int     `db:"is_default"`
+	CreatedAt     string  `db:"created_at"`
+	UpdatedAt     string  `db:"updated_at"`
+	RelId         int     `db:"rel_id"`
+	IdNumber      string  `db:"id_number",json:"IdNumber"`
+	IdType        string  `db:"id_type",json:"IdType"`
+}
+type UserLinkerDB struct {
+	Id            int         `db:"id"`
+	CustomId      int         `db:"custom_id"`
+	Name          string      `db:"name"` //联系人姓名
+	Gender        int         `db:"gender"`
+	Mobile        string      `db:"mobile"`
+	Age           int         `db:"age"`
+	Birthday      null.String `db:"birthday"`
+	Province      null.String `db:"province"`
+	CityId        int         `db:"city_id"`
+	City          null.String `db:"city"`
+	CountyId      int         `db:"county_id"`
+	County        null.String `db:"county"`
+	Address       null.String `db:"address"`
+	DetailAddress null.String `db:"detail_address"`
+	Long          null.Float  `db:"longitude"`
+	Lat           null.Float  `db:"latitude"`
+	RelId         null.Int    `db:"rel_id"`
+	IsDefault     int         `db:"is_default"`
+	CreatedAt     string      `db:"created_at"`
+	UpdatedAt     string      `db:"updated_at"`
+	IdNumber      string      `db:"id_number"`
+	IdType        string      `db:"id_type"`
+}

+ 10 - 0
entity/user_linker_rel.go

@@ -0,0 +1,10 @@
+package entity
+
+type UserLinkerRel struct {
+	Id             int    `db:"id" json:"id"`
+	Relationship   string `db:"relationship" json:"relationship"`
+	Avatar         string `db:"avatar" json:"avatar"`
+	AvatarGray     string `db:"avatar_gray" json:"avatar_gray"`
+	AvatarSmall    string `db:"avatar_small" json:"avatar_small"`
+	RelationshipEn string `db:"relationship_en" json:"relationship_en"`
+}

+ 40 - 0
go.mod

@@ -0,0 +1,40 @@
+module xiaoniaokuaiyan.com/xiaoniao
+
+go 1.14
+
+require (
+	git.xiaoniaokuaiyan.com/qiaozhi/xn-mercator v1.0.4
+	github.com/blevesearch/bleve v1.0.7
+	github.com/boltdb/bolt v1.3.1
+	github.com/cznic/b v0.0.0-20181122101859-a26611c4d92d // indirect
+	github.com/cznic/mathutil v0.0.0-20181122101859-297441e03548 // indirect
+	github.com/cznic/strutil v0.0.0-20181122101858-275e90344537 // indirect
+	github.com/dgrijalva/jwt-go v3.2.0+incompatible
+	github.com/facebookgo/ensure v0.0.0-20200202191622-63f1cf65ac4c // indirect
+	github.com/facebookgo/stack v0.0.0-20160209184415-751773369052 // indirect
+	github.com/facebookgo/subset v0.0.0-20200203212716-c811ad88dec4 // indirect
+	github.com/go-ini/ini v1.55.0
+	github.com/go-kit/kit v0.10.0
+	github.com/go-sql-driver/mysql v1.5.0
+	github.com/go-zoo/bone v1.3.0
+	github.com/golang/protobuf v1.4.1 // indirect
+	github.com/jmhodges/levigo v1.0.0 // indirect
+	github.com/jmoiron/sqlx v1.2.0
+	github.com/leeqvip/gophp v1.0.0
+	github.com/pborman/uuid v1.2.0
+	github.com/qiniu/iconv v0.0.0-20160413084200-e9ee0ddd1a3a
+	github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 // indirect
+	github.com/robfig/cron v1.2.0
+	github.com/smartwalle/alipay/v3 v3.1.7
+	github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c // indirect
+	github.com/yanyiwu/gojieba v1.1.2
+	golang.org/x/net v0.0.0-20200506145744-7e3656a0809f
+	google.golang.org/grpc v1.29.1
+	gopkg.in/bufio.v1 v1.0.0-20140618132640-567b2bfa514e // indirect
+	gopkg.in/guregu/null.v3 v3.5.0
+	gopkg.in/ini.v1 v1.55.0 // indirect
+	gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22
+	gopkg.in/redis.v2 v2.3.2
+)
+
+replace github.com/qiniu/iconv => github.com/silenceqi/iconv v1.1.1

+ 526 - 0
go.sum

@@ -0,0 +1,526 @@
+cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
+cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
+git.xiaoniaokuaiyan.com/qiaozhi/xn-mercator v1.0.4 h1:U4pC2EdTCmGqikwRNOn7bLHzqklUK2wY6Z0d9BUBQVI=
+git.xiaoniaokuaiyan.com/qiaozhi/xn-mercator v1.0.4/go.mod h1:pT4e64MeuGrTVayFOrp4loh1mgHrbojAtusrWe4SP+g=
+github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
+github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
+github.com/RoaringBitmap/roaring v0.4.21 h1:WJ/zIlNX4wQZ9x8Ey33O1UaD9TCTakYsdLFSBcTwH+8=
+github.com/RoaringBitmap/roaring v0.4.21/go.mod h1:D0gp8kJQgE1A4LQ5wFLggQEyvDi06Mq5mKs52e1TwOo=
+github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo=
+github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
+github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g=
+github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c=
+github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
+github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
+github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
+github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
+github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
+github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
+github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
+github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
+github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
+github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
+github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A=
+github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU=
+github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
+github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g=
+github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
+github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
+github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
+github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
+github.com/blevesearch/bleve v1.0.7 h1:4PspZE7XABMSKcVpzAKp0E05Yer1PIYmTWk+1ngNr/c=
+github.com/blevesearch/bleve v1.0.7/go.mod h1:3xvmBtaw12Y4C9iA1RTzwWCof5j5HjydjCTiDE2TeE0=
+github.com/blevesearch/blevex v0.0.0-20190916190636-152f0fe5c040 h1:SjYVcfJVZoCfBlg+fkaq2eoZHTf5HaJfaTeTkOtyfHQ=
+github.com/blevesearch/blevex v0.0.0-20190916190636-152f0fe5c040/go.mod h1:WH+MU2F4T0VmSdaPX+Wu5GYoZBrYWdOZWSjzvYcDmqQ=
+github.com/blevesearch/go-porterstemmer v1.0.3 h1:GtmsqID0aZdCSNiY8SkuPJ12pD4jI+DdXTAn4YRcHCo=
+github.com/blevesearch/go-porterstemmer v1.0.3/go.mod h1:angGc5Ht+k2xhJdZi511LtmxuEf0OVpvUUNrwmM1P7M=
+github.com/blevesearch/mmap-go v1.0.2 h1:JtMHb+FgQCTTYIhtMvimw15dJwu1Y5lrZDMOFXVWPk0=
+github.com/blevesearch/mmap-go v1.0.2/go.mod h1:ol2qBqYaOUsGdm7aRMRrYGgPvnwLe6Y+7LMvAB5IbSA=
+github.com/blevesearch/segment v0.9.0 h1:5lG7yBCx98or7gK2cHMKPukPZ/31Kag7nONpoBt22Ac=
+github.com/blevesearch/segment v0.9.0/go.mod h1:9PfHYUdQCgHktBgvtUOF4x+pc4/l8rdH0u5spnW85UQ=
+github.com/blevesearch/snowballstem v0.9.0 h1:lMQ189YspGP6sXvZQ4WZ+MLawfV8wOmPoD/iWeNXm8s=
+github.com/blevesearch/snowballstem v0.9.0/go.mod h1:PivSj3JMc8WuaFkTSRDW2SlrulNWPl4ABg1tC/hlgLs=
+github.com/blevesearch/zap/v11 v11.0.7 h1:nnmAOP6eXBkqEa1Srq1eqA5Wmn4w+BZjLdjynNxvd+M=
+github.com/blevesearch/zap/v11 v11.0.7/go.mod h1:bJoY56fdU2m/IP4LLz/1h4jY2thBoREvoqbuJ8zhm9k=
+github.com/blevesearch/zap/v12 v12.0.7 h1:y8FWSAYkdc4p1dn4YLxNNr1dxXlSUsakJh2Fc/r6cj4=
+github.com/blevesearch/zap/v12 v12.0.7/go.mod h1:70DNK4ZN4tb42LubeDbfpp6xnm8g3ROYVvvZ6pEoXD8=
+github.com/boltdb/bolt v1.3.1 h1:JQmyP4ZBrce+ZQu0dY660FMfatumYDLun9hBCUVIkF4=
+github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps=
+github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ=
+github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
+github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
+github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
+github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE=
+github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
+github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
+github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8=
+github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI=
+github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
+github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=
+github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
+github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
+github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
+github.com/couchbase/ghistogram v0.1.0/go.mod h1:s1Jhy76zqfEecpNWJfWUiKZookAFaiGOEoyzgHt9i7k=
+github.com/couchbase/moss v0.1.0/go.mod h1:9MaHIaRuy9pvLPUJxB8sh8OrLfyDczECVL37grCIubs=
+github.com/couchbase/vellum v1.0.1 h1:qrj9ohvZedvc51S5KzPfJ6P6z0Vqzv7Lx7k3mVc2WOk=
+github.com/couchbase/vellum v1.0.1/go.mod h1:FcwrEivFpNi24R3jLOs3n+fs5RnuQnQqCLBJ1uAg1W4=
+github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
+github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
+github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
+github.com/cznic/b v0.0.0-20181122101859-a26611c4d92d h1:SwD98825d6bdB+pEuTxWOXiSjBrHdOl/UVp75eI7JT8=
+github.com/cznic/b v0.0.0-20181122101859-a26611c4d92d/go.mod h1:URriBxXwVq5ijiJ12C7iIZqlA69nTlI+LgI6/pwftG8=
+github.com/cznic/mathutil v0.0.0-20181122101859-297441e03548 h1:iwZdTE0PVqJCos1vaoKsclOGD3ADKpshg3SRtYBbwso=
+github.com/cznic/mathutil v0.0.0-20181122101859-297441e03548/go.mod h1:e6NPNENfs9mPDVNRekM7lKScauxd5kXTr1Mfyig6TDM=
+github.com/cznic/strutil v0.0.0-20181122101858-275e90344537 h1:MZRmHqDBd0vxNwenEbKSQqRVT24d3C05ft8kduSwlqM=
+github.com/cznic/strutil v0.0.0-20181122101858-275e90344537/go.mod h1:AHHPPPXTw0h6pVabbcbyGRK1DckRn7r/STdZEeIDzZc=
+github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
+github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
+github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
+github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
+github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
+github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU=
+github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
+github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M=
+github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g=
+github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
+github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
+github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
+github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
+github.com/facebookgo/ensure v0.0.0-20200202191622-63f1cf65ac4c h1:8ISkoahWXwZR41ois5lSJBSVw4D0OV19Ht/JSTzvSv0=
+github.com/facebookgo/ensure v0.0.0-20200202191622-63f1cf65ac4c/go.mod h1:Yg+htXGokKKdzcwhuNDwVvN+uBxDGXJ7G/VN1d8fa64=
+github.com/facebookgo/stack v0.0.0-20160209184415-751773369052 h1:JWuenKqqX8nojtoVVWjGfOF9635RETekkoH6Cc9SX0A=
+github.com/facebookgo/stack v0.0.0-20160209184415-751773369052/go.mod h1:UbMTZqLaRiH3MsBH8va0n7s1pQYcu3uTb8G4tygF4Zg=
+github.com/facebookgo/subset v0.0.0-20200203212716-c811ad88dec4 h1:7HZCaLC5+BZpmbhCOZJ293Lz68O7PYrF2EzeiFMwCLk=
+github.com/facebookgo/subset v0.0.0-20200203212716-c811ad88dec4/go.mod h1:5tD+neXqOorC30/tWg0LCSkrqj/AR6gu8yY8/fpw1q0=
+github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
+github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4=
+github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20=
+github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
+github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
+github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
+github.com/glycerine/go-unsnap-stream v0.0.0-20181221182339-f9677308dec2 h1:Ujru1hufTHVb++eG6OuNDKMxZnGIvF6o/u8q/8h2+I4=
+github.com/glycerine/go-unsnap-stream v0.0.0-20181221182339-f9677308dec2/go.mod h1:/20jfyN9Y5QPEAprSgKAUr+glWDY39ZiUEAYOEv5dsE=
+github.com/glycerine/goconvey v0.0.0-20190410193231-58a59202ab31 h1:gclg6gY70GLy3PbkQ1AERPfmLMMagS60DKF78eWwLn8=
+github.com/glycerine/goconvey v0.0.0-20190410193231-58a59202ab31/go.mod h1:Ogl1Tioa0aV7gstGFO7KhffUsb9M4ydbEbbxpcEDc24=
+github.com/go-ini/ini v1.55.0 h1:0wVcG9udk2C3TGgmdIGKK9ScOZHZB5nbG+gwji9fhhc=
+github.com/go-ini/ini v1.55.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8=
+github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
+github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
+github.com/go-kit/kit v0.10.0 h1:dXFJfIHVvUcpSgDOV+Ne6t7jXri8Tfv2uOLHUZ2XNuo=
+github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o=
+github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
+github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
+github.com/go-logfmt/logfmt v0.5.0 h1:TrB8swr/68K7m9CcGut2g3UOihhbcbiMAYiuTXdEih4=
+github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
+github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
+github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs=
+github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
+github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk=
+github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
+github.com/go-zoo/bone v1.3.0 h1:PY6sHq37FnQhj+4ZyqFIzJQHvrrGx0GEc3vTZZC/OsI=
+github.com/go-zoo/bone v1.3.0/go.mod h1:HI3Lhb7G3UQcAwEhOJ2WyNcsFtQX1WYHa0Hl4OBbhW8=
+github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s=
+github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
+github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
+github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
+github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
+github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
+github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
+github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
+github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
+github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
+github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
+github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
+github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
+github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
+github.com/golang/protobuf v1.4.1 h1:ZFgWrT+bLgsYPirOnRfKLYJLvssAegOj/hgyMFdJZe0=
+github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
+github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
+github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4=
+github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
+github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
+github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
+github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
+github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
+github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
+github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
+github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
+github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
+github.com/google/uuid v1.0.0 h1:b4Gk+7WdP/d3HZH8EJsZpvV7EtDOgaZLtnaNGIu1adA=
+github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
+github.com/gopherjs/gopherjs v0.0.0-20190910122728-9d188e94fb99 h1:twflg0XRTjwKpxb/jFExr4HGq6on2dEOmnL6FV+fgPw=
+github.com/gopherjs/gopherjs v0.0.0-20190910122728-9d188e94fb99/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
+github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
+github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
+github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
+github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
+github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
+github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
+github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
+github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE=
+github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
+github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
+github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
+github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
+github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
+github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
+github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU=
+github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU=
+github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=
+github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
+github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
+github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
+github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90=
+github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
+github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
+github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
+github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
+github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ=
+github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=
+github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
+github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
+github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
+github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg=
+github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
+github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo=
+github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
+github.com/jmhodges/levigo v1.0.0 h1:q5EC36kV79HWeTBWsod3mG11EgStG3qArTKcvlksN1U=
+github.com/jmhodges/levigo v1.0.0/go.mod h1:Q6Qx+uH3RAqyK4rFQroq9RL7mdkABMcfhEI+nNuzMJQ=
+github.com/jmoiron/sqlx v1.2.0 h1:41Ip0zITnmWNR/vHV+S4m+VoUivnWY5E4OJfLZjCJMA=
+github.com/jmoiron/sqlx v1.2.0/go.mod h1:1FEQNm3xlJgrMD+FBdI9+xvCksHtbpVBBw5dYhBSsks=
+github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
+github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
+github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
+github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
+github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
+github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
+github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
+github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
+github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
+github.com/kljensen/snowball v0.6.0/go.mod h1:27N7E8fVU5H68RlUmnWwZCfxgt4POBJfENGMvNRhldw=
+github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
+github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
+github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
+github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
+github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
+github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
+github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
+github.com/leeqvip/gophp v1.0.0 h1:lzWOECV3vkXjzrwoOVYyrfcAfOH+9BqIZLDIwxffy8o=
+github.com/leeqvip/gophp v1.0.0/go.mod h1:DRoO5E9Sk+t4/3LGPCH4QZ/arcASXk9VsqdeTXLgYC4=
+github.com/lib/pq v1.0.0 h1:X5PMW56eZitiTeO7tKzZxFCSpbFZJtkMMooicw2us9A=
+github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
+github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM=
+github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4=
+github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ=
+github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
+github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
+github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
+github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
+github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
+github.com/mattn/go-sqlite3 v1.9.0 h1:pDRiWfl+++eC2FEFRy6jXmQlvp4Yh3z1MJKg4UeYM/4=
+github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
+github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
+github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
+github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
+github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
+github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
+github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
+github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg=
+github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
+github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
+github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
+github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
+github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
+github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
+github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
+github.com/mschoch/smat v0.0.0-20160514031455-90eadee771ae/go.mod h1:qAyveg+e4CE+eKJXWVjKXM4ck2QobLqTDytGJbLLhJg=
+github.com/mschoch/smat v0.2.0 h1:8imxQsjDm8yFEAVBe7azKmKSgzSkZXDuKkSq9374khM=
+github.com/mschoch/smat v0.2.0/go.mod h1:kc9mz7DoBKqDyiRL7VZN8KvXQMWeTaVnttLRXOlotKw=
+github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
+github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg=
+github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU=
+github.com/nats-io/nats-server/v2 v2.1.2/go.mod h1:Afk+wRZqkMQs/p45uXdrVLuab3gwv3Z8C4HTBu8GD/k=
+github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w=
+github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
+github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
+github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
+github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs=
+github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA=
+github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
+github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
+github.com/onsi/ginkgo v1.7.0 h1:WSHQ+IS43OoUrWtD1/bbclrwK8TTH5hzp+umCiuxHgs=
+github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
+github.com/onsi/gomega v1.4.3 h1:RE1xgDvH7imwFD45h+u2SgIfERHlS2yNG4DObb5BSKU=
+github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
+github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk=
+github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis=
+github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74=
+github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
+github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
+github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxSfWAKL3wpBW7V8scJMt8N8gnaMCS9E/cA=
+github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw=
+github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=
+github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=
+github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM=
+github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
+github.com/pborman/uuid v1.2.0 h1:J7Q5mO4ysT1dv8hyrUGHb9+ooztCXu1D8MY8DZYsu3g=
+github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
+github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
+github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac=
+github.com/philhofer/fwd v1.0.0 h1:UbZqGr5Y38ApvM/V/jEljVxwocdweyH+vmYvRPBnbqQ=
+github.com/philhofer/fwd v1.0.0/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU=
+github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc=
+github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
+github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA=
+github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
+github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
+github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs=
+github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
+github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og=
+github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
+github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
+github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
+github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
+github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
+github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
+github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
+github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA=
+github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
+github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
+github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
+github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
+github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
+github.com/rcrowley/go-metrics v0.0.0-20190826022208-cac0b30c2563/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
+github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 h1:OdAsTTz6OkFY5QxjkYwrChwuRruF69c169dPK26NUlk=
+github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
+github.com/robfig/cron v1.2.0 h1:ZjScXvvxeQ63Dbyxy76Fj3AT3Ut0aKsyd2/tl3DTMuQ=
+github.com/robfig/cron v1.2.0/go.mod h1:JGuDeoQd7Z6yL4zQhZ3OPEVHB7fL6Ka6skscFHfmt2k=
+github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
+github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
+github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
+github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
+github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
+github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E=
+github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
+github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
+github.com/silenceqi/iconv v1.1.1 h1:xEZCQmrZK33sTST6peZxbiaLJw8FnMGrb7asHeQ4OOg=
+github.com/silenceqi/iconv v1.1.1/go.mod h1:r2w8A68UNNJK4np1fKZm04c8Pbqbw9m00ch7VtDGF8A=
+github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
+github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
+github.com/smartwalle/alipay/v3 v3.1.7 h1:J4U5slABafKVD/b9gPCZe/3HAPB8Pa2NOYOPcugEJBo=
+github.com/smartwalle/alipay/v3 v3.1.7/go.mod h1:cZUMCCnsux9YAxA0/f3PWUR+7wckWtE1BqxbVRtGij0=
+github.com/smartwalle/crypto4go v1.0.2 h1:9DUEOOsPhmp00438L4oBdcL8EZG1zumecft5bWj5phI=
+github.com/smartwalle/crypto4go v1.0.2/go.mod h1:LQ7vCZIb7BE5+MuMtJBuO8ORkkQ01m4DXDBWPzLbkMY=
+github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
+github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
+github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s=
+github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
+github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
+github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY=
+github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
+github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
+github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
+github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
+github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
+github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
+github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
+github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
+github.com/steveyen/gtreap v0.1.0 h1:CjhzTa274PyJLJuMZwIzCO1PfC00oRa8d1Kc78bFXJM=
+github.com/steveyen/gtreap v0.1.0/go.mod h1:kl/5J7XbrOmlIbYIXdRHDDE5QxHqpk0cmkT7Z4dM9/Y=
+github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw=
+github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw=
+github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI=
+github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
+github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
+github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
+github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
+github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE=
+github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ=
+github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c h1:g+WoO5jjkqGAzHWCjJB1zZfXPIAaDpzXIEJ0eS6B5Ok=
+github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c/go.mod h1:ahpPrc7HpcfEWDQRZEmnXMzHY03mLDYMCxeDzy46i+8=
+github.com/tinylib/msgp v1.1.0 h1:9fQd+ICuRIu/ue4vxJZu6/LzxN0HwMds2nq/0cFvxHU=
+github.com/tinylib/msgp v1.1.0/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE=
+github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
+github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
+github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
+github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
+github.com/willf/bitset v1.1.10 h1:NotGKqX0KwQ72NUzqrjZq5ipPNDQex9lo3WpaS8L2sc=
+github.com/willf/bitset v1.1.10/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4=
+github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
+github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
+github.com/yanyiwu/gojieba v1.1.2 h1:BMwKCwg3G+Nw/Ctqzm/gNgN/6Ljf0Y4f7ddKlzTA+TM=
+github.com/yanyiwu/gojieba v1.1.2/go.mod h1:54wkP7sMJ6bklf7yPl6F+JG71dzVUU1WigZbR47nGdY=
+go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
+go.etcd.io/bbolt v1.3.4 h1:hi1bXHMVrlQh6WwxAy+qZCV/SYIlqo+Ushwdpa4tAKg=
+go.etcd.io/bbolt v1.3.4/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ=
+go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg=
+go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
+go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
+go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
+go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
+go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
+go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
+go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4=
+go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA=
+go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
+go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM=
+golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
+golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
+golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
+golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20190506204251-e1dfcc566284/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 h1:ObdrDkeb4kJdCP557AjRjq69pTHfNouLtWZG7j9rPN8=
+golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
+golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
+golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
+golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
+golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
+golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
+golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
+golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
+golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
+golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200506145744-7e3656a0809f h1:QBjCr1Fz5kw158VqdE9JfI9cJnl/ymnJWAdMuinqL7Y=
+golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
+golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
+golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
+golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20181221143128-b4a75ba826a6/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884=
+golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
+golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
+golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
+golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
+golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
+golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
+golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
+golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
+golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk=
+google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
+google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
+google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
+google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
+google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
+google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
+google.golang.org/genproto v0.0.0-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s=
+google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
+google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
+google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
+google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM=
+google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
+google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
+google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
+google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
+google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
+google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
+google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
+google.golang.org/grpc v1.29.1 h1:EC2SB8S04d2r73uptxphDSUG+kTKVgjRPF+N3xpxRB4=
+google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
+google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
+google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
+google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
+google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
+google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
+google.golang.org/protobuf v1.22.0 h1:cJv5/xdbk1NnMPR1VP9+HU6gupuG9MLBoH1r6RHZ2MY=
+google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
+gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
+gopkg.in/bufio.v1 v1.0.0-20140618132640-567b2bfa514e h1:wGA78yza6bu/mWcc4QfBuIEHEtc06xdiU0X8sY36yUU=
+gopkg.in/bufio.v1 v1.0.0-20140618132640-567b2bfa514e/go.mod h1:xsQCaysVCudhrYTfzYWe577fCe7Ceci+6qjO2Rdc0Z4=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
+gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw=
+gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
+gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
+gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
+gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o=
+gopkg.in/guregu/null.v3 v3.5.0 h1:xTcasT8ETfMcUHn0zTvIYtQud/9Mx5dJqD554SZct0o=
+gopkg.in/guregu/null.v3 v3.5.0/go.mod h1:E4tX2Qe3h7QdL+uZ3a0vqvYwKQsRSQKM5V4YltdgH9Y=
+gopkg.in/ini.v1 v1.55.0 h1:E8yzL5unfpW3M6fz/eB7Cb5MQAYSZ7GKo4Qth+N2sgQ=
+gopkg.in/ini.v1 v1.55.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
+gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22 h1:VpOs+IwYnYBaFnrNAeB8UUWtL3vEUnzSCL1nVjPhqrw=
+gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA=
+gopkg.in/redis.v2 v2.3.2 h1:GPVIIB/JnL1wvfULefy3qXmPu1nfNu2d0yA09FHgwfs=
+gopkg.in/redis.v2 v2.3.2/go.mod h1:4wl9PJ/CqzeHk3LVq1hNLHH8krm3+AXEgut4jVc++LU=
+gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
+gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
+gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
+gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
+gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
+gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
+gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
+honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
+honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
+honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
+sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
+sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU=

+ 623 - 0
logging_middleware.go

@@ -0,0 +1,623 @@
+package main
+
+import (
+	"encoding/json"
+	"io"
+	"net/http"
+	"reflect"
+	"time"
+
+	"github.com/go-kit/kit/endpoint"
+	"github.com/go-kit/kit/log"
+	httptransport "github.com/go-kit/kit/transport/http"
+	"xiaoniaokuaiyan.com/xiaoniao/cerror"
+	"xiaoniaokuaiyan.com/xiaoniao/entity"
+	"xiaoniaokuaiyan.com/xiaoniao/search"
+	"xiaoniaokuaiyan.com/xiaoniao/server"
+)
+
+type loggingMiddleware struct {
+	server.UserService
+	server.AuthService
+	server.SearchService
+	server.FileService
+	server.OrderService
+	server.SMSService
+	server.CartService
+	server.CouponService
+	server.ProductivityService
+	server.WeixinService
+	server.CityService
+	server.UserLinkerService
+	server.ProductService
+	server.DeliverUserService
+	server.SystemService
+	server.ActivityService
+	server.GroupBloodService
+	server.PayService
+	server.JDLService
+	log.Logger
+}
+
+//type ServiceMethod func(interface{}) (interface{}, error)
+
+func (m loggingMiddleware) Login(params map[string]string) (v interface{}, err error) {
+	defer func(begin time.Time) {
+		vbytes, _ := json.Marshal(v)
+		m.Logger.Log(
+			"method", "UserService.Login",
+			"mobile", params["mobile"],
+			"password", params["password"],
+			"v", string(vbytes),
+			"took", time.Since(begin),
+		)
+	}(time.Now())
+	v, err = m.UserService.Login(params)
+	return
+}
+
+func (m loggingMiddleware) LoginV2(params map[string]string) (v interface{}, err error) {
+	defer func(begin time.Time) {
+		vbytes, _ := json.Marshal(v)
+		m.Logger.Log(
+			"method", "UserService.LoginV2",
+			"mobile", params["mobile"],
+			"password", params["password"],
+			"v", string(vbytes),
+			"took", time.Since(begin),
+		)
+	}(time.Now())
+	v, err = m.UserService.LoginV2(params)
+	return
+}
+
+func (m loggingMiddleware) GetHomeInvite(params map[string]string) (v interface{}, err error) {
+	defer func(begin time.Time) {
+		vbytes, _ := json.Marshal(v)
+		m.Logger.Log(
+			"method", "UserService.GetHomeInvite",
+			"mobile", params["mobile"],
+			"password", params["password"],
+			"v", string(vbytes),
+			"took", time.Since(begin),
+		)
+	}(time.Now())
+	v, err = m.UserService.GetHomeInvite(params)
+	return
+}
+
+func (m loggingMiddleware) Regist(mobile, password, vcode string) (v interface{}, err error) {
+	defer func(begin time.Time) {
+		m.Logger.Log(
+			"method", "UserService.Regist",
+			"mobile", mobile,
+			"took", time.Since(begin),
+		)
+	}(time.Now())
+	v, err = m.UserService.Regist(mobile, password, vcode)
+	return
+}
+
+func (m loggingMiddleware) ResetPwd(userName, password, newPassword string) (interface{}, error) {
+	defer func(begin time.Time) {
+		m.Logger.Log(
+			"method", "UserService.ResetPwd",
+			"mobile", userName,
+			"took", time.Since(begin),
+		)
+	}(time.Now())
+	return m.UserService.ResetPwd(userName, password, newPassword)
+}
+
+func (m loggingMiddleware) ForgetPwd(userName, vcode, newPassword string) (interface{}, error) {
+	defer func(begin time.Time) {
+		m.Logger.Log(
+			"method", "UserService.ForgetPwd",
+			"mobile", userName,
+			"took", time.Since(begin),
+		)
+	}(time.Now())
+	return m.UserService.ForgetPwd(userName, vcode, newPassword)
+}
+
+func (m loggingMiddleware) SetOpenid(mobile, openid string, wxType string) (interface{}, error) {
+	defer func(begin time.Time) {
+		m.Logger.Log(
+			"method", "UserService.SetOpenid",
+			"mobile", mobile,
+			"Openid", openid,
+			"took", time.Since(begin),
+		)
+	}(time.Now())
+	return m.UserService.SetOpenid(mobile, openid, wxType)
+}
+
+func (m loggingMiddleware) GetQueueNotice(mobile string) (interface{}, error) {
+	return m.UserService.GetQueueNotice(mobile)
+}
+
+func (m loggingMiddleware) UpdateQueueNotice(notice *entity.QueueNotice) (interface{}, error) {
+	return m.UserService.UpdateQueueNotice(notice)
+}
+
+func (m loggingMiddleware) SendSMS(mobile string, smsType int, params map[string]string) (interface{}, error) {
+	defer func(begin time.Time) {
+		m.Logger.Log(
+			"method", "SMSService.SendSMS",
+			"mobile", mobile,
+			"type", smsType,
+			"took", time.Since(begin),
+		)
+	}(time.Now())
+	return m.SMSService.SendSMS(mobile, smsType, params)
+}
+func (m loggingMiddleware) ValidateCode(mobile, code string, codeType int) (interface{}, error) {
+	return m.SMSService.ValidateCode(mobile, code, codeType)
+}
+
+func (m loggingMiddleware) GetAccessToken(tokenStr string) (v interface{}, err error) {
+	defer func(begin time.Time) {
+		vbuf, _ := json.Marshal(v)
+		m.Logger.Log(
+			"method", "AuthService.GetAccessToken",
+			"tokenStr", tokenStr,
+			"v", string(vbuf),
+			"took", time.Since(begin),
+		)
+	}(time.Now())
+	v, err = m.AuthService.GetAccessToken(tokenStr)
+	return
+}
+
+func (m loggingMiddleware) Query(param *search.QueryParam, uid int) (interface{}, error) {
+	defer func(begin time.Time) {
+		m.Logger.Log(
+			"method", "SearchService.Query",
+			"text", param.Text,
+			"user_id", uid,
+			"took", time.Since(begin),
+		)
+	}(time.Now())
+	return m.SearchService.Query(param, uid)
+}
+func (m loggingMiddleware) Upload(rd io.Reader) (interface{}, error) {
+	return m.FileService.Upload(rd)
+}
+
+// 订单相关接口开始
+func (m loggingMiddleware) AddOrder(orderItem *entity.Order, cityId int, city string) (result interface{}, err error) {
+	defer func(begin time.Time) {
+		errStr := ""
+		if err != nil {
+			errStr = err.Error()
+		}
+		m.Logger.Log(
+			"method", "OrderService.AddOrder",
+			"orderid", orderItem.Id,
+			"took", time.Since(begin),
+			"error", errStr,
+		)
+	}(time.Now())
+	result, err = m.OrderService.AddOrder(orderItem, cityId, city)
+	return
+}
+
+func (m loggingMiddleware) Pay(orderItem *entity.Order, extra map[string]string) (data interface{}, err error) {
+	defer func(begin time.Time) {
+		var errStr string
+		if err != nil {
+			errStr = err.Error()
+		}
+		m.Logger.Log(
+			"method", "OrderService.Pay",
+			"orderid", orderItem.Id,
+			"took", time.Since(begin),
+			"error", errStr,
+		)
+	}(time.Now())
+	data, err = m.OrderService.Pay(orderItem, extra)
+	return
+}
+func (m loggingMiddleware) UpdateOrder(orderItem *entity.Order, upType string) (interface{}, error) {
+	defer func(begin time.Time) {
+		m.Logger.Log(
+			"method", "OrderService.UpdateOrder",
+			"orderid", orderItem.Id,
+			"took", time.Since(begin),
+		)
+	}(time.Now())
+	return m.OrderService.OrderUpdate(orderItem, upType)
+}
+
+func (m loggingMiddleware) CancelOrder(oid string) (bool, error) {
+	defer func(begin time.Time) {
+		m.Logger.Log(
+			"method", "OrderService.CancelOrder",
+			"orderid", oid,
+			"took", time.Since(begin),
+		)
+	}(time.Now())
+	return m.OrderService.CancelOrder(oid)
+}
+func (m loggingMiddleware) DelOrder(oid string) (bool, error) {
+	defer func(begin time.Time) {
+		m.Logger.Log(
+			"method", "OrderService.DelOrder",
+			"orderid", oid,
+			"took", time.Since(begin),
+		)
+	}(time.Now())
+	return m.OrderService.DelOrder(oid)
+}
+
+func (m loggingMiddleware) FailedOrder(oid string) (bool, error) {
+	defer func(begin time.Time) {
+		m.Logger.Log(
+			"method", "OrderService.FailedOrder",
+			"orderid", oid,
+			"took", time.Since(begin),
+		)
+	}(time.Now())
+	return m.OrderService.FailedOrder(oid)
+}
+func (m loggingMiddleware) ListOrder(customId, pageIndex, pageSize, status int, mobile string, isZFB, isHis bool) (interface{}, error) {
+	defer func(begin time.Time) {
+		m.Logger.Log(
+			"method", "OrderService.ListOrder",
+			"customid", customId,
+			"status", status,
+			"took", time.Since(begin),
+		)
+	}(time.Now())
+	return m.OrderService.ListOrder(customId, pageIndex, pageSize, status, mobile, isZFB, isHis)
+}
+
+func (m loggingMiddleware) OrderDetail(orderId string) (interface{}, error) {
+	defer func(begin time.Time) {
+		m.Logger.Log(
+			"method", "OrderService.OrderDetail",
+			"orderid", orderId,
+			"took", time.Since(begin),
+		)
+	}(time.Now())
+	return m.OrderService.OrderDetail(orderId)
+}
+
+func (m loggingMiddleware) OrderReport(orderId string, otype string) (interface{}, error) {
+	defer func(begin time.Time) {
+		m.Logger.Log(
+			"method", "OrderService.OrderReport",
+			"orderid", orderId,
+			"took", time.Since(begin),
+		)
+	}(time.Now())
+	return m.OrderService.OrderReport(orderId, otype)
+}
+
+func (m loggingMiddleware) Refund(params map[string]string) (interface{}, error) {
+	defer func(begin time.Time) {
+		m.Logger.Log(
+			"method", "OrderService.Refund",
+			"params", params,
+			"took", time.Since(begin),
+		)
+	}(time.Now())
+	return m.OrderService.Refund(params)
+}
+
+//订单相关接口结束
+
+// 购物车相关接口开始
+func (m loggingMiddleware) CartList(customId int) (interface{}, error) {
+	return m.CartService.CartList(customId)
+}
+func (m loggingMiddleware) CartAdd(customId int, productId int, quantity int, isAdd bool) (interface{}, error) {
+
+	defer func(begin time.Time) {
+		m.Logger.Log(
+			"method", "CartService.CartAdd",
+			"customid", customId,
+			"productId", productId,
+			"quantity", quantity,
+			"took", time.Since(begin),
+		)
+	}(time.Now())
+	return m.CartService.CartAdd(customId, productId, quantity, isAdd)
+}
+func (m loggingMiddleware) CartRemove(customId int, productIds []int) (interface{}, error) {
+	defer func(begin time.Time) {
+		m.Logger.Log(
+			"method", "CartService.CartRemove",
+			"customid", customId,
+			"productId", productIds,
+			"took", time.Since(begin),
+		)
+	}(time.Now())
+	return m.CartService.CartRemove(customId, productIds)
+}
+
+//购物车相关接口结束
+
+func (m loggingMiddleware) ListCoupon(mobile string, status, pageIndex, pageSize int) (interface{}, error) {
+	defer func(begin time.Time) {
+		m.Logger.Log(
+			"method", "CouponService.ListCoupon",
+			"mobile", mobile,
+			"took", time.Since(begin),
+		)
+	}(time.Now())
+	return m.CouponService.ListCoupon(mobile, status, pageIndex, pageSize)
+}
+func (m loggingMiddleware) Exchange(codeStr string, customId int, mobile string) (interface{}, cerror.CError) {
+	defer func(begin time.Time) {
+		m.Logger.Log(
+			"method", "CouponService.Exchange",
+			"mobile", mobile,
+			"codeStr", codeStr,
+			"took", time.Since(begin),
+		)
+	}(time.Now())
+	return m.CouponService.Exchange(codeStr, customId, mobile)
+}
+func (m loggingMiddleware) GetCoupon(id int) (interface{}, error) {
+	return m.CouponService.GetCoupon(id)
+}
+
+// 产能相关接口
+func (m loggingMiddleware) PtList(cityId int, fromDay string, ptType int, kongFuType int) (interface{}, error) {
+	defer func(begin time.Time) {
+		m.Logger.Log(
+			"method", "ProductivityService.PtList",
+			"fromDay", fromDay,
+			"pttype", ptType,
+			"kongFuType", kongFuType,
+			"took", time.Since(begin),
+		)
+	}(time.Now())
+	return m.ProductivityService.PtList(cityId, fromDay, ptType, kongFuType)
+}
+
+// 微信相关接口
+func (m loggingMiddleware) GetWXAccessToken(accountType string) (interface{}, error) {
+	defer func(begin time.Time) {
+		m.Logger.Log(
+			"method", "WeixinService.GetAccessToken",
+			"took", time.Since(begin),
+		)
+	}(time.Now())
+	return m.WeixinService.GetWXAccessToken(accountType)
+}
+func (m loggingMiddleware) GetJSAPITicket(accountType string) (interface{}, error) {
+	defer func(begin time.Time) {
+		m.Logger.Log(
+			"method", "WeixinService.GetJSAPITicket",
+			"took", time.Since(begin),
+		)
+	}(time.Now())
+	return m.WeixinService.GetJSAPITicket(accountType)
+}
+
+func (m loggingMiddleware) SendTpl(msg string, accountType string) (result interface{}, err error) {
+	defer func(begin time.Time) {
+		errStr := ""
+		if err != nil {
+			errStr = err.Error()
+		}
+		m.Logger.Log(
+			"method", "WeixinService.SendTpl",
+			"took", time.Since(begin),
+			"msg", msg,
+			"error", errStr,
+		)
+	}(time.Now())
+	result, err = m.WeixinService.SendTpl(msg, accountType)
+	return
+}
+func (m loggingMiddleware) GetOpenCityList() (interface{}, error) {
+	return m.CityService.GetOpenCityList()
+}
+
+func (m loggingMiddleware) GetCityAllList() (interface{}, error) {
+	return m.CityService.GetCityAllList()
+}
+
+// 订单联系人相关接口
+func (m loggingMiddleware) LinkerGet(id, cid int) (interface{}, error) {
+	return m.UserLinkerService.LinkerGet(id, cid)
+}
+func (m loggingMiddleware) LinkerAdd(linker *entity.UserLinker) (interface{}, error) {
+	return m.UserLinkerService.LinkerAdd(linker)
+}
+func (m loggingMiddleware) LinkerUpdate(linker *entity.UserLinker) (interface{}, error) {
+	return m.UserLinkerService.LinkerUpdate(linker)
+}
+func (m loggingMiddleware) LinkerList(cid int) (interface{}, error) {
+	return m.UserLinkerService.LinkerList(cid)
+}
+func (m loggingMiddleware) LinkerDefault(cid int) (interface{}, error) {
+	return m.UserLinkerService.LinkerDefault(cid)
+}
+func (m loggingMiddleware) LinkerDel(linker *entity.UserLinker) (interface{}, error) {
+	return m.UserLinkerService.LinkerDel(linker)
+}
+
+func (m loggingMiddleware) ProductGet(pids []int) (interface{}, error) {
+	return m.ProductService.ProductGet(pids)
+}
+
+func (m loggingMiddleware) GetTags(level, cityId int) (interface{}, error) {
+	return m.ProductService.GetTags(level, cityId)
+}
+func (m loggingMiddleware) GetByTags(tags []string, pageIndex, pageSize uint, cityId int) (interface{}, error) {
+	return m.ProductService.GetByTags(tags, pageIndex, pageSize, cityId)
+}
+
+func (m loggingMiddleware) makeHandler(payloadType reflect.Type, endpointFunc interface{}, decodeFunc httptransport.DecodeRequestFunc, shouldLogin ...bool) http.Handler {
+	vf := reflect.ValueOf(endpointFunc)
+	vp := reflect.ValueOf(m)
+	y := vf.Call([]reflect.Value{vp})[0]
+	if decodeFunc == nil {
+		decodeFunc = server.MakeDecodeRequest(payloadType, shouldLogin...)
+	}
+	return httptransport.NewServer(
+		y.Interface().(endpoint.Endpoint),
+		decodeFunc,
+		server.EncodeResponse,
+		httptransport.ServerErrorLogger(log.With(m.Logger, "transport", "HTTP/JSON")),
+	)
+}
+
+// 20220719 不打印日志,部分信息并没有太大意义。免得日志文件增长过快,
+func (m loggingMiddleware) makeHandlerNoLog(payloadType reflect.Type, endpointFunc interface{}, decodeFunc httptransport.DecodeRequestFunc, shouldLogin ...bool) http.Handler {
+	vf := reflect.ValueOf(endpointFunc)
+	vp := reflect.ValueOf(m)
+	y := vf.Call([]reflect.Value{vp})[0]
+	if decodeFunc == nil {
+		decodeFunc = server.MakeDecodeRequest(payloadType, shouldLogin...)
+	}
+	return httptransport.NewServer(
+		y.Interface().(endpoint.Endpoint),
+		decodeFunc,
+		server.EncodeResponseNoLog,
+		httptransport.ServerErrorLogger(log.With(m.Logger, "transport", "HTTP/JSON")),
+	)
+}
+
+func (m loggingMiddleware) GetMeta() map[string]http.Handler {
+	return map[string]http.Handler{
+		"/user/login":               m.makeHandler(reflect.TypeOf(LoginParam{}), makeLoginEndpoint, nil),
+		"/user/loginV2":             m.makeHandler(reflect.TypeOf(LoginV2Param{}), makeLoginV2Endpoint, nil),
+		"/user/logincoupon":         m.makeHandler(reflect.TypeOf(LoginParam{}), makeLoginCouponsEndpoint, nil),
+		"/user/homeinvite":          m.makeHandler(reflect.TypeOf(LoginV2Param{}), makeGetHomeInviteEndpoint, nil),
+		"/user/saveinfo":            m.makeHandler(reflect.TypeOf(entity.User{}), makeSaveInfoEndpoint, nil, true),
+		"/user/savehobby":           m.makeHandler(reflect.TypeOf(entity.User{}), makeSaveHobbyEndpoint, nil, true),
+		"/user/gethobby":            m.makeHandler(nil, makeGetHobbyEndpoint, nil, false),
+		"/user/regist":              m.makeHandler(reflect.TypeOf(RegistParam{}), makeRegistEndpoint, nil),
+		"/user/resetpwd":            m.makeHandler(reflect.TypeOf(ResetPwdParam{}), makeResetPwdEndpoint, nil, true),
+		"/user/forgetpwd":           m.makeHandler(reflect.TypeOf(RegistParam{}), makeForgetPwdEndpoint, nil),
+		"/user/setopenid":           m.makeHandler(reflect.TypeOf(SetOpenidParam{}), makeSetOpenidEndpoint, nil, true),
+		"/user/notice/get":          m.makeHandler(reflect.TypeOf(entity.QueueNotice{}), makeGetQueueNoticeEndpoint, nil, true),
+		"/user/notice/update":       m.makeHandler(reflect.TypeOf(entity.QueueNotice{}), makeUpdateQueueNoticeEndpoint, nil, true),
+		"/user/relationship":        m.makeHandler(nil, makeGetRelationshipEndpoint, nil, false),
+		"/user/update":              m.makeHandler(reflect.TypeOf(entity.User{}), makeUpdateUinfoEndpoint, nil, true),
+		"/user/wxinfo":              m.makeHandler(reflect.TypeOf(""), makeGetUserWxEndpoint, nil, false),
+		"/auth/token":               m.makeHandler(nil, makeAuthEndpoint, server.DecodeAuthRequest),
+		"/search":                   m.makeHandler(nil, makeSearchEndpoint, nil, false),
+		"/file/upload":              m.makeHandler(nil, makeFileUploadEndpoint, server.DecodeFileRequest),
+		"/order/add":                m.makeHandler(reflect.TypeOf(entity.Order{}), makeAddOrderEndpoint, nil, true),
+		"/order/pay":                m.makeHandler(reflect.TypeOf(entity.Order{}), makePayEndpoint, nil, true),
+
+		"/order/inner/add":          m.makeHandler(reflect.TypeOf(entity.Order{}), makeAddOrderEndpoint, nil, false),
+		"/order/inner/pay":          m.makeHandler(reflect.TypeOf(entity.Order{}), makePayEndpoint, nil, false),
+		"/order/list":               m.makeHandler(reflect.TypeOf(ListOrderParam{}), makeListOrderEndpoint, nil, true),
+		"/order/detail":             m.makeHandler(reflect.TypeOf(DetailOrderParam{}), makeOrderDetailEndpoint, nil, true),
+		"/order/detail/code":        m.makeHandler(reflect.TypeOf(DetailOrderParam{}), makeOrderDetailEndpoint, nil, false),
+		"/order/cancel":             m.makeHandler(reflect.TypeOf(DetailOrderParam{}), makeCancelOrderEndpoint, nil, true),
+		"/order/del":                m.makeHandler(reflect.TypeOf(DetailOrderParam{}), makeDelOrderEndpoint, nil, true),
+		"/order/failed":             m.makeHandler(reflect.TypeOf(DetailOrderParam{}), makeFailedOrderEndpoint, nil, true),
+		"/order/report":             m.makeHandler(reflect.TypeOf(DetailOrderParam{}), makeOrderReportEndpoint, nil),
+		"/order/update":             m.makeHandler(reflect.TypeOf(entity.Order{}), makeOrderUpdateEndpoint, nil, true),
+		"/order/refund":             m.makeHandler(reflect.TypeOf(map[string]string{}), makeRefundEndpoint, nil),
+		"/order/survey":             m.makeHandler(reflect.TypeOf(entity.OrderSurvey{}), makeOrderSurveyEndpoint, nil),
+		"/order/savecbinfo":         m.makeHandler(reflect.TypeOf(entity.OrderCallbackInfo{}), makeSaveCallbackInfoEndpoint, nil),
+		"/order/getcbinfo":          m.makeHandler(reflect.TypeOf(""), makeGetCallbackInfoEndpoint, nil),
+		"/order/payquery":           m.makeHandler(reflect.TypeOf(""), makeOrderPayQueryEndpoint, nil, true),
+		"/order/vaildcount":         m.makeHandler(reflect.TypeOf(ListOrderParam{}), makeOrderVaildCountEndpoint, nil),
+		"/sms/send":                 m.makeHandler(reflect.TypeOf(SMSParam{}), makeSMSSendEndpoint, nil),
+		"/sms/sendworld":            m.makeHandler(reflect.TypeOf(SMSParam{}), makeSMSSendWorldEndpoint, nil),
+		"/sms/validatecode":         m.makeHandler(reflect.TypeOf(VcodeParam{}), makeValidateCodeEndpoint, nil),
+		"/cart/list":                m.makeHandler(reflect.TypeOf(entity.Cart{}), makeCartListEndpoint, nil, true),
+		"/cart/add":                 m.makeHandler(reflect.TypeOf(entity.Cart{}), makeCartAddEndpoint, nil, true),
+		"/cart/remove":              m.makeHandler(reflect.TypeOf(CartParam{}), makeCartRemoveEndpoint, nil, true),
+		"/coupon/list":              m.makeHandler(reflect.TypeOf(CouponListParam{}), makeCouponListEndpoint, nil, true),
+		"/coupon/getbyorderid":      m.makeHandler(reflect.TypeOf(""), makeCouponGetByOrderIdEndpoint, nil, true),
+		"/coupon/exchange":          m.makeHandler(reflect.TypeOf(ExchangeParam{}), makeExchangeEndpoint, nil, true),
+		"/coupon/detail":            m.makeHandler(reflect.TypeOf(int(1)), makeCouponGetEndpoint, nil, true),
+		"/coupon/add":               m.makeHandler(reflect.TypeOf(entity.DiscountTicket{}), makeCouponAddEndpoint, nil, true),
+		"/coupon/queryfcode":        m.makeHandler(reflect.TypeOf(""), makeQueryFcodeEndpoint, nil),
+		"/coupon/actlist":           m.makeHandler(reflect.TypeOf(entity.DiscountActParams{}), makeCouponActListEndpoint, nil),
+		"/coupon/receive":           m.makeHandler(reflect.TypeOf(entity.DiscountReceiveParams{}), makeCouponActReceiveEndpoint, nil),
+		"/wx/token":                 m.makeHandler(nil, makeWXAccessTokenEndpoint, nil),
+		"/wx/jsapi_ticket":          m.makeHandler(nil, makeWXApiTicketEndpoint, nil),
+		"/wx/sendtpl":               m.makeHandler(nil, makeSendTplEndpoint, nil),
+		"/wx/jssdksign":             m.makeHandler(reflect.TypeOf(""), makeWXJsSdkSignEndpoint, nil),
+		"/wx/scanpay":               m.makeHandler(reflect.TypeOf(map[string]string{}), makeWxScanPayEndpoint, nil),
+		"/wx/payreason":             m.makeHandler(nil, makeGetPayReasonEndpoint, nil),
+		"/city/openlist":            m.makeHandler(nil, makeCityOpenListEndpoint, nil),
+		"/city/all":                 m.makeHandlerNoLog(nil, makeCityAllEndpoint, nil),
+		"/city/opencounty":          m.makeHandler(nil, makeCityOpenCountyEndpoint, nil),
+		"/city/infobyid":            m.makeHandler(reflect.TypeOf([]int{}), makeGetCityByIdEndpoint, nil),
+		"/city/county":              m.makeHandler(reflect.TypeOf(int(1)), makeGetCountyByCityIdEndpoint, nil),
+		"/userlinker/get":           m.makeHandler(reflect.TypeOf(entity.UserLinker{}), makeLinkerGetEndpoint, nil, true),
+		"/userlinker/add":           m.makeHandler(reflect.TypeOf(entity.UserLinker{}), makeLinkerAddEndpoint, nil, true),
+		"/userlinker/save":          m.makeHandler(reflect.TypeOf(entity.UserLinker{}), makeLinkerUpdateEndpoint, nil, true),
+		"/userlinker/list":          m.makeHandler(reflect.TypeOf(entity.UserLinker{}), makeLinkerListEndpoint, nil, true),
+		"/userlinker/default":       m.makeHandler(reflect.TypeOf(entity.UserLinker{}), makeLinkerDefaultEndpoint, nil, true),
+		"/userlinker/del":           m.makeHandler(reflect.TypeOf(entity.UserLinker{}), makeLinkerDelEndpoint, nil, true),
+		"/userlinker/relationships": m.makeHandler(nil, makeLinkerRelEndpoint, nil, true),
+		"/productivity/list":        m.makeHandler(reflect.TypeOf(PtListParam{}), makeiPtListEndpoint, nil),
+		"/product/get":              m.makeHandler(reflect.TypeOf([]int{}), makeProductGetEndpoint, nil),
+		"/product/getcoordinates":   m.makeHandler(reflect.TypeOf(ProductCoordinatesParam{}), makeProductGetCoordinates, nil),
+		"/product/checkcoordinates": m.makeHandler(reflect.TypeOf(ProductCoordinatesParam{}), makeProductCheckCoordinates, nil),
+		"/product/getbycateid":      m.makeHandler(reflect.TypeOf(GetProductByCateParam{}), makeProductGetByCatIdEndpoint, nil),
+		"/product/cate":             m.makeHandler(reflect.TypeOf(int(1)), makeGetProductCateEndpoint, nil),
+		"/product/recommend":        m.makeHandler(reflect.TypeOf(GetProductByCateParam{}), makeGetRecommendProductEndpoint, nil),
+		"/product/tag":              m.makeHandler(nil, makeGetTagsEndpoint, nil),
+		"/product/getbytag":         m.makeHandler(reflect.TypeOf(GetProductParam{}), makeGetProductByTagsEndpoint, nil),
+		"/product/savegenesign":     m.makeHandler(reflect.TypeOf(entity.ConsumerGeneSign{}), makeSaveConsumerGeneSignEndpoint, nil),
+		"/product/addingcate":       m.makeHandler(reflect.TypeOf(0), makeGetProductAddingCateEndpoint, nil),
+		"/product/addbydpids":       m.makeHandler(reflect.TypeOf([]int{}), makeAddProductByDpidsEndpoint, nil, true),
+		"/product/top":              m.makeHandler(reflect.TypeOf(TopProductParam{}), makeGetProductTopEndpoint, nil),
+		"/product/guess":            m.makeHandler(reflect.TypeOf(ProductGuessParam{}), makeProductGuess, nil),
+		"/duser/orderlist":          m.makeHandler(reflect.TypeOf(GetOrderListParam{}), makeGetOrderListEndpoint, nil),
+		"/duser/orderlist/v2":       m.makeHandler(reflect.TypeOf(GetOrderListParam{}), makeGetOrderListV2Endpoint, nil),
+		"/duser/ordersign":          m.makeHandler(reflect.TypeOf(""), makeGetOrderSignEndpoint, nil),
+		"/duser/saveordersign":      m.makeHandler(reflect.TypeOf(entity.OrderSign{}), makeSaveOrderSignEndpoint, nil),
+		"/duser/regist":             m.makeHandler(reflect.TypeOf(entity.DeliverUser{}), makeRegistDUEndpoint, nil),
+		"/duser/exam":               m.makeHandler(reflect.TypeOf(NourseExamParam{}), makeNurseExamEndpoint, nil),
+		"/system/piclist":           m.makeHandler(nil, makeGetFirstPagePicListEndpoint, nil),
+		"/system/workdays":          m.makeHandler(reflect.TypeOf(int(0)), makeGetWorkdaysEndpoint, nil),
+		"/system/question":          m.makeHandler(reflect.TypeOf(int(0)), makeGetQuestionEndpoint, nil),
+		//"/system/dictlist":          m.makeHandler(reflect.TypeOf(""), makeGetDictListEndpoint, nil),
+		"/system/dictlist":       m.makeHandler(reflect.TypeOf(DictParam{}), makeGetDictListEndpoint, nil),
+
+		"/act/addreporter":       m.makeHandler(reflect.TypeOf(entity.ActReporter{}), makeAddReporterEndpoint, nil),
+		"/act/addinfo":           m.makeHandler(reflect.TypeOf(entity.ActInfo{}), makeAddActInfoEndpoint, nil),
+		"/act/getinfo":           m.makeHandler(reflect.TypeOf(entity.ActInfo{}), makeGetActInfoEndpoint, nil),
+		"/act/upinfo":            m.makeHandler(reflect.TypeOf(entity.ActInfo{}), makeUpdateActinfoEndpoint, nil),
+
+		"/act/withdraw":          m.makeHandler(reflect.TypeOf(entity.ActInfo{}), makeWithdrawActinfoEndpoint, nil),
+		"/act/addinvoice":        m.makeHandler(reflect.TypeOf(entity.ActInfo{}), makeAddInvoice, nil),
+		"/act/getinvoice":        m.makeHandler(reflect.TypeOf(entity.ActInfo{}), makeGetInvoice, nil),
+		"/jicai/gbinfo":          m.makeHandler(reflect.TypeOf(GroupBloodParam{}), makeGetGroupBloodInfoEndpoint, nil, true),
+		"/jicai/enqueue":         m.makeHandler(reflect.TypeOf(GroupBloodParam{}), makeGroupBloodEnqueueEndpoint, nil, true),
+		"/jicai/next":            m.makeHandler(reflect.TypeOf(GroupBloodParam{}), makeGroupBloodNextEndpoint, nil, false),
+		"/jicai/subjectqueue":    m.makeHandler(reflect.TypeOf(GroupBloodParam{}), makeGroupBloodSubjectQueueEndpoint, nil, false),
+		"/jicai/orderinfo":       m.makeHandler(reflect.TypeOf(""), makeGroupBloodGetOrderinfoEndpoint, nil),
+		"/jicai/checkprogress":   m.makeHandler(reflect.TypeOf(""), makeGroupBloodGetProgressinfoEndpoint, nil),
+		"/jicai/confirmchecked":  m.makeHandler(reflect.TypeOf(entity.GPParam{}), makeGroupBloodConfirmCheckEndpoint, nil),
+		"/pay/prepay/get":        m.makeHandler(reflect.TypeOf(map[string]string{}), makeGetPrepayInfoEndpoint, nil, false),
+
+		"/user/customfile/list":        m.makeHandler(reflect.TypeOf(int(1)), makeGetCustomFilelist, nil, true),
+		"/user/customfile/get":         m.makeHandler(reflect.TypeOf(int(1)), makeGetCustomFile, nil, true),
+		"/user/customfile/updatelabel": m.makeHandler(reflect.TypeOf(entity.CustomInfoLabelsDto{}), makeUpdateCustomFileLabel, nil, true),
+		"/user/customfile/add":         m.makeHandler(reflect.TypeOf(entity.CustomFile{}), makeAddCustomFile, nil, true),
+		"/user/customfile/modify":      m.makeHandler(reflect.TypeOf(entity.CustomFile{}), makeModifyCustomFile, nil, true),
+		"/user/customfile/del":         m.makeHandler(reflect.TypeOf(int(1)), makeDelCustomFile, nil, true),
+		"/user/customattachment/add":   m.makeHandler(reflect.TypeOf(entity.CustomAttachment{}), makeAddCustomAttachment, nil, true),
+		"/user/customattachment/count": m.makeHandler(reflect.TypeOf(entity.CustomFileParam{}), makeGetCustomAttachmentCount, nil, true),
+		"/user/customattachment/list":  m.makeHandler(reflect.TypeOf(entity.CustomFileParam{}), makeGetCustomAttachmentList, nil, true),
+		"/user/customrisk/list":        m.makeHandler(reflect.TypeOf(int(1)), makeGetCustomRiskList, nil, true),
+		"/user/yidian/list":            m.makeHandler(reflect.TypeOf(int(1)), makeGetYiDianList, nil, true),
+		"/user/doctorrecommend/list":   m.makeHandler(reflect.TypeOf(int(1)), makeGetDoctorRecommendList, nil, true),
+		"/order/list/customfileid":     m.makeHandler(reflect.TypeOf(ListOrderParam{}), makeListFileOrderEndpoint, nil, true),
+		"/system/dictlist/list":        m.makeHandler(reflect.TypeOf([]DictParam{}), makeGetDictListsEndpoint, nil),
+
+		//京东物流
+		"/order/jdl/calendar": m.makeHandler(reflect.TypeOf(entity.JDLParams{}), makeJDLCalendar, nil),
+		"/order/jdl/add":      m.makeHandler(reflect.TypeOf(entity.JDLParams{}), makeJDLAdd, nil),
+		"/order/jdl/cancel":   m.makeHandler(reflect.TypeOf(entity.JDLCheck{}), makeJDLCancel, nil),
+		"/order/jdl/trace":    m.makeHandler(reflect.TypeOf(entity.JDLCheck{}), makeJDLTrace, nil),
+
+	}
+}

+ 434 - 0
main.go

@@ -0,0 +1,434 @@
+package main
+
+import (
+	"context"
+	"encoding/json"
+	"encoding/xml"
+	"errors"
+	"flag"
+	"fmt"
+	"io/ioutil"
+	stdlog "log"
+	"math/rand"
+	"net/http"
+	"os"
+	"os/signal"
+	"runtime"
+	"syscall"
+	"time"
+	"xiaoniaokuaiyan.com/xiaoniao/pay/ali"
+
+	"gopkg.in/guregu/null.v3"
+
+	"github.com/go-kit/kit/log"
+	"github.com/go-zoo/bone"
+	"github.com/smartwalle/alipay/v3"
+	"xiaoniaokuaiyan.com/xiaoniao/config"
+	dal "xiaoniaokuaiyan.com/xiaoniao/dal"
+	"xiaoniaokuaiyan.com/xiaoniao/pay/wx"
+	"xiaoniaokuaiyan.com/xiaoniao/retry"
+	"xiaoniaokuaiyan.com/xiaoniao/search"
+	"xiaoniaokuaiyan.com/xiaoniao/server"
+	service "xiaoniaokuaiyan.com/xiaoniao/service"
+	"xiaoniaokuaiyan.com/xiaoniao/util"
+)
+
+func checkRuntimeErr(err error) bool {
+	if err != nil {
+		stdlog.Fatalf("error: %v", err)
+		return true
+	}
+	return false
+}
+
+func wxScanPaycbHandler(w http.ResponseWriter, req *http.Request) {
+	if req.Method != "POST" {
+		w.WriteHeader(http.StatusMethodNotAllowed)
+		return
+	}
+	xmlDec := xml.NewDecoder(req.Body)
+	defer req.Body.Close()
+	payResult := &wx.UnionPayResult{}
+	err := xmlDec.Decode(payResult)
+	stdlog.Println("wxpaycb:", payResult)
+	if err != nil {
+		stdlog.Println("wxpaycb_err:", err)
+		w.Write([]byte(err.Error()))
+		return
+	}
+	db := util.GetWriteSqlDB()
+	tcwp := struct {
+		ThirdPNO null.String `db:"third_pay_no"`
+		Source   null.String `db:"usefor"`
+		Remark   null.String `db:"remark"`
+	}{}
+	db.Get(&tcwp, "select usefor,third_pay_no,remark from t_custom_wxscan_pay where id = ?", payResult.OutTradeNo)
+	if tcwp.ThirdPNO.Valid {
+		writeWxPayCbOk(w)
+		return
+	}
+	//thirdPNO := null.String{}
+	//db.Get(&thirdPNO, "select third_pay_no from t_custom_wxscan_pay where id = ?", payResult.OutTradeNo)
+	//if thirdPNO.Valid {
+	//	writeWxPayCbOk(w)
+	//	return
+	//}
+	kv, _ := util.StructToMap(payResult)
+	delete(kv, "sign")
+	jssdk := wx.NewJsSdk()
+	csign := jssdk.ComputePaySignature(kv, config.IniConf.Section("weixin").Key("wx.apikey").Value())
+	if csign != payResult.Sign {
+		stdlog.Println("wxpaycb_err: wrong sign")
+		_, err = util.SendMail(util.MailList{
+			{"liuguiqi", "liugq@xniao.com.cn"},
+			{"guoxiaozhou", "43572650@qq.com"},
+			{"houyoufang", "houyf@xniao.com.cn"},
+		}, "您的商户订单号为:"+payResult.OutTradeNo+"由于签名校验错误导致订单信息", "微信支付回调错误消息提醒")
+		if err != nil {
+			stdlog.Println("SEND_MAIL_ERROR:", err)
+		}
+		w.Write([]byte("wrong sign"))
+		return
+	}
+	if payResult.ReturnCode == "SUCCESS" && payResult.ResultCode == "SUCCESS" {
+		payTime, _ := time.Parse("20060102150405", payResult.TimeEnd)
+		actualPay := payResult.TotalFee
+		_, err = db.Exec("update t_custom_wxscan_pay set third_pay_no = ?, actual_payment = ?, payment_time = ? where id = ?", payResult.TransactionId, actualPay, payTime.Format("2006-01-02 15:04:05"), payResult.OutTradeNo)
+		if err != nil {
+			stdlog.Println("UPDATE_SCANPAY_STATUS:", err)
+		} else {
+			client := util.GetRedis()
+			msg := map[string]interface{}{
+				"user":    "system",
+				"channel": "SCANPAY-INFORM",
+				"data": map[string]interface{}{
+					"id":        payResult.OutTradeNo,
+					"total_fee": payResult.TotalFee,
+				},
+			}
+			buf, _ := json.Marshal(msg)
+			client.Publish("xn-message", string(buf))
+		}
+	}
+	writeWxPayCbOk(w)
+	if tcwp.Source.ValueOrZero() == "jsl" && tcwp.Remark.ValueOrZero() != "" {
+		go orderSrv.JinShuiLianServer(tcwp.Remark.ValueOrZero())
+	}
+}
+
+func writeWxPayCbOk(w http.ResponseWriter) {
+	okXml := `<xml>
+	  <return_code><![CDATA[SUCCESS]]></return_code>
+	    <return_msg><![CDATA[OK]]></return_msg>
+		</xml>`
+	w.Write([]byte(okXml))
+}
+func wxPaycbHandler(w http.ResponseWriter, req *http.Request) {
+	if req.Method != "POST" {
+		w.WriteHeader(http.StatusMethodNotAllowed)
+		return
+	}
+	//xmlDec := xml.NewDecoder(req.Body)
+	buf, _ := ioutil.ReadAll(req.Body)
+	defer req.Body.Close()
+	payResult := &wx.UnionPayResult{}
+	err := xml.Unmarshal(buf, payResult)
+	//err := xmlDec.Decode(payResult)
+	stdlog.Println("wxpaycb:", payResult)
+	if err != nil {
+		stdlog.Println("wxpaycb_err:", err)
+		w.Write([]byte(err.Error()))
+		return
+	}
+	db := util.GetWriteSqlDB()
+	thirdPNO := null.String{}
+	db.Get(&thirdPNO, "select third_pay_no from t_order where pay_no = ?", payResult.OutTradeNo)
+	if thirdPNO.Valid {
+		writeWxPayCbOk(w)
+		return
+	}
+	kv, _ := util.StructToMap(payResult)
+	delete(kv, "sign")
+	jssdk := wx.NewJsSdk()
+	csign := jssdk.ComputePaySignature(kv, config.IniConf.Section("weixin").Key("wx.apikey").Value())
+	if csign != payResult.Sign {
+		fmt.Println(string(buf))
+		stdlog.Println("wxpaycb_err: wrong sign", csign)
+		go func() {
+			retry.Run(&retry.Policy{Attempts: 3, Sleep: time.Second, Factor: 2},
+				func() error {
+					rt, _ := orderSrv.WxPayQuery(map[string]string{"out_trade_no": payResult.OutTradeNo})
+					if rt != nil && rt["status"] == "SUCCESS" {
+						return retry.Stop(errors.New("success"))
+					}
+					return errors.New("OUT_TIMES")
+				})
+		}()
+
+		_, err = util.SendMail(util.MailList{
+			{"liuguiqi", "liugq@xniao.com.cn"},
+			{"guoxiaozhou", "43572650@qq.com"},
+			{"houyoufang", "houyf@xniao.com.cn"},
+		}, "您的商户订单号为:"+payResult.OutTradeNo+"由于签名校验错误导致订单信息", "微信支付回调错误消息提醒")
+		if err != nil {
+			stdlog.Println("SEND_MAIL_ERROR:", err)
+		}
+		w.Write([]byte("wrong sign"))
+		return
+	}
+	if payResult.ReturnCode == "SUCCESS" && payResult.ResultCode == "SUCCESS" {
+		orderSrv.WxPayCB(kv)
+		/*db := util.GetWriteSqlDB()
+		payTime, _ := time.Parse("20060102150405", payResult.TimeEnd)
+		actualPay := payResult.TotalFee
+		_, err = db.Exec("update t_order set status = ?, third_pay_no = ?, actual_payment = ?, payment_time = ?, pay_type = ? where pay_no = ?", 2, payResult.TransactionId, actualPay, payTime.Format("2006-01-02 15:04:05"), constants.PAYMENTTYPE_WEIXIN, payResult.OutTradeNo)
+		if err != nil {
+			stdlog.Println("UPDATE_PAY_STATUS:", err)
+		} else {
+			go func() {
+				strSql := "select id, mobile, custom_mobile from t_order where pay_no = ?"
+				var orderItem = &entity.OrderDB{}
+				err = db.Get(orderItem, strSql, payResult.OutTradeNo)
+				if err == nil {
+					sms := &service.SMSService{dal.DefaultSMSCodeDal}
+					sms.SendSMS(orderItem.Mobile, int(constants.SMS_ORDER_PAID_INFORM), map[string]string{"orderId": orderItem.Id})
+				}
+				//inform admin
+				client := util.GetRedis()
+				client.Select(2)
+				msg := map[string]interface{}{
+					"user":    "system",
+					"orderid": orderItem.Id,
+					"status":  constants.ORDERSTATUS_UNRECEIVE,
+				}
+				buf, _ := json.Marshal(msg)
+				client.Publish("order-status-change", string(buf))
+				client.HDel("order_unpay", orderItem.Id)
+			}()
+			var wxType = ""
+			if payResult.AppId == config.IniConf.Section("weixin").Key("wx.mp.appid").Value() {
+				wxType = "mp"
+			}
+			_, err = orderSrv.SendWxPaySuccessMsg(map[string]string{
+				"pay_no":  payResult.OutTradeNo,
+				"openid":  payResult.OpenId,
+				"money":   fmt.Sprintf("%.2f元", float32(payResult.TotalFee)/100),
+				"wx_type": wxType,
+			})
+			if err != nil {
+				stdlog.Println(err)
+			}
+		}*/
+
+	}
+	writeWxPayCbOk(w)
+}
+
+func aliPayHandler(w http.ResponseWriter, req *http.Request) {
+	if req.Method != "POST" {
+		w.WriteHeader(http.StatusMethodNotAllowed)
+		return
+	}
+	payResult, err := ali.GetAliClient().GetTradeNotification(req)
+	if err != nil {
+		fmt.Fprint(w, err.Error())
+		return
+	}
+	defer fmt.Fprint(w, "success")
+	db := util.GetWriteSqlDB()
+	thirdPNO := null.String{}
+	db.Get(&thirdPNO, "select third_pay_no from t_order where pay_no = ?", payResult.OutTradeNo)
+	if thirdPNO.Valid {
+		return
+	}
+	if payResult.TradeStatus == alipay.TradeStatusSuccess {
+		//成功
+		kv := map[string]string{
+			"gmt_payment":  payResult.GmtPayment,
+			"total_amount": payResult.TotalAmount,
+			"out_trade_no": payResult.OutTradeNo,
+			"trade_no":     payResult.TradeNo,
+		}
+		orderSrv.AliPayCB(kv)
+	} else {
+		//去主动查询
+	}
+}
+
+var orderSrv *service.OrderService
+var Version string
+
+func main() {
+	runtime.GOMAXPROCS(runtime.NumCPU() * 2)
+	fs := flag.NewFlagSet("", flag.ExitOnError)
+	var (
+		httpAddr = fs.String("http.addr", ":8000", "Address for HTTP (JSON) server")
+		//grpcAddr = fs.String("grpc.addr", ":8001", "Address for grpc server")
+		configFile = fs.String("f", "config.ini", "app config file")
+		version    = fs.Bool("version", false, "print app version")
+	)
+	fs.Parse(os.Args[1:])
+	if *version {
+		fmt.Println(Version)
+		return
+	}
+	config.Reload(*configFile)
+
+	port:=":"+config.IniConf.Section("server").Key("Listen").String()
+	if port!=":"{
+		httpAddr=&port
+	}
+	var logger log.Logger
+	{
+		logger = log.NewLogfmtLogger(os.Stderr)
+		logger = log.With(logger, "ts", log.DefaultTimestamp)
+		logger = log.With(logger, "caller", log.DefaultCaller)
+		stdlog.SetFlags(0)                             // flags are handled by Go kit's logger
+		stdlog.SetOutput(log.NewStdlibAdapter(logger)) // redirect anything using stdlib log to us
+	}
+	// Business domain
+	//var svc interface{}
+	//{
+	userSvc := &service.UserService{
+		IUser: dal.DefaultUserDal,
+	}
+	smsSvc := &service.SMSService{
+		ISMSCode: dal.DefaultSMSCodeDal,
+	}
+	authSvc := &service.AuthService{}
+	fileSvc := &service.FileService{}
+	searchSrv := &service.SearchService{}
+	cartSrv := &service.CartService{
+		ICart: dal.DefaultCartDal,
+	}
+	couponSrv := &service.CouponService{
+		ICoupon: dal.DefaultCouponDal,
+	}
+	ptSrv := &service.ProductivityService{}
+	wxSrv := &service.WeixinService{
+		Weixin:   wx.NewWeixin(config.IniConf.Section("weixin").Key("wx.appid").Value(), config.IniConf.Section("weixin").Key("wx.secret").Value()),
+		WeixinMp: wx.NewWeixin(config.IniConf.Section("weixin").Key("wx.mp.appid").Value(), config.IniConf.Section("weixin").Key("wx.mp.secret").Value()),
+		JsSdk:    wx.NewJsSdk(),
+	}
+	orderSrv = &service.OrderService{
+		IOrder:        dal.DefaultOrderDal,
+		WeixinService: wxSrv,
+	}
+	citySrv := &service.CityService{
+		ICity: dal.DefaultCityDal,
+	}
+	ulSrv := &service.UserLinkerService{
+		IUserLinker: dal.DefaultUserLinkerDal,
+	}
+	productSrv := &service.ProductService{
+		IProduct: dal.DefaultProductDal,
+	}
+
+	duSrv := &service.DeliverUserService{
+		IDeliverUserDal: dal.DefaultDeliverUserDal,
+		WeixinService:   wxSrv,
+	}
+
+	sysSrv := &service.SystemService{}
+	actSrv := &service.ActivityService{
+		WeixinService: wxSrv,
+	}
+	gbSrv := &service.GroupBloodService{
+		WeixinService: wxSrv,
+	}
+	paySrv := &service.PayService{}
+
+	jdlSrv := &service.JDLService{}
+
+	svc:=loggingMiddleware{
+		UserService:         userSvc,
+		AuthService:         authSvc,
+		SearchService:       searchSrv,
+		FileService:         fileSvc,
+		OrderService:        orderSrv,
+		SMSService:          smsSvc,
+		CartService:         cartSrv,
+		CouponService:       couponSrv,
+		ProductivityService: ptSrv,
+		WeixinService:       wxSrv,
+		CityService:         citySrv,
+		UserLinkerService:   ulSrv,
+		ProductService:      productSrv,
+		DeliverUserService:  duSrv,
+		SystemService:       sysSrv,
+		ActivityService:     actSrv,
+		GroupBloodService:   gbSrv,
+		PayService:          paySrv,
+		JDLService:          jdlSrv,
+		Logger:              logger,
+	}
+	//svc := loggingMiddleware{userSvc, authSvc, searchSrv, fileSvc, orderSrv, smsSvc, cartSrv, couponSrv, ptSrv, wxSrv, citySrv, ulSrv, productSrv, duSrv, sysSrv, thirdSrv, actSrv, gbSrv, paySrv, jdlSrv, logger}
+	//}
+	// Mechanical stuff
+	rand.Seed(time.Now().UnixNano())
+	errc := make(chan error)
+
+	var mServer *http.Server
+	go func() {
+		errc <- interrupt()
+		mServer.Shutdown(context.Background())
+	}()
+	// Transport: gRPC
+	/*go func() {
+		transportLogger := log.NewContext(logger).With("transport", "gRPC")
+		ln, err := net.Listen("tcp", *grpcAddr)
+		if err != nil {
+			errc <- err
+			return
+		}
+		s := grpc.NewServer() // uses its own, internal context
+		pb.RegisterUserServiceServer(s, grpcBinding{svc})
+		transportLogger.Log("addr", *grpcAddr)
+		errc <- s.Serve(ln)
+	}()*/
+	// Transport: HTTP/JSON
+	//root := context.Background()
+	go func() {
+		var (
+			transportLogger = log.With(logger, "transport", "HTTP/JSON")
+			mux             = bone.New()
+		)
+		mux.HandleFunc("/wx/paycb", wxPaycbHandler)
+		mux.HandleFunc("/wx/scanpaycb", wxScanPaycbHandler)
+		//mux.HandleFunc("/wx/paycb", wxPaycbHandlerV2)
+		//mux.HandleFunc("/wx/scanpaycb", wxScanPaycbHandlerV2)
+		mux.HandleFunc("/zfb/paycb", aliPayHandler)
+		mux.GetFunc("/version", func(w http.ResponseWriter, req *http.Request) {
+			fmt.Fprintf(w, "current app version is %s", Version)
+		})
+		RegistService(svc, mux)
+
+		transportLogger.Log("addr", *httpAddr)
+		mServer = &http.Server{Addr: *httpAddr, Handler: mux}
+		//errc <- http.ListenAndServe(*httpAddr, mux)
+		errc <- mServer.ListenAndServe()
+	}()
+	go search.UpdateIndex()
+	go util.TimingTask()
+	//go func() {
+	//	ch := make(chan os.Signal)
+	//	signal.Notify(ch, syscall.SIGUSR2) //syscall.SIGHUP
+	//	for {
+	//		<-ch
+	//		config.Reload("")
+	//	}
+	//}()
+	logger.Log("fatal", <-errc)
+}
+func interrupt() error {
+	c := make(chan os.Signal)
+	signal.Notify(c, os.Interrupt, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGKILL)
+	return fmt.Errorf("%s", <-c)
+}
+
+func RegistService(svc server.Service, mux *bone.Mux) {
+	handlers := svc.GetMeta()
+	for uri, handler := range handlers {
+		mux.Handle(uri, handler)
+	}
+}

+ 171 - 0
params.go

@@ -0,0 +1,171 @@
+package main
+
+import (
+	"xiaoniaokuaiyan.com/xiaoniao/entity"
+)
+
+type RegistParam struct {
+	Mobile   string `json:"mobile"`
+	Password string `json:"password"`
+	Vcode    string `json:"vcode"`
+}
+
+type ResetPwdParam struct {
+	Mobile      string `json:"mobile"`
+	Password    string `json:"password"`
+	NewPassword string `json:"newPassword"`
+}
+
+type ListOrderParam struct {
+	CustomId  int    `json:"customId"`
+	PageIndex int    `json:"pageIndex"`
+	PageSize  int    `json:"pageSize"`
+	Status    int    `json:"status"`
+	Mobile    string `json:"mobile"`
+}
+
+type SMSParam struct {
+	Mobile string `json:"mobile"`
+	Type   int    `json:"type"`
+}
+
+type VcodeParam struct {
+	Mobile   string `json:"mobile"`
+	Code     string `json:"code"`
+	CodeType int    `json:"code_type"`
+}
+
+type CouponListParam struct {
+	Mobile    string `json:"mobile"`
+	Status    int    `json:"status"`
+	PageIndex int    `json:"pageIndex"`
+	PageSize  int    `json:"pageSize"`
+}
+
+type DetailOrderParam struct {
+	OrderId  string `json:"orderId"`
+	CustomId int    `json:"customId"`
+	Type     string `json:"type"`
+}
+
+type PtListParam struct {
+	CityId  int    `json:"cityId"`
+	FromDay string `json:"fromDay"`
+	PtType  int    `json:"ptType"`
+	KongFuType int `json:"kongFuType"`
+}
+
+type ExchangeParam struct {
+	CodeStr  string `json:"codeStr"`
+	CustomId int    `json:"customId"`
+	Mobile   string `json:"mobile"`
+}
+type CartParam struct {
+	ProductIds []int `json:"pids"`
+	CustomId   int   `json:"cid"`
+}
+
+type TagParam struct {
+	CityId   int `json:"cityId"`
+	ParentId int `json:"pid"`
+}
+
+type GetProductParam struct {
+	PageSize  uint     `json:"pageSize"`
+	PageIndex uint     `json:"pageIndex"`
+	Tags      []string `json:"tags"`
+	CateId    int      `json:"cateId"`
+	CityId    int      `json:"cityId"`
+}
+
+type GetProductByCateParam struct {
+	PageSize  int    `json:"page_size"`
+	PageIndex int    `json:"page_index"`
+	CateIds   []int  `json:"cate_ids"`
+	CityId    int    `json:"city_id"`
+	SortBy    string `json:"sort_by"`
+	SortDir   int    `json:"sort_dir"`
+}
+
+type SetOpenidParam struct {
+	Mobile string `json:"mobile"`
+	Openid string `json:"openid"`
+}
+
+type GetOrderListParam struct {
+	Openid    string `json:"openid"`
+	Status    int    `json:"status"`
+	PageIndex int    `json:"pageIndex"`
+	PageSize  int    `json:"pageSize"`
+}
+
+type HouseKeepingReportParam struct {
+	Name      string `json:"name"`
+	IdNumber  string `json:"id_number"`
+	ProductId int    `json:"product_id"`
+	Mobile    string `json:"mobile"`
+	VCode     string `json:"vcode"`
+}
+
+type GroupBloodParam struct {
+	CustomId  int `json:"custom_id"`
+	SubjectId int `json:"subject_id"`
+	OperType  int `json:"oper"`
+	Status    int `json:"status"`
+}
+
+type YoukeParam struct {
+	Mobile string `json:"mobile"`
+	Vcode  string `json:"vcode"`
+}
+
+type JDParam struct {
+	Mobile    string `json:"mobile"`
+	Erp       string `json:"erp"`
+	IsMarried string `json:"is_married"`
+	AddrId    int    `json:"addr_id"`
+	FromDay   string `json:"from_day"`
+	OperType  string `json:"oper_type"`
+	Openid    string `json:"openid"`
+}
+
+type NourseExamParam struct {
+	Oper          string                 `json:"oper"`
+	Type          string                 `json:"type"`
+	Questions     []entity.ExamQuestion  `json:"quetions"`
+	DUser         *entity.DeliverUser    `json:"deliver_user"`
+	StudyLog      entity.DeliverStudyLog `json:"study_log"`
+	OrderId       string                 `json:"order_id"`
+	DeliverUserId int                    `json:"deliver_user_id"`
+	City          string                 `json:"city"`
+	PageSize      int                    `json:"page_size"`
+	PageIndex     int                    `json:"page_index"`
+	Workdays      []string               `json:"workdays"`
+	Money         int                    `json:"money"`
+	ChatMsg       *entity.DeliverChatMsg `json:"chat_msg"`
+	Openid        string                 `json:"openid"`
+	IsSkip        string                 `json:"is_skip"`
+
+	ProductId int                      `json:"product_id"`      //20221009 护士加项考试传参
+	Answers   []entity.ProductQuestion `json:"product_answers"` //20221009 护士加项考试传参
+}
+type TopProductParam struct {
+	Size   int `json:"size"`
+	CityId int `json:"city_id"`
+}
+
+type DictParam struct {
+	Class    string `json:"class"`
+	Ordernum string `json:"ordernum"`
+}
+
+type ProductCoordinatesParam struct {
+	Pid         []int  `json:"pid"`
+	Coordinates string `json:"coordinates"`
+	CityId      int    `json:"city_id"`
+}
+
+type ProductGuessParam struct {
+	CityId int    `json:"city_id"`
+	Mobile string `json:"mobile"`
+}

+ 50 - 0
pay/ali/client.go

@@ -0,0 +1,50 @@
+package ali
+
+import (
+	"fmt"
+	"github.com/smartwalle/alipay/v3"
+	"io/ioutil"
+	"sync"
+	"xiaoniaokuaiyan.com/xiaoniao/config"
+)
+
+/**
+* @Author: qz
+* @Date: 2021/8/6 10:41
+* @Description:
+ */
+
+var aliClient *alipay.Client
+var once sync.Once
+
+type Config map[string]string
+
+var DefaultConfig Config
+
+func createClient() {
+	sec := config.IniConf.Section("ali")
+	DefaultConfig = Config{
+		"appid":        sec.Key("ali.appid").Value(),
+		"private_key":  sec.Key("ali.private_key").Value(),
+		"app_crt":      sec.Key("ali.app_crt").Value(),
+		"ali_crt":      sec.Key("ali.ali_crt").Value(),
+		"ali_root_crt": sec.Key("ali.ali_root_crt").Value(),
+	}
+	privateKey, err := ioutil.ReadFile(DefaultConfig["private_key"])
+	if err != nil {
+		fmt.Println(err)
+		return
+	}
+	aliClient, _ = alipay.New(DefaultConfig["appid"], string(privateKey), true)
+	aliClient.LoadAliPayPublicCertFromFile(DefaultConfig["ali_crt"])
+	aliClient.LoadAliPayRootCertFromFile(DefaultConfig["ali_root_crt"])
+	aliClient.LoadAppPublicCertFromFile(DefaultConfig["app_crt"])
+}
+
+func GetAliClient() *alipay.Client {
+	once.Do(func() {
+		createClient()
+		config.RegistChangeCallback(createClient)
+	})
+	return aliClient
+}

+ 85 - 0
pay/wx/cache.go

@@ -0,0 +1,85 @@
+package wx
+
+import (
+	"errors"
+	"time"
+)
+
+type CacheItem struct {
+	Value     string
+	ExpiresIn int64
+	UpdatedAt time.Time
+}
+
+func (item *CacheItem) IsExpired() bool {
+	periodDuration := time.Duration((item.ExpiresIn - 120) * 1000 * 1000 * 1000)
+	return item.UpdatedAt.Add(periodDuration).Before(time.Now())
+}
+
+type WXCache interface {
+	GetAccessToken() (string, error)
+	GetJsTicket() (string, error)
+}
+
+func NewWXCache(appId, secret string) WXCache {
+	return DefaultWXCache{
+		"appId":  appId,
+		"secret": secret,
+	}
+}
+
+type DefaultWXCache map[string]interface{}
+
+func (cache DefaultWXCache) GetAccessToken() (string, error) {
+	if accessTokenCache, ok := cache["accessTokenCache"]; ok {
+		if cacheItem, ok := accessTokenCache.(*CacheItem); ok && !cacheItem.IsExpired() {
+			return cacheItem.Value, nil
+		}
+	}
+	weixin := NewWeixin(cache["appId"].(string), cache["secret"].(string))
+	accessTokenRes, err := weixin.GetAccessToken()
+	if err != nil {
+		return "", err
+	}
+	if accessTokenRes.ErrCode != 0 {
+		return "", errors.New(accessTokenRes.ErrMsg)
+	}
+	//cache accesstoken
+	tokenCache := &CacheItem{
+		Value:     accessTokenRes.AccessToken,
+		UpdatedAt: time.Now(),
+		ExpiresIn: accessTokenRes.ExpiresIn,
+	}
+	cache["accessTokenCache"] = tokenCache
+	return accessTokenRes.AccessToken, nil
+}
+
+func (cache DefaultWXCache) GetJsTicket() (string, error) {
+	if jsTicketCache, ok := cache["jsTicketCache"]; ok {
+		if cacheItem, ok := jsTicketCache.(*CacheItem); ok && !cacheItem.IsExpired() {
+			return cacheItem.Value, nil
+		}
+	}
+	accessToken, err := cache.GetAccessToken()
+	if err != nil {
+		return "", err
+	}
+	wxJsSdk := NewJsSdk()
+	ticketRes, err := wxJsSdk.GetTicket(accessToken)
+	if err != nil {
+		return "", err
+	}
+	if ticketRes.ErrCode != 0 {
+		return "", errors.New(ticketRes.ErrMsg)
+	}
+	//cache
+	//jsTicket
+	ticketCache := &CacheItem{
+		Value:     ticketRes.Ticket,
+		UpdatedAt: time.Now(),
+		ExpiresIn: ticketRes.ExpiresIn,
+	}
+	cache["jsTicketCache"] = ticketCache
+	return ticketCache.Value, nil
+
+}

+ 24 - 0
pay/wx/config.go

@@ -0,0 +1,24 @@
+package wx
+
+import "xiaoniaokuaiyan.com/xiaoniao/config"
+
+type Config map[string]string
+
+var DefaultConfig Config
+
+func InitConfig() {
+	sec := config.IniConf.Section("weixin")
+	DefaultConfig = Config{
+		"appid":            sec.Key("wx.appid").Value(),
+		"secret":           sec.Key("wx.secret").Value(),
+		"apikey":           sec.Key("wx.apikey").Value(),
+		"mch_id":           sec.Key("wx.mch_id").Value(),
+		"paycb_notify_url": sec.Key("wx.paycb_notify_url").Value(),
+		"cert_file":        sec.Key("wx.cert_file").Value(),
+		"key_file":         sec.Key("wx.key_file").Value(),
+	}
+}
+
+func init() {
+	config.RegistChangeCallback(InitConfig)
+}

+ 130 - 0
pay/wx/jssdk.go

@@ -0,0 +1,130 @@
+package wx
+
+import (
+	"bytes"
+	"crypto/md5"
+	"crypto/sha1"
+	"encoding/json"
+	"fmt"
+	"io/ioutil"
+	"math/rand"
+	"net/http"
+	"net/url"
+	"sort"
+	"strings"
+	"sync"
+	"time"
+)
+
+type TicketResponse struct {
+	ErrCode   int    `json:"errcode"`
+	ErrMsg    string `json:"errmsg"`
+	Ticket    string `json:"ticket"`
+	ExpiresIn int64  `json:"expires_in"`
+}
+
+type SignPackage map[string]interface{}
+type JsSdk interface {
+	GenerateNoncestr(length int) string
+	GetTicket(token string) (*TicketResponse, error)
+	ComputeSignature(token, ticket, signUrl string) (SignPackage, error)
+	ComputePaySignature(params PkgComponents, apikey string) string
+}
+
+type JsSdkDefault struct {
+}
+
+func NewJsSdk() JsSdk {
+	return &JsSdkDefault{}
+}
+
+var chars string = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
+var bufPool = sync.Pool{
+	New: func() interface{} {
+		return new(bytes.Buffer)
+	},
+}
+
+func (sdk *JsSdkDefault) GenerateNoncestr(length int) string {
+	buf := bufPool.Get().(*bytes.Buffer)
+	defer func() {
+		buf.Reset()
+		bufPool.Put(buf)
+	}()
+	var ridx int
+	upBound := len(chars)
+	for i := 0; i < length; i++ {
+		ridx = rand.Intn(upBound)
+		buf.WriteByte(chars[ridx])
+	}
+	return buf.String()
+}
+
+func (sdk *JsSdkDefault) GetTicket(accessToken string) (*TicketResponse, error) {
+	serviceUrl := "https://api.weixin.qq.com/cgi-bin/ticket/getticket"
+	reqParams := url.Values{}
+	reqParams.Add("type", "jsapi")
+	reqParams.Add("access_token", accessToken)
+	serviceUrl += "?" + reqParams.Encode()
+	res, err := http.Get(serviceUrl)
+	if err != nil {
+		return nil, err
+	}
+	defer res.Body.Close()
+	bytesBuf, err := ioutil.ReadAll(res.Body)
+	if err != nil {
+		return nil, err
+	}
+
+	ticketRes := &TicketResponse{}
+	err = json.Unmarshal(bytesBuf, ticketRes)
+	if err != nil {
+		return nil, err
+	}
+	return ticketRes, nil
+}
+
+func (sdk *JsSdkDefault) ComputeSignature(accessToken, ticket, signUrl string) (SignPackage, error) {
+	timestamp := time.Now().Unix()
+	noncestr := sdk.GenerateNoncestr(16)
+	params := PkgComponents{
+		"jsapi_ticket": ticket,
+		"noncestr":     noncestr,
+		"timestamp":    fmt.Sprintf("%d", timestamp),
+		"url":          signUrl,
+	}
+	rawStr := params.buildRawQueryString()
+	signature := sha1.Sum([]byte(rawStr))
+
+	return SignPackage{
+		"access_token": accessToken,
+		"ticket":       ticket,
+		"noncestr":     noncestr,
+		"timestamp":    timestamp,
+		"signature":    fmt.Sprintf("%x", signature),
+	}, nil
+}
+
+func (sdk *JsSdkDefault) ComputePaySignature(components PkgComponents, apikey string) string {
+	rawStr := components.buildRawQueryString() + "&key=" + apikey
+	signature := md5.Sum([]byte(rawStr))
+	return strings.ToUpper(fmt.Sprintf("%x", signature))
+}
+
+type PkgComponents map[string]string
+
+func (pc PkgComponents) buildRawQueryString() string {
+	qstr := ""
+	keys := []string{}
+	for key := range pc {
+		keys = append(keys, key)
+	}
+	sort.Strings(keys)
+	for _, key := range keys {
+		if pc[key] == "" {
+			continue
+		}
+		qstr += key + "=" + pc[key] + "&"
+	}
+	return qstr[0 : len(qstr)-1]
+}

+ 129 - 0
pay/wx/request_response.go

@@ -0,0 +1,129 @@
+package wx
+
+import "encoding/xml"
+
+/*type UnionPayRequest struct {
+	AppId          string `xml:"appid"`            //公众账号ID(是)
+	MchId          string `xml:"mch_id"`           //商户号(是)
+	DeviceInfo     string `xml:"device_info"`      //设备号
+	NonceStr       string `xml:"nonce_str"`        //随机字符串(是)
+	Sign           string `xml:"sign"`             //签名(是)
+	Body           string `xml:"body"`             //商品描述(是)
+	Detail         string `xml:"detail"`           //商品详情
+	Attach         string `xml:"attach"`           //附加数据
+	OutTradeNo     string `xml:"out_trade_no"`     //商户订单号(是)
+	FeeType        string `xml:"fee_type"`         //货币类型
+	TotalFee       int    `xml:"total_fee"`        //总金额(是)
+	SpbillCreateIp string `xml:"spbill_create_ip"` //终端IP(是)
+	TimeStart      string `xml:"time_start"`       //交易起始时间
+	TimeExpire     string `xml:"time_expire"`      //交易结束时间
+	GoodsTag       string `xml:"goods_tag"`        //商品标记
+	NotifyUrl      string `xml:"notify_url"`       //通知地址(是)
+	TradeType      string `xml:"trade_type"`       //交易类型(是)
+	ProductId      string `xml:"product_id"`       //商品ID
+	LimitPay       string `xml:"limit_pay"`        //指定支付方式
+	OpenId         string `xml:"openid"`           //用户标识
+}*/
+type UnionPayRequest map[string]string
+
+func (s UnionPayRequest) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
+
+	tokens := []xml.Token{start}
+
+	for key, value := range s {
+		t := xml.StartElement{Name: xml.Name{"", key}}
+		tokens = append(tokens, t, xml.CharData(value), xml.EndElement{t.Name})
+	}
+
+	tokens = append(tokens, xml.EndElement{start.Name})
+
+	for _, t := range tokens {
+		err := e.EncodeToken(t)
+		if err != nil {
+			return err
+		}
+	}
+	// flush to ensure tokens are
+	// written
+	err := e.Flush()
+	if err != nil {
+		return err
+	}
+	return nil
+}
+
+type UnionPayResponse struct {
+	ReturnCode string `xml:"return_code"`
+	ReturnMsg  string `xml:"return_msg"`
+	AppId      string `xml:"appid"`
+	MchId      string `xml:"mch_id"`
+	DeviceInfo string `xml:"device_info"` //设备号
+	NonceStr   string `xml:"nonce_str"`
+	Sign       string `xml:"sign"`
+	ResultCode string `xml:"result_code"` //业务结果
+	ErrCode    string `xml:"err_code"`
+	ErrCodeDes string `xml:"err_code_des"`
+	TradeType  string `xml:"trade_type"`
+	PrepayId   string `xml:"prepay_id"`
+	CodeUrl    string `xml:"code_url"`
+	MWebUrl    string `xml:"mweb_url"` //h5支付中间回调页
+}
+
+type UnionPayResult struct {
+	ReturnCode    string `xml:"return_code"`
+	ReturnMsg     string `xml:"return_msg"`
+	AppId         string `xml:"appid"`
+	MchId         string `xml:"mch_id"`
+	DeviceInfo    string `xml:"device_info"` //设备号
+	NonceStr      string `xml:"nonce_str"`
+	Sign          string `xml:"sign"`
+	ResultCode    string `xml:"result_code"` //业务结果
+	ErrCode       string `xml:"err_code"`
+	ErrCodeDes    string `xml:"err_code_des"`
+	OpenId        string `xml:"openid"`
+	IsSubscribe   string `xml:"is_subscribe"`
+	TradeType     string `xml:"trade_type"`
+	BankType      string `xml:"bank_type"`
+	TotalFee      int    `xml:"total_fee"`
+	FeeType       string `xml:"fee_type"`
+	CashFee       int    `xml:"cash_fee"`
+	CashFeeType   string `xml:"cash_fee_type"`
+	CouponFee     int    `xml:"coupon_fee"`
+	CouponCount   int    `xml:"coupon_count"`
+	CouponFee0    int    `xml:"coupon_fee_0"`
+	CouponId0     string `xml:"coupon_id_0"`
+	TransactionId string `xml:"transaction_id"`
+	OutTradeNo    string `xml:"out_trade_no"`
+	Attach        string `xml:"attach"`
+	TimeEnd       string `xml:"time_end"`
+	TradeState    string `xml:"trade_state"`
+}
+
+//type UnionPayResult map[string]string
+
+/*type OrderQueryResult struct {
+	ReturnCode    string `xml:"return_code"`
+	ReturnMsg     string `xml:"return_msg"`
+	AppId         string `xml:"appid"`
+	MchId         string `xml:"mch_id"`
+	DeviceInfo    string `xml:"device_info"` //设备号
+	NonceStr      string `xml:"nonce_str"`
+	Sign          string `xml:"sign"`
+	ResultCode    string `xml:"result_code"` //业务结果
+	ErrCode       string `xml:"err_code"`
+	ErrCodeDes    string `xml:"err_code_des"`
+	OpenId        string `xml:"openid"`
+	IsSubscribe   string `xml:"is_subscribe"`
+	TradeType     string `xml:"trade_type"`
+	BankType      string `xml:"bank_type"`
+	TotalFee      int    `xml:"total_fee"`
+	FeeType       string `xml:"fee_type"`
+	CashFee       int    `xml:"cash_fee"`
+	CashFeeType   string `xml:"cash_fee_type"`
+	CouponFee     int    `xml:"coupon_fee"`
+	CouponCount   int    `xml:"coupon_count"`
+	TransactionId string `xml:"transaction_id"`
+	OutTradeNo    string `xml:"out_trade_no"`
+	Attach        string `xml:"attach"`
+	TimeEnd       string `xml:"time_end"`
+}*/

+ 291 - 0
pay/wx/weixin.go

@@ -0,0 +1,291 @@
+package wx
+
+import (
+	"bytes"
+	"crypto/tls"
+	"encoding/json"
+	"encoding/xml"
+	"errors"
+	"fmt"
+	"io"
+	"io/ioutil"
+	"net/http"
+	"net/url"
+	"time"
+)
+
+type AccessToken struct {
+	TokenStr  string `json:"access_token"`
+	ExpiresAt int64  `json:"expires_at"`
+}
+
+func (token *AccessToken) IsExpired() bool {
+	return time.Now().Unix()+10 > token.ExpiresAt
+}
+
+type AccessTokenResponse struct {
+	ErrCode     int    `json:"errcode"`
+	ErrMsg      string `json:"errmsg"`
+	AccessToken string `json:"access_token"`
+	ExpiresIn   int64  `json:"expires_in"`
+}
+
+type Message map[string]interface{}
+
+type Weixin interface {
+	GetAccessToken() (*AccessTokenResponse, error)
+	PrepareOrder(reqInfo UnionPayRequest) (*UnionPayResponse, error)
+	OrderQuery(reqInfo UnionPayRequest) (map[string]string, error)
+	Refund(param UnionPayRequest, certFile, keyFile string) (map[string]string, error)
+	Send(msg Message, token string) error
+	SendTpl(msg string, token, wxType string) error
+	SendRedpack(param UnionPayRequest, certFile, keyFile string) (map[string]string, error)
+	GetHBInfo(param UnionPayRequest, certFile, keyFile string) (map[string]string, error)
+}
+
+var appInfo struct {
+	appid, secret string
+	isInit        bool
+}
+
+func Init(appid, secret string) Weixin {
+	appInfo.appid = appid
+	appInfo.secret = secret
+	appInfo.isInit = true
+	return NewWeixin(appid, secret)
+}
+
+func NewWeixin(appid, secret string) Weixin {
+	if appid == "" && appInfo.isInit {
+		appid = appInfo.appid
+	}
+	if secret == "" && appInfo.isInit {
+		secret = appInfo.secret
+	}
+	return &defaultWeixin{
+		AppId:  appid,
+		Secret: secret,
+	}
+}
+
+type defaultWeixin struct {
+	AppId  string
+	Secret string
+}
+
+func (weixin *defaultWeixin) GetAccessToken() (*AccessTokenResponse, error) {
+	var serviceUrl string = "https://api.weixin.qq.com/cgi-bin/token"
+	reqParams := url.Values{}
+	reqParams.Add("grant_type", "client_credential")
+	reqParams.Add("appid", weixin.AppId)
+	reqParams.Add("secret", weixin.Secret)
+	serviceUrl += "?" + reqParams.Encode()
+	res, err := http.Get(serviceUrl)
+	if err != nil {
+		return nil, err
+	}
+	defer res.Body.Close()
+	resBuf, err := ioutil.ReadAll(res.Body)
+	if err != nil {
+		return nil, err
+	}
+	tokenRes := &AccessTokenResponse{}
+	err = json.Unmarshal(resBuf, tokenRes)
+	if err != nil {
+		//return nil, err
+		return nil, fmt.Errorf("%s", string(resBuf))
+	}
+	if tokenRes.ErrCode != 0 {
+		return nil, fmt.Errorf("%d::%s", tokenRes.ErrCode, tokenRes.ErrMsg)
+	}
+	return tokenRes, nil
+}
+
+func (weixin *defaultWeixin) PrepareOrder(reqInfo UnionPayRequest) (*UnionPayResponse, error) {
+	var serviceUrl string = "https://api.mch.weixin.qq.com/pay/unifiedorder"
+	reqBytes, err := xml.Marshal(reqInfo)
+	if err != nil {
+		return nil, err
+	}
+	reader := bytes.NewReader(reqBytes)
+	resp, err := http.Post(serviceUrl, "application/xml", reader)
+	if err != nil {
+		return nil, err
+	}
+	defer resp.Body.Close()
+	resBuf, err := ioutil.ReadAll(resp.Body)
+	if err != nil {
+		return nil, err
+	}
+	payRes := &UnionPayResponse{}
+	err = xml.Unmarshal(resBuf, payRes)
+	return payRes, err
+}
+
+func (weixin *defaultWeixin) OrderQuery(reqInfo UnionPayRequest) (map[string]string, error) {
+	var serviceUrl string = "https://api.mch.weixin.qq.com/pay/orderquery"
+	reqBytes, err := xml.Marshal(reqInfo)
+	if err != nil {
+		return nil, err
+	}
+	reader := bytes.NewReader(reqBytes)
+	resp, err := http.Post(serviceUrl, "application/xml", reader)
+	if err != nil {
+		return nil, err
+	}
+	defer resp.Body.Close()
+	/*resBuf, err := ioutil.ReadAll(resp.Body)
+	if err != nil {
+		return nil, err
+	}
+	//qRes := &UnionPayResult{}
+	//err = xml.Unmarshal(resBuf, qRes)
+	fmt.Println(string(resBuf))
+	*/
+	qRes := xmlToMap(resp.Body)
+	return qRes, nil
+
+}
+
+func (weixin *defaultWeixin) Refund(params UnionPayRequest, certFile, keyFile string) (map[string]string, error) {
+	var serviceUrl string = "https://api.mch.weixin.qq.com/secapi/pay/refund"
+	return secureRequest(serviceUrl, params, certFile, keyFile)
+}
+
+func (weixin *defaultWeixin) SendRedpack(params UnionPayRequest, certFile, keyFile string) (map[string]string, error) {
+	var serviceUrl string = "https://api.mch.weixin.qq.com/mmpaymkttransfers/sendredpack"
+	//var serviceUrl string = "https://api.mch.weixin.qq.com/sandboxnew/mmpaymkttransfers/sendredpack"
+	return secureRequest(serviceUrl, params, certFile, keyFile)
+}
+
+func (weixin *defaultWeixin) GetHBInfo(params UnionPayRequest, certFile, keyFile string) (map[string]string, error) {
+	var serviceUrl string = "https://api.mch.weixin.qq.com/mmpaymkttransfers/gethbinfo"
+	return secureRequest(serviceUrl, params, certFile, keyFile)
+}
+
+func secureRequest(serviceUrl string, params UnionPayRequest, certFile, keyFile string) (map[string]string, error) {
+	reqBytes, err := xml.Marshal(params)
+	if err != nil {
+		return nil, err
+	}
+	reader := bytes.NewReader(reqBytes)
+	client, err := getSecureClient(certFile, keyFile)
+	if err != nil {
+		return nil, err
+	}
+	resp, err := client.Post(serviceUrl, "application/xml", reader)
+	if err != nil {
+		return nil, err
+	}
+	defer resp.Body.Close()
+	ret := xmlToMap(resp.Body)
+
+	return ret, nil
+}
+
+func (weixin *defaultWeixin) Send(msg Message, token string) error {
+	var serviceUrl string = "https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=" + token
+	var buffer bytes.Buffer
+
+	enc := json.NewEncoder(&buffer)
+	enc.SetEscapeHTML(false)
+	err := enc.Encode(msg)
+	if err != nil {
+		return err
+	}
+	reader := bytes.NewReader(buffer.Bytes())
+	resp, err := http.Post(serviceUrl, "application/json", reader)
+	if err != nil {
+		return err
+	}
+	defer resp.Body.Close()
+	buf, err := ioutil.ReadAll(resp.Body)
+	if err != nil {
+		return err
+	}
+	var httpRes = struct {
+		ErrCode uint16 `json:"errcode"`
+		ErrMsg  string `json:"errmsg"`
+	}{}
+	err = json.Unmarshal(buf, &httpRes)
+	if err != nil {
+		return err
+	}
+	if httpRes.ErrCode == 0 {
+		return nil
+	} else {
+		return errors.New(httpRes.ErrMsg)
+	}
+}
+
+func (weixin *defaultWeixin) SendTpl(msg string, token, wxType string) error {
+	var serviceUrl string = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token="
+	if wxType == "mp" {
+		serviceUrl = "https://api.weixin.qq.com/cgi-bin/message/wxopen/template/send?access_token="
+	}
+	serviceUrl += token
+	reader := bytes.NewReader([]byte(msg))
+	resp, err := http.Post(serviceUrl, "application/json", reader)
+	if err != nil {
+		return err
+	}
+	defer resp.Body.Close()
+	buf, err := ioutil.ReadAll(resp.Body)
+	if err != nil {
+		return err
+	}
+	var httpRes = struct {
+		ErrCode uint16 `json:"errcode"`
+		ErrMsg  string `json:"errmsg"`
+		MsgId   uint64 `json:"msgid"`
+	}{}
+	err = json.Unmarshal(buf, &httpRes)
+	if err != nil {
+		//return err
+		return fmt.Errorf("%s", string(buf))
+	}
+	if httpRes.ErrCode == 0 {
+		return nil
+	} else {
+		//return errors.New(httpRes.ErrMsg)
+		return fmt.Errorf("%d::%s", httpRes.ErrCode, httpRes.ErrMsg)
+	}
+}
+
+func getSecureClient(certFile, keyFile string) (*http.Client, error) {
+	cert, err := tls.LoadX509KeyPair(certFile, keyFile)
+	if err != nil {
+		return nil, err
+	}
+	ssl := &tls.Config{
+		Certificates: []tls.Certificate{cert},
+	}
+	return &http.Client{
+		Transport: &http.Transport{
+			TLSClientConfig: ssl,
+		},
+	}, nil
+}
+
+func xmlToMap(r io.Reader) map[string]string {
+	m := make(map[string]string)
+	// the current value stack
+	values := make([]string, 0)
+
+	p := xml.NewDecoder(r)
+	for token, err := p.Token(); err == nil; token, err = p.Token() {
+		switch t := token.(type) {
+		case xml.CharData:
+			// push
+			values = append(values, string([]byte(t)))
+		case xml.EndElement:
+			if t.Name.Local == "xml" {
+				continue
+			}
+			m[t.Name.Local] = values[len(values)-1]
+			// pop
+			values = values[:len(values)]
+		}
+	}
+	return m
+}

+ 0 - 0
retry/retry.go


Some files were not shown because too many files changed in this diff