From fa38f3312baf970b6c14a6c9b66f1c709fa294d8 Mon Sep 17 00:00:00 2001 From: DengBiao <2319963317@qq.com> Date: Wed, 28 Sep 2022 19:45:27 +0800 Subject: [PATCH] first commit --- db/db.go | 84 ---- db/model/pay_channel.go | 18 - db/model/pay_channel_master.go | 12 - db/model/sys_cfg.go | 7 - go.mod | 5 +- lib/icbc/api.go | 151 -------- lib/local_alipay/api.go | 176 --------- lib/local_wechat/api.go | 303 --------------- md/alipay.go | 17 - md/app_redis_key.go | 19 - md/basic.go | 6 - md/cfg.go | 15 + md/cfg_app.go | 16 - md/icbc.go | 12 - md/join.go | 102 ----- md/join_bank_card_pay.go | 11 - md/kudian.go | 69 ---- md/platform.go | 40 -- md/wxpay.go | 40 -- pay/init.go | 34 -- pay/logs/1.txt | 0 pay/logs/zyos_website.logs | 2 - pay/pay_by_icbcmo.go | 26 -- pay/pay_by_join.go | 146 ------- pay/pay_by_join_bank_card.go | 203 ---------- pay/pay_by_kudian.go | 208 ---------- pay/pay_by_own.go | 117 ------ pay/pay_config.go | 36 -- pay/pay_test.go | 41 -- pay/tmp/1.txt | 0 pay/tmp/zyos_website.logs | 1 - rabbit/init.go | 39 ++ rabbit/pool.go | 390 +++++++++++++++++++ rabbitmq/init.go | 16 + rabbitmq/tools.go | 187 +++++++++ test/direct_exchange.md | 14 + test/direct_exchange_test.go | 83 ++++ test/fanout_exchange.md | 18 + test/fanout_exchange_test.go | 72 ++++ test/join_pay_test.go | 11 - test/single_queue.md | 14 + test/single_queue_test.go | 111 ++++++ test/topic_exchange.md | 33 ++ test/topic_exchange_test.go | 73 ++++ test/work_queue.md | 15 + test/work_queue_test.go | 76 ++++ utils/cache/base.go | 421 -------------------- utils/cache/redis.go | 403 ------------------- utils/cache/redis_cluster.go | 622 ------------------------------ utils/cache/redis_pool.go | 324 ---------------- utils/cache/redis_pool_cluster.go | 617 ----------------------------- utils/convert.go | 366 ------------------ utils/curl.go | 209 ---------- utils/file.go | 22 -- utils/logx/log.go | 245 ------------ utils/logx/output.go | 105 ----- utils/logx/sugar.go | 192 --------- utils/md5.go | 12 - utils/serialize.go | 23 -- 59 files changed, 1159 insertions(+), 5471 deletions(-) delete mode 100644 db/db.go delete mode 100644 db/model/pay_channel.go delete mode 100644 db/model/pay_channel_master.go delete mode 100644 db/model/sys_cfg.go delete mode 100644 lib/icbc/api.go delete mode 100644 lib/local_alipay/api.go delete mode 100644 lib/local_wechat/api.go delete mode 100644 md/alipay.go delete mode 100644 md/app_redis_key.go delete mode 100644 md/basic.go create mode 100644 md/cfg.go delete mode 100644 md/cfg_app.go delete mode 100644 md/icbc.go delete mode 100644 md/join.go delete mode 100644 md/join_bank_card_pay.go delete mode 100644 md/kudian.go delete mode 100644 md/platform.go delete mode 100644 md/wxpay.go delete mode 100644 pay/init.go delete mode 100644 pay/logs/1.txt delete mode 100644 pay/logs/zyos_website.logs delete mode 100644 pay/pay_by_icbcmo.go delete mode 100644 pay/pay_by_join.go delete mode 100644 pay/pay_by_join_bank_card.go delete mode 100644 pay/pay_by_kudian.go delete mode 100644 pay/pay_by_own.go delete mode 100644 pay/pay_config.go delete mode 100644 pay/pay_test.go delete mode 100644 pay/tmp/1.txt delete mode 100644 pay/tmp/zyos_website.logs create mode 100644 rabbit/init.go create mode 100644 rabbit/pool.go create mode 100644 rabbitmq/init.go create mode 100644 rabbitmq/tools.go create mode 100644 test/direct_exchange.md create mode 100644 test/direct_exchange_test.go create mode 100644 test/fanout_exchange.md create mode 100644 test/fanout_exchange_test.go delete mode 100644 test/join_pay_test.go create mode 100644 test/single_queue.md create mode 100644 test/single_queue_test.go create mode 100644 test/topic_exchange.md create mode 100644 test/topic_exchange_test.go create mode 100644 test/work_queue.md create mode 100644 test/work_queue_test.go delete mode 100644 utils/cache/base.go delete mode 100644 utils/cache/redis.go delete mode 100644 utils/cache/redis_cluster.go delete mode 100644 utils/cache/redis_pool.go delete mode 100644 utils/cache/redis_pool_cluster.go delete mode 100644 utils/convert.go delete mode 100644 utils/curl.go delete mode 100644 utils/file.go delete mode 100644 utils/logx/log.go delete mode 100644 utils/logx/output.go delete mode 100644 utils/logx/sugar.go delete mode 100644 utils/md5.go delete mode 100644 utils/serialize.go diff --git a/db/db.go b/db/db.go deleted file mode 100644 index cc3e6cc..0000000 --- a/db/db.go +++ /dev/null @@ -1,84 +0,0 @@ -package db - -import ( - "code.fnuoos.com/go_rely_warehouse/zyos_go_pay.git/md" - "database/sql" - "fmt" - _ "github.com/go-sql-driver/mysql" //必须导入mysql驱动,否则会panic - "os" - "time" - "xorm.io/xorm" - "xorm.io/xorm/log" -) - -var Db *xorm.Engine - -//根据DB配置文件初始化数据库 -func InitDB(c *md.DBCfg) error { - var ( - err error - f *os.File - ) - //创建Orm引擎 - if Db, err = xorm.NewEngine("mysql", fmt.Sprintf("%s:%s@tcp(%s)/%s?charset=utf8mb4", c.User, c.Psw, c.Host, c.Name)); err != nil { - return err - } - Db.SetConnMaxLifetime(c.MaxLifetime * time.Second) //设置最长连接时间 - Db.SetMaxOpenConns(c.MaxOpenConns) //设置最大打开连接数 - Db.SetMaxIdleConns(c.MaxIdleConns) //设置连接池的空闲数大小 - if err = Db.Ping(); err != nil { //尝试ping数据库 - return err - } - if c.ShowLog { //根据配置文件设置日志 - Db.ShowSQL(true) //设置是否打印sql - Db.Logger().SetLevel(0) //设置日志等级 - //修改日志文件存放路径文件名是%s.logs - path := fmt.Sprintf(c.Path, c.Name) - f, err = os.OpenFile(path, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0777) - if err != nil { - os.RemoveAll(c.Path) - if f, err = os.OpenFile(c.Path, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0777); err != nil { - return err - } - } - logger := log.NewSimpleLogger(f) - logger.ShowSQL(true) - Db.SetLogger(logger) - } - return nil -} - -/********************************************* 公用方法 *********************************************/ - -// QueryNativeString 查询原生sql -func QueryNativeString(Db *xorm.Engine, sql string, args ...interface{}) ([]map[string]string, error) { - results, err := Db.SQL(sql, args...).QueryString() - return results, err -} - -// UpdateComm common update -func UpdateComm(Db *xorm.Engine, id interface{}, model interface{}) (int64, error) { - row, err := Db.ID(id).Update(model) - return row, err -} - -// InsertComm common insert -func InsertComm(Db *xorm.Engine, model interface{}) (int64, error) { - row, err := Db.InsertOne(model) - return row, err -} - -// InsertCommWithSession common insert -func InsertCommWithSession(session *xorm.Session, model interface{}) (int64, error) { - row, err := session.InsertOne(model) - return row, err -} - -// ExecuteOriginalSql 执行原生sql -func ExecuteOriginalSql(session *xorm.Session, sql string) (sql.Result, error) { - result, err := session.Exec(sql) - if err != nil { - return nil, err - } - return result, nil -} diff --git a/db/model/pay_channel.go b/db/model/pay_channel.go deleted file mode 100644 index 702a641..0000000 --- a/db/model/pay_channel.go +++ /dev/null @@ -1,18 +0,0 @@ -package model - -import "time" - -type PayChannel struct { - Id int `json:"id" xorm:"not null pk autoincr INT(11)"` - Name string `json:"name" xorm:"not null comment('渠道名称') VARCHAR(255)"` - IsUse int `json:"is_use" xorm:"not null default 1 comment('是否开启;1:开启;0:关闭') TINYINT(1)"` - ThirdPartyId string `json:"third_party_id" xorm:"not null comment('第三方聚合支付的渠道id') VARCHAR(20)"` - Kind string `json:"kind" xorm:"not null comment('渠道种类(self:自有支付 zhiYing:智莺支付 thirdParty 第三方聚合支付 )') VARCHAR(255)"` - ModuleIdentifier string `json:"module_identifier" xorm:"not null comment('模块标识符') VARCHAR(255)"` - ModuleName string `json:"module_name" xorm:"not null comment('模块名称') VARCHAR(255)"` - CommissionRate string `json:"commission_rate" xorm:"not null comment('抽成比例(千分之)') VARCHAR(255)"` - Memo string `json:"memo" xorm:"not null comment('备注') VARCHAR(255)"` - Ext string `json:"ext" xorm:"comment('拓展字段(json存储)') TEXT"` - CreateAt time.Time `json:"create_at" xorm:"default 'CURRENT_TIMESTAMP' comment('创建时间') TIMESTAMP"` - UpdateAt time.Time `json:"update_at" xorm:"default 'CURRENT_TIMESTAMP' comment('更新时间') TIMESTAMP"` -} diff --git a/db/model/pay_channel_master.go b/db/model/pay_channel_master.go deleted file mode 100644 index c72f497..0000000 --- a/db/model/pay_channel_master.go +++ /dev/null @@ -1,12 +0,0 @@ -package model - -type PayChannelMaster struct { - Id int `json:"id" xorm:"not null pk autoincr INT(11)"` - ChannelId int `json:"channel_id" xorm:"not null default 1 comment('支付通道id') INT(11)"` - Identifier string `json:"identifier" xorm:"not null comment('场景标识符') VARCHAR(255)"` - MasterId int `json:"master_id" xorm:"not null default 1 comment('站长id') INT(11)"` - MasterNickname string `json:"master_nickname" xorm:"not null comment('站长名称') VARCHAR(255)"` - ThirdPartyId string `json:"third_party_id" xorm:"not null comment('第三方聚合支付的渠道id') VARCHAR(50)"` - MasterAppName string `json:"master_app_name" xorm:"not null comment('站长应用名称') VARCHAR(50)"` - AppId int `json:"app_id" xorm:"not null default 1 comment('应用id(mid)') INT(20)"` -} diff --git a/db/model/sys_cfg.go b/db/model/sys_cfg.go deleted file mode 100644 index 22d906b..0000000 --- a/db/model/sys_cfg.go +++ /dev/null @@ -1,7 +0,0 @@ -package model - -type SysCfg struct { - Key string `json:"key" xorm:"not null pk comment('键') VARCHAR(127)"` - Val string `json:"val" xorm:"comment('值') TEXT"` - Memo string `json:"memo" xorm:"not null default '' comment('备注') VARCHAR(255)"` -} diff --git a/go.mod b/go.mod index 17610f7..9de5d1e 100644 --- a/go.mod +++ b/go.mod @@ -1,8 +1,9 @@ -module code.fnuoos.com/go_rely_warehouse/zyos_go_pay.git +module code.fnuoos.com/go_rely_warehouse/zyos_go_mq.git go 1.15 require ( + code.fnuoos.com/go_rely_warehouse/zyos_go_pay.git v1.4.4 github.com/forgoer/openssl v1.2.1 github.com/gin-gonic/gin v1.8.0 github.com/go-redis/redis v6.15.9+incompatible @@ -10,10 +11,10 @@ require ( github.com/gomodule/redigo v1.8.8 github.com/iGoogle-ink/gopay v1.5.36 github.com/pkg/errors v0.9.1 + github.com/streadway/amqp v1.0.0 // indirect github.com/syyongx/php2go v0.9.7 go.uber.org/zap v1.16.0 golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97 gopkg.in/natefinch/lumberjack.v2 v2.0.0 - xorm.io/builder v0.3.10 // indirect xorm.io/xorm v1.3.0 ) diff --git a/lib/icbc/api.go b/lib/icbc/api.go deleted file mode 100644 index afdd29a..0000000 --- a/lib/icbc/api.go +++ /dev/null @@ -1,151 +0,0 @@ -package icbc - -import ( - "code.fnuoos.com/go_rely_warehouse/zyos_go_pay.git/md" - zhios_pay_utils "code.fnuoos.com/go_rely_warehouse/zyos_go_pay.git/utils" - "crypto" - "crypto/rand" - "crypto/rsa" - "encoding/base64" - "encoding/json" - "errors" - "fmt" - "golang.org/x/crypto/ssh" - "sort" - "strings" - "time" -) - -func ShowIntegral(appId, privateKeyStr string, param map[string]string) (int, error) { - bizContent := map[string]string{ - "name": param["name"], //客户姓名 - "mobile": param["mobile"], //手机号码 - "mobileArea": param["mobileArea"], //手机国际代码 853、852、86 - "optFlag": param["optFlag"], //客户姓名 - "cardNo": param["cardNo"], - "cardType": param["cardType"], - } - if param["optFlag"] == "1" { - bizContent["otp"] = param["otp"] - } - marshal, _ := json.Marshal(bizContent) - param["biz_content"] = string(marshal) - send := Send("/macaufh/mybank/account/cuscredit/cuscreditquery/V1", appId, privateKeyStr, param) - var data = md.IcbcRes{} - err := json.Unmarshal([]byte(send), &data) - fmt.Println("icbc===============", send) - fmt.Println("icbc===============", err) - var cusCredit = 0 - if err != nil { - return cusCredit, err - } - if data.ResponseBizContent.Success { - return data.ResponseBizContent.CusCredit, nil - } - return cusCredit, errors.New(data.ResponseBizContent.ReturnMsg) -} - -//积分扣除 -func DeductIntegral(appId, privateKeyStr string, param map[string]string) error { - bizContent := map[string]string{ - "name": param["name"], //客户姓名 - "mobile": param["mobile"], //手机号码 - "mobileArea": param["mobileArea"], //手机国际代码 853、852、86 - "optFlag": param["optFlag"], //客户姓名 - "cardNo": param["cardNo"], - "cardType": param["cardType"], - "cusCredit": param["cusCredit"], - } - if param["optFlag"] == "1" { - bizContent["otp"] = param["otp"] - } - marshal, _ := json.Marshal(bizContent) - param["biz_content"] = string(marshal) - send := Send("/macaufh/mybank/account/cuscredit/cuscreditconsume/V1", appId, privateKeyStr, param) - var data = md.IcbcRes{} - err := json.Unmarshal([]byte(send), &data) - fmt.Println("icbc===============", send) - fmt.Println("icbc===============", err) - if err != nil { - return err - } - if data.ResponseBizContent.Success { - return nil - } - return errors.New(data.ResponseBizContent.ReturnMsg) - -} -func DefaultParam(method, appId, privateKeyStr string, param map[string]string) map[string]interface{} { - now := time.Now() - arg := map[string]interface{}{ - "app_id": appId, - "msg_id": zhios_pay_utils.Int64ToStr(now.Unix()), - "format": "json", - "charset": "utf-8", - "sign_type": "RSA2", - "timestamp": now.Format("2006-01-02 15:04:05"), - } - if param["biz_content"] != "" { - arg["biz_content"] = param["biz_content"] - } - getSign, err2 := GetSign(method, privateKeyStr, arg) - if err2 != nil { - return nil - } - fmt.Println(getSign) - arg["sign"] = getSign - return arg -} -func Send(method string, appId, privateKeyStr string, param map[string]string) string { - req := DefaultParam(method, appId, privateKeyStr, param) - url := "https://apipcs.icbcmo.site/api" + method - headers := map[string]string{ - "Content-Type": "application/x-www-form-urlencoded", - } - fmt.Println(req) - - //for k, v := range req { - // if strings.Contains(url, "?") == false { - // url += "?" + k + "=" + php2go.URLEncode(v.(string)) - // } else { - // url += "&" + k + "=" + php2go.URLEncode(v.(string)) - // } - //} - fmt.Println(url) - res, err := zhios_pay_utils.CurlPost(url, req, headers) - if err != nil { - fmt.Println(err) - return "" - } - fmt.Println(string(res)) - return string(res) -} -func GetSign(method, privateKeyStr string, param map[string]interface{}) (string, error) { - privateKey, err := ssh.ParseRawPrivateKey([]byte(privateKeyStr)) - if err != nil { - return "", err - } - keys := make([]string, 0, len(param)) - for k := range param { - keys = append(keys, k) - } - sort.Strings(keys) - data := "/api" + method - for _, v := range keys { - if strings.Contains(data, "?") == false { - data += "?" + v + "=" + param[v].(string) - } else { - data += "&" + v + "=" + param[v].(string) - } - } - fmt.Println(privateKey.(*rsa.PrivateKey)) - fmt.Println(data) - h := crypto.Hash.New(crypto.SHA256) - h.Write([]byte(data)) - hashed := h.Sum(nil) - sign, err := rsa.SignPKCS1v15(rand.Reader, privateKey.(*rsa.PrivateKey), crypto.SHA256, hashed) - if err != nil { - return "", nil - } - return base64.StdEncoding.EncodeToString(sign), nil -} diff --git a/lib/local_alipay/api.go b/lib/local_alipay/api.go deleted file mode 100644 index 2723e41..0000000 --- a/lib/local_alipay/api.go +++ /dev/null @@ -1,176 +0,0 @@ -package local_alipay - -import ( - "code.fnuoos.com/go_rely_warehouse/zyos_go_pay.git/md" - "fmt" - "github.com/iGoogle-ink/gopay" - "github.com/iGoogle-ink/gopay/alipay" -) - -// TradeAppPay is 支付宝APP支付 -// 抖音头条小程序使用APP调起 -func TradeAppPay(appID, priKey, subject, orderID, amount, notiURL, RSA, PKCS string, paySet *md.PayData) (string, error) { - //初始化支付宝客户端 - // appID 是在支付宝申请的APPID - // priKey 是支付宝私钥 - // subject 是支付订单的主题 - // orderID 是智莺这边生成的订单id - // amount 是付费金额 - // notiURL 通知地址url - // passback_params 回调通知参数 - - client := alipay.NewClient(appID, priKey, true) - client.DebugSwitch = gopay.DebugOn - //判断密钥的类型 - rsa_type := alipay.RSA2 - pkcs_type := alipay.PKCS1 - if RSA == "1" { - rsa_type = alipay.RSA - } - if PKCS == "1" { - pkcs_type = alipay.PKCS8 - } - if paySet.PayAliUseType == "1" { - rsa_type = alipay.RSA2 - pkcs_type = alipay.PKCS8 - } - //配置公共参数 - client.SetCharset("utf-8"). - SetSignType(rsa_type). - SetPrivateKeyType(pkcs_type) - if notiURL != "" { - client.SetNotifyUrl(notiURL) - } - //新支付宝支付 - if paySet.PayAliUseType == "1" { - client.SetAppCertSN(paySet.PayAppCertSn) - aliPayRootCertSN := "687b59193f3f462dd5336e5abf83c5d8_02941eef3187dddf3d3b83462e1dfcf6" - client.SetAliPayRootCertSN(aliPayRootCertSN) - client.SetAliPayPublicCertSN(paySet.PayAlipayrsaPublicKey) - } - fmt.Println(client) - //请求参数 - body := make(gopay.BodyMap) - body.Set("subject", subject) - body.Set("body", subject) - body.Set("out_trade_no", orderID) - body.Set("total_amount", amount) - body.Set("timeout_express", "30m") - - // body.Set("passback_params", orderID) - //手机APP支付参数请求 - payParam, err := client.TradeAppPay(body) - if err != nil { - return "", err - } - return payParam, nil -} - -// TradeAppPay is 支付宝H5支付 -func TradeWapPay(appID, priKey, subject, orderID, amount, notiURL, RSA, PKCS, page_url string, paySet *md.PayData) (string, error) { - //aliPayPublicKey := "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1wn1sU/8Q0rYLlZ6sq3enrPZw2ptp6FecHR2bBFLjJ+sKzepROd0bKddgj+Mr1ffr3Ej78mLdWV8IzLfpXUi945DkrQcOUWLY0MHhYVG2jSs/qzFfpzmtut2Cl2TozYpE84zom9ei06u2AXLMBkU6VpznZl+R4qIgnUfByt3Ix5b3h4Cl6gzXMAB1hJrrrCkq+WvWb3Fy0vmk/DUbJEz8i8mQPff2gsHBE1nMPvHVAMw1GMk9ImB4PxucVek4ZbUzVqxZXphaAgUXFK2FSFU+Q+q1SPvHbUsjtIyL+cLA6H/6ybFF9Ffp27Y14AHPw29+243/SpMisbGcj2KD+evBwIDAQAB" - privateKey := priKey - //判断密钥的类型 - rsa_type := alipay.RSA2 - pkcs_type := alipay.PKCS1 - if RSA == "1" { - rsa_type = alipay.RSA - } - if PKCS == "1" { - pkcs_type = alipay.PKCS8 - } - if paySet.PayAliUseType == "1" { - rsa_type = alipay.RSA2 - pkcs_type = alipay.PKCS8 - } - //初始化支付宝客户端 - // appId:应用ID - // privateKey:应用秘钥 - // isProd:是否是正式环境 - client := alipay.NewClient(appID, privateKey, true) - //配置公共参数 - client.SetCharset("utf-8"). - SetSignType(rsa_type). - SetPrivateKeyType(pkcs_type). - SetReturnUrl(page_url). - SetNotifyUrl(notiURL) - //新支付宝支付 - if paySet.PayAliUseType == "1" { - client.SetAppCertSN(paySet.PayAppCertSn) - aliPayRootCertSN := "687b59193f3f462dd5336e5abf83c5d8_02941eef3187dddf3d3b83462e1dfcf6" - client.SetAliPayRootCertSN(aliPayRootCertSN) - client.SetAliPayPublicCertSN(paySet.PayAlipayrsaPublicKey) - } - //请求参数 - body := make(gopay.BodyMap) - body.Set("subject", subject) - body.Set("out_trade_no", orderID) - // quit_url is 用户付款中途退出返回商户网站的地址 - body.Set("quit_url", notiURL) - body.Set("total_amount", amount) - // product_code is 销售产品码,商家和支付宝签约的产品码 - body.Set("product_code", "QUICK_WAP_WAY") - //手机网站支付请求 - payUrl, err := client.TradeWapPay(body) - if err != nil { - return "", err - - } - return payUrl, nil -} - -// TradeAppPay is 支付宝小程序本身支付 -func TradeCreate(appID, priKey, subject, orderID, amount, notiURL, RSA, PKCS string, paySet *md.PayData) (*alipay.TradeCreateResponse, error) { - //aliPayPublicKey := "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1wn1sU/8Q0rYLlZ6sq3enrPZw2ptp6FecHR2bBFLjJ+sKzepROd0bKddgj+Mr1ffr3Ej78mLdWV8IzLfpXUi945DkrQcOUWLY0MHhYVG2jSs/qzFfpzmtut2Cl2TozYpE84zom9ei06u2AXLMBkU6VpznZl+R4qIgnUfByt3Ix5b3h4Cl6gzXMAB1hJrrrCkq+WvWb3Fy0vmk/DUbJEz8i8mQPff2gsHBE1nMPvHVAMw1GMk9ImB4PxucVek4ZbUzVqxZXphaAgUXFK2FSFU+Q+q1SPvHbUsjtIyL+cLA6H/6ybFF9Ffp27Y14AHPw29+243/SpMisbGcj2KD+evBwIDAQAB" - privateKey := priKey - rsa_type := alipay.RSA2 - pkcs_type := alipay.PKCS1 - if RSA == "1" { - rsa_type = alipay.RSA - } - if PKCS == "1" { - pkcs_type = alipay.PKCS8 - } - if paySet.PayAliUseType == "1" { - rsa_type = alipay.RSA2 - pkcs_type = alipay.PKCS8 - } - //初始化支付宝客户端 - // appId:应用ID - // privateKey:应用私钥,支持PKCS1和PKCS8 - // isProd:是否是正式环境 - client := alipay.NewClient(appID, privateKey, true) - //配置公共参数 - client.SetCharset("utf-8"). - SetSignType(rsa_type). - SetPrivateKeyType(pkcs_type). - SetNotifyUrl(notiURL) - if paySet.PayAliUseType == "1" { - client.SetAppCertSN(paySet.PayAppCertSn) - aliPayRootCertSN := "687b59193f3f462dd5336e5abf83c5d8_02941eef3187dddf3d3b83462e1dfcf6" - client.SetAliPayRootCertSN(aliPayRootCertSN) - client.SetAliPayPublicCertSN(paySet.PayAlipayrsaPublicKey) - } - //请求参数 - body := make(gopay.BodyMap) - body.Set("subject", subject) - // 支付宝小程序支付时 buyer_id 为必传参数,需要提前获取,获取方法如下两种 - // 1、local_alipay.SystemOauthToken() 返回取值:rsp.SystemOauthTokenResponse.UserId - // 2、client.SystemOauthToken() 返回取值:aliRsp.SystemOauthTokenResponse.UserId - buyer_id, err := client.SystemOauthToken(body) - if err != nil { - return nil, err - } - body.Set("buyer_id", buyer_id) - body.Set("out_trade_no", orderID) - body.Set("total_amount", amount) - //创建订单 - aliRsp, err := client.TradeCreate(body) - - if err != nil { - return nil, err - } - - return aliRsp, nil - -} diff --git a/lib/local_wechat/api.go b/lib/local_wechat/api.go deleted file mode 100644 index b89835a..0000000 --- a/lib/local_wechat/api.go +++ /dev/null @@ -1,303 +0,0 @@ -package local_wxpay - -import ( - zhios_pay_utils "code.fnuoos.com/go_rely_warehouse/zyos_go_pay.git/utils" - "code.fnuoos.com/go_rely_warehouse/zyos_go_pay.git/utils/logx" - "fmt" - "github.com/iGoogle-ink/gopay" - "github.com/iGoogle-ink/gopay/pkg/util" - "github.com/iGoogle-ink/gopay/wechat" - v3 "github.com/iGoogle-ink/gopay/wechat/v3" - "strconv" - "time" -) - -func NewClient(appId, mchId, apiKey string, isProd bool) *wechat.Client { - // 初始化微信客户端 - // appId:应用ID - // mchId:商户ID - // apiKey:API秘钥值 - // isProd:是否是正式环境 - client := wechat.NewClient(appId, mchId, apiKey, isProd) - // 打开Debug开关,输出请求日志,默认关闭 - client.DebugSwitch = gopay.DebugOn - // 设置国家:不设置默认 中国国内 - // wechat.China:中国国内 - // wechat.China2:中国国内备用 - // wechat.SoutheastAsia:东南亚 - // wechat.Other:其他国家 - client.SetCountry(wechat.China) - // 添加微信证书 Path 路径 - // certFilePath:apiclient_cert.pem 路径 - // keyFilePath:apiclient_key.pem 路径 - // pkcs12FilePath:apiclient_cert.p12 路径 - // 返回err - //client.AddCertFilePath() - - // 添加微信证书内容 Content - // certFileContent:apiclient_cert.pem 内容 - // keyFileContent:apiclient_key.pem 内容 - // pkcs12FileContent:apiclient_cert.p12 内容 - // 返回err - //client.AddCertFileContent() - return client -} - -// TradeAppPay is 微信APP支付 -func TradeAppPay(client *wechat.Client, subject, orderID, amount, notifyUrl string) (map[string]string, error) { - // 初始化 BodyMap - bm := make(gopay.BodyMap) - bm.Set("nonce_str", util.GetRandomString(32)). - Set("body", subject). - Set("out_trade_no", orderID). - Set("total_fee", amount). - Set("spbill_create_ip", "127.0.0.1"). - Set("notify_url", notifyUrl). - Set("trade_type", wechat.TradeType_App). - Set("sign_type", wechat.SignType_MD5) - /*.Set("openid", "o0Df70H2Q0fY8JXh1aFPIRyOBgu8")*/ - // 预下单 - wxRsp, err := client.UnifiedOrder(bm) - if err != nil { - _ = zhios_pay_logx.Warn(err) - return nil, err - } - _, err = wechat.VerifySign(client.ApiKey, wechat.SignType_MD5, wxRsp) - if err != nil { - _ = zhios_pay_logx.Warn(err) - return nil, err - } - //if !ok { - // return nil, errors.New("验签失败") - //} - timeStamp := strconv.FormatInt(time.Now().Unix(), 10) - paySign := wechat.GetAppPaySign(client.AppId, client.MchId, wxRsp.NonceStr, wxRsp.PrepayId, wechat.SignType_MD5, timeStamp, client.ApiKey) - res := map[string]string{ - "appid": client.AppId, - "partnerid": client.MchId, - "prepayid": wxRsp.PrepayId, - "sign": paySign, - "package": "Sign=WXPay", - "noncestr": wxRsp.NonceStr, - "timestamp": timeStamp, - } - return res, nil -} - -// TradeAppPay is 微信H5支付 -func TradeH5Pay(client *wechat.Client, subject, orderID, amount, notifyUrl string) (map[string]string, error) { - // 初始化 BodyMap - bm := make(gopay.BodyMap) - bm.Set("nonce_str", util.GetRandomString(32)). - Set("body", subject). - Set("out_trade_no", orderID). - Set("total_fee", amount). - Set("spbill_create_ip", "121.196.29.49"). - Set("notify_url", notifyUrl). - Set("trade_type", wechat.TradeType_H5). - Set("sign_type", wechat.SignType_MD5). - SetBodyMap("scene_info", func(bm gopay.BodyMap) { - bm.SetBodyMap("h5_info", func(bm gopay.BodyMap) { - bm.Set("type", "Wap") - bm.Set("wap_url", "https://www.fumm.cc") - bm.Set("wap_name", "zyos") - }) - }) - /*.Set("openid", "o0Df70H2Q0fY8JXh1aFPIRyOBgu8")*/ - // 预下单 - wxRsp, err := client.UnifiedOrder(bm) - if err != nil { - _ = zhios_pay_logx.Warn(err) - return nil, err - } - _, err = wechat.VerifySign(client.ApiKey, wechat.SignType_MD5, wxRsp) - if err != nil { - _ = zhios_pay_logx.Warn(err) - return nil, err - } - timeStamp := strconv.FormatInt(time.Now().Unix(), 10) - packages := "prepay_id=" + wxRsp.PrepayId - paySign := wechat.GetH5PaySign(client.AppId, wxRsp.NonceStr, packages, wechat.SignType_MD5, timeStamp, client.ApiKey) - fmt.Println("paySign===", paySign) - r := map[string]string{ - "redirect_url": wxRsp.MwebUrl, - } - return r, nil -} - -// TradeMiniProgPay is 微信小程序支付 ☑️ -func TradeMiniProgPay(client *wechat.Client, subject, orderID, amount, notifyUrl, openid string) (map[string]string, error) { - // 初始化 BodyMap - bm := make(gopay.BodyMap) - bm.Set("nonce_str", util.GetRandomString(32)). - Set("body", subject). - Set("openid", openid). - Set("out_trade_no", orderID). - Set("total_fee", amount). - Set("spbill_create_ip", "127.0.0.1"). - Set("notify_url", notifyUrl). - Set("trade_type", wechat.TradeType_Mini). - Set("sign_type", wechat.SignType_MD5) - // 预下单 - wxRsp, err := client.UnifiedOrder(bm) - if err != nil { - _ = zhios_pay_logx.Warn(err) - return nil, err - } - fmt.Println(wxRsp) - timeStamp := strconv.FormatInt(time.Now().Unix(), 10) - packages := "prepay_id=" + wxRsp.PrepayId - paySign := wechat.GetMiniPaySign(client.AppId, wxRsp.NonceStr, packages, wechat.SignType_MD5, timeStamp, client.ApiKey) - res := map[string]string{ - "appId": client.AppId, - "paySign": paySign, - "signType": wechat.SignType_MD5, - "package": packages, - "nonceStr": wxRsp.NonceStr, - "timeStamp": timeStamp, - } - return res, nil -} - -// TradeAppPayV3 is 微信APP支付v3 -func TradeAppPayV3(client *v3.ClientV3, subject, orderID, amount, notifyUrl string) (map[string]string, error) { - // 初始化 BodyMap - amountNew := zhios_pay_utils.AnyToFloat64(amount) * 100 - bm := make(gopay.BodyMap) - bm.Set("nonce_str", util.GetRandomString(32)). - Set("body", subject). - Set("out_trade_no", orderID). - Set("total_fee", amountNew). - Set("spbill_create_ip", "127.0.0.1"). - Set("notify_url", notifyUrl). - Set("trade_type", wechat.TradeType_App). - Set("sign_type", wechat.SignType_MD5) - /*.Set("openid", "o0Df70H2Q0fY8JXh1aFPIRyOBgu8")*/ - //// 预下单 - //wxRsp, err := v3.UnifiedOrder(bm) - //if err != nil { - // _ = zhios_pay_logx.Warn(err) - // return nil, err - //} - //_, err = wechat.VerifySign(client.ApiKey, wechat.SignType_MD5, wxRsp) - //if err != nil { - // _ = zhios_pay_logx.Warn(err) - // return nil, err - //} - ////if !ok { - //// return nil, errors.New("验签失败") - ////} - //timeStamp := strconv.FormatInt(time.Now().Unix(), 10) - //paySign := wechat.GetAppPaySign(client.AppId, client.MchId, wxRsp.NonceStr, wxRsp.PrepayId, wechat.SignType_MD5, timeStamp, client.ApiKey) - //res := map[string]string{ - // "appid": client.AppId, - // "partnerid": client.MchId, - // "prepayid": wxRsp.PrepayId, - // "sign": paySign, - // "package": "Sign=WXPay", - // "noncestr": wxRsp.NonceStr, - // "timestamp": timeStamp, - //} - //return res, nil - return nil, nil -} - -//// TradeJSAPIPay is 微信JSAPI支付 -func TradeJSAPIPay(client *wechat.Client, subject, orderID, amount, notifyUrl, openid string) (map[string]string, error) { - // 初始化 BodyMap - bm := make(gopay.BodyMap) - bm.Set("nonce_str", util.GetRandomString(32)). - Set("body", subject). - Set("out_trade_no", orderID). - Set("total_fee", amount). - Set("spbill_create_ip", "121.196.29.49"). - Set("notify_url", notifyUrl). - Set("trade_type", wechat.TradeType_JsApi). - Set("sign_type", wechat.SignType_MD5). - Set("openid", openid). - SetBodyMap("scene_info", func(bm gopay.BodyMap) { - bm.SetBodyMap("h5_info", func(bm gopay.BodyMap) { - bm.Set("type", "Wap") - bm.Set("wap_url", "https://www.fumm.cc") - bm.Set("wap_name", "zyos") - }) - }) - // 预下单 - wxRsp, err := client.UnifiedOrder(bm) - if err != nil { - _ = zhios_pay_logx.Warn(err) - return nil, err - } - _, err = wechat.VerifySign(client.ApiKey, wechat.SignType_MD5, wxRsp) - if err != nil { - _ = zhios_pay_logx.Warn(err) - return nil, err - } - //if !ok { - // return nil, errors.New("验签失败") - //} - timeStamp := strconv.FormatInt(time.Now().Unix(), 10) - //paySign := wechat.GetAppPaySign(client.AppId, client.MchId, wxRsp.NonceStr, wxRsp.PrepayId, wechat.SignType_MD5, timeStamp, client.ApiKey) - packages := "prepay_id=" + wxRsp.PrepayId - paySign := wechat.GetJsapiPaySign(client.AppId, wxRsp.NonceStr, packages, wechat.SignType_MD5, timeStamp, client.ApiKey) - - zhios_pay_logx.Info("wxRsp.PrepayId:" + wxRsp.PrepayId) - zhios_pay_logx.Info("wxRsp.PrepayId:" + wxRsp.PrepayId) - zhios_pay_logx.Info("wxRsp.PrepayId:" + openid) - res := map[string]string{ - "appid": client.AppId, - "partnerid": client.MchId, - "prepayid": wxRsp.PrepayId, - "sign": paySign, - "package": "prepay_id=" + wxRsp.PrepayId, - "noncestr": wxRsp.NonceStr, - "timestamp": timeStamp, - } - return res, nil -} - -// TradeH5PayV3 is 微信H5支付v3 -func TradeH5PayV3(client *wechat.Client, subject, orderID, amount, notifyUrl string) (string, error) { - // 初始化 BodyMap - bm := make(gopay.BodyMap) - bm.Set("nonce_str", util.GetRandomString(32)). - Set("body", subject). - Set("out_trade_no", orderID). - Set("total_fee", amount). - Set("spbill_create_ip", "127.0.0.1"). - Set("notify_url", notifyUrl). - Set("trade_type", wechat.TradeType_App). - Set("device_info", "WEB"). - Set("sign_type", wechat.SignType_MD5). - SetBodyMap("scene_info", func(bm gopay.BodyMap) { - bm.SetBodyMap("h5_info", func(bm gopay.BodyMap) { - bm.Set("type", "Wap") - bm.Set("wap_url", "https://www.fumm.cc") - bm.Set("wap_name", "H5测试支付") - }) - }) /*.Set("openid", "o0Df70H2Q0fY8JXh1aFPIRyOBgu8")*/ - // 预下单 - wxRsp, err := client.UnifiedOrder(bm) - if err != nil { - _ = zhios_pay_logx.Warn(err) - return "", err - } - // ====APP支付 paySign==== - timeStamp := strconv.FormatInt(time.Now().Unix(), 10) - // 获取APP支付的 paySign - // 注意:package 参数因为是固定值,无需开发者再传入 - // appId:AppID - // partnerid:partnerid - // nonceStr:随机字符串 - // prepayId:统一下单成功后得到的值 - // signType:签名方式,务必与统一下单时用的签名方式一致 - // timeStamp:时间 - // apiKey:API秘钥值 - paySign := wechat.GetAppPaySign(client.AppId, client.MchId, wxRsp.NonceStr, wxRsp.PrepayId, wechat.SignType_MD5, timeStamp, client.ApiKey) - return paySign, nil -} - -// TradeMiniProgPayV3 is 微信小程序支付v3 -func TradeMiniProgPayV3(client *v3.ClientV3, subject, orderID, amount, notifyUrl string) (string, error) { - return "", nil -} diff --git a/md/alipay.go b/md/alipay.go deleted file mode 100644 index 17799ac..0000000 --- a/md/alipay.go +++ /dev/null @@ -1,17 +0,0 @@ -package md - -type AliPayPayParams struct { - Subject string `json:"subject" binding:"required"` - Amount string `json:"amount" binding:"required"` - OrderType string `json:"order_type" binding:"required"` - OrdId string `json:"ord_id"` -} - -type PayData struct { - PayAppCertSn string `json:"pay_app_cert_sn"` - PayAlipayRootCertSn string `json:"pay_alipay_root_cert_sn"` - PayAlipayrsaPublicKey string `json:"pay_alipayrsa_public_key"` - PayAliUseType string `json:"pay_ali_use_type"` - PriKey string `json:"pay_ali_new_private_key"` - WxAppletFilepathUrl string `json:"wx_applet_filepath_url"` -} diff --git a/md/app_redis_key.go b/md/app_redis_key.go deleted file mode 100644 index d7d5f33..0000000 --- a/md/app_redis_key.go +++ /dev/null @@ -1,19 +0,0 @@ -package md - -// 缓存key统一管理, %s格式化为masterId -const ( - AppCfgCacheKey = "%s:cfg_cache:%s" // 占位符: masterId, key的第一个字母 - VirtualCoinCfgCacheKey = "%s:virtual_coin_cfg" - PlanRewardCfgCacheKey = "%s:plan_reward_cfg" - UnionSetCacheCfg = "%s:union_set_cfg:%s" // 联盟设置缓存key - - UserFinValidUpdateLock = "%s:user_fin_valid_update_lock:%s" // 用户余额更新锁(能拿到锁才能更新余额) - - WithdrawApplyQueueListKey = "withdraw_apply_queue" // 提现队列 - - TplBottomNavRedisKey = "%s:tpl_nav_bottom_key:%s" // master_id platform - - SysModByIdRedisKey = "%s:sys_mod_tpl_by_id:%s" - - CfgCacheTime = 86400 -) diff --git a/md/basic.go b/md/basic.go deleted file mode 100644 index 8551066..0000000 --- a/md/basic.go +++ /dev/null @@ -1,6 +0,0 @@ -package md - -const ( - ZHIOS_PAY_URL_PRD = "http://pay.zhios.cn" - ZHIOS_PAY_URL_DEV = "http://pay.izhyin.com" -) diff --git a/md/cfg.go b/md/cfg.go new file mode 100644 index 0000000..e288d04 --- /dev/null +++ b/md/cfg.go @@ -0,0 +1,15 @@ +package md + +import ( + "code.fnuoos.com/go_rely_warehouse/zyos_go_mq.git/rabbit" +) + +//Mq配置结构体 +type MQCfg struct { + Host string `json:"host"` + Port string `json:"port"` + User string `json:"user"` + Pwd string `json:"pwd"` + Uri string `json:"uri"` + Pool *rabbit.Pool `json:"pool"` +} diff --git a/md/cfg_app.go b/md/cfg_app.go deleted file mode 100644 index c380303..0000000 --- a/md/cfg_app.go +++ /dev/null @@ -1,16 +0,0 @@ -package md - -import "time" - -//数据库配置结构体 -type DBCfg struct { - Host string `yaml:"host"` //ip及端口 - Name string `yaml:"name"` //库名 - User string `yaml:"user"` //用户 - Psw string `yaml:"psw"` //密码 - ShowLog bool `yaml:"show_log"` //是否显示SQL语句 - MaxLifetime time.Duration `yaml:"max_lifetime"` - MaxOpenConns int `yaml:"max_open_conns"` - MaxIdleConns int `yaml:"max_idle_conns"` - Path string `yaml:"path"` //日志文件存放路径 -} diff --git a/md/icbc.go b/md/icbc.go deleted file mode 100644 index bdc966a..0000000 --- a/md/icbc.go +++ /dev/null @@ -1,12 +0,0 @@ -package md - -type IcbcRes struct { - ResponseBizContent struct { - CusCredit int `json:"cusCredit"` - MsgID string `json:"msg_id"` - ReturnCode int64 `json:"return_code"` - ReturnMsg string `json:"return_msg"` - Success bool `json:"success"` - } `json:"response_biz_content"` - Sign string `json:"sign"` -} diff --git a/md/join.go b/md/join.go deleted file mode 100644 index 2b0547d..0000000 --- a/md/join.go +++ /dev/null @@ -1,102 +0,0 @@ -package md - -const ( - JoinPayUrl = "https://www.joinpay.com/trade/uniPayApi.action" - PayTestAccount = "888118100005250" - PayTestSecretKey = "a12ceace4cc5423eae32b4626adf56c9" - Q1FrpCodeALIPAY = "ALIPAY_H5" //支付宝固定 - Q1FrpCodeWEIXINPAYAPP = "WEIXIN_APP3" //微信固定(应该) - //Q1FrpCodeWEIXINPAYH5 = "WEIXIN_H5_PLUS" - //Q1FrpCodeWEIXINPAYGZH = "WEIXIN_GZH" - //Q1FrpCodeWEIXINPAYXCX = "WEIXIN_XCX" - PayTestAliAccount = "777146200391877" - PayTestWeChatAccount = "777196100391173" - WEIXINPATH = "/pages/payIndex/payIndex?rc_result=" -) - -// -// JoinPayReq -// @Description: 汇聚支付-聚合支付-支付接口-请求参数信息体 -// @Url: https://www.joinpay.com/open-platform/pages/document.html?apiName=%E8%81%9A%E5%90%88%E6%94%AF%E4%BB%98&id=6 -// -type JoinPayReq struct { - P0Version string `json:"p0_Version" label:"版本号;目前版本号为:2.1;是"` - P1MerchantNo string `json:"p1_MerchantNo" label:"商户编号;商户在支付平台系统的唯一身份标识;是"` - P2OrderNo string `json:"p2_OrderNo" label:"商户订单号;商户系统提交的唯一订单号。仅支持由英文字母、阿拉伯数字、下划线(英文符号“_”)组成的订单号传输;是"` - P3Amount string `json:"p3_Amount" label:"订单金额;单位:元,精确到分,保留两位小数。例如:10.23。;是"` - P4Cur string `json:"p4_Cur" label:"交易币种;默认设置为1(代表人民币);是"` - P5ProductName string `json:"p5_ProductName" label:"商品名称;用于支付时显示在支付平台网关上的订单产品信息;是"` - P6ProductDesc string `json:"p6_ProductDesc" label:"商品描述;对商品信息进行描述;否"` - P7Mp string `json:"p7_Mp" label:"公用回传参数;如果商户请求时传递了该参数,则返回给商户时会原值传回;否"` - P9NotifyUrl string `json:"p9_NotifyUrl" label:"服务器异步通知地址;汇聚支付系统主动通知商户网站里指定的 http 地址。 -异步通知地址需按: -1.AB|notifyUrl 的规则上送才会返回用户标识和平台优惠金额; -2.云闪付 CD|notifyUrl 的规则上才会返回用户支付的卡类型;是"` - Q1FrpCode string `json:"q1_FrpCode" label:"交易类型;可见md模型里提供的;是"` - Q2MerchantBankCode string `json:"q2_MerchantBankCode" label:"银行商户编码;非必填;否"` - Q4IsShowPic string `json:"q4_IsShowPic" label:"是否展示图片;默认为空,不输出图片;填1表示输出图片,仅交易类型为主扫时可用(即当q1_FrpCode=ALIPAY_NATIVE、WEIXIN_NATIVE、JD_NATIVE、QQ_NATIVE、UNIONPAY_NATIVE、BAIDU_NATIVE、SUNING_NATIVE);否"` - Q5OpenId string `json:"q5_OpenId" label:"微信Openid; -公众号获取用户Openid,公众号支付商户及微信小程序商户必填(即当q1_FrpCode=WEIXIN_GZH、WEIXIN_XCX);否"` - Q6AuthCode string `json:"q6_AuthCode" label:" -付款码数字;付款码数字被扫支付必填(即当q1_FrpCode= ALIPAY_CARD、WEIXIN_CARD、JD_CARD、QQ_CARD、UNIONPAY_CARD;否"` - Q7AppId string `json:"q7_AppId" label:"APPID;微信公众号、微信小程序、微信App、微信app+支付必填(即当q1_FrpCode= WEIXIN_GZH、WEIXIN_XCX、WEIXIN_APP3、WEIXIN_H5_PLUS【对应报备小程序appid】);否"` - Q8TerminalNo string `json:"q8_TerminalNo" label:" -终端设备号; -通过终端信息采集接口获取,由汇聚生成。微信/支付宝被扫支付必填(即当q1_FrpCode= ALIPAY_CARD、WEIXIN_CARD);否"` - Q9TransactionModel string `json:"q9_TransactionModel" label:"支付宝H5模式;支付宝H5选填,默认为空 - -1.模式一:当 q9_TransactionModel = MODEL1或为空时,有应答参数返回,rc_Result中返回html,需进行重定向跳转;2.模式二:当 q9_TransactionModel = MODEL2时,直接跳转链接,不返回应答参数。;否"` - QATradeMerchantNo string `json:"qa_TradeMerchantNo" label:"报备商户号;请填写报备产品后返回的报备商户号;是"` - QBbuyerId string `json:"qb_buyerId" label:"买家的支付宝唯一用户号;支付宝服务窗支付必填(即当q1_FrpCode=ALIPAY_FWC )(买家的支付宝唯一用户号(2088开头16位纯数字));否"` - QJDJPlan string `json:"qj_DJPlan" label:"点金计划;该字段参数值为JSON串;否"` - QKDisablePayModel string `json:"qk_DisablePayModel" label:"禁用支付方式;目前仅支持使用微信和支付宝支付时可禁用某些方式,详细枚举值见附录;否"` - QLTerminalIp string `json:"ql_TerminalIp" label:"终端设备IP; -商户端终端设备 IP 地址。微信/支付宝被扫支付必填(即当q1_FrpCode= ALIPAY_CARD、WEIXIN_CARD);否"` - Hmac string `json:"hmac" label:"签名数据;参见签名机制;是"` -} - -type JoinPayResponse struct { - R7TrxNo string `json:"r7_TrxNo"` - RbCodeMsg string `json:"rb_CodeMsg"` - R2OrderNo string `json:"r2_OrderNo"` - R3Amount string `json:"r3_Amount"` - R6FrpCode string `json:"r6_FrpCode"` - RcResult string `json:"rc_Result"` - RaCode int `json:"ra_Code"` - Hmac string `json:"hmac"` - RdPic string `json:"rd_Pic"` - R4Cur string `json:"r4_Cur"` - R5Mp string `json:"r5_Mp"` - R8MerchantBankCode string `json:"r8_MerchantBankCode"` - R0Version string `json:"r0_Version"` - R1MerchantNo string `json:"r1_MerchantNo"` -} - -type JoinPayResponseWeChatRcResult struct { - OrderNo string `json:"order_no"` - TrxNo string `json:"trx_no"` - PayeeName string `json:"payee_name"` - OriginalID string `json:"original_id"` - AppID string `json:"app_id"` - ProductName string `json:"product_name"` - OrderAmout string `json:"order_amout"` -} - -type JoinPayCallBack struct { - R1MerchantNo string `json:"r1_MerchantNo" form:"r1_MerchantNo"` - R2OrderNo string `json:"r2_OrderNo" form:"r2_OrderNo"` - R3Amount string `json:"r3_Amount" form:"r3_Amount"` - R4Cur string `json:"r4_Cur" form:"r4_Cur"` - R5Mp string `json:"r5_Mp" form:"r5_Mp"` - R6Status int `json:"r6_Status" form:"r6_Status"` - R7TrxNo string `json:"r7_TrxNo" form:"r7_TrxNo"` - R8BankOrderNo string `json:"r8_BankOrderNo" form:"r8_BankOrderNo"` - R9BankTrxNo string `json:"r9_BankTrxNo" form:"r9_BankTrxNo"` - RaPayTime string `json:"ra_PayTime" form:"ra_PayTime"` - RbDealTime string `json:"rb_DealTime" form:"rb_DealTime"` - RcBankCode string `json:"rc_BankCode" form:"rc_BankCode"` - RdOpenId string `json:"rd_OpenId" form:"rd_OpenId"` - ReDiscountAmount string `json:"re_DiscountAmount" form:"re_DiscountAmount"` - RhcardType string `json:"rh_cardType" form:"rh_cardType"` - Hmac string `json:"hmac" form:"hmac"` -} diff --git a/md/join_bank_card_pay.go b/md/join_bank_card_pay.go deleted file mode 100644 index 4971859..0000000 --- a/md/join_bank_card_pay.go +++ /dev/null @@ -1,11 +0,0 @@ -package md - -type JoinBankCardPayCallBack struct { - BizCode string `json:"biz_code"` - BizMsg string `json:"biz_msg"` - Data string `json:"data"` - MchNo string `json:"mch_no"` - RandStr string `json:"rand_str"` - Sign string `json:"sign"` - SignType string `json:"sign_type"` -} diff --git a/md/kudian.go b/md/kudian.go deleted file mode 100644 index b4e04b8..0000000 --- a/md/kudian.go +++ /dev/null @@ -1,69 +0,0 @@ -package md - -type KuDianWxPayParams struct { - AppId string `json:"app_id"` - OpenId string `json:"open_id"` - OutTradeNo string `json:"out_trade_no"` - Description string `json:"description"` - NotifyUrl string `json:"notify_url"` - TotalAmount string `json:"total_amount" binding:"required"` - Attach string `json:"attach" binding:"required"` - MustParams struct { - ShopId string `json:"shop_id"` - KuDianMchId string `json:"ku_dian_mch_id"` - KuDianSecretKey string `json:"ku_dian_secret_key"` - } `json:"must_params"` -} - -type KuDianAliAppPayParams struct { - OutTradeNo string `json:"out_trade_no"` - Description string `json:"description"` - NotifyUrl string `json:"notify_url"` - UserId string `json:"user_id"` - TotalAmount string `json:"total_amount" binding:"required"` - Attach string `json:"attach" binding:"required"` - TradeType string `json:"trade_type"` - SenceInfo struct { - WapUrl string `json:"wap_url"` - WapName string `json:"wap_name"` - ReturnUrl string `json:"return_url"` - } `json:"sence_info"` - MustParams struct { - ShopId string `json:"shop_id"` - KuDianMchId string `json:"ku_dian_mch_id"` - KuDianSecretKey string `json:"ku_dian_secret_key"` - } `json:"must_params"` -} - -type MakePayParamsByKuDian struct { - RequestUrl string `json:"request_url"` - Params interface{} `json:"params"` -} - -const ( - WX_APPLET_PAY_URL = "zy-base-widget-sub/pages/cashier/cashier?unique_identifier=" - WX_APP_TO_APPLET_PAY_UNIQUE_IDENTIFIER = "%s:wx_app_to_applet_pay_unique_identifier:%s:%s" // 酷点支付 - App跳转小程序支付 (mid + store_id + 纳秒时间戳) - WX_APP_TO_APPLET_PAY_UNIQUE_IDENTIFIER_CACHE_TIME = 60 * 10 //缓存10分钟 -) - -// ########################################### 酷点支付 - 回调结构体 ############################################### - -type KuDianPayCallback struct { - Code int `json:"code"` - Msg string `json:"msg"` - Result string `json:"result"` -} - -type KuDianPayCallbackResp struct { - MchId string `json:"mch_id"` //商户id - PayNo string `json:"pay_no"` //聚合支付订单号 - OutTradeNo string `json:"out_trade_no"` //业务系统订单号 - TransactionId string `json:"transaction_id"` //支付平台交易流水号。微信、支付宝、云闪付等用户支付使用的平台返回流水号 - Fee int `json:"fee"` //交易总额,单位:分 - ReceivedFee int `json:"received_fee"` //商户实收金额,单位:分 - PayTime string `json:"pay_time"` //支付时间,格式"yyyy-MM-dd HH:mm:ss" - Payment string `json:"payment"` //支付方式 - Body string `json:"body"` //支付简要描述 - Status int `json:"status"` //支付状态 - Attach string `json:"attach"` //附加信息 -} diff --git a/md/platform.go b/md/platform.go deleted file mode 100644 index b479ab5..0000000 --- a/md/platform.go +++ /dev/null @@ -1,40 +0,0 @@ -package md - -const ( - /*********** DEVICE ***********/ - PLATFORM_WX_APPLET = "wx_applet" // 小程序 - PLATFORM_TOUTIAO_APPLET = "toutiao_applet" - PLATFORM_TIKTOK_APPLET = "tiktok_applet" - PLATFORM_BAIDU_APPLET = "baidu_applet" - PLATFORM_ALIPAY_APPLET = "alipay_applet" - PLATFORM_WAP = "wap" //h5 - PLATFORM_ANDROID = "android" - PLATFORM_IOS = "ios" - PLATFORM_PC = "pc" - PLATFORM_JSAPI = "jsapi" // 公众号 -) - -const WX_PAY_BROWSER = "wx_pay_browser" // 用于判断显示支付方式 - -var PlatformList = map[string]struct{}{ - PLATFORM_WX_APPLET: {}, - PLATFORM_TOUTIAO_APPLET: {}, - PLATFORM_TIKTOK_APPLET: {}, - PLATFORM_BAIDU_APPLET: {}, - PLATFORM_ALIPAY_APPLET: {}, - PLATFORM_WAP: {}, - PLATFORM_ANDROID: {}, - PLATFORM_IOS: {}, - PLATFORM_PC: {}, -} - -var PlatformMap = map[string]string{ - "android": "2", - "ios": "2", - "wap": "4", // 和小程序公用模板 - "wx_applet": "4", //微信小程序 - "tiktok_applet": "4", - "baidu_applet": "4", - "alipay_applet": "4", - "toutiao_applet": "4", -} diff --git a/md/wxpay.go b/md/wxpay.go deleted file mode 100644 index 5526176..0000000 --- a/md/wxpay.go +++ /dev/null @@ -1,40 +0,0 @@ -package md - -type WxPayParams struct { - Subject string `json:"subject" binding:"required"` - Amount string `json:"amount" binding:"required"` - OrderType string `json:"order_type" binding:"required"` - OrdId string `json:"ord_id"` - PayWxAppid string `json:"pay_wx_appid"` - PayWxMchId string `json:"pay_wx_mch_id"` - PayWxApiKey string `json:"pay_wx_api_key"` - NotifyUrl string `json:"notify_url"` - ThirdPartyWechatOpenid string `json:"third_party_wechat_openid"` - Platform string `json:"platform"` - PayType string `json:"pay_type"` - PayThirdPartyId string `json:"pay_third_party_id"` - KuDianNotifyUrl string `json:"ku_dian_notify_url"` - -} - -type WxPayCallback struct { - AppId string `json:"appid"` - BankType string `json:"bank_type"` - CashFee string `json:"cash_fee"` - FeeType string `json:"fee_type"` - IsSubscribe string `json:"is_subscribe"` - MasterID string `json:"master_id"` - MchID string `json:"mch_id"` - NonceStr string `json:"nonce_str"` - Openid string `json:"openid"` - OrderType string `json:"order_type"` - OutTradeNo string `json:"out_trade_no"` - PayMethod string `json:"pay_method"` - ResultCode string `json:"result_code"` - ReturnCode string `json:"return_code"` - Sign string `json:"sign"` - TimeEnd string `json:"time_end"` - TotalFee string `json:"total_fee"` - TradeType string `json:"trade_type"` - TransactionID string `json:"transaction_id"` -} diff --git a/pay/init.go b/pay/init.go deleted file mode 100644 index ae8d935..0000000 --- a/pay/init.go +++ /dev/null @@ -1,34 +0,0 @@ -package pay - -import ( - "code.fnuoos.com/go_rely_warehouse/zyos_go_pay.git/db" - "code.fnuoos.com/go_rely_warehouse/zyos_go_pay.git/md" -) - -var cfg = md.DBCfg{ - Host: "", - Name: "", - User: "", - Psw: "", - ShowLog: false, - MaxLifetime: 0, - MaxOpenConns: 0, - MaxIdleConns: 0, - Path: "", -} - -func Init(host, name, user, psw string) error { - cfg.Host = host - cfg.Name = name - cfg.User = user - cfg.Psw = psw - cfg.ShowLog = true - cfg.MaxLifetime = 30 - cfg.MaxOpenConns = 100 - cfg.MaxIdleConns = 100 - cfg.Path = "./tmp/%s.logs" - if err := db.InitDB(&cfg); err != nil { - return err - } - return nil -} diff --git a/pay/logs/1.txt b/pay/logs/1.txt deleted file mode 100644 index e69de29..0000000 diff --git a/pay/logs/zyos_website.logs b/pay/logs/zyos_website.logs deleted file mode 100644 index 504dd55..0000000 --- a/pay/logs/zyos_website.logs +++ /dev/null @@ -1,2 +0,0 @@ -[xorm] [info] 2022/05/31 10:40:31.829104 [SQL] SELECT `id`, `channel_id`, `identifier`, `master_id`, `master_nickname`, `app_id` FROM `pay_channel_master` WHERE (app_id = ?) AND (identifier = ?) LIMIT 1 [35618318 mall] - 28.9565ms -[xorm] [info] 2022/05/31 10:41:41.231871 [SQL] SELECT `id`, `channel_id`, `identifier`, `master_id`, `master_nickname`, `app_id` FROM `pay_channel_master` WHERE (app_id = ?) AND (identifier = ?) LIMIT 1 [35618318 mall] - 24.9118ms diff --git a/pay/pay_by_icbcmo.go b/pay/pay_by_icbcmo.go deleted file mode 100644 index 097e4b7..0000000 --- a/pay/pay_by_icbcmo.go +++ /dev/null @@ -1,26 +0,0 @@ -package pay - -import "code.fnuoos.com/go_rely_warehouse/zyos_go_pay.git/lib/icbc" - -//澳门工行积分 -func ShowIntegral(appId, privateKeyStr string, param map[string]string) (int, error) { - cusCredit, err := icbc.ShowIntegral(appId, privateKeyStr, param) - return cusCredit, err -} - -func DeductIntegral(appId, privateKeyStr string, param map[string]string) error { - err := icbc.DeductIntegral(appId, privateKeyStr, param) - return err -} - -//澳门工行积分短信 -func ShowIntegralSms(appId, privateKeyStr string, param map[string]string) (int, error) { - cusCredit, err := icbc.ShowIntegral(appId, privateKeyStr, param) - return cusCredit, err -} - -//澳门工行积分短信 -func DeductIntegralSms(appId, privateKeyStr string, param map[string]string) error { - err := icbc.DeductIntegral(appId, privateKeyStr, param) - return err -} diff --git a/pay/pay_by_join.go b/pay/pay_by_join.go deleted file mode 100644 index 490c96f..0000000 --- a/pay/pay_by_join.go +++ /dev/null @@ -1,146 +0,0 @@ -package pay - -import ( - "code.fnuoos.com/go_rely_warehouse/zyos_go_pay.git/md" - zhios_pay_utils "code.fnuoos.com/go_rely_warehouse/zyos_go_pay.git/utils" - "crypto/tls" - "io/ioutil" - "net/http" - "net/url" - "strings" -) - -func UniPayByJoin(payParams *md.JoinPayReq, paySecretKey string, isPrd bool) (*md.JoinPayResponse, error) { - payParams.P0Version = "2.1" - payParams.P4Cur = "1" - //可注释行: - //payParams.P1MerchantNo = md.PayTestAccount - //payParams.P2OrderNo = "95271" - //payParams.P3Amount = "0.1" - //payParams.P5ProductName = "测试商品" - //payParams.P9NotifyUrl = "AB|https://www.baidu.com" - //--交易类型 - //payParams.Q1FrpCode = md.Q1FrpCodeWEIXINPAYAPP - //payParams.Q1FrpCode = md.Q1FrpCodeALIPAY - //原始微信AppId - //payParams.Q7AppId = "gh_5a236de9850a" - //微信AppId - //payParams.Q7AppId = "wx5bb10bb79cb5da1c" - //商家报备编号(分微信和支付宝的);支付宝的: - //payParams.QATradeMerchantNo = md.PayTestAliAccount - //商家报备编号(分微信和支付宝的);微信的: - //payParams.QATradeMerchantNo = md.PayTestWeChatAccount - //不可注释行: - postData := url.Values{} - creatHmac(payParams, paySecretKey, &postData) - zhios_pay_utils.FilePutContents("UniPayByJoin", zhios_pay_utils.SerializeStr(map[string]interface{}{ - "data": payParams, - })) - tr := &http.Transport{ - TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, - } - client := &http.Client{Transport: tr} - response, err := client.Post(md.JoinPayUrl, "application/x-www-form-urlencoded", strings.NewReader(postData.Encode())) - if err != nil { - return nil, err - } - defer response.Body.Close() - body, err := ioutil.ReadAll(response.Body) - resp := md.JoinPayResponse{} - zhios_pay_utils.Unserialize(body, &resp) - return &resp, err -} - -func creatHmac(payParams *md.JoinPayReq, paySecretKey string, postData *url.Values) { - hmac := "" - if payParams.P0Version != "" { - postData.Add("p0_Version", payParams.P0Version) - hmac = hmac + payParams.P0Version - } - if payParams.P1MerchantNo != "" { - postData.Add("p1_MerchantNo", payParams.P1MerchantNo) - hmac = hmac + payParams.P1MerchantNo - } - if payParams.P2OrderNo != "" { - postData.Add("p2_OrderNo", payParams.P2OrderNo) - hmac = hmac + payParams.P2OrderNo - } - if payParams.P3Amount != "" { - postData.Add("p3_Amount", payParams.P3Amount) - hmac = hmac + payParams.P3Amount - } - if payParams.P4Cur != "" { - postData.Add("p4_Cur", payParams.P4Cur) - hmac = hmac + payParams.P4Cur - } - if payParams.P5ProductName != "" { - postData.Add("p5_ProductName", payParams.P5ProductName) - hmac = hmac + payParams.P5ProductName - } - if payParams.P6ProductDesc != "" { - postData.Add("p6_ProductDesc", payParams.P6ProductDesc) - hmac = hmac + payParams.P6ProductDesc - } - if payParams.P7Mp != "" { - postData.Add("p7_Mp", payParams.P7Mp) - hmac = hmac + payParams.P7Mp - } - if payParams.P9NotifyUrl != "" { - postData.Add("p9_NotifyUrl", payParams.P9NotifyUrl) - hmac = hmac + payParams.P9NotifyUrl - } - if payParams.Q1FrpCode != "" { - postData.Add("q1_FrpCode", payParams.Q1FrpCode) - hmac = hmac + payParams.Q1FrpCode - } - if payParams.Q2MerchantBankCode != "" { - postData.Add("q2_MerchantBankCode", payParams.Q2MerchantBankCode) - hmac = hmac + payParams.Q2MerchantBankCode - } - if payParams.Q4IsShowPic != "" { - postData.Add("q4_IsShowPic", payParams.Q4IsShowPic) - hmac = hmac + payParams.Q4IsShowPic - } - if payParams.Q5OpenId != "" { - postData.Add("q5_OpenId", payParams.Q5OpenId) - hmac = hmac + payParams.Q5OpenId - } - if payParams.Q6AuthCode != "" { - postData.Add("q6_AuthCode", payParams.Q6AuthCode) - hmac = hmac + payParams.Q6AuthCode - } - if payParams.Q7AppId != "" { - postData.Add("q7_AppId", payParams.Q7AppId) - hmac = hmac + payParams.Q7AppId - } - if payParams.Q8TerminalNo != "" { - postData.Add("q8_TerminalNo", payParams.Q8TerminalNo) - hmac = hmac + payParams.Q8TerminalNo - } - if payParams.Q9TransactionModel != "" { - postData.Add("q9_TransactionModel", payParams.Q9TransactionModel) - hmac = hmac + payParams.Q9TransactionModel - } - if payParams.QATradeMerchantNo != "" { - postData.Add("qa_TradeMerchantNo", payParams.QATradeMerchantNo) - hmac = hmac + payParams.QATradeMerchantNo - } - if payParams.QBbuyerId != "" { - postData.Add("qb_buyerId", payParams.QBbuyerId) - hmac = hmac + payParams.QBbuyerId - } - if payParams.QJDJPlan != "" { - postData.Add("qj_DJPlan", payParams.QJDJPlan) - hmac = hmac + payParams.QJDJPlan - } - if payParams.QKDisablePayModel != "" { - postData.Add("qk_DisablePayModel", payParams.QKDisablePayModel) - hmac = hmac + payParams.QKDisablePayModel - } - if payParams.QLTerminalIp != "" { - postData.Add("ql_TerminalIp", payParams.QLTerminalIp) - hmac = hmac + payParams.QLTerminalIp - } - payParams.Hmac = zhios_pay_utils.Md5(hmac + paySecretKey) - postData.Add("hmac", payParams.Hmac) -} diff --git a/pay/pay_by_join_bank_card.go b/pay/pay_by_join_bank_card.go deleted file mode 100644 index 3edf8e2..0000000 --- a/pay/pay_by_join_bank_card.go +++ /dev/null @@ -1,203 +0,0 @@ -package pay - -import ( - zhios_pay_utils "code.fnuoos.com/go_rely_warehouse/zyos_go_pay.git/utils" - "crypto" - "crypto/md5" - "crypto/rand" - "crypto/rsa" - "crypto/x509" - "encoding/base64" - "encoding/json" - "encoding/pem" - "errors" - "fmt" - "github.com/forgoer/openssl" - "github.com/syyongx/php2go" - "golang.org/x/crypto/ssh" - mathRand "math/rand" - "sort" - "time" -) - -/*** -method fastPay.agreement.signSms - -data 请求交易的数据,具体参数见下表 - -mch_no 商户在支付平台系统的唯一身份标识。(注:商户编号和商户密钥在汇聚商户后台获取) -pub_key 公钥 - -pri_key 私钥 -*/ - -func GetSms(pubKey, platformKey, priKey, mch_no string, args map[string]string) (string, error) { - param := map[string]string{ - "mch_no": mch_no, - } - param["sec_key"] = randomString(16) - args["payer_name"] = AesEncryptECB([]byte(args["payer_name"]), []byte(param["sec_key"])) - args["id_no"] = AesEncryptECB([]byte(args["id_no"]), []byte(param["sec_key"])) - args["bank_card_no"] = AesEncryptECB([]byte(args["bank_card_no"]), []byte(param["sec_key"])) - args["mobile_no"] = AesEncryptECB([]byte(args["mobile_no"]), []byte(param["sec_key"])) - args["expire_date"] = AesEncryptECB([]byte(args["expire_date"]), []byte(param["sec_key"])) - data, _ := json.Marshal(args) - param["data"] = string(data) - send, err := Send("fastPay.agreement.signSms", platformKey, priKey, param) - return send, err -} - -func SignContract(pubKey, platformKey, priKey, mch_no string, args map[string]string) (string, error) { - param := map[string]string{ - "mch_no": mch_no, - } - param["sec_key"] = randomString(16) - data, _ := json.Marshal(args) - param["data"] = string(data) - send, err := Send("fastPay.agreement.smsSign", platformKey, priKey, param) - return send, err - -} - -func UnSignContract(pubKey, platformKey, priKey, mch_no string, args map[string]string) (string, error) { - param := map[string]string{ - "mch_no": mch_no, - } - param["sec_key"] = randomString(16) - args["sign_no"] = AesEncryptECB([]byte(args["sign_no"]), []byte(param["sec_key"])) - data, _ := json.Marshal(args) - param["data"] = string(data) - send, err := Send("fastPay.agreement.unSign", platformKey, priKey, param) - return send, err -} -func GetPaySms(pubKey, platformKey, priKey, mchNo string, args map[string]string) (string, error) { - param := map[string]string{ - "mch_no": mchNo, - } - param["sec_key"] = randomString(16) - args["sign_no"] = AesEncryptECB([]byte(args["sign_no"]), []byte(param["sec_key"])) - data, _ := json.Marshal(args) - param["data"] = string(data) - send, err := Send("fastPay.agreement.paySms", platformKey, priKey, param) - return send, err -} -func PayDoing(pubKey, platformKey, priKey, mchNo string, args map[string]string) (string, error) { - param := map[string]string{ - "mch_no": mchNo, - } - param["sec_key"] = randomString(16) - data, _ := json.Marshal(args) - param["data"] = string(data) - send, err := Send("fastPay.agreement.smsPay", platformKey, priKey, param) - return send, err -} - -func Send(method, platformKey, priKey string, param map[string]string) (string, error) { - //priKey = strings.ReplaceAll(priKey, "+", "\n") - //priKey = "-----BEGIN PRIVATE KEY-----\n" + priKey + "\n-----END PRIVATE KEY-----" - router := "https://api.joinpay.com/fastpay" - param["method"] = method - param["version"] = "1.0" - param["rand_str"] = randomString(32) - param["sign_type"] = "2" - sign, err := GetSign(priKey, param) - if err != nil { - return "", err - } - param["sign"] = sign - if param["sec_key"] != "" { //rsa加密 - encrypts, err := RsaEncrypts([]byte(param["sec_key"]), []byte(platformKey)) - if err != nil { - return "", err - } - param["sec_key"] = string(encrypts) - } - post, err := zhios_pay_utils.CurlPost(router, param, nil) - fmt.Println(string(post)) - fmt.Println(err) - return string(post), nil -} - -func GetSign(privateKeyStr string, param map[string]string) (string, error) { - privateKey, err := ssh.ParseRawPrivateKey([]byte(privateKeyStr)) - if err != nil { - return "", err - } - keys := make([]string, 0, len(param)) - for k := range param { - keys = append(keys, k) - } - sort.Strings(keys) - data := "" - for _, v := range keys { - if v == "sign" || v == "sec_key" { - continue - } - if data != "" { - data += "&" + v + "=" + param[v] - } else { - data += v + "=" + param[v] - } - } - - fmt.Println("md5 before2:>>>>", data) - hashMd5 := md5.Sum([]byte(data)) - fmt.Println("md5 before2:>>>>", hashMd5) - hashed := hashMd5[:] - fmt.Println("hashed:>>>>", hashed) - fmt.Println("hashed_string:>>>>", string(hashed)) - sign, err := rsa.SignPKCS1v15(rand.Reader, privateKey.(*rsa.PrivateKey), crypto.MD5, hashed) - if err != nil { - return "", err - } - return base64.StdEncoding.EncodeToString(sign), nil -} - -// 公钥加密 -func RsaEncrypts(data, keyBytes []byte) (string, error) { - var ciphertext string - //解密pem格式的公钥 - block, _ := pem.Decode(keyBytes) - if block == nil { - return ciphertext, errors.New("公钥错误") - } - // 解析公钥 - pubInterface, err := x509.ParsePKIXPublicKey(block.Bytes) - if err != nil { - return ciphertext, err - } - // 类型断言 - pub := pubInterface.(*rsa.PublicKey) - //加密 - ciphertext1, err := rsa.EncryptPKCS1v15(rand.Reader, pub, data) - if err != nil { - return ciphertext, err - } - return base64.StdEncoding.EncodeToString(ciphertext1), nil -} -func randomString(ln int) string { - letters := []rune("1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") - b := make([]rune, ln) - r := mathRand.New(mathRand.NewSource(time.Now().UnixNano())) - for i := range b { - b[i] = letters[r.Intn(len(letters))] - } - return string(b) -} - -func AesEncryptECB(origData []byte, key []byte) string { - str, _ := openssl.AesECBEncrypt(origData, key, openssl.PKCS7_PADDING) - value := php2go.Base64Encode(string(str)) - - return value -} -func generateKey(key []byte) (genKey []byte) { - genKey = make([]byte, 16) - copy(genKey, key) - for i := 16; i < len(key); { - for j := 0; j < 16 && i < len(key); j, i = j+1, i+1 { - genKey[j] ^= key[i] - } - } - return genKey -} diff --git a/pay/pay_by_kudian.go b/pay/pay_by_kudian.go deleted file mode 100644 index 212c615..0000000 --- a/pay/pay_by_kudian.go +++ /dev/null @@ -1,208 +0,0 @@ -package pay - -import ( - "code.fnuoos.com/go_rely_warehouse/zyos_go_pay.git/md" - zhios_pay_utils "code.fnuoos.com/go_rely_warehouse/zyos_go_pay.git/utils" - "code.fnuoos.com/go_rely_warehouse/zyos_go_pay.git/utils/cache" - "encoding/json" - "fmt" - "github.com/gin-gonic/gin" - "github.com/pkg/errors" - "time" -) - -//酷点 - 支付宝APP支付 -func AliAppPayByKuDian(payParams *md.KuDianAliAppPayParams, isPrd bool) (string, error) { - var url string - if isPrd == true { - url = md.ZHIOS_PAY_URL_PRD + "/kuDianPay/Pay/aliAppPay" - } else { - url = md.ZHIOS_PAY_URL_DEV + "/kuDianPay/Pay/aliAppPay" - } - zhios_pay_utils.FilePutContents("AliAppPayByKuDian", zhios_pay_utils.SerializeStr(map[string]interface{}{ - "data": payParams, - })) - bytes, err := zhios_pay_utils.CurlPost(url, zhios_pay_utils.Serialize(payParams), nil) - if err != nil { - return "", err - } - var result struct { - Code int `json:"code"` - Msg string `json:"msg"` - Data map[string]string `json:"data"` - } - zhios_pay_utils.FilePutContents("AliAppPayByKuDian", zhios_pay_utils.SerializeStr(result)) - err = json.Unmarshal(bytes, &result) - if err != nil { - return "", err - } - if result.Code != 0 { - return "", errors.New(result.Msg) - } - zhios_pay_utils.FilePutContents("AliAppPayByKuDian", zhios_pay_utils.SerializeStr(result.Data["data"])) - return result.Data["url"], nil -} - -// 酷点 - 支付宝JsAPi支付 -func AliJsApiPayByKuDian(payParams *md.KuDianAliAppPayParams, isPrd bool) (string, error) { - var url string - if isPrd == true { - url = md.ZHIOS_PAY_URL_PRD + "/kuDianPay/Pay/aliJsApiPay" - } else { - url = md.ZHIOS_PAY_URL_DEV + "/kuDianPay/Pay/aliJsApiPay" - } - zhios_pay_utils.FilePutContents("AliAppPayByKuDian", zhios_pay_utils.SerializeStr(map[string]interface{}{ - "data": payParams, - })) - bytes, err := zhios_pay_utils.CurlPost(url, zhios_pay_utils.Serialize(payParams), nil) - if err != nil { - return "", err - } - var result struct { - Code int `json:"code"` - Msg string `json:"msg"` - Data map[string]string `json:"data"` - } - zhios_pay_utils.FilePutContents("AliAppPayByKuDian", zhios_pay_utils.SerializeStr(result)) - err = json.Unmarshal(bytes, &result) - if err != nil { - return "", err - } - if result.Code != 0 { - return "", errors.New(result.Msg) - } - zhios_pay_utils.FilePutContents("AliAppPayByKuDian", zhios_pay_utils.SerializeStr(result.Data["data"])) - return result.Data["trade_no"], nil -} - -// 酷点 - 微信小程序支付 -func WxAppletPayByKuDian(payParams *md.KuDianWxPayParams, isPrd bool) (interface{}, error) { - var url string - if isPrd == true { - url = md.ZHIOS_PAY_URL_PRD + "/kuDianPay/Pay/wxJsAPi" - } else { - url = md.ZHIOS_PAY_URL_DEV + "/kuDianPay/Pay/wxJsAPi" - } - zhios_pay_utils.FilePutContents("WxAppletPayByKuDian", zhios_pay_utils.SerializeStr(map[string]interface{}{ - "data": payParams, - })) - bytes, err := zhios_pay_utils.CurlPost(url, zhios_pay_utils.Serialize(payParams), nil) - if err != nil { - return nil, err - } - var result struct { - Code int `json:"code"` - Msg string `json:"msg"` - Data map[string]interface{} `json:"data"` - } - zhios_pay_utils.FilePutContents("WxAppletPayByKuDian", zhios_pay_utils.SerializeStr(result)) - err = json.Unmarshal(bytes, &result) - if err != nil { - return nil, err - } - if result.Code != 0 { - return nil, errors.New(result.Msg) - } - zhios_pay_utils.FilePutContents("WxAppletPayByKuDian", zhios_pay_utils.SerializeStr(result.Data["data"])) - return result.Data["data"], nil -} - -// 酷点 - 检查返回参数 -func CheckAllCallbackParamsByKuDian(c *gin.Context) (md.KuDianPayCallbackResp, error) { - var dataWx md.KuDianPayCallback - var dataPay md.KuDianPayCallbackResp - if err := c.ShouldBindJSON(&dataWx); err != nil { - fmt.Println(">>>>>>>>>CheckAllCallbackParamsByKuDian>>>>>>>>>>>>>>", err) - return dataPay, err - } - if err := json.Unmarshal([]byte(dataWx.Result), &dataPay); err != nil { - fmt.Println(">>>>>>>>>CheckAllCallbackParamsByKuDian>>>>>>>>>>>>>>", err) - return dataPay, err - } - zhios_pay_utils.FilePutContents("CheckAllCallbackParamsByKuDian", zhios_pay_utils.SerializeStr(dataPay)) - return dataPay, nil -} - -/** - * MakePayParamsByKuDian(构造酷点支付参数[APP跳转小程序支付]) - * @param url string 请求URL - * @param uniqueIdentifierOne string 标识占位符-第一个 (示例: 如 masterId) - * @param uniqueIdentifierTwo string 标识占位符-第二个 (示例: 如 uid) - * @param appletOriginalId string 小程序原始id - * @param queryParams string url上参数(示例: "&ord_id=123131313434343&state_zh=待支付&total=6.66") - * @param params map 请求参数 - */ -func MakePayParamsByKuDian(url, uniqueIdentifierOne, uniqueIdentifierTwo, appletOriginalId, queryParams string, params map[string]interface{}) (map[string]string, error) { - if params == nil { - return nil, errors.New("参数解析错误") - } - data := md.MakePayParamsByKuDian{ - RequestUrl: url, - Params: params, - } - redisKey := fmt.Sprintf(md.WX_APP_TO_APPLET_PAY_UNIQUE_IDENTIFIER, uniqueIdentifierOne, uniqueIdentifierTwo, zhios_pay_utils.AnyToString(time.Now().UnixNano())) - cache.SetJson(redisKey, data, md.WX_APP_TO_APPLET_PAY_UNIQUE_IDENTIFIER_CACHE_TIME) - var r = map[string]string{} - r["use_pay_method"] = "third_party" - r["applet_original_id"] = appletOriginalId - r["wx_url"] = md.WX_APPLET_PAY_URL + redisKey + "&" + queryParams - return r, nil -} - -func KuDianAlipayConfig(req, payConfig map[string]string) (*md.KuDianAliAppPayParams, error) { - var payParams = &md.KuDianAliAppPayParams{ - OutTradeNo: payConfig["ord_id"], - NotifyUrl: payConfig["notify_url"], - Description: payConfig["subject"], - TotalAmount: payConfig["amount"], - Attach: req["mid"], - MustParams: struct { - ShopId string `json:"shop_id"` - KuDianMchId string `json:"ku_dian_mch_id"` - KuDianSecretKey string `json:"ku_dian_secret_key"` - }{ - ShopId: payConfig["pay_third_party_id"], - KuDianMchId: req["ku_dian_mch_id"], - KuDianSecretKey: req["ku_dian_secret_key"], - }, - } - if payConfig["trade_type"] != "" { - payParams.TradeType = payConfig["trade_type"] - } - if payConfig["wap_mame"] != "" { - payParams.SenceInfo.WapName = payConfig["wap_mame"] - } - if payConfig["return_url"] != "" { - payParams.SenceInfo.ReturnUrl = payConfig["return_url"] - } - if payConfig["wap_url"] != "" { - payParams.SenceInfo.WapUrl = payConfig["wap_url"] - } - if payConfig["trade_type"] != "" { - payParams.TradeType = payConfig["trade_type"] - } - - return payParams, nil -} - -func KuDianWxConfig(req, payConfig map[string]string) (*md.KuDianWxPayParams, error) { - var payParams = &md.KuDianWxPayParams{ - OutTradeNo: payConfig["ord_id"], - NotifyUrl: payConfig["notify_url"], - Description: payConfig["subject"], - TotalAmount: payConfig["amount"], - AppId: req["wx_app_id"], - OpenId: req["wx_open_id"], - Attach: req["mid"], - MustParams: struct { - ShopId string `json:"shop_id"` - KuDianMchId string `json:"ku_dian_mch_id"` - KuDianSecretKey string `json:"ku_dian_secret_key"` - }{ - ShopId: payConfig["pay_third_party_id"], - KuDianMchId: req["ku_dian_mch_id"], - KuDianSecretKey: req["ku_dian_secret_key"], - }, - } - return payParams, nil -} diff --git a/pay/pay_by_own.go b/pay/pay_by_own.go deleted file mode 100644 index 7f6b174..0000000 --- a/pay/pay_by_own.go +++ /dev/null @@ -1,117 +0,0 @@ -package pay - -import ( - "code.fnuoos.com/go_rely_warehouse/zyos_go_pay.git/lib/local_alipay" - local_wxpay "code.fnuoos.com/go_rely_warehouse/zyos_go_pay.git/lib/local_wechat" - "code.fnuoos.com/go_rely_warehouse/zyos_go_pay.git/md" - zhios_pay_utils "code.fnuoos.com/go_rely_warehouse/zyos_go_pay.git/utils" - "fmt" - "github.com/pkg/errors" -) - -/** -自有支付 支付宝 -req 传参 - -ord_id //订单号 -amount //总金额 -subject //描述 -order_type //订单类型 -notify_url //自有支付回调地址 -platform //平台 由前端header传来的 -pay_app_cert_sn //应用公钥证书 值 -pay_alipayrsa_public_key //支付宝公钥证书 值 -pay_ali_use_type //支付宝选择版本 0旧版 1新版 -private_key //支付宝商户私钥 数据库字段 旧版 pay_ali_private_key 新版 pay_ali_new_private_key -app_id //支付宝appId 数据库字段 旧版 pay_ali_app_id 新版 pay_ali_new_app_id -rsa //支付宝密钥长度 旧版使用 数据库字段 pay_ali_key_len_type -pkcs //支付宝密钥格式 旧版使用 数据库字段 pay_ali_key_format_type -page_url //支付宝wap支付成功跳转链接 -*/ - -func AlipayCofing(args map[string]string) *md.PayData { - var paySet = &md.PayData{ - PayAppCertSn: args["pay_app_cert_sn"], - PayAlipayrsaPublicKey: args["pay_alipayrsa_public_key"], - PayAliUseType: args["pay_ali_use_type"], - } - return paySet -} -func AlipayApp(args map[string]string) (string, error) { - paySet := AlipayCofing(args) - if args["private_key"] == "" || args["app_id"] == "" { - return "", errors.New("请在后台正确配置支付宝") - } - param, err := local_alipay.TradeAppPay(args["app_id"], args["private_key"], args["subject"], args["ord_id"], args["amount"], args["notify_url"], args["rsa"], args["pkcs"], paySet) - if err != nil { - fmt.Println("支付宝错误日志") - fmt.Println(param) - fmt.Println(err) - return "", errors.New("支付宝订单创建失败") - } - return zhios_pay_utils.AnyToString(param), nil -} - -func AlipayWap(args map[string]string) (string, error) { - paySet := AlipayCofing(args) - if args["private_key"] == "" || args["app_id"] == "" { - return "", errors.New("请在后台正确配置支付宝") - } - param, err := local_alipay.TradeWapPay(args["app_id"], args["private_key"], args["subject"], args["ord_id"], args["amount"], args["notify_url"], args["rsa"], args["pkcs"], args["page_url"], paySet) - if err != nil { - fmt.Println("支付宝错误日志") - fmt.Println(param) - fmt.Println(err) - return "", errors.New("支付宝订单创建失败") - } - return zhios_pay_utils.AnyToString(param), nil -} - -func AlipayApplet(args map[string]string) (string, error) { - paySet := AlipayCofing(args) - if args["private_key"] == "" || args["app_id"] == "" { - return "", errors.New("请在后台正确配置支付宝") - } - param, err := local_alipay.TradeCreate(args["app_id"], args["private_key"], args["subject"], args["ord_id"], args["amount"], args["notify_url"], args["rsa"], args["pkcs"], paySet) - if err != nil { - fmt.Println("支付宝错误日志") - fmt.Println(param) - fmt.Println(err) - return "", errors.New("支付宝订单创建失败") - } - return zhios_pay_utils.AnyToString(param), nil -} - -// 微信app支付v2 -func WxAppPay(params map[string]string) (map[string]string, error) { - client := local_wxpay.NewClient(params["pay_wx_appid"], params["pay_wx_mch_id"], params["pay_wx_api_key"], true) - r, err := local_wxpay.TradeAppPay(client, params["subject"], params["ord_id"], params["amount"], params["notify_url"]) - return r, err -} - -// 微信H5支付v2 -func WxH5Pay(params map[string]string) (map[string]string, error) { - client := local_wxpay.NewClient(params["pay_wx_appid"], params["pay_wx_mch_id"], params["pay_wx_api_key"], true) - r, err := local_wxpay.TradeH5Pay(client, params["subject"], params["ord_id"], params["amount"], params["notify_url"]) - return r, err -} - -// 微信小程序v2 -func WxMiniProgPay(params map[string]string) (map[string]string, error) { - client := local_wxpay.NewClient(params["pay_wx_appid"], params["pay_wx_mch_id"], params["pay_wx_api_key"], true) - if params["third_party_wechat_openid"] == "" { - return nil, errors.New("请先授权微信") - } - r, err := local_wxpay.TradeMiniProgPay(client, params["subject"], params["ord_id"], params["amount"], params["notify_url"], params["third_party_wechat_openid"]) - return r, err -} - -// 微信JSAPI支付 -func WxAppJSAPIPay(params map[string]string) (map[string]string, error) { - client := local_wxpay.NewClient(params["pay_wx_appid"], params["pay_wx_mch_id"], params["pay_wx_api_key"], true) - if params["third_party_wechat_openid"] == "" { - return nil, errors.New("请先授权微信") - } - r, err := local_wxpay.TradeJSAPIPay(client, params["subject"], params["ord_id"], params["amount"], params["notify_url"], params["third_party_wechat_openid"]) - return r, err -} diff --git a/pay/pay_config.go b/pay/pay_config.go deleted file mode 100644 index b3ebef0..0000000 --- a/pay/pay_config.go +++ /dev/null @@ -1,36 +0,0 @@ -package pay - -import ( - "code.fnuoos.com/go_rely_warehouse/zyos_go_pay.git/db" - "code.fnuoos.com/go_rely_warehouse/zyos_go_pay.git/db/model" - "errors" -) - -//支付渠道获取 -func JudgePayChannel(mid, paySceneIdentifier string) (model.PayChannelMaster, error) { - var payChannelMaster = model.PayChannelMaster{} - res, err := db.Db.Where("app_id = ?", mid).And("identifier = ?", paySceneIdentifier).Get(&payChannelMaster) - if err != nil { - return payChannelMaster, err - } - if !res { - return payChannelMaster, errors.New("查询数据失败") - } - if payChannelMaster.ChannelId == 0 { - return payChannelMaster, errors.New("请联系服务商绑定支付渠道") - } - return payChannelMaster, nil -} - -//支付方式获取 -func JudgePayChannelPayType(channelId string) (model.PayChannel, error) { - var payChannel = model.PayChannel{} - res, err := db.Db.Where("id = ? and is_use=?", channelId, 1).Get(&payChannel) - if err != nil { - return payChannel, err - } - if !res { - return payChannel, errors.New("查询数据失败") - } - return payChannel, nil -} diff --git a/pay/pay_test.go b/pay/pay_test.go deleted file mode 100644 index 916c42d..0000000 --- a/pay/pay_test.go +++ /dev/null @@ -1,41 +0,0 @@ -package pay - -import ( - "code.fnuoos.com/go_rely_warehouse/zyos_go_pay.git/lib/icbc" - "fmt" - "testing" - "time" -) - -func TestIcbc(t1 *testing.T) { - t := time.Now() - stime := time.Date(t.Year(), t.Month(), t.Day(), t.Hour(), 0, 0, 0, t.Location()).Format("2006-1-02 15:04:05") - fmt.Println(stime) -} -func TestIcbcShow(t *testing.T) { - param := map[string]string{ - "name": "象揪巒", //客户姓名 - "mobile": "66732397", //手机号码 - "mobileArea": "853", //手机国际代码 853、852、86 *- - "optFlag": "1", // - "otp": "921507", - "cardNo": "5305068200048153", - "cardType": "C", - } - integral, err := icbc.ShowIntegral("011904180095001", "-----BEGIN PRIVATE KEY-----\nMIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDFaVbTHQF1WNlz\n0ZFgioxApDFBtwlVsoJ8Ov6WdfKLO5aikZjZJNcR2dhtgFSCvpLx/L6p/v+Jv6kl\nnJ6ZGdH1e8Yy7zcrOZd20KNawfsVYfbMFZ0yqygAfif96Uw0k2qwpXLZ6KSlV/PT\nA900571+yv2o4mu7fyHTimojwcrfVIKu+6kgidlHd7usciEvvcplV7xafZmzpG+h\n+qlF8iQ9hxou85dvF9HBox8ZkFay0xMy/QqXRYxzIaZgfAF0io/tuthol+6WUZ/M\nLzzkAwn9E4/YM1GE3qzXXE5TZmyEOV/pE+VKzfhj5sMrO1EnzLAsWGWXNd4ISKsV\noeGmtnFpAgMBAAECggEBAL7fOQnqc6yIecgYCt4zV6RwnQeS+D2Z2bxQNjQ4Wojw\n1pbc+9KIYkJqRW6qtAuuQ9ohrCAl4+HGJL+vDVGuu2kFgf9heBAdISvKUwe/owtr\nqvpss494GbdQQ06nsfzrxC6D6eZzoC4WOjP++nTa1Eex8UzHj668H3Kv1Cw6hfMj\nymxsjvV6X6a0Dp2IXiqzDlWRYPzrj3TLxz1AOLyNJP1VaVHaizTL45AT5+9dtkNc\n0kF4KTCfYLMZK9BjlgtgL4dTVun/MVuVeYb2xYUUdJ/lZ501xnwc/OG1zRPmmnIe\nPC8d6kr1VqvODL2xsPZFjha+oIhkVQPvOyjqfNLtBRkCgYEA49TsSdj8wC8iGXs7\nhXTCylH28Fomx1DITujYabhYtfmDD0IIBUU3drOtl8VHDby7wX7pDgCT8JEvbPLQ\n3FlxEgw6YWfhkOo/64MMK6hE9f0VQh2vnWL3S/5zpll5r2ZHkib4SkjWSC2q9qNA\n30lsdCAIJk3xuv6plv+9Q/0M6WsCgYEA3dGWk/o2MU589j4UspWjPSBAMyI/thzX\nYGn73jvk+RAPOxwXkAA0A9azqwvE8YfoQSNe8128OpSvcnmreXc4HphLCeR/Fbls\nDxI/f8C3Qn/LmGK8P795kQaZRDzHw1gBRpshGjEuQy7m7psR14o8gM7cof73d71W\nMzvGEPeioXsCgYEAmQpzOtv2VEaU+lbsUaZwHqXWYfe86tBZ7Z+9l66McJjNr9ck\nOh4XtrXVmwiaxSCNYtoURSKgPc3Y9K9bG1k9eeka4kl8nPKtw08BQuZChJbfy8zT\nJb7P7Y1cNFcQRYFH/GYPDR9GSa/bktdxAUx5/Ltznf9nrLvaQaNCiMQYA0cCgYA0\nomoHnQTE+GngiGSi56z/cSqqt4LEtN1KbHuuhSnVC8GBdi4FJncxPf4OJVHLOkOb\nSUhbmS9z+xoSoNpWjTqMz/hmVYjuX7xLazoUF2ek6Ownsa4XtlijWByAO6fvK2/K\nED9vlqHyoSt9DODT82Jd8jgaXITeLdhJefKKzigSBwKBgH7miTS77XP1n5nMMlbp\nNVPWF40CB7bt4VBslrJA/u0dmEfEKAhRBh6Cg1+l88Q4o/eWR/RjzqTR1Q3XaS3d\nQcwMzAiA+4aqtywStD8v6iRsA/p9A5QYjPsKze3B6urNgzGz8hMqsRLL3NyeYS+3\nCtK4zuKHZKPLivbxALqfJKkH\n-----END PRIVATE KEY-----", param) - fmt.Println(integral) - fmt.Println(err) -} -func TestIcbcDeduct(t *testing.T) { - param := map[string]string{ - "name": "象揪巒", //客户姓名 - "mobile": "66732397", //手机号码 - "mobileArea": "853", //手机国际代码 853、852、86 *- - "optFlag": "1", // - "otp": "179305", - "cardNo": "5305068200048153", - "cardType": "C", - "cusCredit": "1", - } - icbc.DeductIntegral("10000000000000203505", "-----BEGIN PRIVATE KEY-----\nMIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQCZBYj5SOjewCZ+\nGx2dAj/Lvp/TlDeVseoUl7V1X4K0jzAyo8kwYzMip5SPKj64zbkydyxqUOdEI5vk\nhfUtnZcb8PI7+lhgoBc6nv7Po+pZuP+0OkxhRvgbL+b0O/e2I3dQJOmfafQNLU1x\n3Nf3uqHtLbFuzrGKmG7zrP6to+tqY7+a+mq/o59ZSkDTWFH094jsrLtngu85hKSf\n0N7moxak+LWJF0Czqd4xI8kXfIW5O3t/jaWJPomm1fZSjlbf4VvPXVahkLOV4+Tk\naTlbMrc7ouGPVTGQo0UtWX4CVy30/QvDMfUuhTSw7S/xMO+u7r4wWrNxkEjxIu/m\nzwDFC3Q1AgMBAAECggEBAI2M4Tg4ibIEbZcZ3jrvabQ/kflWklSXT8Hc1K7Ou0nr\natptSB7KpPLZskL9AShSpY5ZT2zJiiUuC3dJs5OOw8nFCU8SNc6sSNChY3UQXCjD\nSUae5yjVTY1YsnwbPPnvtN8eRj6A9JF75rf9Yop2ynNsYUXvTay3dWtUDAL0L0Ep\nsyiU7tcbQ2NjpgVQhTpoP5cPF1ao7kwD2Ky5KmicLSjU7eLUqSvvV+O6Dw8Y5HaA\n96b57zW0J7WL7Jdo4XrfPqJ8zpQP+o7hjAulekNfOtep33TsR4MO8f9nphSUgCb0\nvlJw94nwfzvKfYGaGxRulAr4FXNBSab+H2cYsP6v88ECgYEA4cyBV+XYqEDWOWQS\nxn+zArrfUpk4J4jRnDFyAUdohhC1IKvGjhACmCg3+n8g857+HPixjGdGg0ukh2da\npHJ9FbmEmz+te/fnA0IkQTweUHQP9pJGR3DLn0WQzqBK2Ifp1cQAGWOyFRChqPb4\nemIeL80YubYW8Mgl9+EWF5Tw4G8CgYEArX0Xetk1rAmgg5RWMESh2v2Dbv9XqfDx\nk9AyCmjP21nyizzXCCw7W5MmGl0Av+nXSa78b2nXvXsz/d6/PyW0BtaO8pQX/ZWg\nVxJrUhRMA6JTg0ho/g793jF0nMBSpdivDwy1529PId8WpyeGGm7CMmSOy0SZuHiu\nTB4UJ9sr/5sCgYEAwjOPszeeReet2CJ3+31tSxXKaVIad/Y2wa3NLchq35OTFQxo\nc1rVwGQm8S1R+/Zs/CHxIp7YiKgQU9zSmslVR9ANezEjVpH6gFTstaatM+j+qcVY\n6KzclJnSV8SJWv5aYV53715Nlcx+HcJ8J1YoPFibwW4ZAPJDpZRT2ehh28UCgYBv\nBeKEx4RFeFO0YLVXZlR+JEZ8PgQHyR2QDmg3qSN7qHBDEsg5frTtwZlcva/BIRCZ\nItaBJibeJ336NRYGf0ZaKeyI6KUBr0NQ9YSgnkSW/saa+TfXfhiQnO2XcqxxXd2J\nsASo+t6VOoLwraZwO/ki7p9DDb+iAfjo1UboyqW5iQKBgQCzXyhRfacrW0kgmEp6\nCWR0oQgD54aXj1JjUkEe+gE6E7LY9Cl+yAdHBYmyCzS014jNX93+Bpg1XhoR1knO\n78A8Q7sPCrP908ycKul668daDXHp55CGpScxsx3z9jJs5ori+ZncSDAnHf0T0OjX\n+nDJPGN/gp9/WqApT1L4SLlDxg==\n-----END PRIVATE KEY-----", param) -} diff --git a/pay/tmp/1.txt b/pay/tmp/1.txt deleted file mode 100644 index e69de29..0000000 diff --git a/pay/tmp/zyos_website.logs b/pay/tmp/zyos_website.logs deleted file mode 100644 index 610ab51..0000000 --- a/pay/tmp/zyos_website.logs +++ /dev/null @@ -1 +0,0 @@ -[xorm] [info] 2022/07/07 10:46:11.171900 [SQL] SELECT `id`, `channel_id`, `identifier`, `master_id`, `master_nickname`, `third_party_id`, `master_app_name`, `app_id` FROM `pay_channel_master` WHERE (app_id = ?) AND (identifier = ?) LIMIT 1 [35618318 mall] - 26.2547ms diff --git a/rabbit/init.go b/rabbit/init.go new file mode 100644 index 0000000..758461b --- /dev/null +++ b/rabbit/init.go @@ -0,0 +1,39 @@ +package rabbit + +import ( + "fmt" + "time" +) + +var Cfg MQCfg + +//Mq配置结构体 +type MQCfg struct { + Host string `json:"host"` + Port string `json:"port"` + User string `json:"user"` + Pwd string `json:"pwd"` + Uri string `json:"uri"` + Pool *Pool `json:"pool"` +} + +func Init(host, port, user, pwd string) error { + Cfg.Host = host + Cfg.Port = port + Cfg.User = user + Cfg.Pwd = pwd + Cfg.Uri = fmt.Sprintf("amqp://%s:%s@%s:%s/", user, pwd, host, port) + var conf = Config{ + Host: Cfg.Uri, + MinConn: 10, + MaxConn: 50, + MaxChannelPerConn: 10, + MaxLifetime: time.Duration(3600), + } + pool, err := NewPool(&conf) // 建立连接池 + if err != nil { + return err + } + Cfg.Pool = pool + return nil +} diff --git a/rabbit/pool.go b/rabbit/pool.go new file mode 100644 index 0000000..7c2ec4c --- /dev/null +++ b/rabbit/pool.go @@ -0,0 +1,390 @@ +package rabbit + +import ( + "encoding/json" + "errors" + "fmt" + "github.com/streadway/amqp" + "log" + "os" + "sync" + "sync/atomic" + "time" +) + +const ( + defaultLogPrefix = "[rabbit-pool]" +) + +var ( + ErrInvalidConfig = errors.New("invalid pool config\n") + ErrFailedConnection = errors.New("failed to establish connection\n") + ErrConnectionMaximum = errors.New("the number of connections exceeds the maximum\n") + ErrChannelMaximum = errors.New("the number of channels exceeds the maximum\n") + ErrGetChannelTimeOut = errors.New("get channel timeout\n") +) + +type LoggerInter interface { + Print(v ...interface{}) +} + +type Config struct { + Host string // MQ的地址 + MinConn int // 最少建立的连接数 + MaxConn int // 最大建立的连接数 + MaxChannelPerConn int // 每个连接最多建立的信道数量 + MaxLifetime time.Duration +} + +// 连接池 +type Pool struct { + mu *sync.Mutex + conf *Config + logger LoggerInter + connectionNum int32 + connections map[int64]*Connection + connectionSerialNumber int64 + idleChannels chan *Channel +} + +func NewPool(conf *Config, logger ...LoggerInter) (*Pool, error) { + if conf.MaxConn <= 0 || conf.MinConn > conf.MaxConn { + return nil, ErrInvalidConfig + } + p := &Pool{ + mu: new(sync.Mutex), + connections: make(map[int64]*Connection), + idleChannels: make(chan *Channel, conf.MaxConn*conf.MaxChannelPerConn), + } + + if conf.MaxLifetime == 0 { + conf.MaxLifetime = time.Duration(3600) + } + + if len(logger) > 0 { + p.SetLogger(logger[0]) + } else { + p.SetLogger(log.New(os.Stdout, defaultLogPrefix, log.LstdFlags)) + } + p.conf = conf + + var conn *Connection + var err error + // 建立最少连接数 + for i := 0; i < conf.MinConn; i++ { + conn, err = p.NewConnection() + if err != nil { + p.GetLogger().Print(ErrFailedConnection.Error()) + return nil, ErrFailedConnection + } + p.connections[conn.connIdentity] = conn + } + return p, nil +} + +func (p *Pool) SetConfig(conf *Config) *Pool { + p.conf = conf + return p +} + +func (p *Pool) GetConfig() *Config { + return p.conf +} + +func (p *Pool) SetLogger(logger LoggerInter) *Pool { + p.logger = logger + return p +} + +func (p *Pool) GetLogger() LoggerInter { + return p.logger +} + +func (p *Pool) NewConnection() (*Connection, error) { + // 判断连接是否达到最大值 + if atomic.AddInt32(&p.connectionNum, 1) > int32(p.conf.MaxConn) { + atomic.AddInt32(&p.connectionNum, -1) + return nil, ErrConnectionMaximum + } + conn, err := amqp.Dial(p.conf.Host) + if err != nil { + atomic.AddInt32(&p.connectionNum, -1) + return nil, err + } + + return &Connection{ + mu: new(sync.Mutex), + conn: conn, + pool: p, + channelNum: 0, + expireTime: time.Duration(time.Now().Unix()) + p.conf.MaxLifetime, + connIdentity: atomic.AddInt64(&p.connectionSerialNumber, 1), + }, nil +} + +func (p *Pool) CloseConnection(c *Connection) error { + p.mu.Lock() + defer p.mu.Unlock() + atomic.AddInt32(&p.connectionNum, -1) + delete(p.connections, c.connIdentity) + return c.conn.Close() +} + +func (p *Pool) GetChannel() (*Channel, error) { + ch, _ := p.getOrCreate() + if ch != nil { + return ch, nil + } + + C := time.After(time.Second * 10) + for { + ch, _ := p.getOrCreate() + if ch != nil { + return ch, nil + } + select { + case <-C: + p.GetLogger().Print(ErrGetChannelTimeOut.Error()) + return nil, ErrGetChannelTimeOut + default: + } + } +} + +func (p *Pool) getOrCreate() (*Channel, error) { + // 池中是否有空闲channel + var ( + ch *Channel + err error + ) + select { + case ch = <-p.idleChannels: + return ch, nil + default: + } + + p.mu.Lock() + defer p.mu.Unlock() + // 池中已有连接是否可以建立新的channel + for _, conn := range p.connections { + if conn.CheckExpire() { + continue + } + ch, err = conn.NewChannel() + if ch != nil { + return ch, nil + } + } + // 新建连接获取新的channel + var conn *Connection + conn, err = p.NewConnection() + if err != nil { + return nil, err + } + p.connections[conn.connIdentity] = conn + ch, err = conn.NewChannel() + if err != nil { + return nil, err + } + return ch, nil +} + +func (p *Pool) ReleaseChannel(ch *Channel) error { + p.idleChannels <- ch + return nil +} + +type Connection struct { + mu *sync.Mutex + conn *amqp.Connection + pool *Pool + expireTime time.Duration + isExpire bool + connIdentity int64 // 连接标记 + channelNum int32 // 该连接的信道数量 + channelSerialNumber int64 // 第几个channel +} + +func (c *Connection) NewChannel() (*Channel, error) { + c.mu.Lock() + defer c.mu.Unlock() + if atomic.AddInt32(&c.channelNum, 1) > int32(c.pool.conf.MaxChannelPerConn) { + atomic.AddInt32(&c.channelNum, -1) + return nil, ErrChannelMaximum + } + ch, err := c.conn.Channel() + if err != nil { + atomic.AddInt32(&c.channelNum, -1) + return nil, err + } + return &Channel{ + Channel: ch, + conn: c, + chanIdentity: atomic.AddInt64(&c.channelSerialNumber, 1), + }, nil +} + +func (c *Connection) ReleaseChannel(ch *Channel) error { + if c.CheckExpire() { + return c.CloseChannel(ch) + } + return c.pool.ReleaseChannel(ch) +} + +func (c *Connection) CloseChannel(ch *Channel) error { + c.mu.Lock() + defer c.mu.Unlock() + atomic.AddInt32(&c.channelNum, -1) + var err = ch.Channel.Close() + if atomic.LoadInt32(&c.channelNum) <= 0 && c.CheckExpire() { + return c.pool.CloseConnection(c) + } + return err +} + +// 检查是否过期 +func (c *Connection) CheckExpire() bool { + if c.isExpire { + return true + } + if time.Duration(time.Now().Unix()) > c.expireTime { + c.isExpire = true + } + return c.isExpire +} + +/************************************************************************************************************/ + +type Channel struct { + *amqp.Channel + conn *Connection + chanIdentity int64 // 该连接的第几个channel + Name string + exchange string +} + +func (ch *Channel) Release() error { + return ch.conn.ReleaseChannel(ch) +} + +func (ch *Channel) Close() error { + return ch.conn.CloseChannel(ch) +} + +// QueueDeclare 声明交换机 +func (ch *Channel) QueueDeclare(queue string) { + _, e := ch.Channel.QueueDeclare(queue, false, true, false, false, nil) + failOnError(e, "声明交换机!") +} + +// QueueDelete 删除交换机 +func (ch *Channel) QueueDelete(queue string) { + _, e := ch.Channel.QueueDelete(queue, false, true, false) + failOnError(e, "删除队列失败!") +} + +// NewExchange 初始化交换机 +//s:rabbitmq服务器的链接,name:交换机名字,typename:交换机类型 +func NewExchange(s string, name string, typename string) { + //连接rabbitmq + conn, e := amqp.Dial(s) + failOnError(e, "连接Rabbitmq服务器失败!") + ch, e := conn.Channel() + failOnError(e, "无法打开频道!") + e = ch.ExchangeDeclare( + name, // name + typename, // type + true, // durable + false, // auto-deleted + false, // internal + false, // no-wait + nil, // arguments + ) + failOnError(e, "初始化交换机失败!") + +} + +// ExchangeDelete 删除交换机 +func (ch *Channel) ExchangeDelete(exchange string) { + e := ch.Channel.ExchangeDelete(exchange, false, true) + failOnError(e, "绑定队列失败!") +} + +// Bind 绑定消息队列到哪个exchange +func (ch *Channel) Bind(queueName string, exchange string, key string) { + e := ch.Channel.QueueBind( + queueName, + key, + exchange, + false, + nil, + ) + failOnError(e, "绑定队列失败!") + ch.exchange = exchange +} + +// Qos 配置队列参数 +func (ch *Channel) Qos(prefetchCount int) { + e := ch.Channel.Qos(prefetchCount, 0, false) + failOnError(e, "无法设置QoS") +} + +//Send 向消息队列发送消息 +//可以往某个消息队列发送消息 +func (ch *Channel) Send(queue string, body interface{}) { + str, e := json.Marshal(body) + failOnError(e, "消息序列化失败!") + e = ch.Channel.Publish( + "", //交换 + queue, //路由键 + false, //必填 + false, //立即 + amqp.Publishing{ + ReplyTo: ch.Name, + Body: []byte(str), + }) + msg := "向队列:" + ch.Name + "发送消息失败!" + failOnError(e, msg) +} + +// Publish 向exchange发送消息 +// 可以往某个exchange发送消息 +func (ch *Channel) Publish(exchange string, body interface{}, key string) { + str, e := json.Marshal(body) + failOnError(e, "消息序列化失败!") + e = ch.Channel.Publish( + exchange, + key, + false, + false, + amqp.Publishing{ + ContentType: "text/plain", + DeliveryMode: amqp.Transient, + Priority: 0, + Body: []byte(str)}, + ) + failOnError(e, "向路由发送消息失败!") +} + +// 接收某个消息队列的消息 +func (ch *Channel) Consume(name string) <-chan amqp.Delivery { + c, e := ch.Channel.Consume( + name, // 指定从哪个队列中接收消息 + "", // 用来区分多个消费者 + false, // 是否自动应答 + false, // 是否独有 + false, // 如果设置为true,表示不能将同一个connection中发送的消息传递给这个connection中的消费者 + false, // 列是否阻塞 + nil, + ) + failOnError(e, "接收消息失败!") + return c +} + +//错误处理函数 +func failOnError(err error, msg string) { + if err != nil { + log.Fatalf("%s: %s", msg, err) + panic(fmt.Sprintf("%s:%s", msg, err)) + } +} diff --git a/rabbitmq/init.go b/rabbitmq/init.go new file mode 100644 index 0000000..7acec52 --- /dev/null +++ b/rabbitmq/init.go @@ -0,0 +1,16 @@ +package rabbitmq + +import ( + "code.fnuoos.com/go_rely_warehouse/zyos_go_mq.git/md" + "fmt" +) + +var Cfg md.MQCfg + +func Init(host, port, user, pwd string) { + Cfg.Host = host + Cfg.Port = port + Cfg.User = user + Cfg.Pwd = pwd + Cfg.Uri = fmt.Sprintf("amqp://%s:%s@%s:%s/", user, pwd, host, port) +} diff --git a/rabbitmq/tools.go b/rabbitmq/tools.go new file mode 100644 index 0000000..6701055 --- /dev/null +++ b/rabbitmq/tools.go @@ -0,0 +1,187 @@ +package rabbitmq + +import ( + "encoding/json" + "fmt" + "github.com/streadway/amqp" + "log" +) + +// RabbitMQ 声明队列类型 +type RabbitMQ struct { + conn *amqp.Connection + channel *amqp.Channel + Name string + exchange string +} + +// Connect 连接服务器 +func Connect(s string) *RabbitMQ { + //连接rabbitmq + conn, e := amqp.Dial(s) + failOnError(e, "连接Rabbitmq服务器失败!") + ch, e := conn.Channel() + failOnError(e, "无法打开频道!") + mq := new(RabbitMQ) + mq.conn = conn + mq.channel = ch + return mq +} + +//New 初始化单个消息队列 +//s: rabbitmq服务器的链接 name:队列名字 +func New(s string, name string) *RabbitMQ { + //连接rabbitmq + conn, e := amqp.Dial(s) + failOnError(e, "连接Rabbitmq服务器失败!") + ch, e := conn.Channel() + failOnError(e, "无法打开频道!") + q, e := ch.QueueDeclare( + name, //队列名 + false, //是否开启持久化 + true, //不使用时删除 + false, //排他 + false, //不等待 + nil, //参数 + ) + failOnError(e, "初始化队列失败!") + + mq := new(RabbitMQ) + mq.channel = ch + mq.conn = conn + mq.Name = q.Name + return mq +} + +// QueueDeclare 声明交换机 +func (q *RabbitMQ) QueueDeclare(queue string) { + _, e := q.channel.QueueDeclare(queue, false, true, false, false, nil) + failOnError(e, "声明交换机!") +} + +// QueueDelete 删除交换机 +func (q *RabbitMQ) QueueDelete(queue string) { + _, e := q.channel.QueueDelete(queue, false, true, false) + failOnError(e, "删除队列失败!") +} + +// Qos 配置队列参数 +func (q *RabbitMQ) Qos(prefetchCount int) { + e := q.channel.Qos(prefetchCount, 0, false) + failOnError(e, "无法设置QoS") +} + +//配置交换机参数 + +// NewExchange 初始化交换机 +//s:rabbitmq服务器的链接,name:交换机名字,typename:交换机类型 +func NewExchange(s string, name string, typename string) { + //连接rabbitmq + conn, e := amqp.Dial(s) + failOnError(e, "连接Rabbitmq服务器失败!") + ch, e := conn.Channel() + failOnError(e, "无法打开频道!") + e = ch.ExchangeDeclare( + name, // name + typename, // type + true, // durable + false, // auto-deleted + false, // internal + false, // no-wait + nil, // arguments + ) + failOnError(e, "初始化交换机失败!") + +} + +// ExchangeDelete 删除交换机 +func (q *RabbitMQ) ExchangeDelete(exchange string) { + e := q.channel.ExchangeDelete(exchange, false, true) + failOnError(e, "绑定队列失败!") +} + +// Bind 绑定消息队列到哪个exchange +func (q *RabbitMQ) Bind(exchange string, key string) { + e := q.channel.QueueBind( + q.Name, + key, + exchange, + false, + nil, + ) + failOnError(e, "绑定队列失败!") + q.exchange = exchange +} + +//Send 向消息队列发送消息 +//可以往某个消息队列发送消息 +func (q *RabbitMQ) Send(queue string, body interface{}) { + str, e := json.Marshal(body) + failOnError(e, "消息序列化失败!") + e = q.channel.Publish( + "", //交换 + queue, //路由键 + false, //必填 + false, //立即 + amqp.Publishing{ + ReplyTo: q.Name, + Body: []byte(str), + }) + msg := "向队列:" + q.Name + "发送消息失败!" + failOnError(e, msg) +} + +// Publish 向exchange发送消息 +// 可以往某个exchange发送消息 +func (q *RabbitMQ) Publish(exchange string, body interface{}, key string) { + str, e := json.Marshal(body) + failOnError(e, "消息序列化失败!") + e = q.channel.Publish( + exchange, + key, + false, + false, + amqp.Publishing{ReplyTo: q.Name, + Body: []byte(str)}, + ) + failOnError(e, "向路由发送消息失败!") +} + +// Consume 接收某个消息队列的消息 +func (q *RabbitMQ) Consume() <-chan amqp.Delivery { + c, e := q.channel.Consume( + q.Name, // 指定从哪个队列中接收消息 + "", // 用来区分多个消费者 + false, // 是否自动应答 + false, // 是否独有 + false, // 如果设置为true,表示不能将同一个connection中发送的消息传递给这个connection中的消费者 + false, // 列是否阻塞 + nil, + ) + failOnError(e, "接收消息失败!") + return c +} + +// 关闭信道 +func (q *RabbitMQ) CloseChannel() { + q.channel.Close() +} + +// 关闭连接 +func (q *RabbitMQ) CloseConn() { + q.conn.Close() +} + +// 销毁(断开channel和connection) +func (q *RabbitMQ) Destroy() { + q.channel.Close() //关闭信道资源 + q.conn.Close() //关闭链接资源 +} + +//错误处理函数 +func failOnError(err error, msg string) { + if err != nil { + log.Fatalf("%s: %s", msg, err) + panic(fmt.Sprintf("%s:%s", msg, err)) + } +} diff --git a/test/direct_exchange.md b/test/direct_exchange.md new file mode 100644 index 0000000..fcbd9de --- /dev/null +++ b/test/direct_exchange.md @@ -0,0 +1,14 @@ +## 路由Routing(direct) +路由模式其实就是全值匹配模式(direct),发送端发送消息需要带有路由键,就是下面发送端程序的routing key1,是一个字符串,发送端发给exchange。 +路由模式下的exchange会匹配这个路由键,如下面这个图,发送者发送时带有orange此路由键时,这条消息只会被转发给Q1队列。 +如果路由键没有匹配上的怎么办?全值匹配,没有匹配到,那么所有接收者都接收不到消息,消息只会发送给匹配的队列,接收端的路由键是绑定exchange的时候用的。 + +------ + + +*__注意:接收队列可以绑定多个路由键到exchange上,比如下面,当发送路由键为black,green,会被Q2接收。__* + + +- ![image-20220113153420444](../images/md/direct.jpg) + + diff --git a/test/direct_exchange_test.go b/test/direct_exchange_test.go new file mode 100644 index 0000000..2abfab0 --- /dev/null +++ b/test/direct_exchange_test.go @@ -0,0 +1,83 @@ +package test + +import ( + "code.fnuoos.com/go_rely_warehouse/zyos_go_mq.git/rabbitmq" + "log" + "strconv" + "strings" + "testing" + "time" +) + +const DirectExchangeName = "test_direct_exchange" +const DirectExchangeRoutingKey1 = "direct_exchange_routing_key_1" +const DirectExchangeRoutingKey2 = "direct_exchange_routing_key_2" + +func TestDirectExchangeSend(t *testing.T) { + ch := rabbitmq.Connect("amqp://user:password@ip:port/") + rabbitmq.NewExchange("amqp://user:password@ip:port/", DirectExchangeName, "direct") + i := 0 + for { + time.Sleep(1) + greetings := []string{"HelloWorld!", strconv.Itoa(i)} + if i%2 == 1 { + //如果是奇数 + ch.Publish("exchange", strings.Join(greetings, " "), DirectExchangeRoutingKey1) + } else { + ch.Publish("exchange", strings.Join(greetings, " "), DirectExchangeRoutingKey2) + } + i = i + 1 + } +} + +func TestDirectExchangeReceive1(t *testing.T) { + // 1.接收者,首先自己队列 + // 2.创建交换机 + // 3.将自己绑定到交换机上 + // 4.接收交换机上发过来的消息 + //第一个参数指定rabbitmq服务器的链接,第二个参数指定创建队列的名字 + + receiveMq := rabbitmq.New("amqp://user:password@ip:port/", "test_direct_exchange_receive_queue_1") + + //第一个参数:rabbitmq服务器的链接,第二个参数:交换机名字,第三个参数:交换机类型 + rabbitmq.NewExchange("amqp://user:password@ip:port/", "exchange", "direct") + + receiveMq.Bind(DirectExchangeName, DirectExchangeRoutingKey1) + + //4 + for { + //接收消息时,指定 + messages := receiveMq.Consume() + go func() { + for msg := range messages { + log.Printf("recevie1 Received a message: %s", msg.Body) + } + }() + } +} + +func TestDirectExchangeReceive2(t *testing.T) { + // 1.接收者,首先自己队列 + // 2.创建交换机 + // 3.将自己绑定到交换机上 + // 4.接收交换机上发过来的消息 + //第一个参数指定rabbitmq服务器的链接,第二个参数指定创建队列的名字 + + receiveMq := rabbitmq.New("amqp://user:password@ip:port/", "test_direct_exchange_receive_queue_2") + + //第一个参数:rabbitmq服务器的链接,第二个参数:交换机名字,第三个参数:交换机类型 + rabbitmq.NewExchange("amqp://user:password@ip:port/", "exchange", "direct") + + receiveMq.Bind(DirectExchangeName, DirectExchangeRoutingKey2) + + //4 + for { + //接收消息时,指定 + messages := receiveMq.Consume() + go func() { + for msg := range messages { + log.Printf("recevie1 Received a message: %s", msg.Body) + } + }() + } +} diff --git a/test/fanout_exchange.md b/test/fanout_exchange.md new file mode 100644 index 0000000..5c825d2 --- /dev/null +++ b/test/fanout_exchange.md @@ -0,0 +1,18 @@ +## 发布/订阅 Publish/Subscribe(fanout) + +#### 什么是exchange(交换机) ? +exchange。其作用就是类似路由器, +> exchange(交换机)有多个种类:direct,fanout,topic,header(非路由键匹配,功能和direct类似,很少用)。 + +发送端发送消息需要带有 routing key 就是路由键,服务器会根据路由键将消息从交换器路由到队列上去,所以发送端和接收端之间有了中介。 + +------ +### `fanout` 广播模式下(1:N): +- fanout 模式下,它会将发到这个exchange的消息广播到关注此exchange的所有接收端上。 +- 发送端连接到rabbitmq后,创建exchange,需要指定交换机的名字和类型,fanout为广播,然后向此exchange发送消息,其它就不用管了。 + + +- ![image-20220113153420444](../images/md/fanout.png) + + +*__注意:`fanout`广播模式下的exchange的发送端是不需要带路由键(routing key)的。__* \ No newline at end of file diff --git a/test/fanout_exchange_test.go b/test/fanout_exchange_test.go new file mode 100644 index 0000000..cacd5aa --- /dev/null +++ b/test/fanout_exchange_test.go @@ -0,0 +1,72 @@ +package test + +import ( + "code.fnuoos.com/go_rely_warehouse/zyos_go_mq.git/rabbitmq" + "log" + "strconv" + "strings" + "testing" + "time" +) + +const FanoutExchangeName = "test_fanout_exchange" + +func TestFanoutExchangeSend(t *testing.T) { + ch := rabbitmq.Connect("amqp://user:password@ip:port/") + rabbitmq.NewExchange("amqp://user:password@ip:port/", FanoutExchangeName, "fanout") + i := 0 + for { + time.Sleep(1) + greetings := []string{"Helloworld!", strconv.Itoa(i)} + ch.Publish(FanoutExchangeName, strings.Join(greetings, " "), "") + i = i + 1 + } +} + +func TestFanoutExchangeReceive1(t *testing.T) { + // 1.接收者,首先创建自己队列 + // 2.创建交换机 + // 3.将自己绑定到交换机上 + // 4.接收交换机上发过来的消息 + + //第一个参数指定rabbitmq服务器的链接,第二个参数指定创建队列的名字 + receiveMq := rabbitmq.New("amqp://user:password@ip:port/", "test_fanout_exchange_receive_queue_1") + //第一个参数:rabbitmq服务器的链接,第二个参数:交换机名字,第三个参数:交换机类型 + rabbitmq.NewExchange("amqp://user:password@ip:port/", FanoutExchangeName, "fanout") + // 队列绑定到exchange + receiveMq.Bind(FanoutExchangeName, "") + //4 + for { + //接收消息时,指定 + msgs := receiveMq.Consume() + go func() { + for d := range msgs { + log.Printf("recevie1 Received a message: %s", d.Body) + } + }() + } +} + +func TestFanoutExchangeReceive2(t *testing.T) { + // 1.接收者,首先创建自己队列 + // 2.创建交换机 + // 3.将自己绑定到交换机上 + // 4.接收交换机上发过来的消息 + + //第一个参数指定rabbitmq服务器的链接,第二个参数指定创建队列的名字 + receiveMq := rabbitmq.New("amqp://user:password@ip:port/", "test_fanout_exchange_receive_queue_2") + //第一个参数:rabbitmq服务器的链接,第二个参数:交换机名字,第三个参数:交换机类型 + rabbitmq.NewExchange("amqp://user:password@ip:port/", FanoutExchangeName, "fanout") + // 队列绑定到exchange + receiveMq.Bind(FanoutExchangeName, "") + //4 + for { + //接收消息时,指定 + msgs := receiveMq.Consume() + go func() { + for d := range msgs { + log.Printf("recevie1 Received a message: %s", d.Body) + } + }() + } +} diff --git a/test/join_pay_test.go b/test/join_pay_test.go deleted file mode 100644 index dd95946..0000000 --- a/test/join_pay_test.go +++ /dev/null @@ -1,11 +0,0 @@ -package test - -import ( - "code.fnuoos.com/go_rely_warehouse/zyos_go_pay.git/md" - "code.fnuoos.com/go_rely_warehouse/zyos_go_pay.git/pay" - "testing" -) - -func TestUniPayByJoin(t *testing.T) { - pay.UniPayByJoin(&md.JoinPayReq{},"a12ceace4cc5423eae32b4626adf56c9" ,false) -} diff --git a/test/single_queue.md b/test/single_queue.md new file mode 100644 index 0000000..6d2d5f5 --- /dev/null +++ b/test/single_queue.md @@ -0,0 +1,14 @@ +## 单一队列(单收单发) +在下图中,“P”是我们的生产者, “C”是我们的消费者。 中间的框是一个队列-RabbitMQ代表使用者保留的消息缓冲区。 + +- 示例图 ![image-20220113153420444](../images/md/single.png) +------ + +> 单发单收模式下:一发一收 + +发送端只需要创建队列,然后向队列发送消息。 +接收端也需要创建队列,因为如果接收端先启动,没有此队列就会报错,虽然发送端和接收端都创建此队列,但rabbitmq还是很智能的,它只会创建一次。 + +需要注意的地方: +* 1.发送端和接收端都需要创建同名队列 +* 2.接收端指定从这个同名队列中接收消息 \ No newline at end of file diff --git a/test/single_queue_test.go b/test/single_queue_test.go new file mode 100644 index 0000000..69e18fa --- /dev/null +++ b/test/single_queue_test.go @@ -0,0 +1,111 @@ +package test + +import ( + "code.fnuoos.com/go_rely_warehouse/zyos_go_mq.git/rabbit" + "code.fnuoos.com/go_rely_warehouse/zyos_go_mq.git/rabbitmq" + "fmt" + "github.com/streadway/amqp" + "log" + "strconv" + "strings" + "testing" +) + +const SingleQueueName = "test_single_queue" + +func TestSend(t *testing.T) { + var host, port, user, pwd string + log.SetFlags(log.Lshortfile | log.LstdFlags) + log.Println("input host,port,user,pwd") + fmt.Scanf("%s %s %s %s", &host, &port, &user, &pwd) + if host == "" && port == "" && user == "" && pwd == "" { + host = "10.10.140.138" + port = "5672" + user = "admin" + pwd = "123456" + } + rabbitmq.Init(host, port, user, pwd) + //第一个参数指定rabbitmq服务器的链接,第二个参数指定创建队列的名字 + sendMq := rabbitmq.New(rabbitmq.Cfg.Uri, SingleQueueName) + i := 0 + for { + if i > 100 { + break + } + //time.Sleep(time.Second * 1) + greetings := []string{"HelloWorld!", strconv.Itoa(i)} + sendMq.Send(SingleQueueName, strings.Join(greetings, " ")) + i = i + 1 + } +} + +func TestReceive(t *testing.T) { + var host, port, user, pwd string + log.SetFlags(log.Lshortfile | log.LstdFlags) + log.Println("input host,port,user,pwd") + fmt.Scanf("%s %s %s %s", &host, &port, &user, &pwd) + if host == "" && port == "" && user == "" && pwd == "" { + host = "10.10.140.138" + port = "5672" + user = "admin" + pwd = "123456" + } + //ch, err := GetChannel + rabbitmq.Init(host, port, user, pwd) + //第一个参数指定rabbitmq服务器的链接,第二个参数指定创建队列的名字 + receiveMq := rabbitmq.New(rabbitmq.Cfg.Uri, SingleQueueName) + //for { + receiveMq.Qos(5) + //接收消息时,指定 + messages := receiveMq.Consume() + + forever := make(chan bool) //开辟管道 + //启用协程处理消息 + go func() { + for msg := range messages { + log.Printf("Received a message: %s", msg.Body) + + msg.Ack(false) + + //msg.Reject(true) + } + }() + log.Printf("[*] Waiting for message,To exit press CTRL+C") + <-forever +} + +func TestReceive1(t *testing.T) { + var host, port, user, pwd string + log.SetFlags(log.Lshortfile | log.LstdFlags) + log.Println("input host,port,user,pwd") + fmt.Scanf("%s %s %s %s", &host, &port, &user, &pwd) + if host == "" && port == "" && user == "" && pwd == "" { + host = "10.10.140.138" + port = "5672" + user = "admin" + pwd = "123456" + } + rabbit.Init(host, port, user, pwd) + ch, err := rabbit.Cfg.Pool.GetChannel() + if err != nil { + fmt.Println(err.Error()) + } + + defer ch.Release() + ch.Qos(5) + delivery := ch.Consume(SingleQueueName) + + var res amqp.Delivery + var ok bool + //for { + res, ok = <-delivery + if ok == true { + fmt.Println(string(res.Body)) + _ = res.Ack(false) + } else { + fmt.Println("error getting message") + //break + } + //} + fmt.Println("get msg done") +} diff --git a/test/topic_exchange.md b/test/topic_exchange.md new file mode 100644 index 0000000..11d8922 --- /dev/null +++ b/test/topic_exchange.md @@ -0,0 +1,33 @@ +## Topic类型的exchange + +- direct是全值匹配,那么topic就可以部分匹配,又可以全值匹配,比direct更加灵活。 + +消息发送到topic类型的exchange上时不能随意指定routing_key(一定是指由一系列由点号连接单词的字符串,单词可以是任意的,但一般都会与消息或多或少的有些关联)。 Routing key的长度不能超过255个字节。 + +Binding key也一定要是同样的方式。Topic类型的exchange就像一个直接的交换:一个由生产者指定了确定routing key的消息将会被推送给所有Binding key能与之匹配的消费者。然而这种绑定有两种特殊的情况: + * (星号):可以(只能)匹配一个单词 + * #(井号):可以匹配多个单词(或者零个) + * 举例说明:如下图 + ![image-20220113153420444](../images/md/topic.jpg) + + 在这个例子中,我们将会发送一些描述动物的消息。Routing key的第一个单词是描述速度的,第二个单词是描述颜色的,第三个是描述物种的:“..”。 + 这里我们创建三个Binding:Binding key为”*.orange.*”的Q1,和binding key为”*.*.rabbit”和”lazy.#”的Q2。 + 这些binding可以总结为: + - Q1对所有橘色的(orange)的动物感兴趣; + - Q2希望能拿到所有兔子的(rabbit)信息,还有比较懒惰的(lazy.#)动物信息。 + +一条以” quick.orange.rabbit”为routing key的消息将会推送到Q1和Q2两个queue上,routing key为“lazy.orange.elephant”的消息同样会被推送到Q1和Q2上。但如果routing key为”quick.orange.fox”的话,消息只会被推送到Q1上;routing key为”lazy.brown.fox”的消息会被推送到Q2上,routing key为"lazy.pink.rabbit”的消息也会被推送到Q2上,但同一条消息只会被推送到Q2上一次。 + +如果在发送消息时所指定的exchange和routing key在消费者端没有对应的exchange和binding key与之绑定的话,那么这条消息将会被丢弃掉。例如:"orange"和"quick.orange.male.rabbit"。但是routing为”lazy.orange.male.rabbit”的消息,将会被推到Q2上。 + +Topic类型的exchange: + +------ + +Topic类型的exchange是很强大的,也可以实现其它类型的exchange。 + +- 当一个队列被绑定为binding key为”#”时,它将会接收所有的消息,此时和fanout类型的exchange很像。 +- 当binding key不包含”*”和”#”时,这时候就很像direct类型的exchange。 + + + diff --git a/test/topic_exchange_test.go b/test/topic_exchange_test.go new file mode 100644 index 0000000..3c1a06c --- /dev/null +++ b/test/topic_exchange_test.go @@ -0,0 +1,73 @@ +package test + +import ( + "code.fnuoos.com/go_rely_warehouse/zyos_go_mq.git/rabbitmq" + "fmt" + "log" + "testing" + "time" +) + +const TopicExchangeName = "test_topic_exchange" + +func TestTopicExchangeSend(t *testing.T) { + var host, port, user, pwd string + fmt.Scanf("%s %s %s %s", &host, &port, &user, &pwd) + rabbitmq.Init(host, port, user, pwd) + ch := rabbitmq.Connect(rabbitmq.Cfg.Uri) + rabbitmq.NewExchange(rabbitmq.Cfg.Uri, TopicExchangeName, "topic") + for { + time.Sleep(1) + ch.Publish("exchange", "hello world", "lazy.orange.elephant") + } +} + +func TestTopicExchangeReceive1(t *testing.T) { + // 1.接收者,首先自己队列 + // 2.创建交换机 + // 3.将自己绑定到交换机上 + // 4.接收交换机上发过来的消息 + //第一个参数指定rabbitmq服务器的链接,第二个参数指定创建队列的名字 + + receiveMq := rabbitmq.New("amqp://user:password@ip:port/", "test_topic_exchange_receive_queue_1") + + //第一个参数:rabbitmq服务器的链接,第二个参数:交换机名字,第三个参数:交换机类型 + rabbitmq.NewExchange("amqp://user:password@ip:port/", TopicExchangeName, "topic") + + receiveMq.Bind(TopicExchangeName, "*.orange.*") + + for { + //接收消息时,指定 + messages := receiveMq.Consume() + go func() { + for msg := range messages { + log.Printf("recevie1 Received a message: %s", msg.Body) + } + }() + } +} + +func TestTopicExchangeReceive2(t *testing.T) { + // 1.接收者,首先自己队列 + // 2.创建交换机 + // 3.将自己绑定到交换机上 + // 4.接收交换机上发过来的消息 + //第一个参数指定rabbitmq服务器的链接,第二个参数指定创建队列的名字 + + receiveMq := rabbitmq.New("amqp://user:password@ip:port/", "test_topic_exchange_receive_queue_2") + + //第一个参数:rabbitmq服务器的链接,第二个参数:交换机名字,第三个参数:交换机类型 + rabbitmq.NewExchange("amqp://user:password@ip:port/", TopicExchangeName, "topic") + + receiveMq.Bind(TopicExchangeName, "*.*.rabbit") + receiveMq.Bind(TopicExchangeName, "lazy.#") + for { + //接收消息时,指定 + messages := receiveMq.Consume() + go func() { + for msg := range messages { + log.Printf("recevie1 Received a message: %s", msg.Body) + } + }() + } +} diff --git a/test/work_queue.md b/test/work_queue.md new file mode 100644 index 0000000..a2c9a95 --- /dev/null +++ b/test/work_queue.md @@ -0,0 +1,15 @@ +## 工作队列(多收单发) +工作队列和单发单收模式比起来,接收端可以有多个,接收端多了以后就会出现数据分配问题,发过来的数据到底该被哪个接收端接收,所以有两种模式: +* 公平分发:每个接收端接收消息的概率是相等的,发送端会循环依次给每个接收端发送消息,图一是公平分发,公平分发是rabbitmq默认模式。 +* 公平派遣:保证接收端在处理完某个任务,并发送确认信息后,RabbitMQ才会向它推送新的消息,在此之间若是有新的消息话,将会被推送到其它接收端,若所有的接收端都在处理任务,那么就会等待,图二为公平派遣。 + +> *__注意:__ 使用公平派遣模式时,消费者设置atuoack为false,需要手动回复ack。 关闭自动应答是为了消费者逻辑处理结束前不接受下一条消息,这样哪个消费者逻辑处理的快,接收的消息自然就多,从而实现公平分发。* + +------ + +- 示例图1 ![image-20220113153420444](../images/md/work_1.png) + + +- 示例图2 ![image-20220113153420444](../images/md/work_2.png) + + diff --git a/test/work_queue_test.go b/test/work_queue_test.go new file mode 100644 index 0000000..4796dbf --- /dev/null +++ b/test/work_queue_test.go @@ -0,0 +1,76 @@ +package test + +import ( + "code.fnuoos.com/go_rely_warehouse/zyos_go_mq.git/rabbitmq" + "log" + "strconv" + "strings" + "testing" + "time" +) + +const WorkQueueName = "test_work_queue" + +/** +TODO:: 公平分发模式下的发送端和接收端(一个发动端,多个接受端) +*/ +func TestWorkSend(t *testing.T) { + //第一个参数指定rabbitmq服务器的链接,第二个参数指定创建队列的名字 + sendMq := rabbitmq.New("链接", WorkQueueName) + i := 0 + for { + time.Sleep(time.Second * 5) + greetings := []string{"HelloWorld!", strconv.Itoa(i)} + sendMq.Send("hello", strings.Join(greetings, " ")) + i = i + 1 + } +} + +func TestWorkReceive1(t *testing.T) { + //第一个参数指定rabbitmq服务器的链接,第二个参数指定创建队列的名字 + receiveMq := rabbitmq.New("amqp://user:password@ip:port/", WorkQueueName) + for { + //接收消息时,指定 + messages := receiveMq.Consume() + go func() { + for msg := range messages { + log.Printf("Received a message: %s", msg.Body) + } + }() + } +} + +func TestWorkReceive2(t *testing.T) { + //第一个参数指定rabbitmq服务器的链接,第二个参数指定创建队列的名字 + receiveMq := rabbitmq.New("amqp://user:password@ip:port/", WorkQueueName) + for { + //接收消息时,指定 + messages := receiveMq.Consume() + go func() { + for msg := range messages { + log.Printf("Received a message: %s", msg.Body) + } + }() + } +} + +/** +TODO:: 公平派遣模式下的发送端和接收端(公平派遣模式下发送端与公平分发相同,接收端只需要加一端配置代码) +*/ +func TestWorkReceive3(t *testing.T) { + //第一个参数指定rabbitmq服务器的链接,第二个参数指定创建队列的名字 + receiveMq := rabbitmq.New("amqp://user:password@ip:port/", WorkQueueName) + + //todo::配置公平派遣 + //(将预取计数设置为1。这告诉RabbitMQ一次不要给工人一个以上的消息。换句话说,在处理并确认上一条消息之前,不要将新消息发送给工作人员。而是将其分派给不忙的下一个工作程序。) + receiveMq.Qos(1) + for { + //接收消息时,指定 + messages := receiveMq.Consume() + go func() { + for msg := range messages { + log.Printf("Received a message: %s", msg.Body) + } + }() + } +} diff --git a/utils/cache/base.go b/utils/cache/base.go deleted file mode 100644 index 64648dd..0000000 --- a/utils/cache/base.go +++ /dev/null @@ -1,421 +0,0 @@ -package cache - -import ( - "errors" - "fmt" - "strconv" - "time" -) - -const ( - redisDialTTL = 10 * time.Second - redisReadTTL = 3 * time.Second - redisWriteTTL = 3 * time.Second - redisIdleTTL = 10 * time.Second - redisPoolTTL = 10 * time.Second - redisPoolSize int = 512 - redisMaxIdleConn int = 64 - redisMaxActive int = 512 -) - -var ( - ErrNil = errors.New("nil return") - ErrWrongArgsNum = errors.New("args num error") - ErrNegativeInt = errors.New("redis cluster: unexpected value for Uint64") -) - -// 以下为提供类型转换 - -func Int(reply interface{}, err error) (int, error) { - if err != nil { - return 0, err - } - switch reply := reply.(type) { - case int: - return reply, nil - case int8: - return int(reply), nil - case int16: - return int(reply), nil - case int32: - return int(reply), nil - case int64: - x := int(reply) - if int64(x) != reply { - return 0, strconv.ErrRange - } - return x, nil - case uint: - n := int(reply) - if n < 0 { - return 0, strconv.ErrRange - } - return n, nil - case uint8: - return int(reply), nil - case uint16: - return int(reply), nil - case uint32: - n := int(reply) - if n < 0 { - return 0, strconv.ErrRange - } - return n, nil - case uint64: - n := int(reply) - if n < 0 { - return 0, strconv.ErrRange - } - return n, nil - case []byte: - data := string(reply) - if len(data) == 0 { - return 0, ErrNil - } - - n, err := strconv.ParseInt(data, 10, 0) - return int(n), err - case string: - if len(reply) == 0 { - return 0, ErrNil - } - - n, err := strconv.ParseInt(reply, 10, 0) - return int(n), err - case nil: - return 0, ErrNil - case error: - return 0, reply - } - return 0, fmt.Errorf("redis cluster: unexpected type for Int, got type %T", reply) -} - -func Int64(reply interface{}, err error) (int64, error) { - if err != nil { - return 0, err - } - switch reply := reply.(type) { - case int: - return int64(reply), nil - case int8: - return int64(reply), nil - case int16: - return int64(reply), nil - case int32: - return int64(reply), nil - case int64: - return reply, nil - case uint: - n := int64(reply) - if n < 0 { - return 0, strconv.ErrRange - } - return n, nil - case uint8: - return int64(reply), nil - case uint16: - return int64(reply), nil - case uint32: - return int64(reply), nil - case uint64: - n := int64(reply) - if n < 0 { - return 0, strconv.ErrRange - } - return n, nil - case []byte: - data := string(reply) - if len(data) == 0 { - return 0, ErrNil - } - - n, err := strconv.ParseInt(data, 10, 64) - return n, err - case string: - if len(reply) == 0 { - return 0, ErrNil - } - - n, err := strconv.ParseInt(reply, 10, 64) - return n, err - case nil: - return 0, ErrNil - case error: - return 0, reply - } - return 0, fmt.Errorf("redis cluster: unexpected type for Int64, got type %T", reply) -} - -func Uint64(reply interface{}, err error) (uint64, error) { - if err != nil { - return 0, err - } - switch reply := reply.(type) { - case uint: - return uint64(reply), nil - case uint8: - return uint64(reply), nil - case uint16: - return uint64(reply), nil - case uint32: - return uint64(reply), nil - case uint64: - return reply, nil - case int: - if reply < 0 { - return 0, ErrNegativeInt - } - return uint64(reply), nil - case int8: - if reply < 0 { - return 0, ErrNegativeInt - } - return uint64(reply), nil - case int16: - if reply < 0 { - return 0, ErrNegativeInt - } - return uint64(reply), nil - case int32: - if reply < 0 { - return 0, ErrNegativeInt - } - return uint64(reply), nil - case int64: - if reply < 0 { - return 0, ErrNegativeInt - } - return uint64(reply), nil - case []byte: - data := string(reply) - if len(data) == 0 { - return 0, ErrNil - } - - n, err := strconv.ParseUint(data, 10, 64) - return n, err - case string: - if len(reply) == 0 { - return 0, ErrNil - } - - n, err := strconv.ParseUint(reply, 10, 64) - return n, err - case nil: - return 0, ErrNil - case error: - return 0, reply - } - return 0, fmt.Errorf("redis cluster: unexpected type for Uint64, got type %T", reply) -} - -func Float64(reply interface{}, err error) (float64, error) { - if err != nil { - return 0, err - } - - var value float64 - err = nil - switch v := reply.(type) { - case float32: - value = float64(v) - case float64: - value = v - case int: - value = float64(v) - case int8: - value = float64(v) - case int16: - value = float64(v) - case int32: - value = float64(v) - case int64: - value = float64(v) - case uint: - value = float64(v) - case uint8: - value = float64(v) - case uint16: - value = float64(v) - case uint32: - value = float64(v) - case uint64: - value = float64(v) - case []byte: - data := string(v) - if len(data) == 0 { - return 0, ErrNil - } - value, err = strconv.ParseFloat(string(v), 64) - case string: - if len(v) == 0 { - return 0, ErrNil - } - value, err = strconv.ParseFloat(v, 64) - case nil: - err = ErrNil - case error: - err = v - default: - err = fmt.Errorf("redis cluster: unexpected type for Float64, got type %T", v) - } - - return value, err -} - -func Bool(reply interface{}, err error) (bool, error) { - if err != nil { - return false, err - } - switch reply := reply.(type) { - case bool: - return reply, nil - case int64: - return reply != 0, nil - case []byte: - data := string(reply) - if len(data) == 0 { - return false, ErrNil - } - - return strconv.ParseBool(data) - case string: - if len(reply) == 0 { - return false, ErrNil - } - - return strconv.ParseBool(reply) - case nil: - return false, ErrNil - case error: - return false, reply - } - return false, fmt.Errorf("redis cluster: unexpected type for Bool, got type %T", reply) -} - -func Bytes(reply interface{}, err error) ([]byte, error) { - if err != nil { - return nil, err - } - switch reply := reply.(type) { - case []byte: - if len(reply) == 0 { - return nil, ErrNil - } - return reply, nil - case string: - data := []byte(reply) - if len(data) == 0 { - return nil, ErrNil - } - return data, nil - case nil: - return nil, ErrNil - case error: - return nil, reply - } - return nil, fmt.Errorf("redis cluster: unexpected type for Bytes, got type %T", reply) -} - -func String(reply interface{}, err error) (string, error) { - if err != nil { - return "", err - } - - value := "" - err = nil - switch v := reply.(type) { - case string: - if len(v) == 0 { - return "", ErrNil - } - - value = v - case []byte: - if len(v) == 0 { - return "", ErrNil - } - - value = string(v) - case int: - value = strconv.FormatInt(int64(v), 10) - case int8: - value = strconv.FormatInt(int64(v), 10) - case int16: - value = strconv.FormatInt(int64(v), 10) - case int32: - value = strconv.FormatInt(int64(v), 10) - case int64: - value = strconv.FormatInt(v, 10) - case uint: - value = strconv.FormatUint(uint64(v), 10) - case uint8: - value = strconv.FormatUint(uint64(v), 10) - case uint16: - value = strconv.FormatUint(uint64(v), 10) - case uint32: - value = strconv.FormatUint(uint64(v), 10) - case uint64: - value = strconv.FormatUint(v, 10) - case float32: - value = strconv.FormatFloat(float64(v), 'f', -1, 32) - case float64: - value = strconv.FormatFloat(v, 'f', -1, 64) - case bool: - value = strconv.FormatBool(v) - case nil: - err = ErrNil - case error: - err = v - default: - err = fmt.Errorf("redis cluster: unexpected type for String, got type %T", v) - } - - return value, err -} - -func Strings(reply interface{}, err error) ([]string, error) { - if err != nil { - return nil, err - } - switch reply := reply.(type) { - case []interface{}: - result := make([]string, len(reply)) - for i := range reply { - if reply[i] == nil { - continue - } - switch subReply := reply[i].(type) { - case string: - result[i] = subReply - case []byte: - result[i] = string(subReply) - default: - return nil, fmt.Errorf("redis cluster: unexpected element type for String, got type %T", reply[i]) - } - } - return result, nil - case []string: - return reply, nil - case nil: - return nil, ErrNil - case error: - return nil, reply - } - return nil, fmt.Errorf("redis cluster: unexpected type for Strings, got type %T", reply) -} - -func Values(reply interface{}, err error) ([]interface{}, error) { - if err != nil { - return nil, err - } - switch reply := reply.(type) { - case []interface{}: - return reply, nil - case nil: - return nil, ErrNil - case error: - return nil, reply - } - return nil, fmt.Errorf("redis cluster: unexpected type for Values, got type %T", reply) -} diff --git a/utils/cache/redis.go b/utils/cache/redis.go deleted file mode 100644 index 4e5f047..0000000 --- a/utils/cache/redis.go +++ /dev/null @@ -1,403 +0,0 @@ -package cache - -import ( - "encoding/json" - "errors" - "log" - "strings" - "time" - - redigo "github.com/gomodule/redigo/redis" -) - -// configuration -type Config struct { - Server string - Password string - MaxIdle int // Maximum number of idle connections in the pool. - - // Maximum number of connections allocated by the pool at a given time. - // When zero, there is no limit on the number of connections in the pool. - MaxActive int - - // Close connections after remaining idle for this duration. If the value - // is zero, then idle connections are not closed. Applications should set - // the timeout to a value less than the server's timeout. - IdleTimeout time.Duration - - // If Wait is true and the pool is at the MaxActive limit, then Get() waits - // for a connection to be returned to the pool before returning. - Wait bool - KeyPrefix string // prefix to all keys; example is "dev environment name" - KeyDelimiter string // delimiter to be used while appending keys; example is ":" - KeyPlaceholder string // placeholder to be parsed using given arguments to obtain a final key; example is "?" -} - -var pool *redigo.Pool -var conf *Config - -func NewRedis(addr string) { - if addr == "" { - panic("\nredis connect string cannot be empty\n") - } - pool = &redigo.Pool{ - MaxIdle: redisMaxIdleConn, - IdleTimeout: redisIdleTTL, - MaxActive: redisMaxActive, - // MaxConnLifetime: redisDialTTL, - Wait: true, - Dial: func() (redigo.Conn, error) { - c, err := redigo.Dial("tcp", addr, - redigo.DialConnectTimeout(redisDialTTL), - redigo.DialReadTimeout(redisReadTTL), - redigo.DialWriteTimeout(redisWriteTTL), - ) - if err != nil { - log.Println("Redis Dial failed: ", err) - return nil, err - } - return c, err - }, - TestOnBorrow: func(c redigo.Conn, t time.Time) error { - _, err := c.Do("PING") - if err != nil { - log.Println("Unable to ping to redis server:", err) - } - return err - }, - } - conn := pool.Get() - defer conn.Close() - if conn.Err() != nil { - println("\nredis connect " + addr + " error: " + conn.Err().Error()) - } else { - println("\nredis connect " + addr + " success!\n") - } -} - -func Do(cmd string, args ...interface{}) (reply interface{}, err error) { - conn := pool.Get() - defer conn.Close() - return conn.Do(cmd, args...) -} - -func GetPool() *redigo.Pool { - return pool -} - -func ParseKey(key string, vars []string) (string, error) { - arr := strings.Split(key, conf.KeyPlaceholder) - actualKey := "" - if len(arr) != len(vars)+1 { - return "", errors.New("redis/connection.go: Insufficient arguments to parse key") - } else { - for index, val := range arr { - if index == 0 { - actualKey = arr[index] - } else { - actualKey += vars[index-1] + val - } - } - } - return getPrefixedKey(actualKey), nil -} - -func getPrefixedKey(key string) string { - return conf.KeyPrefix + conf.KeyDelimiter + key -} -func StripEnvKey(key string) string { - return strings.TrimLeft(key, conf.KeyPrefix+conf.KeyDelimiter) -} -func SplitKey(key string) []string { - return strings.Split(key, conf.KeyDelimiter) -} -func Expire(key string, ttl int) (interface{}, error) { - return Do("EXPIRE", key, ttl) -} -func Persist(key string) (interface{}, error) { - return Do("PERSIST", key) -} - -func Del(key string) (interface{}, error) { - return Do("DEL", key) -} -func Set(key string, data interface{}) (interface{}, error) { - // set - return Do("SET", key, data) -} -func SetNX(key string, data interface{}) (interface{}, error) { - return Do("SETNX", key, data) -} -func SetEx(key string, data interface{}, ttl int) (interface{}, error) { - return Do("SETEX", key, ttl, data) -} - -func SetJson(key string, data interface{}, ttl int) bool { - c, err := json.Marshal(data) - if err != nil { - return false - } - if ttl < 1 { - _, err = Set(key, c) - } else { - _, err = SetEx(key, c, ttl) - } - if err != nil { - return false - } - return true -} - -func GetJson(key string, dst interface{}) error { - b, err := GetBytes(key) - if err != nil { - return err - } - if err = json.Unmarshal(b, dst); err != nil { - return err - } - return nil -} - -func Get(key string) (interface{}, error) { - // get - return Do("GET", key) -} -func GetTTL(key string) (time.Duration, error) { - ttl, err := redigo.Int64(Do("TTL", key)) - return time.Duration(ttl) * time.Second, err -} -func GetBytes(key string) ([]byte, error) { - return redigo.Bytes(Do("GET", key)) -} -func GetString(key string) (string, error) { - return redigo.String(Do("GET", key)) -} -func GetStringMap(key string) (map[string]string, error) { - return redigo.StringMap(Do("GET", key)) -} -func GetInt(key string) (int, error) { - return redigo.Int(Do("GET", key)) -} -func GetInt64(key string) (int64, error) { - return redigo.Int64(Do("GET", key)) -} -func GetStringLength(key string) (int, error) { - return redigo.Int(Do("STRLEN", key)) -} -func ZAdd(key string, score float64, data interface{}) (interface{}, error) { - return Do("ZADD", key, score, data) -} -func ZAddNX(key string, score float64, data interface{}) (interface{}, error) { - return Do("ZADD", key, "NX", score, data) -} -func ZRem(key string, data interface{}) (interface{}, error) { - return Do("ZREM", key, data) -} -func ZRange(key string, start int, end int, withScores bool) ([]interface{}, error) { - if withScores { - return redigo.Values(Do("ZRANGE", key, start, end, "WITHSCORES")) - } - return redigo.Values(Do("ZRANGE", key, start, end)) -} -func ZRemRangeByScore(key string, start int64, end int64) ([]interface{}, error) { - return redigo.Values(Do("ZREMRANGEBYSCORE", key, start, end)) -} -func ZCard(setName string) (int64, error) { - return redigo.Int64(Do("ZCARD", setName)) -} -func ZScan(setName string) (int64, error) { - return redigo.Int64(Do("ZCARD", setName)) -} -func SAdd(setName string, data interface{}) (interface{}, error) { - return Do("SADD", setName, data) -} -func SCard(setName string) (int64, error) { - return redigo.Int64(Do("SCARD", setName)) -} -func SIsMember(setName string, data interface{}) (bool, error) { - return redigo.Bool(Do("SISMEMBER", setName, data)) -} -func SMembers(setName string) ([]string, error) { - return redigo.Strings(Do("SMEMBERS", setName)) -} -func SRem(setName string, data interface{}) (interface{}, error) { - return Do("SREM", setName, data) -} -func HSet(key string, HKey string, data interface{}) (interface{}, error) { - return Do("HSET", key, HKey, data) -} - -func HGet(key string, HKey string) (interface{}, error) { - return Do("HGET", key, HKey) -} - -func HMGet(key string, hashKeys ...string) ([]interface{}, error) { - ret, err := Do("HMGET", key, hashKeys) - if err != nil { - return nil, err - } - reta, ok := ret.([]interface{}) - if !ok { - return nil, errors.New("result not an array") - } - return reta, nil -} - -func HMSet(key string, hashKeys []string, vals []interface{}) (interface{}, error) { - if len(hashKeys) == 0 || len(hashKeys) != len(vals) { - var ret interface{} - return ret, errors.New("bad length") - } - input := []interface{}{key} - for i, v := range hashKeys { - input = append(input, v, vals[i]) - } - return Do("HMSET", input...) -} - -func HGetString(key string, HKey string) (string, error) { - return redigo.String(Do("HGET", key, HKey)) -} -func HGetFloat(key string, HKey string) (float64, error) { - f, err := redigo.Float64(Do("HGET", key, HKey)) - return f, err -} -func HGetInt(key string, HKey string) (int, error) { - return redigo.Int(Do("HGET", key, HKey)) -} -func HGetInt64(key string, HKey string) (int64, error) { - return redigo.Int64(Do("HGET", key, HKey)) -} -func HGetBool(key string, HKey string) (bool, error) { - return redigo.Bool(Do("HGET", key, HKey)) -} -func HDel(key string, HKey string) (interface{}, error) { - return Do("HDEL", key, HKey) -} - -func HGetAll(key string) (map[string]interface{}, error) { - vals, err := redigo.Values(Do("HGETALL", key)) - if err != nil { - return nil, err - } - num := len(vals) / 2 - result := make(map[string]interface{}, num) - for i := 0; i < num; i++ { - key, _ := redigo.String(vals[2*i], nil) - result[key] = vals[2*i+1] - } - return result, nil -} - -func FlushAll() bool { - res, _ := redigo.String(Do("FLUSHALL")) - if res == "" { - return false - } - return true -} - -// NOTE: Use this in production environment with extreme care. -// Read more here:https://redigo.io/commands/keys -func Keys(pattern string) ([]string, error) { - return redigo.Strings(Do("KEYS", pattern)) -} - -func HKeys(key string) ([]string, error) { - return redigo.Strings(Do("HKEYS", key)) -} - -func Exists(key string) bool { - count, err := redigo.Int(Do("EXISTS", key)) - if count == 0 || err != nil { - return false - } - return true -} - -func Incr(key string) (int64, error) { - return redigo.Int64(Do("INCR", key)) -} - -func Decr(key string) (int64, error) { - return redigo.Int64(Do("DECR", key)) -} - -func IncrBy(key string, incBy int64) (int64, error) { - return redigo.Int64(Do("INCRBY", key, incBy)) -} - -func DecrBy(key string, decrBy int64) (int64, error) { - return redigo.Int64(Do("DECRBY", key)) -} - -func IncrByFloat(key string, incBy float64) (float64, error) { - return redigo.Float64(Do("INCRBYFLOAT", key, incBy)) -} - -func DecrByFloat(key string, decrBy float64) (float64, error) { - return redigo.Float64(Do("DECRBYFLOAT", key, decrBy)) -} - -// use for message queue -func LPush(key string, data interface{}) (interface{}, error) { - // set - return Do("LPUSH", key, data) -} - -func LPop(key string) (interface{}, error) { - return Do("LPOP", key) -} - -func LPopString(key string) (string, error) { - return redigo.String(Do("LPOP", key)) -} -func LPopFloat(key string) (float64, error) { - f, err := redigo.Float64(Do("LPOP", key)) - return f, err -} -func LPopInt(key string) (int, error) { - return redigo.Int(Do("LPOP", key)) -} -func LPopInt64(key string) (int64, error) { - return redigo.Int64(Do("LPOP", key)) -} - -func RPush(key string, data interface{}) (interface{}, error) { - // set - return Do("RPUSH", key, data) -} - -func RPop(key string) (interface{}, error) { - return Do("RPOP", key) -} - -func RPopString(key string) (string, error) { - return redigo.String(Do("RPOP", key)) -} -func RPopFloat(key string) (float64, error) { - f, err := redigo.Float64(Do("RPOP", key)) - return f, err -} -func RPopInt(key string) (int, error) { - return redigo.Int(Do("RPOP", key)) -} -func RPopInt64(key string) (int64, error) { - return redigo.Int64(Do("RPOP", key)) -} - -func Scan(cursor int64, pattern string, count int64) (int64, []string, error) { - var items []string - var newCursor int64 - - values, err := redigo.Values(Do("SCAN", cursor, "MATCH", pattern, "COUNT", count)) - if err != nil { - return 0, nil, err - } - values, err = redigo.Scan(values, &newCursor, &items) - if err != nil { - return 0, nil, err - } - return newCursor, items, nil -} diff --git a/utils/cache/redis_cluster.go b/utils/cache/redis_cluster.go deleted file mode 100644 index 901f30c..0000000 --- a/utils/cache/redis_cluster.go +++ /dev/null @@ -1,622 +0,0 @@ -package cache - -import ( - "strconv" - "time" - - "github.com/go-redis/redis" -) - -var pools *redis.ClusterClient - -func NewRedisCluster(addrs []string) error { - opt := &redis.ClusterOptions{ - Addrs: addrs, - PoolSize: redisPoolSize, - PoolTimeout: redisPoolTTL, - IdleTimeout: redisIdleTTL, - DialTimeout: redisDialTTL, - ReadTimeout: redisReadTTL, - WriteTimeout: redisWriteTTL, - } - pools = redis.NewClusterClient(opt) - if err := pools.Ping().Err(); err != nil { - return err - } - return nil -} - -func RCGet(key string) (interface{}, error) { - res, err := pools.Get(key).Result() - if err != nil { - return nil, convertError(err) - } - return []byte(res), nil -} -func RCSet(key string, value interface{}) error { - err := pools.Set(key, value, 0).Err() - return convertError(err) -} -func RCGetSet(key string, value interface{}) (interface{}, error) { - res, err := pools.GetSet(key, value).Result() - if err != nil { - return nil, convertError(err) - } - return []byte(res), nil -} -func RCSetNx(key string, value interface{}) (int64, error) { - res, err := pools.SetNX(key, value, 0).Result() - if err != nil { - return 0, convertError(err) - } - if res { - return 1, nil - } - return 0, nil -} -func RCSetEx(key string, value interface{}, timeout int64) error { - _, err := pools.Set(key, value, time.Duration(timeout)*time.Second).Result() - if err != nil { - return convertError(err) - } - return nil -} - -// nil表示成功,ErrNil表示数据库内已经存在这个key,其他表示数据库发生错误 -func RCSetNxEx(key string, value interface{}, timeout int64) error { - res, err := pools.SetNX(key, value, time.Duration(timeout)*time.Second).Result() - if err != nil { - return convertError(err) - } - if res { - return nil - } - return ErrNil -} -func RCMGet(keys ...string) ([]interface{}, error) { - res, err := pools.MGet(keys...).Result() - return res, convertError(err) -} - -// 为确保多个key映射到同一个slot,每个key最好加上hash tag,如:{test} -func RCMSet(kvs map[string]interface{}) error { - pairs := make([]string, 0, len(kvs)*2) - for k, v := range kvs { - val, err := String(v, nil) - if err != nil { - return err - } - pairs = append(pairs, k, val) - } - return convertError(pools.MSet(pairs).Err()) -} - -// 为确保多个key映射到同一个slot,每个key最好加上hash tag,如:{test} -func RCMSetNX(kvs map[string]interface{}) (bool, error) { - pairs := make([]string, 0, len(kvs)*2) - for k, v := range kvs { - val, err := String(v, nil) - if err != nil { - return false, err - } - pairs = append(pairs, k, val) - } - res, err := pools.MSetNX(pairs).Result() - return res, convertError(err) -} -func RCExpireAt(key string, timestamp int64) (int64, error) { - res, err := pools.ExpireAt(key, time.Unix(timestamp, 0)).Result() - if err != nil { - return 0, convertError(err) - } - if res { - return 1, nil - } - return 0, nil -} -func RCDel(keys ...string) (int64, error) { - args := make([]interface{}, 0, len(keys)) - for _, key := range keys { - args = append(args, key) - } - res, err := pools.Del(keys...).Result() - if err != nil { - return res, convertError(err) - } - return res, nil -} -func RCIncr(key string) (int64, error) { - res, err := pools.Incr(key).Result() - if err != nil { - return res, convertError(err) - } - return res, nil -} -func RCIncrBy(key string, delta int64) (int64, error) { - res, err := pools.IncrBy(key, delta).Result() - if err != nil { - return res, convertError(err) - } - return res, nil -} -func RCExpire(key string, duration int64) (int64, error) { - res, err := pools.Expire(key, time.Duration(duration)*time.Second).Result() - if err != nil { - return 0, convertError(err) - } - if res { - return 1, nil - } - return 0, nil -} -func RCExists(key string) (bool, error) { - res, err := pools.Exists(key).Result() - if err != nil { - return false, convertError(err) - } - if res > 0 { - return true, nil - } - return false, nil -} -func RCHGet(key string, field string) (interface{}, error) { - res, err := pools.HGet(key, field).Result() - if err != nil { - return nil, convertError(err) - } - return []byte(res), nil -} -func RCHLen(key string) (int64, error) { - res, err := pools.HLen(key).Result() - if err != nil { - return res, convertError(err) - } - return res, nil -} -func RCHSet(key string, field string, val interface{}) error { - value, err := String(val, nil) - if err != nil && err != ErrNil { - return err - } - _, err = pools.HSet(key, field, value).Result() - if err != nil { - return convertError(err) - } - return nil -} -func RCHDel(key string, fields ...string) (int64, error) { - args := make([]interface{}, 0, len(fields)+1) - args = append(args, key) - for _, field := range fields { - args = append(args, field) - } - res, err := pools.HDel(key, fields...).Result() - if err != nil { - return 0, convertError(err) - } - return res, nil -} - -func RCHMGet(key string, fields ...string) (interface{}, error) { - args := make([]interface{}, 0, len(fields)+1) - args = append(args, key) - for _, field := range fields { - args = append(args, field) - } - if len(fields) == 0 { - return nil, ErrNil - } - res, err := pools.HMGet(key, fields...).Result() - if err != nil { - return nil, convertError(err) - } - return res, nil -} -func RCHMSet(key string, kvs ...interface{}) error { - if len(kvs) == 0 { - return nil - } - if len(kvs)%2 != 0 { - return ErrWrongArgsNum - } - var err error - v := map[string]interface{}{} // todo change - v["field"], err = String(kvs[0], nil) - if err != nil && err != ErrNil { - return err - } - v["value"], err = String(kvs[1], nil) - if err != nil && err != ErrNil { - return err - } - pairs := make([]string, 0, len(kvs)-2) - if len(kvs) > 2 { - for _, kv := range kvs[2:] { - kvString, err := String(kv, nil) - if err != nil && err != ErrNil { - return err - } - pairs = append(pairs, kvString) - } - } - v["paris"] = pairs - _, err = pools.HMSet(key, v).Result() - if err != nil { - return convertError(err) - } - return nil -} - -func RCHKeys(key string) ([]string, error) { - res, err := pools.HKeys(key).Result() - if err != nil { - return res, convertError(err) - } - return res, nil -} -func RCHVals(key string) ([]interface{}, error) { - res, err := pools.HVals(key).Result() - if err != nil { - return nil, convertError(err) - } - rs := make([]interface{}, 0, len(res)) - for _, res := range res { - rs = append(rs, res) - } - return rs, nil -} -func RCHGetAll(key string) (map[string]string, error) { - vals, err := pools.HGetAll(key).Result() - if err != nil { - return nil, convertError(err) - } - return vals, nil -} -func RCHIncrBy(key, field string, delta int64) (int64, error) { - res, err := pools.HIncrBy(key, field, delta).Result() - if err != nil { - return res, convertError(err) - } - return res, nil -} -func RCZAdd(key string, kvs ...interface{}) (int64, error) { - args := make([]interface{}, 0, len(kvs)+1) - args = append(args, key) - args = append(args, kvs...) - if len(kvs) == 0 { - return 0, nil - } - if len(kvs)%2 != 0 { - return 0, ErrWrongArgsNum - } - zs := make([]redis.Z, len(kvs)/2) - for i := 0; i < len(kvs); i += 2 { - idx := i / 2 - score, err := Float64(kvs[i], nil) - if err != nil && err != ErrNil { - return 0, err - } - zs[idx].Score = score - zs[idx].Member = kvs[i+1] - } - res, err := pools.ZAdd(key, zs...).Result() - if err != nil { - return res, convertError(err) - } - return res, nil -} -func RCZRem(key string, members ...string) (int64, error) { - args := make([]interface{}, 0, len(members)) - args = append(args, key) - for _, member := range members { - args = append(args, member) - } - res, err := pools.ZRem(key, members).Result() - if err != nil { - return res, convertError(err) - } - return res, err -} - -func RCZRange(key string, min, max int64, withScores bool) (interface{}, error) { - res := make([]interface{}, 0) - if withScores { - zs, err := pools.ZRangeWithScores(key, min, max).Result() - if err != nil { - return nil, convertError(err) - } - for _, z := range zs { - res = append(res, z.Member, strconv.FormatFloat(z.Score, 'f', -1, 64)) - } - } else { - ms, err := pools.ZRange(key, min, max).Result() - if err != nil { - return nil, convertError(err) - } - for _, m := range ms { - res = append(res, m) - } - } - return res, nil -} -func RCZRangeByScoreWithScore(key string, min, max int64) (map[string]int64, error) { - opt := new(redis.ZRangeBy) - opt.Min = strconv.FormatInt(int64(min), 10) - opt.Max = strconv.FormatInt(int64(max), 10) - opt.Count = -1 - opt.Offset = 0 - vals, err := pools.ZRangeByScoreWithScores(key, *opt).Result() - if err != nil { - return nil, convertError(err) - } - res := make(map[string]int64, len(vals)) - for _, val := range vals { - key, err := String(val.Member, nil) - if err != nil && err != ErrNil { - return nil, err - } - res[key] = int64(val.Score) - } - return res, nil -} -func RCLRange(key string, start, stop int64) (interface{}, error) { - res, err := pools.LRange(key, start, stop).Result() - if err != nil { - return nil, convertError(err) - } - return res, nil -} -func RCLSet(key string, index int, value interface{}) error { - err := pools.LSet(key, int64(index), value).Err() - return convertError(err) -} -func RCLLen(key string) (int64, error) { - res, err := pools.LLen(key).Result() - if err != nil { - return res, convertError(err) - } - return res, nil -} -func RCLRem(key string, count int, value interface{}) (int, error) { - val, _ := value.(string) - res, err := pools.LRem(key, int64(count), val).Result() - if err != nil { - return int(res), convertError(err) - } - return int(res), nil -} -func RCTTl(key string) (int64, error) { - duration, err := pools.TTL(key).Result() - if err != nil { - return int64(duration.Seconds()), convertError(err) - } - return int64(duration.Seconds()), nil -} -func RCLPop(key string) (interface{}, error) { - res, err := pools.LPop(key).Result() - if err != nil { - return nil, convertError(err) - } - return res, nil -} -func RCRPop(key string) (interface{}, error) { - res, err := pools.RPop(key).Result() - if err != nil { - return nil, convertError(err) - } - return res, nil -} -func RCBLPop(key string, timeout int) (interface{}, error) { - res, err := pools.BLPop(time.Duration(timeout)*time.Second, key).Result() - if err != nil { - // 兼容redis 2.x - if err == redis.Nil { - return nil, ErrNil - } - return nil, err - } - return res[1], nil -} -func RCBRPop(key string, timeout int) (interface{}, error) { - res, err := pools.BRPop(time.Duration(timeout)*time.Second, key).Result() - if err != nil { - // 兼容redis 2.x - if err == redis.Nil { - return nil, ErrNil - } - return nil, convertError(err) - } - return res[1], nil -} -func RCLPush(key string, value ...interface{}) error { - args := make([]interface{}, 0, len(value)+1) - args = append(args, key) - args = append(args, value...) - vals := make([]string, 0, len(value)) - for _, v := range value { - val, err := String(v, nil) - if err != nil && err != ErrNil { - return err - } - vals = append(vals, val) - } - _, err := pools.LPush(key, vals).Result() // todo ... - if err != nil { - return convertError(err) - } - return nil -} -func RCRPush(key string, value ...interface{}) error { - args := make([]interface{}, 0, len(value)+1) - args = append(args, key) - args = append(args, value...) - vals := make([]string, 0, len(value)) - for _, v := range value { - val, err := String(v, nil) - if err != nil && err != ErrNil { - if err == ErrNil { - continue - } - return err - } - if val == "" { - continue - } - vals = append(vals, val) - } - _, err := pools.RPush(key, vals).Result() // todo ... - if err != nil { - return convertError(err) - } - return nil -} - -// 为确保srcKey跟destKey映射到同一个slot,srcKey和destKey需要加上hash tag,如:{test} -func RCBRPopLPush(srcKey string, destKey string, timeout int) (interface{}, error) { - res, err := pools.BRPopLPush(srcKey, destKey, time.Duration(timeout)*time.Second).Result() - if err != nil { - return nil, convertError(err) - } - return res, nil -} - -// 为确保srcKey跟destKey映射到同一个slot,srcKey和destKey需要加上hash tag,如:{test} -func RCRPopLPush(srcKey string, destKey string) (interface{}, error) { - res, err := pools.RPopLPush(srcKey, destKey).Result() - if err != nil { - return nil, convertError(err) - } - return res, nil -} -func RCSAdd(key string, members ...interface{}) (int64, error) { - args := make([]interface{}, 0, len(members)+1) - args = append(args, key) - args = append(args, members...) - ms := make([]string, 0, len(members)) - for _, member := range members { - m, err := String(member, nil) - if err != nil && err != ErrNil { - return 0, err - } - ms = append(ms, m) - } - res, err := pools.SAdd(key, ms).Result() // todo ... - if err != nil { - return res, convertError(err) - } - return res, nil -} -func RCSPop(key string) ([]byte, error) { - res, err := pools.SPop(key).Result() - if err != nil { - return nil, convertError(err) - } - return []byte(res), nil -} -func RCSIsMember(key string, member interface{}) (bool, error) { - m, _ := member.(string) - res, err := pools.SIsMember(key, m).Result() - if err != nil { - return res, convertError(err) - } - return res, nil -} -func RCSRem(key string, members ...interface{}) (int64, error) { - args := make([]interface{}, 0, len(members)+1) - args = append(args, key) - args = append(args, members...) - ms := make([]string, 0, len(members)) - for _, member := range members { - m, err := String(member, nil) - if err != nil && err != ErrNil { - return 0, err - } - ms = append(ms, m) - } - res, err := pools.SRem(key, ms).Result() // todo ... - if err != nil { - return res, convertError(err) - } - return res, nil -} -func RCSMembers(key string) ([]string, error) { - res, err := pools.SMembers(key).Result() - if err != nil { - return nil, convertError(err) - } - return res, nil -} -func RCScriptLoad(luaScript string) (interface{}, error) { - res, err := pools.ScriptLoad(luaScript).Result() - if err != nil { - return nil, convertError(err) - } - return res, nil -} -func RCEvalSha(sha1 string, numberKeys int, keysArgs ...interface{}) (interface{}, error) { - vals := make([]interface{}, 0, len(keysArgs)+2) - vals = append(vals, sha1, numberKeys) - vals = append(vals, keysArgs...) - keys := make([]string, 0, numberKeys) - args := make([]string, 0, len(keysArgs)-numberKeys) - for i, value := range keysArgs { - val, err := String(value, nil) - if err != nil && err != ErrNil { - return nil, err - } - if i < numberKeys { - keys = append(keys, val) - } else { - args = append(args, val) - } - } - res, err := pools.EvalSha(sha1, keys, args).Result() - if err != nil { - return nil, convertError(err) - } - return res, nil -} -func RCEval(luaScript string, numberKeys int, keysArgs ...interface{}) (interface{}, error) { - vals := make([]interface{}, 0, len(keysArgs)+2) - vals = append(vals, luaScript, numberKeys) - vals = append(vals, keysArgs...) - keys := make([]string, 0, numberKeys) - args := make([]string, 0, len(keysArgs)-numberKeys) - for i, value := range keysArgs { - val, err := String(value, nil) - if err != nil && err != ErrNil { - return nil, err - } - if i < numberKeys { - keys = append(keys, val) - } else { - args = append(args, val) - } - } - res, err := pools.Eval(luaScript, keys, args).Result() - if err != nil { - return nil, convertError(err) - } - return res, nil -} -func RCGetBit(key string, offset int64) (int64, error) { - res, err := pools.GetBit(key, offset).Result() - if err != nil { - return res, convertError(err) - } - return res, nil -} -func RCSetBit(key string, offset uint32, value int) (int, error) { - res, err := pools.SetBit(key, int64(offset), value).Result() - return int(res), convertError(err) -} -func RCGetClient() *redis.ClusterClient { - return pools -} -func convertError(err error) error { - if err == redis.Nil { - // 为了兼容redis 2.x,这里不返回 ErrNil,ErrNil在调用redis_cluster_reply函数时才返回 - return nil - } - return err -} diff --git a/utils/cache/redis_pool.go b/utils/cache/redis_pool.go deleted file mode 100644 index ca38b3f..0000000 --- a/utils/cache/redis_pool.go +++ /dev/null @@ -1,324 +0,0 @@ -package cache - -import ( - "errors" - "log" - "strings" - "time" - - redigo "github.com/gomodule/redigo/redis" -) - -type RedisPool struct { - *redigo.Pool -} - -func NewRedisPool(cfg *Config) *RedisPool { - return &RedisPool{&redigo.Pool{ - MaxIdle: cfg.MaxIdle, - IdleTimeout: cfg.IdleTimeout, - MaxActive: cfg.MaxActive, - Wait: cfg.Wait, - Dial: func() (redigo.Conn, error) { - c, err := redigo.Dial("tcp", cfg.Server) - if err != nil { - log.Println("Redis Dial failed: ", err) - return nil, err - } - if cfg.Password != "" { - if _, err := c.Do("AUTH", cfg.Password); err != nil { - c.Close() - log.Println("Redis AUTH failed: ", err) - return nil, err - } - } - return c, err - }, - TestOnBorrow: func(c redigo.Conn, t time.Time) error { - _, err := c.Do("PING") - if err != nil { - log.Println("Unable to ping to redis server:", err) - } - return err - }, - }} -} - -func (p *RedisPool) Do(cmd string, args ...interface{}) (reply interface{}, err error) { - conn := pool.Get() - defer conn.Close() - return conn.Do(cmd, args...) -} - -func (p *RedisPool) GetPool() *redigo.Pool { - return pool -} - -func (p *RedisPool) ParseKey(key string, vars []string) (string, error) { - arr := strings.Split(key, conf.KeyPlaceholder) - actualKey := "" - if len(arr) != len(vars)+1 { - return "", errors.New("redis/connection.go: Insufficient arguments to parse key") - } else { - for index, val := range arr { - if index == 0 { - actualKey = arr[index] - } else { - actualKey += vars[index-1] + val - } - } - } - return getPrefixedKey(actualKey), nil -} - -func (p *RedisPool) getPrefixedKey(key string) string { - return conf.KeyPrefix + conf.KeyDelimiter + key -} -func (p *RedisPool) StripEnvKey(key string) string { - return strings.TrimLeft(key, conf.KeyPrefix+conf.KeyDelimiter) -} -func (p *RedisPool) SplitKey(key string) []string { - return strings.Split(key, conf.KeyDelimiter) -} -func (p *RedisPool) Expire(key string, ttl int) (interface{}, error) { - return Do("EXPIRE", key, ttl) -} -func (p *RedisPool) Persist(key string) (interface{}, error) { - return Do("PERSIST", key) -} - -func (p *RedisPool) Del(key string) (interface{}, error) { - return Do("DEL", key) -} -func (p *RedisPool) Set(key string, data interface{}) (interface{}, error) { - // set - return Do("SET", key, data) -} -func (p *RedisPool) SetNX(key string, data interface{}) (interface{}, error) { - return Do("SETNX", key, data) -} -func (p *RedisPool) SetEx(key string, data interface{}, ttl int) (interface{}, error) { - return Do("SETEX", key, ttl, data) -} -func (p *RedisPool) Get(key string) (interface{}, error) { - // get - return Do("GET", key) -} -func (p *RedisPool) GetStringMap(key string) (map[string]string, error) { - // get - return redigo.StringMap(Do("GET", key)) -} - -func (p *RedisPool) GetTTL(key string) (time.Duration, error) { - ttl, err := redigo.Int64(Do("TTL", key)) - return time.Duration(ttl) * time.Second, err -} -func (p *RedisPool) GetBytes(key string) ([]byte, error) { - return redigo.Bytes(Do("GET", key)) -} -func (p *RedisPool) GetString(key string) (string, error) { - return redigo.String(Do("GET", key)) -} -func (p *RedisPool) GetInt(key string) (int, error) { - return redigo.Int(Do("GET", key)) -} -func (p *RedisPool) GetStringLength(key string) (int, error) { - return redigo.Int(Do("STRLEN", key)) -} -func (p *RedisPool) ZAdd(key string, score float64, data interface{}) (interface{}, error) { - return Do("ZADD", key, score, data) -} -func (p *RedisPool) ZRem(key string, data interface{}) (interface{}, error) { - return Do("ZREM", key, data) -} -func (p *RedisPool) ZRange(key string, start int, end int, withScores bool) ([]interface{}, error) { - if withScores { - return redigo.Values(Do("ZRANGE", key, start, end, "WITHSCORES")) - } - return redigo.Values(Do("ZRANGE", key, start, end)) -} -func (p *RedisPool) SAdd(setName string, data interface{}) (interface{}, error) { - return Do("SADD", setName, data) -} -func (p *RedisPool) SCard(setName string) (int64, error) { - return redigo.Int64(Do("SCARD", setName)) -} -func (p *RedisPool) SIsMember(setName string, data interface{}) (bool, error) { - return redigo.Bool(Do("SISMEMBER", setName, data)) -} -func (p *RedisPool) SMembers(setName string) ([]string, error) { - return redigo.Strings(Do("SMEMBERS", setName)) -} -func (p *RedisPool) SRem(setName string, data interface{}) (interface{}, error) { - return Do("SREM", setName, data) -} -func (p *RedisPool) HSet(key string, HKey string, data interface{}) (interface{}, error) { - return Do("HSET", key, HKey, data) -} - -func (p *RedisPool) HGet(key string, HKey string) (interface{}, error) { - return Do("HGET", key, HKey) -} - -func (p *RedisPool) HMGet(key string, hashKeys ...string) ([]interface{}, error) { - ret, err := Do("HMGET", key, hashKeys) - if err != nil { - return nil, err - } - reta, ok := ret.([]interface{}) - if !ok { - return nil, errors.New("result not an array") - } - return reta, nil -} - -func (p *RedisPool) HMSet(key string, hashKeys []string, vals []interface{}) (interface{}, error) { - if len(hashKeys) == 0 || len(hashKeys) != len(vals) { - var ret interface{} - return ret, errors.New("bad length") - } - input := []interface{}{key} - for i, v := range hashKeys { - input = append(input, v, vals[i]) - } - return Do("HMSET", input...) -} - -func (p *RedisPool) HGetString(key string, HKey string) (string, error) { - return redigo.String(Do("HGET", key, HKey)) -} -func (p *RedisPool) HGetFloat(key string, HKey string) (float64, error) { - f, err := redigo.Float64(Do("HGET", key, HKey)) - return float64(f), err -} -func (p *RedisPool) HGetInt(key string, HKey string) (int, error) { - return redigo.Int(Do("HGET", key, HKey)) -} -func (p *RedisPool) HGetInt64(key string, HKey string) (int64, error) { - return redigo.Int64(Do("HGET", key, HKey)) -} -func (p *RedisPool) HGetBool(key string, HKey string) (bool, error) { - return redigo.Bool(Do("HGET", key, HKey)) -} -func (p *RedisPool) HDel(key string, HKey string) (interface{}, error) { - return Do("HDEL", key, HKey) -} -func (p *RedisPool) HGetAll(key string) (map[string]interface{}, error) { - vals, err := redigo.Values(Do("HGETALL", key)) - if err != nil { - return nil, err - } - num := len(vals) / 2 - result := make(map[string]interface{}, num) - for i := 0; i < num; i++ { - key, _ := redigo.String(vals[2*i], nil) - result[key] = vals[2*i+1] - } - return result, nil -} - -// NOTE: Use this in production environment with extreme care. -// Read more here:https://redigo.io/commands/keys -func (p *RedisPool) Keys(pattern string) ([]string, error) { - return redigo.Strings(Do("KEYS", pattern)) -} - -func (p *RedisPool) HKeys(key string) ([]string, error) { - return redigo.Strings(Do("HKEYS", key)) -} - -func (p *RedisPool) Exists(key string) (bool, error) { - count, err := redigo.Int(Do("EXISTS", key)) - if count == 0 { - return false, err - } else { - return true, err - } -} - -func (p *RedisPool) Incr(key string) (int64, error) { - return redigo.Int64(Do("INCR", key)) -} - -func (p *RedisPool) Decr(key string) (int64, error) { - return redigo.Int64(Do("DECR", key)) -} - -func (p *RedisPool) IncrBy(key string, incBy int64) (int64, error) { - return redigo.Int64(Do("INCRBY", key, incBy)) -} - -func (p *RedisPool) DecrBy(key string, decrBy int64) (int64, error) { - return redigo.Int64(Do("DECRBY", key)) -} - -func (p *RedisPool) IncrByFloat(key string, incBy float64) (float64, error) { - return redigo.Float64(Do("INCRBYFLOAT", key, incBy)) -} - -func (p *RedisPool) DecrByFloat(key string, decrBy float64) (float64, error) { - return redigo.Float64(Do("DECRBYFLOAT", key, decrBy)) -} - -// use for message queue -func (p *RedisPool) LPush(key string, data interface{}) (interface{}, error) { - // set - return Do("LPUSH", key, data) -} - -func (p *RedisPool) LPop(key string) (interface{}, error) { - return Do("LPOP", key) -} - -func (p *RedisPool) LPopString(key string) (string, error) { - return redigo.String(Do("LPOP", key)) -} -func (p *RedisPool) LPopFloat(key string) (float64, error) { - f, err := redigo.Float64(Do("LPOP", key)) - return float64(f), err -} -func (p *RedisPool) LPopInt(key string) (int, error) { - return redigo.Int(Do("LPOP", key)) -} -func (p *RedisPool) LPopInt64(key string) (int64, error) { - return redigo.Int64(Do("LPOP", key)) -} - -func (p *RedisPool) RPush(key string, data interface{}) (interface{}, error) { - // set - return Do("RPUSH", key, data) -} - -func (p *RedisPool) RPop(key string) (interface{}, error) { - return Do("RPOP", key) -} - -func (p *RedisPool) RPopString(key string) (string, error) { - return redigo.String(Do("RPOP", key)) -} -func (p *RedisPool) RPopFloat(key string) (float64, error) { - f, err := redigo.Float64(Do("RPOP", key)) - return float64(f), err -} -func (p *RedisPool) RPopInt(key string) (int, error) { - return redigo.Int(Do("RPOP", key)) -} -func (p *RedisPool) RPopInt64(key string) (int64, error) { - return redigo.Int64(Do("RPOP", key)) -} - -func (p *RedisPool) Scan(cursor int64, pattern string, count int64) (int64, []string, error) { - var items []string - var newCursor int64 - - values, err := redigo.Values(Do("SCAN", cursor, "MATCH", pattern, "COUNT", count)) - if err != nil { - return 0, nil, err - } - values, err = redigo.Scan(values, &newCursor, &items) - if err != nil { - return 0, nil, err - } - - return newCursor, items, nil -} diff --git a/utils/cache/redis_pool_cluster.go b/utils/cache/redis_pool_cluster.go deleted file mode 100644 index cd1911b..0000000 --- a/utils/cache/redis_pool_cluster.go +++ /dev/null @@ -1,617 +0,0 @@ -package cache - -import ( - "strconv" - "time" - - "github.com/go-redis/redis" -) - -type RedisClusterPool struct { - client *redis.ClusterClient -} - -func NewRedisClusterPool(addrs []string) (*RedisClusterPool, error) { - opt := &redis.ClusterOptions{ - Addrs: addrs, - PoolSize: 512, - PoolTimeout: 10 * time.Second, - IdleTimeout: 10 * time.Second, - DialTimeout: 10 * time.Second, - ReadTimeout: 3 * time.Second, - WriteTimeout: 3 * time.Second, - } - c := redis.NewClusterClient(opt) - if err := c.Ping().Err(); err != nil { - return nil, err - } - return &RedisClusterPool{client: c}, nil -} - -func (p *RedisClusterPool) Get(key string) (interface{}, error) { - res, err := p.client.Get(key).Result() - if err != nil { - return nil, convertError(err) - } - return []byte(res), nil -} -func (p *RedisClusterPool) Set(key string, value interface{}) error { - err := p.client.Set(key, value, 0).Err() - return convertError(err) -} -func (p *RedisClusterPool) GetSet(key string, value interface{}) (interface{}, error) { - res, err := p.client.GetSet(key, value).Result() - if err != nil { - return nil, convertError(err) - } - return []byte(res), nil -} -func (p *RedisClusterPool) SetNx(key string, value interface{}) (int64, error) { - res, err := p.client.SetNX(key, value, 0).Result() - if err != nil { - return 0, convertError(err) - } - if res { - return 1, nil - } - return 0, nil -} -func (p *RedisClusterPool) SetEx(key string, value interface{}, timeout int64) error { - _, err := p.client.Set(key, value, time.Duration(timeout)*time.Second).Result() - if err != nil { - return convertError(err) - } - return nil -} - -// nil表示成功,ErrNil表示数据库内已经存在这个key,其他表示数据库发生错误 -func (p *RedisClusterPool) SetNxEx(key string, value interface{}, timeout int64) error { - res, err := p.client.SetNX(key, value, time.Duration(timeout)*time.Second).Result() - if err != nil { - return convertError(err) - } - if res { - return nil - } - return ErrNil -} -func (p *RedisClusterPool) MGet(keys ...string) ([]interface{}, error) { - res, err := p.client.MGet(keys...).Result() - return res, convertError(err) -} - -// 为确保多个key映射到同一个slot,每个key最好加上hash tag,如:{test} -func (p *RedisClusterPool) MSet(kvs map[string]interface{}) error { - pairs := make([]string, 0, len(kvs)*2) - for k, v := range kvs { - val, err := String(v, nil) - if err != nil { - return err - } - pairs = append(pairs, k, val) - } - return convertError(p.client.MSet(pairs).Err()) -} - -// 为确保多个key映射到同一个slot,每个key最好加上hash tag,如:{test} -func (p *RedisClusterPool) MSetNX(kvs map[string]interface{}) (bool, error) { - pairs := make([]string, 0, len(kvs)*2) - for k, v := range kvs { - val, err := String(v, nil) - if err != nil { - return false, err - } - pairs = append(pairs, k, val) - } - res, err := p.client.MSetNX(pairs).Result() - return res, convertError(err) -} -func (p *RedisClusterPool) ExpireAt(key string, timestamp int64) (int64, error) { - res, err := p.client.ExpireAt(key, time.Unix(timestamp, 0)).Result() - if err != nil { - return 0, convertError(err) - } - if res { - return 1, nil - } - return 0, nil -} -func (p *RedisClusterPool) Del(keys ...string) (int64, error) { - args := make([]interface{}, 0, len(keys)) - for _, key := range keys { - args = append(args, key) - } - res, err := p.client.Del(keys...).Result() - if err != nil { - return res, convertError(err) - } - return res, nil -} -func (p *RedisClusterPool) Incr(key string) (int64, error) { - res, err := p.client.Incr(key).Result() - if err != nil { - return res, convertError(err) - } - return res, nil -} -func (p *RedisClusterPool) IncrBy(key string, delta int64) (int64, error) { - res, err := p.client.IncrBy(key, delta).Result() - if err != nil { - return res, convertError(err) - } - return res, nil -} -func (p *RedisClusterPool) Expire(key string, duration int64) (int64, error) { - res, err := p.client.Expire(key, time.Duration(duration)*time.Second).Result() - if err != nil { - return 0, convertError(err) - } - if res { - return 1, nil - } - return 0, nil -} -func (p *RedisClusterPool) Exists(key string) (bool, error) { // todo (bool, error) - res, err := p.client.Exists(key).Result() - if err != nil { - return false, convertError(err) - } - if res > 0 { - return true, nil - } - return false, nil -} -func (p *RedisClusterPool) HGet(key string, field string) (interface{}, error) { - res, err := p.client.HGet(key, field).Result() - if err != nil { - return nil, convertError(err) - } - return []byte(res), nil -} -func (p *RedisClusterPool) HLen(key string) (int64, error) { - res, err := p.client.HLen(key).Result() - if err != nil { - return res, convertError(err) - } - return res, nil -} -func (p *RedisClusterPool) HSet(key string, field string, val interface{}) error { - value, err := String(val, nil) - if err != nil && err != ErrNil { - return err - } - _, err = p.client.HSet(key, field, value).Result() - if err != nil { - return convertError(err) - } - return nil -} -func (p *RedisClusterPool) HDel(key string, fields ...string) (int64, error) { - args := make([]interface{}, 0, len(fields)+1) - args = append(args, key) - for _, field := range fields { - args = append(args, field) - } - res, err := p.client.HDel(key, fields...).Result() - if err != nil { - return 0, convertError(err) - } - return res, nil -} - -func (p *RedisClusterPool) HMGet(key string, fields ...string) (interface{}, error) { - args := make([]interface{}, 0, len(fields)+1) - args = append(args, key) - for _, field := range fields { - args = append(args, field) - } - if len(fields) == 0 { - return nil, ErrNil - } - res, err := p.client.HMGet(key, fields...).Result() - if err != nil { - return nil, convertError(err) - } - return res, nil -} -func (p *RedisClusterPool) HMSet(key string, kvs ...interface{}) error { - if len(kvs) == 0 { - return nil - } - if len(kvs)%2 != 0 { - return ErrWrongArgsNum - } - var err error - v := map[string]interface{}{} // todo change - v["field"], err = String(kvs[0], nil) - if err != nil && err != ErrNil { - return err - } - v["value"], err = String(kvs[1], nil) - if err != nil && err != ErrNil { - return err - } - pairs := make([]string, 0, len(kvs)-2) - if len(kvs) > 2 { - for _, kv := range kvs[2:] { - kvString, err := String(kv, nil) - if err != nil && err != ErrNil { - return err - } - pairs = append(pairs, kvString) - } - } - v["paris"] = pairs - _, err = p.client.HMSet(key, v).Result() - if err != nil { - return convertError(err) - } - return nil -} - -func (p *RedisClusterPool) HKeys(key string) ([]string, error) { - res, err := p.client.HKeys(key).Result() - if err != nil { - return res, convertError(err) - } - return res, nil -} -func (p *RedisClusterPool) HVals(key string) ([]interface{}, error) { - res, err := p.client.HVals(key).Result() - if err != nil { - return nil, convertError(err) - } - rs := make([]interface{}, 0, len(res)) - for _, res := range res { - rs = append(rs, res) - } - return rs, nil -} -func (p *RedisClusterPool) HGetAll(key string) (map[string]string, error) { - vals, err := p.client.HGetAll(key).Result() - if err != nil { - return nil, convertError(err) - } - return vals, nil -} -func (p *RedisClusterPool) HIncrBy(key, field string, delta int64) (int64, error) { - res, err := p.client.HIncrBy(key, field, delta).Result() - if err != nil { - return res, convertError(err) - } - return res, nil -} -func (p *RedisClusterPool) ZAdd(key string, kvs ...interface{}) (int64, error) { - args := make([]interface{}, 0, len(kvs)+1) - args = append(args, key) - args = append(args, kvs...) - if len(kvs) == 0 { - return 0, nil - } - if len(kvs)%2 != 0 { - return 0, ErrWrongArgsNum - } - zs := make([]redis.Z, len(kvs)/2) - for i := 0; i < len(kvs); i += 2 { - idx := i / 2 - score, err := Float64(kvs[i], nil) - if err != nil && err != ErrNil { - return 0, err - } - zs[idx].Score = score - zs[idx].Member = kvs[i+1] - } - res, err := p.client.ZAdd(key, zs...).Result() - if err != nil { - return res, convertError(err) - } - return res, nil -} -func (p *RedisClusterPool) ZRem(key string, members ...string) (int64, error) { - args := make([]interface{}, 0, len(members)) - args = append(args, key) - for _, member := range members { - args = append(args, member) - } - res, err := p.client.ZRem(key, members).Result() - if err != nil { - return res, convertError(err) - } - return res, err -} - -func (p *RedisClusterPool) ZRange(key string, min, max int64, withScores bool) (interface{}, error) { - res := make([]interface{}, 0) - if withScores { - zs, err := p.client.ZRangeWithScores(key, min, max).Result() - if err != nil { - return nil, convertError(err) - } - for _, z := range zs { - res = append(res, z.Member, strconv.FormatFloat(z.Score, 'f', -1, 64)) - } - } else { - ms, err := p.client.ZRange(key, min, max).Result() - if err != nil { - return nil, convertError(err) - } - for _, m := range ms { - res = append(res, m) - } - } - return res, nil -} -func (p *RedisClusterPool) ZRangeByScoreWithScore(key string, min, max int64) (map[string]int64, error) { - opt := new(redis.ZRangeBy) - opt.Min = strconv.FormatInt(int64(min), 10) - opt.Max = strconv.FormatInt(int64(max), 10) - opt.Count = -1 - opt.Offset = 0 - vals, err := p.client.ZRangeByScoreWithScores(key, *opt).Result() - if err != nil { - return nil, convertError(err) - } - res := make(map[string]int64, len(vals)) - for _, val := range vals { - key, err := String(val.Member, nil) - if err != nil && err != ErrNil { - return nil, err - } - res[key] = int64(val.Score) - } - return res, nil -} -func (p *RedisClusterPool) LRange(key string, start, stop int64) (interface{}, error) { - res, err := p.client.LRange(key, start, stop).Result() - if err != nil { - return nil, convertError(err) - } - return res, nil -} -func (p *RedisClusterPool) LSet(key string, index int, value interface{}) error { - err := p.client.LSet(key, int64(index), value).Err() - return convertError(err) -} -func (p *RedisClusterPool) LLen(key string) (int64, error) { - res, err := p.client.LLen(key).Result() - if err != nil { - return res, convertError(err) - } - return res, nil -} -func (p *RedisClusterPool) LRem(key string, count int, value interface{}) (int, error) { - val, _ := value.(string) - res, err := p.client.LRem(key, int64(count), val).Result() - if err != nil { - return int(res), convertError(err) - } - return int(res), nil -} -func (p *RedisClusterPool) TTl(key string) (int64, error) { - duration, err := p.client.TTL(key).Result() - if err != nil { - return int64(duration.Seconds()), convertError(err) - } - return int64(duration.Seconds()), nil -} -func (p *RedisClusterPool) LPop(key string) (interface{}, error) { - res, err := p.client.LPop(key).Result() - if err != nil { - return nil, convertError(err) - } - return res, nil -} -func (p *RedisClusterPool) RPop(key string) (interface{}, error) { - res, err := p.client.RPop(key).Result() - if err != nil { - return nil, convertError(err) - } - return res, nil -} -func (p *RedisClusterPool) BLPop(key string, timeout int) (interface{}, error) { - res, err := p.client.BLPop(time.Duration(timeout)*time.Second, key).Result() - if err != nil { - // 兼容redis 2.x - if err == redis.Nil { - return nil, ErrNil - } - return nil, err - } - return res[1], nil -} -func (p *RedisClusterPool) BRPop(key string, timeout int) (interface{}, error) { - res, err := p.client.BRPop(time.Duration(timeout)*time.Second, key).Result() - if err != nil { - // 兼容redis 2.x - if err == redis.Nil { - return nil, ErrNil - } - return nil, convertError(err) - } - return res[1], nil -} -func (p *RedisClusterPool) LPush(key string, value ...interface{}) error { - args := make([]interface{}, 0, len(value)+1) - args = append(args, key) - args = append(args, value...) - vals := make([]string, 0, len(value)) - for _, v := range value { - val, err := String(v, nil) - if err != nil && err != ErrNil { - return err - } - vals = append(vals, val) - } - _, err := p.client.LPush(key, vals).Result() // todo ... - if err != nil { - return convertError(err) - } - return nil -} -func (p *RedisClusterPool) RPush(key string, value ...interface{}) error { - args := make([]interface{}, 0, len(value)+1) - args = append(args, key) - args = append(args, value...) - vals := make([]string, 0, len(value)) - for _, v := range value { - val, err := String(v, nil) - if err != nil && err != ErrNil { - if err == ErrNil { - continue - } - return err - } - if val == "" { - continue - } - vals = append(vals, val) - } - _, err := p.client.RPush(key, vals).Result() // todo ... - if err != nil { - return convertError(err) - } - return nil -} - -// 为确保srcKey跟destKey映射到同一个slot,srcKey和destKey需要加上hash tag,如:{test} -func (p *RedisClusterPool) BRPopLPush(srcKey string, destKey string, timeout int) (interface{}, error) { - res, err := p.client.BRPopLPush(srcKey, destKey, time.Duration(timeout)*time.Second).Result() - if err != nil { - return nil, convertError(err) - } - return res, nil -} - -// 为确保srcKey跟destKey映射到同一个slot,srcKey和destKey需要加上hash tag,如:{test} -func (p *RedisClusterPool) RPopLPush(srcKey string, destKey string) (interface{}, error) { - res, err := p.client.RPopLPush(srcKey, destKey).Result() - if err != nil { - return nil, convertError(err) - } - return res, nil -} -func (p *RedisClusterPool) SAdd(key string, members ...interface{}) (int64, error) { - args := make([]interface{}, 0, len(members)+1) - args = append(args, key) - args = append(args, members...) - ms := make([]string, 0, len(members)) - for _, member := range members { - m, err := String(member, nil) - if err != nil && err != ErrNil { - return 0, err - } - ms = append(ms, m) - } - res, err := p.client.SAdd(key, ms).Result() // todo ... - if err != nil { - return res, convertError(err) - } - return res, nil -} -func (p *RedisClusterPool) SPop(key string) ([]byte, error) { - res, err := p.client.SPop(key).Result() - if err != nil { - return nil, convertError(err) - } - return []byte(res), nil -} -func (p *RedisClusterPool) SIsMember(key string, member interface{}) (bool, error) { - m, _ := member.(string) - res, err := p.client.SIsMember(key, m).Result() - if err != nil { - return res, convertError(err) - } - return res, nil -} -func (p *RedisClusterPool) SRem(key string, members ...interface{}) (int64, error) { - args := make([]interface{}, 0, len(members)+1) - args = append(args, key) - args = append(args, members...) - ms := make([]string, 0, len(members)) - for _, member := range members { - m, err := String(member, nil) - if err != nil && err != ErrNil { - return 0, err - } - ms = append(ms, m) - } - res, err := p.client.SRem(key, ms).Result() // todo ... - if err != nil { - return res, convertError(err) - } - return res, nil -} -func (p *RedisClusterPool) SMembers(key string) ([]string, error) { - res, err := p.client.SMembers(key).Result() - if err != nil { - return nil, convertError(err) - } - return res, nil -} -func (p *RedisClusterPool) ScriptLoad(luaScript string) (interface{}, error) { - res, err := p.client.ScriptLoad(luaScript).Result() - if err != nil { - return nil, convertError(err) - } - return res, nil -} -func (p *RedisClusterPool) EvalSha(sha1 string, numberKeys int, keysArgs ...interface{}) (interface{}, error) { - vals := make([]interface{}, 0, len(keysArgs)+2) - vals = append(vals, sha1, numberKeys) - vals = append(vals, keysArgs...) - keys := make([]string, 0, numberKeys) - args := make([]string, 0, len(keysArgs)-numberKeys) - for i, value := range keysArgs { - val, err := String(value, nil) - if err != nil && err != ErrNil { - return nil, err - } - if i < numberKeys { - keys = append(keys, val) - } else { - args = append(args, val) - } - } - res, err := p.client.EvalSha(sha1, keys, args).Result() - if err != nil { - return nil, convertError(err) - } - return res, nil -} -func (p *RedisClusterPool) Eval(luaScript string, numberKeys int, keysArgs ...interface{}) (interface{}, error) { - vals := make([]interface{}, 0, len(keysArgs)+2) - vals = append(vals, luaScript, numberKeys) - vals = append(vals, keysArgs...) - keys := make([]string, 0, numberKeys) - args := make([]string, 0, len(keysArgs)-numberKeys) - for i, value := range keysArgs { - val, err := String(value, nil) - if err != nil && err != ErrNil { - return nil, err - } - if i < numberKeys { - keys = append(keys, val) - } else { - args = append(args, val) - } - } - res, err := p.client.Eval(luaScript, keys, args).Result() - if err != nil { - return nil, convertError(err) - } - return res, nil -} -func (p *RedisClusterPool) GetBit(key string, offset int64) (int64, error) { - res, err := p.client.GetBit(key, offset).Result() - if err != nil { - return res, convertError(err) - } - return res, nil -} -func (p *RedisClusterPool) SetBit(key string, offset uint32, value int) (int, error) { - res, err := p.client.SetBit(key, int64(offset), value).Result() - return int(res), convertError(err) -} -func (p *RedisClusterPool) GetClient() *redis.ClusterClient { - return pools -} diff --git a/utils/convert.go b/utils/convert.go deleted file mode 100644 index ded0d90..0000000 --- a/utils/convert.go +++ /dev/null @@ -1,366 +0,0 @@ -package zhios_pay_utils - -import ( - "encoding/binary" - "encoding/json" - "fmt" - "math" - "strconv" - "strings" -) - -func ToString(raw interface{}, e error) (res string) { - if e != nil { - return "" - } - return AnyToString(raw) -} - -func ToInt64(raw interface{}, e error) int64 { - if e != nil { - return 0 - } - return AnyToInt64(raw) -} - -func AnyToBool(raw interface{}) bool { - switch i := raw.(type) { - case float32, float64, int, int64, uint, uint8, uint16, uint32, uint64, int8, int16, int32: - return i != 0 - case []byte: - return i != nil - case string: - if i == "false" { - return false - } - return i != "" - case error: - return false - case nil: - return true - } - val := fmt.Sprint(raw) - val = strings.TrimLeft(val, "&") - if strings.TrimLeft(val, "{}") == "" { - return false - } - if strings.TrimLeft(val, "[]") == "" { - return false - } - // ptr type - b, err := json.Marshal(raw) - if err != nil { - return false - } - if strings.TrimLeft(string(b), "\"\"") == "" { - return false - } - if strings.TrimLeft(string(b), "{}") == "" { - return false - } - return true -} - -func AnyToInt64(raw interface{}) int64 { - switch i := raw.(type) { - case string: - res, _ := strconv.ParseInt(i, 10, 64) - return res - case []byte: - return BytesToInt64(i) - case int: - return int64(i) - case int64: - return i - case uint: - return int64(i) - case uint8: - return int64(i) - case uint16: - return int64(i) - case uint32: - return int64(i) - case uint64: - return int64(i) - case int8: - return int64(i) - case int16: - return int64(i) - case int32: - return int64(i) - case float32: - return int64(i) - case float64: - return int64(i) - case error: - return 0 - case bool: - if i { - return 1 - } - return 0 - } - return 0 -} - -func AnyToString(raw interface{}) string { - switch i := raw.(type) { - case []byte: - return string(i) - case int: - return strconv.FormatInt(int64(i), 10) - case int64: - return strconv.FormatInt(i, 10) - case float32: - return Float64ToStr(float64(i)) - case float64: - return Float64ToStr(i) - case uint: - return strconv.FormatInt(int64(i), 10) - case uint8: - return strconv.FormatInt(int64(i), 10) - case uint16: - return strconv.FormatInt(int64(i), 10) - case uint32: - return strconv.FormatInt(int64(i), 10) - case uint64: - return strconv.FormatInt(int64(i), 10) - case int8: - return strconv.FormatInt(int64(i), 10) - case int16: - return strconv.FormatInt(int64(i), 10) - case int32: - return strconv.FormatInt(int64(i), 10) - case string: - return i - case error: - return i.Error() - case bool: - return strconv.FormatBool(i) - } - return fmt.Sprintf("%#v", raw) -} - -func AnyToFloat64(raw interface{}) float64 { - switch i := raw.(type) { - case []byte: - f, _ := strconv.ParseFloat(string(i), 64) - return f - case int: - return float64(i) - case int64: - return float64(i) - case float32: - return float64(i) - case float64: - return i - case uint: - return float64(i) - case uint8: - return float64(i) - case uint16: - return float64(i) - case uint32: - return float64(i) - case uint64: - return float64(i) - case int8: - return float64(i) - case int16: - return float64(i) - case int32: - return float64(i) - case string: - f, _ := strconv.ParseFloat(i, 64) - return f - case bool: - if i { - return 1 - } - } - return 0 -} - -func ToByte(raw interface{}, e error) []byte { - if e != nil { - return []byte{} - } - switch i := raw.(type) { - case string: - return []byte(i) - case int: - return Int64ToBytes(int64(i)) - case int64: - return Int64ToBytes(i) - case float32: - return Float32ToByte(i) - case float64: - return Float64ToByte(i) - case uint: - return Int64ToBytes(int64(i)) - case uint8: - return Int64ToBytes(int64(i)) - case uint16: - return Int64ToBytes(int64(i)) - case uint32: - return Int64ToBytes(int64(i)) - case uint64: - return Int64ToBytes(int64(i)) - case int8: - return Int64ToBytes(int64(i)) - case int16: - return Int64ToBytes(int64(i)) - case int32: - return Int64ToBytes(int64(i)) - case []byte: - return i - case error: - return []byte(i.Error()) - case bool: - if i { - return []byte("true") - } - return []byte("false") - } - return []byte(fmt.Sprintf("%#v", raw)) -} - -func Int64ToBytes(i int64) []byte { - var buf = make([]byte, 8) - binary.BigEndian.PutUint64(buf, uint64(i)) - return buf -} - -func BytesToInt64(buf []byte) int64 { - return int64(binary.BigEndian.Uint64(buf)) -} - -func StrToInt(s string) int { - res, _ := strconv.Atoi(s) - return res -} - -func StrToInt64(s string) int64 { - res, _ := strconv.ParseInt(s, 10, 64) - return res -} - -func Float32ToByte(float float32) []byte { - bits := math.Float32bits(float) - bytes := make([]byte, 4) - binary.LittleEndian.PutUint32(bytes, bits) - - return bytes -} - -func ByteToFloat32(bytes []byte) float32 { - bits := binary.LittleEndian.Uint32(bytes) - return math.Float32frombits(bits) -} - -func Float64ToByte(float float64) []byte { - bits := math.Float64bits(float) - bytes := make([]byte, 8) - binary.LittleEndian.PutUint64(bytes, bits) - return bytes -} - -func ByteToFloat64(bytes []byte) float64 { - bits := binary.LittleEndian.Uint64(bytes) - return math.Float64frombits(bits) -} - -func Float64ToStr(f float64) string { - return strconv.FormatFloat(f, 'f', 2, 64) -} -func Float64ToStrPrec1(f float64) string { - return strconv.FormatFloat(f, 'f', 1, 64) -} -func Float64ToStrByPrec(f float64, prec int) string { - return strconv.FormatFloat(f, 'f', prec, 64) -} - -func Float32ToStr(f float32) string { - return Float64ToStr(float64(f)) -} - -func StrToFloat64(s string) float64 { - res, err := strconv.ParseFloat(s, 64) - if err != nil { - return 0 - } - return res -} -func StrToFormat(s string, prec int) string { - ex := strings.Split(s, ".") - if len(ex) == 2 { - if StrToFloat64(ex[1]) == 0 { //小数点后面为空就是不要小数点了 - return ex[0] - } - //看取多少位 - str := ex[1] - str1 := str - if prec < len(str) { - str1 = str[0:prec] - } else { - for i := 0; i < prec-len(str); i++ { - str1 += "0" - } - } - if prec > 0 { - return ex[0] + "." + str1 - } else { - return ex[0] - } - } - return s -} - -func StrToFloat32(s string) float32 { - res, err := strconv.ParseFloat(s, 32) - if err != nil { - return 0 - } - return float32(res) -} - -func StrToBool(s string) bool { - b, _ := strconv.ParseBool(s) - return b -} - -func BoolToStr(b bool) string { - if b { - return "true" - } - return "false" -} - -func FloatToInt64(f float64) int64 { - return int64(f) -} - -func IntToStr(i int) string { - return strconv.Itoa(i) -} - -func Int64ToStr(i int64) string { - return strconv.FormatInt(i, 10) -} - -func IntToFloat64(i int) float64 { - s := strconv.Itoa(i) - res, err := strconv.ParseFloat(s, 64) - if err != nil { - return 0 - } - return res -} -func Int64ToFloat64(i int64) float64 { - s := strconv.FormatInt(i, 10) - res, err := strconv.ParseFloat(s, 64) - if err != nil { - return 0 - } - return res -} diff --git a/utils/curl.go b/utils/curl.go deleted file mode 100644 index fb081a0..0000000 --- a/utils/curl.go +++ /dev/null @@ -1,209 +0,0 @@ -package zhios_pay_utils - -import ( - "bytes" - "crypto/tls" - "fmt" - "io" - "io/ioutil" - "net/http" - "net/url" - "sort" - "strings" - "time" -) - -var CurlDebug bool - -func CurlGet(router string, header map[string]string) ([]byte, error) { - return curl(http.MethodGet, router, nil, header) -} -func CurlGetJson(router string, body interface{}, header map[string]string) ([]byte, error) { - return curl_new(http.MethodGet, router, body, header) -} - -// 只支持form 与json 提交, 请留意body的类型, 支持string, []byte, map[string]string -func CurlPost(router string, body interface{}, header map[string]string) ([]byte, error) { - return curl(http.MethodPost, router, body, header) -} - -func CurlPut(router string, body interface{}, header map[string]string) ([]byte, error) { - return curl(http.MethodPut, router, body, header) -} - -// 只支持form 与json 提交, 请留意body的类型, 支持string, []byte, map[string]string -func CurlPatch(router string, body interface{}, header map[string]string) ([]byte, error) { - return curl(http.MethodPatch, router, body, header) -} - -// CurlDelete is curl delete -func CurlDelete(router string, body interface{}, header map[string]string) ([]byte, error) { - return curl(http.MethodDelete, router, body, header) -} - -func curl(method, router string, body interface{}, header map[string]string) ([]byte, error) { - var reqBody io.Reader - contentType := "application/json" - switch v := body.(type) { - case string: - reqBody = strings.NewReader(v) - case []byte: - reqBody = bytes.NewReader(v) - case map[string]string: - val := url.Values{} - for k, v := range v { - val.Set(k, v) - } - reqBody = strings.NewReader(val.Encode()) - contentType = "application/x-www-form-urlencoded" - case map[string]interface{}: - val := url.Values{} - for k, v := range v { - val.Set(k, v.(string)) - } - reqBody = strings.NewReader(val.Encode()) - contentType = "application/x-www-form-urlencoded" - } - if header == nil { - header = map[string]string{"Content-Type": contentType} - } - if _, ok := header["Content-Type"]; !ok { - header["Content-Type"] = contentType - } - resp, er := CurlReq(method, router, reqBody, header) - if er != nil { - return nil, er - } - res, err := ioutil.ReadAll(resp.Body) - if CurlDebug { - blob := SerializeStr(body) - if contentType != "application/json" { - blob = HttpBuild(body) - } - fmt.Printf("\n\n=====================\n[url]: %s\n[time]: %s\n[method]: %s\n[content-type]: %v\n[req_header]: %s\n[req_body]: %#v\n[resp_err]: %v\n[resp_header]: %v\n[resp_body]: %v\n=====================\n\n", - router, - time.Now().Format("2006-01-02 15:04:05.000"), - method, - contentType, - HttpBuildQuery(header), - blob, - err, - SerializeStr(resp.Header), - string(res), - ) - } - resp.Body.Close() - return res, err -} - -func curl_new(method, router string, body interface{}, header map[string]string) ([]byte, error) { - var reqBody io.Reader - contentType := "application/json" - - if header == nil { - header = map[string]string{"Content-Type": contentType} - } - if _, ok := header["Content-Type"]; !ok { - header["Content-Type"] = contentType - } - resp, er := CurlReq(method, router, reqBody, header) - if er != nil { - return nil, er - } - res, err := ioutil.ReadAll(resp.Body) - if CurlDebug { - blob := SerializeStr(body) - if contentType != "application/json" { - blob = HttpBuild(body) - } - fmt.Printf("\n\n=====================\n[url]: %s\n[time]: %s\n[method]: %s\n[content-type]: %v\n[req_header]: %s\n[req_body]: %#v\n[resp_err]: %v\n[resp_header]: %v\n[resp_body]: %v\n=====================\n\n", - router, - time.Now().Format("2006-01-02 15:04:05.000"), - method, - contentType, - HttpBuildQuery(header), - blob, - err, - SerializeStr(resp.Header), - string(res), - ) - } - resp.Body.Close() - return res, err -} - -func CurlReq(method, router string, reqBody io.Reader, header map[string]string) (*http.Response, error) { - req, _ := http.NewRequest(method, router, reqBody) - if header != nil { - for k, v := range header { - req.Header.Set(k, v) - } - } - // 绕过github等可能因为特征码返回503问题 - // https://www.imwzk.com/posts/2021-03-14-why-i-always-get-503-with-golang/ - defaultCipherSuites := []uint16{0xc02f, 0xc030, 0xc02b, 0xc02c, 0xcca8, 0xcca9, 0xc013, 0xc009, - 0xc014, 0xc00a, 0x009c, 0x009d, 0x002f, 0x0035, 0xc012, 0x000a} - client := &http.Client{ - Transport: &http.Transport{ - TLSClientConfig: &tls.Config{ - InsecureSkipVerify: true, - CipherSuites: append(defaultCipherSuites[8:], defaultCipherSuites[:8]...), - }, - }, - // 获取301重定向 - CheckRedirect: func(req *http.Request, via []*http.Request) error { - return http.ErrUseLastResponse - }, - } - return client.Do(req) -} - -// 组建get请求参数,sortAsc true为小到大,false为大到小,nil不排序 a=123&b=321 -func HttpBuildQuery(args map[string]string, sortAsc ...bool) string { - str := "" - if len(args) == 0 { - return str - } - if len(sortAsc) > 0 { - keys := make([]string, 0, len(args)) - for k := range args { - keys = append(keys, k) - } - if sortAsc[0] { - sort.Strings(keys) - } else { - sort.Sort(sort.Reverse(sort.StringSlice(keys))) - } - for _, k := range keys { - str += "&" + k + "=" + args[k] - } - } else { - for k, v := range args { - str += "&" + k + "=" + v - } - } - return str[1:] -} - -func HttpBuild(body interface{}, sortAsc ...bool) string { - params := map[string]string{} - if args, ok := body.(map[string]interface{}); ok { - for k, v := range args { - params[k] = AnyToString(v) - } - return HttpBuildQuery(params, sortAsc...) - } - if args, ok := body.(map[string]string); ok { - for k, v := range args { - params[k] = AnyToString(v) - } - return HttpBuildQuery(params, sortAsc...) - } - if args, ok := body.(map[string]int); ok { - for k, v := range args { - params[k] = AnyToString(v) - } - return HttpBuildQuery(params, sortAsc...) - } - return AnyToString(body) -} diff --git a/utils/file.go b/utils/file.go deleted file mode 100644 index a1dafed..0000000 --- a/utils/file.go +++ /dev/null @@ -1,22 +0,0 @@ -package zhios_pay_utils - -import ( - "os" - "path" - "strings" - "time" -) - -// 获取文件后缀 -func FileExt(fname string) string { - return strings.ToLower(strings.TrimLeft(path.Ext(fname), ".")) -} - -func FilePutContents(fileName string, content string) { - fd, _ := os.OpenFile("./tmp/"+fileName+".logs", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0644) - fd_time := time.Now().Format("2006-01-02 15:04:05") - fd_content := strings.Join([]string{"[", fd_time, "] ", content, "\n"}, "") - buf := []byte(fd_content) - fd.Write(buf) - fd.Close() -} diff --git a/utils/logx/log.go b/utils/logx/log.go deleted file mode 100644 index ebfb498..0000000 --- a/utils/logx/log.go +++ /dev/null @@ -1,245 +0,0 @@ -package zhios_pay_logx - -import ( - "os" - "strings" - "time" - - "go.uber.org/zap" - "go.uber.org/zap/zapcore" -) - -type LogConfig struct { - AppName string `yaml:"app_name" json:"app_name" toml:"app_name"` - Level string `yaml:"level" json:"level" toml:"level"` - StacktraceLevel string `yaml:"stacktrace_level" json:"stacktrace_level" toml:"stacktrace_level"` - IsStdOut bool `yaml:"is_stdout" json:"is_stdout" toml:"is_stdout"` - TimeFormat string `yaml:"time_format" json:"time_format" toml:"time_format"` // second, milli, nano, standard, iso, - Encoding string `yaml:"encoding" json:"encoding" toml:"encoding"` // console, json - Skip int `yaml:"skip" json:"skip" toml:"skip"` - - IsFileOut bool `yaml:"is_file_out" json:"is_file_out" toml:"is_file_out"` - FileDir string `yaml:"file_dir" json:"file_dir" toml:"file_dir"` - FileName string `yaml:"file_name" json:"file_name" toml:"file_name"` - FileMaxSize int `yaml:"file_max_size" json:"file_max_size" toml:"file_max_size"` - FileMaxAge int `yaml:"file_max_age" json:"file_max_age" toml:"file_max_age"` -} - -var ( - l *LogX = defaultLogger() - conf *LogConfig -) - -// default logger setting -func defaultLogger() *LogX { - conf = &LogConfig{ - Level: "debug", - StacktraceLevel: "error", - IsStdOut: true, - TimeFormat: "standard", - Encoding: "console", - Skip: 2, - } - writers := []zapcore.WriteSyncer{os.Stdout} - lg, lv := newZapLogger(setLogLevel(conf.Level), setLogLevel(conf.StacktraceLevel), conf.Encoding, conf.TimeFormat, conf.Skip, zapcore.NewMultiWriteSyncer(writers...)) - zap.RedirectStdLog(lg) - return &LogX{logger: lg, atomLevel: lv} -} - -// initial standard log, if you don't init, it will use default logger setting -func InitDefaultLogger(cfg *LogConfig) { - var writers []zapcore.WriteSyncer - if cfg.IsStdOut || (!cfg.IsStdOut && !cfg.IsFileOut) { - writers = append(writers, os.Stdout) - } - if cfg.IsFileOut { - writers = append(writers, NewRollingFile(cfg.FileDir, cfg.FileName, cfg.FileMaxSize, cfg.FileMaxAge)) - } - - lg, lv := newZapLogger(setLogLevel(cfg.Level), setLogLevel(cfg.StacktraceLevel), cfg.Encoding, cfg.TimeFormat, cfg.Skip, zapcore.NewMultiWriteSyncer(writers...)) - zap.RedirectStdLog(lg) - if cfg.AppName != "" { - lg = lg.With(zap.String("app", cfg.AppName)) // 加上应用名称 - } - l = &LogX{logger: lg, atomLevel: lv} -} - -// create a new logger -func NewLogger(cfg *LogConfig) *LogX { - var writers []zapcore.WriteSyncer - if cfg.IsStdOut || (!cfg.IsStdOut && !cfg.IsFileOut) { - writers = append(writers, os.Stdout) - } - if cfg.IsFileOut { - writers = append(writers, NewRollingFile(cfg.FileDir, cfg.FileName, cfg.FileMaxSize, cfg.FileMaxAge)) - } - - lg, lv := newZapLogger(setLogLevel(cfg.Level), setLogLevel(cfg.StacktraceLevel), cfg.Encoding, cfg.TimeFormat, cfg.Skip, zapcore.NewMultiWriteSyncer(writers...)) - zap.RedirectStdLog(lg) - if cfg.AppName != "" { - lg = lg.With(zap.String("app", cfg.AppName)) // 加上应用名称 - } - return &LogX{logger: lg, atomLevel: lv} -} - -// create a new zaplog logger -func newZapLogger(level, stacktrace zapcore.Level, encoding, timeType string, skip int, output zapcore.WriteSyncer) (*zap.Logger, *zap.AtomicLevel) { - encCfg := zapcore.EncoderConfig{ - TimeKey: "T", - LevelKey: "L", - NameKey: "N", - CallerKey: "C", - MessageKey: "M", - StacktraceKey: "S", - LineEnding: zapcore.DefaultLineEnding, - EncodeCaller: zapcore.ShortCallerEncoder, - EncodeDuration: zapcore.NanosDurationEncoder, - EncodeLevel: zapcore.LowercaseLevelEncoder, - } - setTimeFormat(timeType, &encCfg) // set time type - atmLvl := zap.NewAtomicLevel() // set level - atmLvl.SetLevel(level) - encoder := zapcore.NewJSONEncoder(encCfg) // 确定encoder格式 - if encoding == "console" { - encoder = zapcore.NewConsoleEncoder(encCfg) - } - return zap.New(zapcore.NewCore(encoder, output, atmLvl), zap.AddCaller(), zap.AddStacktrace(stacktrace), zap.AddCallerSkip(skip)), &atmLvl -} - -// set log level -func setLogLevel(lvl string) zapcore.Level { - switch strings.ToLower(lvl) { - case "panic": - return zapcore.PanicLevel - case "fatal": - return zapcore.FatalLevel - case "error": - return zapcore.ErrorLevel - case "warn", "warning": - return zapcore.WarnLevel - case "info": - return zapcore.InfoLevel - default: - return zapcore.DebugLevel - } -} - -// set time format -func setTimeFormat(timeType string, z *zapcore.EncoderConfig) { - switch strings.ToLower(timeType) { - case "iso": // iso8601 standard - z.EncodeTime = zapcore.ISO8601TimeEncoder - case "sec": // only for unix second, without millisecond - z.EncodeTime = func(t time.Time, enc zapcore.PrimitiveArrayEncoder) { - enc.AppendInt64(t.Unix()) - } - case "second": // unix second, with millisecond - z.EncodeTime = zapcore.EpochTimeEncoder - case "milli", "millisecond": // millisecond - z.EncodeTime = zapcore.EpochMillisTimeEncoder - case "nano", "nanosecond": // nanosecond - z.EncodeTime = zapcore.EpochNanosTimeEncoder - default: // standard format - z.EncodeTime = func(t time.Time, enc zapcore.PrimitiveArrayEncoder) { - enc.AppendString(t.Format("2006-01-02 15:04:05.000")) - } - } -} - -func GetLevel() string { - switch l.atomLevel.Level() { - case zapcore.PanicLevel: - return "panic" - case zapcore.FatalLevel: - return "fatal" - case zapcore.ErrorLevel: - return "error" - case zapcore.WarnLevel: - return "warn" - case zapcore.InfoLevel: - return "info" - default: - return "debug" - } -} - -func SetLevel(lvl string) { - l.atomLevel.SetLevel(setLogLevel(lvl)) -} - -// temporary add call skip -func AddCallerSkip(skip int) *LogX { - l.logger.WithOptions(zap.AddCallerSkip(skip)) - return l -} - -// permanent add call skip -func AddDepth(skip int) *LogX { - l.logger = l.logger.WithOptions(zap.AddCallerSkip(skip)) - return l -} - -// permanent add options -func AddOptions(opts ...zap.Option) *LogX { - l.logger = l.logger.WithOptions(opts...) - return l -} - -func AddField(k string, v interface{}) { - l.logger.With(zap.Any(k, v)) -} - -func AddFields(fields map[string]interface{}) *LogX { - for k, v := range fields { - l.logger.With(zap.Any(k, v)) - } - return l -} - -// Normal log -func Debug(e interface{}, args ...interface{}) error { - return l.Debug(e, args...) -} -func Info(e interface{}, args ...interface{}) error { - return l.Info(e, args...) -} -func Warn(e interface{}, args ...interface{}) error { - return l.Warn(e, args...) -} -func Error(e interface{}, args ...interface{}) error { - return l.Error(e, args...) -} -func Panic(e interface{}, args ...interface{}) error { - return l.Panic(e, args...) -} -func Fatal(e interface{}, args ...interface{}) error { - return l.Fatal(e, args...) -} - -// Format logs -func Debugf(format string, args ...interface{}) error { - return l.Debugf(format, args...) -} -func Infof(format string, args ...interface{}) error { - return l.Infof(format, args...) -} -func Warnf(format string, args ...interface{}) error { - return l.Warnf(format, args...) -} -func Errorf(format string, args ...interface{}) error { - return l.Errorf(format, args...) -} -func Panicf(format string, args ...interface{}) error { - return l.Panicf(format, args...) -} -func Fatalf(format string, args ...interface{}) error { - return l.Fatalf(format, args...) -} - -func formatFieldMap(m FieldMap) []Field { - var res []Field - for k, v := range m { - res = append(res, zap.Any(k, v)) - } - return res -} diff --git a/utils/logx/output.go b/utils/logx/output.go deleted file mode 100644 index 2d6aa6a..0000000 --- a/utils/logx/output.go +++ /dev/null @@ -1,105 +0,0 @@ -package zhios_pay_logx - -import ( - "bytes" - "io" - "os" - "path/filepath" - "time" - - "gopkg.in/natefinch/lumberjack.v2" -) - -// output interface -type WriteSyncer interface { - io.Writer - Sync() error -} - -// split writer -func NewRollingFile(dir, filename string, maxSize, MaxAge int) WriteSyncer { - s, err := os.Stat(dir) - if err != nil || !s.IsDir() { - os.RemoveAll(dir) - if err := os.MkdirAll(dir, 0766); err != nil { - panic(err) - } - } - return newLumberjackWriteSyncer(&lumberjack.Logger{ - Filename: filepath.Join(dir, filename), - MaxSize: maxSize, // megabytes, MB - MaxAge: MaxAge, // days - LocalTime: true, - Compress: false, - }) -} - -type lumberjackWriteSyncer struct { - *lumberjack.Logger - buf *bytes.Buffer - logChan chan []byte - closeChan chan interface{} - maxSize int -} - -func newLumberjackWriteSyncer(l *lumberjack.Logger) *lumberjackWriteSyncer { - ws := &lumberjackWriteSyncer{ - Logger: l, - buf: bytes.NewBuffer([]byte{}), - logChan: make(chan []byte, 5000), - closeChan: make(chan interface{}), - maxSize: 1024, - } - go ws.run() - return ws -} - -func (l *lumberjackWriteSyncer) run() { - ticker := time.NewTicker(1 * time.Second) - - for { - select { - case <-ticker.C: - if l.buf.Len() > 0 { - l.sync() - } - case bs := <-l.logChan: - _, err := l.buf.Write(bs) - if err != nil { - continue - } - if l.buf.Len() > l.maxSize { - l.sync() - } - case <-l.closeChan: - l.sync() - return - } - } -} - -func (l *lumberjackWriteSyncer) Stop() { - close(l.closeChan) -} - -func (l *lumberjackWriteSyncer) Write(bs []byte) (int, error) { - b := make([]byte, len(bs)) - for i, c := range bs { - b[i] = c - } - l.logChan <- b - return 0, nil -} - -func (l *lumberjackWriteSyncer) Sync() error { - return nil -} - -func (l *lumberjackWriteSyncer) sync() error { - defer l.buf.Reset() - _, err := l.Logger.Write(l.buf.Bytes()) - if err != nil { - return err - } - return nil -} diff --git a/utils/logx/sugar.go b/utils/logx/sugar.go deleted file mode 100644 index 736a1be..0000000 --- a/utils/logx/sugar.go +++ /dev/null @@ -1,192 +0,0 @@ -package zhios_pay_logx - -import ( - "errors" - "fmt" - "strconv" - - "go.uber.org/zap" -) - -type LogX struct { - logger *zap.Logger - atomLevel *zap.AtomicLevel -} - -type Field = zap.Field -type FieldMap map[string]interface{} - -// 判断其他类型--start -func getFields(msg string, format bool, args ...interface{}) (string, []Field) { - var str []interface{} - var fields []zap.Field - if len(args) > 0 { - for _, v := range args { - if f, ok := v.(Field); ok { - fields = append(fields, f) - } else if f, ok := v.(FieldMap); ok { - fields = append(fields, formatFieldMap(f)...) - } else { - str = append(str, AnyToString(v)) - } - } - if format { - return fmt.Sprintf(msg, str...), fields - } - str = append([]interface{}{msg}, str...) - return fmt.Sprintln(str...), fields - } - return msg, []Field{} -} - -func (l *LogX) Debug(s interface{}, args ...interface{}) error { - es, e := checkErr(s) - if es != "" { - msg, field := getFields(es, false, args...) - l.logger.Debug(msg, field...) - } - return e -} -func (l *LogX) Info(s interface{}, args ...interface{}) error { - es, e := checkErr(s) - if es != "" { - msg, field := getFields(es, false, args...) - l.logger.Info(msg, field...) - } - return e -} -func (l *LogX) Warn(s interface{}, args ...interface{}) error { - es, e := checkErr(s) - if es != "" { - msg, field := getFields(es, false, args...) - l.logger.Warn(msg, field...) - } - return e -} -func (l *LogX) Error(s interface{}, args ...interface{}) error { - es, e := checkErr(s) - if es != "" { - msg, field := getFields(es, false, args...) - l.logger.Error(msg, field...) - } - return e -} -func (l *LogX) DPanic(s interface{}, args ...interface{}) error { - es, e := checkErr(s) - if es != "" { - msg, field := getFields(es, false, args...) - l.logger.DPanic(msg, field...) - } - return e -} -func (l *LogX) Panic(s interface{}, args ...interface{}) error { - es, e := checkErr(s) - if es != "" { - msg, field := getFields(es, false, args...) - l.logger.Panic(msg, field...) - } - return e -} -func (l *LogX) Fatal(s interface{}, args ...interface{}) error { - es, e := checkErr(s) - if es != "" { - msg, field := getFields(es, false, args...) - l.logger.Fatal(msg, field...) - } - return e -} - -func checkErr(s interface{}) (string, error) { - switch e := s.(type) { - case error: - return e.Error(), e - case string: - return e, errors.New(e) - case []byte: - return string(e), nil - default: - return "", nil - } -} - -func (l *LogX) LogError(err error) error { - return l.Error(err.Error()) -} - -func (l *LogX) Debugf(msg string, args ...interface{}) error { - s, f := getFields(msg, true, args...) - l.logger.Debug(s, f...) - return errors.New(s) -} - -func (l *LogX) Infof(msg string, args ...interface{}) error { - s, f := getFields(msg, true, args...) - l.logger.Info(s, f...) - return errors.New(s) -} - -func (l *LogX) Warnf(msg string, args ...interface{}) error { - s, f := getFields(msg, true, args...) - l.logger.Warn(s, f...) - return errors.New(s) -} - -func (l *LogX) Errorf(msg string, args ...interface{}) error { - s, f := getFields(msg, true, args...) - l.logger.Error(s, f...) - return errors.New(s) -} - -func (l *LogX) DPanicf(msg string, args ...interface{}) error { - s, f := getFields(msg, true, args...) - l.logger.DPanic(s, f...) - return errors.New(s) -} - -func (l *LogX) Panicf(msg string, args ...interface{}) error { - s, f := getFields(msg, true, args...) - l.logger.Panic(s, f...) - return errors.New(s) -} - -func (l *LogX) Fatalf(msg string, args ...interface{}) error { - s, f := getFields(msg, true, args...) - l.logger.Fatal(s, f...) - return errors.New(s) -} - -func AnyToString(raw interface{}) string { - switch i := raw.(type) { - case []byte: - return string(i) - case int: - return strconv.FormatInt(int64(i), 10) - case int64: - return strconv.FormatInt(i, 10) - case float32: - return strconv.FormatFloat(float64(i), 'f', 2, 64) - case float64: - return strconv.FormatFloat(i, 'f', 2, 64) - case uint: - return strconv.FormatInt(int64(i), 10) - case uint8: - return strconv.FormatInt(int64(i), 10) - case uint16: - return strconv.FormatInt(int64(i), 10) - case uint32: - return strconv.FormatInt(int64(i), 10) - case uint64: - return strconv.FormatInt(int64(i), 10) - case int8: - return strconv.FormatInt(int64(i), 10) - case int16: - return strconv.FormatInt(int64(i), 10) - case int32: - return strconv.FormatInt(int64(i), 10) - case string: - return i - case error: - return i.Error() - } - return fmt.Sprintf("%#v", raw) -} diff --git a/utils/md5.go b/utils/md5.go deleted file mode 100644 index 6db0583..0000000 --- a/utils/md5.go +++ /dev/null @@ -1,12 +0,0 @@ -package zhios_pay_utils - -import ( - "crypto/md5" - "encoding/hex" -) - -func Md5(str string) string { - h := md5.New() - h.Write([]byte(str)) - return hex.EncodeToString(h.Sum(nil)) -} diff --git a/utils/serialize.go b/utils/serialize.go deleted file mode 100644 index edd84ed..0000000 --- a/utils/serialize.go +++ /dev/null @@ -1,23 +0,0 @@ -package zhios_pay_utils - -import ( - "encoding/json" -) - -func Serialize(data interface{}) []byte { - res, err := json.Marshal(data) - if err != nil { - return []byte{} - } - return res -} - -func Unserialize(b []byte, dst interface{}) { - if err := json.Unmarshal(b, dst); err != nil { - dst = nil - } -} - -func SerializeStr(data interface{}, arg ...interface{}) string { - return string(Serialize(data)) -}