diff --git a/controllers/callback_controller.go b/controllers/callback_controller.go index 86f37bd..2783e3e 100644 --- a/controllers/callback_controller.go +++ b/controllers/callback_controller.go @@ -1,8 +1,10 @@ package controllers import ( + "git.rosy.net.cn/jx-print/globals" "git.rosy.net.cn/jx-print/services" "github.com/gin-gonic/gin" + "io/ioutil" ) type CallbackController struct { @@ -15,3 +17,8 @@ func (t *CallbackController) Msg(c *gin.Context) { }) } } + +func (t *CallbackController) TlPayCallback(c *gin.Context) { + data, _ := ioutil.ReadAll(c.Request.Body) + globals.SugarLogger.Debugf("TlPayCallback msg: %v", string(data)) +} diff --git a/controllers/controller.go b/controllers/controller.go index b36e2d8..7b1196f 100644 --- a/controllers/controller.go +++ b/controllers/controller.go @@ -5,8 +5,8 @@ import ( "fmt" "git.rosy.net.cn/jx-print/globals" "git.rosy.net.cn/jx-print/model" + "git.rosy.net.cn/jx-print/putils" "git.rosy.net.cn/jx-print/services" - "git.rosy.net.cn/jx-print/utils" "github.com/dchest/captcha" "github.com/gin-gonic/gin" "net/http" @@ -44,7 +44,7 @@ func checkToken(c *gin.Context) (tokenInfo *model.TokenInfo) { tokenInfo.Token = cookie.Value } globals.SugarLogger.Debugf("checkToken token: %v", tokenInfo.Token) - if tokenMap = utils.GetKey(tokenInfo.Token).(map[string]interface{}); tokenMap == nil { + if tokenMap = putils.GetKey(tokenInfo.Token).(map[string]interface{}); tokenMap == nil { err = fmt.Errorf("token过期或无效,请重新登录!") c.JSON(http.StatusOK, &CallBack{ Desc: err.Error(), @@ -63,7 +63,7 @@ func checkToken(c *gin.Context) (tokenInfo *model.TokenInfo) { }) return nil } - globals.SugarLogger.Debugf("checkToken user: %v", utils.Format4Output(user, true)) + globals.SugarLogger.Debugf("checkToken user: %v", putils.Format4Output(user, true)) } return tokenInfo } @@ -106,8 +106,8 @@ func callFunc(c *gin.Context, worker func() (retVal interface{}, errCode string, func captchaVerify(c *gin.Context, code string) bool { //session := sessions.Default(c) - if captchaId := utils.GetKey(c.ClientIP() + model.SessionKey).(string); captchaId != "" { - utils.DelKey(c.ClientIP() + model.SessionKey) + if captchaId := putils.GetKey(c.ClientIP() + model.SessionKey).(string); captchaId != "" { + putils.DelKey(c.ClientIP() + model.SessionKey) if captcha.VerifyString(captchaId, code) { return true } else { diff --git a/controllers/order_controller.go b/controllers/order_controller.go index 48d5cc1..5cdd6d2 100644 --- a/controllers/order_controller.go +++ b/controllers/order_controller.go @@ -2,6 +2,7 @@ package controllers import ( "git.rosy.net.cn/jx-print/model" + "git.rosy.net.cn/jx-print/services" "github.com/gin-gonic/gin" ) @@ -24,6 +25,7 @@ func CreateOrder(c *gin.Context) { return } if !callFunc(c, func() (retVal interface{}, errCode string, err error) { + retVal, err = services.CreateOrder(tokenInfo, param.OrderType, param.Origin, param.ThingID, param.TypeID) return retVal, "", err }) { return @@ -48,6 +50,7 @@ func Pay(c *gin.Context) { return } if !callFunc(c, func() (retVal interface{}, errCode string, err error) { + retVal, err = services.Pay(tokenInfo, param.OrderID, param.PayType, param.VendorPayType) return retVal, "", err }) { return diff --git a/controllers/print_controller.go b/controllers/print_controller.go index d87a43d..06ea2a9 100644 --- a/controllers/print_controller.go +++ b/controllers/print_controller.go @@ -2,8 +2,8 @@ package controllers import ( "git.rosy.net.cn/jx-print/model" + "git.rosy.net.cn/jx-print/putils" "git.rosy.net.cn/jx-print/services" - "git.rosy.net.cn/jx-print/utils" "github.com/gin-gonic/gin" ) @@ -25,7 +25,7 @@ func AddPrinters(c *gin.Context) { if tokenInfo = checkToken(c); tokenInfo == nil { return } - if err = utils.UnmarshalUseNumber([]byte(param.Prints), &printInfos); err != nil { + if err = putils.UnmarshalUseNumber([]byte(param.Prints), &printInfos); err != nil { buildErrJson(c, err) return } @@ -87,7 +87,7 @@ func DelPrinters(c *gin.Context) { if tokenInfo = checkToken(c); tokenInfo == nil { return } - if err = utils.UnmarshalUseNumber([]byte(param.PrintNos), &printNos); err != nil { + if err = putils.UnmarshalUseNumber([]byte(param.PrintNos), &printNos); err != nil { buildErrJson(c, err) return } diff --git a/controllers/user_controller.go b/controllers/user_controller.go index ea4a2f1..b61f48a 100644 --- a/controllers/user_controller.go +++ b/controllers/user_controller.go @@ -4,15 +4,15 @@ import ( "encoding/json" "git.rosy.net.cn/jx-print/globals" "git.rosy.net.cn/jx-print/model" + "git.rosy.net.cn/jx-print/putils" "git.rosy.net.cn/jx-print/services" - "git.rosy.net.cn/jx-print/utils" "github.com/gin-gonic/gin" "net/http" ) //刷新验证码 POST func RefreshCode(c *gin.Context) { - utils.Captcha(c, 4) + putils.Captcha(c, 4) } type UserParam struct { diff --git a/dao/dao.go b/dao/dao.go index bd827b8..42cf656 100644 --- a/dao/dao.go +++ b/dao/dao.go @@ -2,7 +2,7 @@ package dao import ( "fmt" - putils "git.rosy.net.cn/jx-print/utils" + putils "git.rosy.net.cn/jx-print/putils" "github.com/jmoiron/sqlx" "reflect" "strings" diff --git a/dao/order_dao.go b/dao/order_dao.go new file mode 100644 index 0000000..fc3a67d --- /dev/null +++ b/dao/order_dao.go @@ -0,0 +1,20 @@ +package dao + +import ( + "git.rosy.net.cn/jx-print/model" + "github.com/jmoiron/sqlx" +) + +func GetOrder(db *sqlx.DB, orderID string) (order *model.PayOrder, err error) { + var ( + orders []*model.PayOrder + ) + sql := ` + SELECT * FROM pay_order WHERE order_id = ? + ` + sqlParams := []interface{}{orderID} + if err = db.Select(&orders, sql, sqlParams...); err == nil && len(orders) > 0 { + return orders[0], err + } + return order, err +} diff --git a/model/model.go b/model/model.go index 95f19bd..05f14ee 100644 --- a/model/model.go +++ b/model/model.go @@ -41,6 +41,14 @@ const ( OrderOriginWxMini = "weixinmini" OrderOriginOpenAPI = "openAPI" + + OrderStatusWaitPay = 0 //待支付 + OrderStatusPaid = 1 //已支付 + OrderStatusPayFail = 2 + OrderStatusPayCancel = 3 + OrderStatusRefund = 4 + + PayTypeTL = "tl" //通联支付 ) const ( @@ -64,7 +72,7 @@ type TokenInfo struct { type FlowConfig struct { ID int `json:"id"` - Price int `json:"price"` + Price int64 `json:"price"` Flow float64 `json:"flow"` Unit string `json:"unit"` } @@ -207,7 +215,7 @@ type PayOrder struct { OrderType string `json:"order_type" db:"order_type"` //订单类型,流量充值等 Origin string `json:"origin"` //订单来源,小程序,开放后台 Status int `json:"status"` //订单状态,待支付2,已支付5,支付成功110,支付失败115 - PayPrice int `json:"pay_price" db:"pay_price"` //支付金额 + PayPrice int64 `json:"pay_price" db:"pay_price"` //支付金额 TransactionID string `json:"transaction_id" db:"transaction_id"` // 支付成功后,支付方生成的事务ID PayFinishedAt *time.Time `json:"pay_finished_at" db:"pay_finished_at"` PrepayID string `json:"prepay_id" db:"prepay_id"` // 下单后,支付前,支付方生成的事务ID diff --git a/utils/redis.go b/putils/redis.go similarity index 98% rename from utils/redis.go rename to putils/redis.go index cee20f1..6a502f4 100644 --- a/utils/redis.go +++ b/putils/redis.go @@ -1,4 +1,4 @@ -package utils +package putils import ( "git.rosy.net.cn/baseapi/utils" diff --git a/utils/utils.go b/putils/utils.go similarity index 91% rename from utils/utils.go rename to putils/utils.go index 16b54d7..ae37f12 100644 --- a/utils/utils.go +++ b/putils/utils.go @@ -1,7 +1,8 @@ -package utils +package putils import ( "bytes" + "crypto/md5" "encoding/json" "fmt" "git.rosy.net.cn/baseapi" @@ -10,6 +11,7 @@ import ( "git.rosy.net.cn/jx-print/model" "github.com/dchest/captcha" "github.com/gin-gonic/gin" + "math" "math/rand" "net/http" "strings" @@ -40,6 +42,7 @@ var ( "MB": struct{}{}, "GB": struct{}{}, } + orderNoBeginTimestamp = utils.Str2Time("2010-01-01 00:00:00").Unix() ) func RandStringBytes(n int) string { @@ -251,3 +254,18 @@ func FlowKB2Other(flowKB float64) (flow float64, unit string) { } return flow, unit } + +func GenOrderNo() (orderNo int64) { + var prefix = utils.Str2Int64(time.Now().Format("20060102")) + const randPartNum = 1000 + orderNo = time.Now().Unix() - orderNoBeginTimestamp + orderNo = orderNo * randPartNum + md5Bytes := md5.Sum([]byte(utils.GetUUID())) + randPart := 0 + for k, v := range md5Bytes { + randPart += int(v) << ((k % 3) * 8) + } + orderNo += int64(randPart % randPartNum) + orderNo += int64(math.Pow10(int(math.Log10(float64(orderNo)))+1)) * prefix + return orderNo +} diff --git a/services/app.go b/services/app.go index 2828309..93f3df1 100644 --- a/services/app.go +++ b/services/app.go @@ -6,7 +6,7 @@ import ( "git.rosy.net.cn/jx-print/dao" "git.rosy.net.cn/jx-print/globals" "git.rosy.net.cn/jx-print/model" - putils "git.rosy.net.cn/jx-print/utils" + putils "git.rosy.net.cn/jx-print/putils" "github.com/gin-gonic/gin" "time" ) diff --git a/services/misc/misc.go b/services/misc/misc.go index 6c20e0a..29450a7 100644 --- a/services/misc/misc.go +++ b/services/misc/misc.go @@ -2,8 +2,8 @@ package misc import ( "git.rosy.net.cn/baseapi/utils" + putils "git.rosy.net.cn/jx-print/putils" "git.rosy.net.cn/jx-print/services" - putils "git.rosy.net.cn/jx-print/utils" "git.rosy.net.cn/jx-print/globals" "time" diff --git a/services/order.go b/services/order.go index e867300..7c63314 100644 --- a/services/order.go +++ b/services/order.go @@ -1,7 +1,93 @@ package services -import "git.rosy.net.cn/jx-print/model" +import ( + "encoding/json" + "fmt" + "git.rosy.net.cn/baseapi/platformapi/tonglianpayapi" + "git.rosy.net.cn/baseapi/utils" + "git.rosy.net.cn/jx-print/dao" + "git.rosy.net.cn/jx-print/globals" + "git.rosy.net.cn/jx-print/model" + "git.rosy.net.cn/jx-print/putils" + "git.rosy.net.cn/jx-print/services/api" + "github.com/jmoiron/sqlx" + "strings" + "time" +) -func CreateOrder(tokenInfo *model.TokenInfo) (err error) { - return err +var ( + findOrderPayPriceMap = map[string]func(db *sqlx.DB, typeID string) (int64, error){ + model.OrderTypeFlow: func(db *sqlx.DB, typeID string) (payPrice int64, err error) { + var flowCfg []*model.FlowConfig + if config, err2 := dao.GetConfig(db, model.ConfigTypeSys, model.OrderTypeFlow); err2 == nil && config != nil { + if err = json.Unmarshal([]byte(config.Value), &flowCfg); err == nil && len(flowCfg) > 0 { + for _, v := range flowCfg { + if v.ID == utils.Str2Int(typeID) { + payPrice = v.Price + break + } + } + } + } else { + err = err2 + } + return payPrice, err + }, + } + + payFunc = map[string]func(db *sqlx.DB, order *model.PayOrder, vendorPayType string) (err error){ + model.PayTypeTL: func(db *sqlx.DB, order *model.PayOrder, vendorPayType string) (err error) { + param := &tonglianpayapi.CreateUnitorderOrderParam{ + Trxamt: int(order.PayPrice), + NotifyUrl: "http://print.jxc4.com/callback/tlPayCallback", + Reqsn: order.OrderID, + PayType: vendorPayType, + } + if vendorPayType != tonglianpayapi.PayTypeWxCode { + return fmt.Errorf("暂不支持的支付类型!vendorPayType :%s", vendorPayType) + } + result, err := api.TLpayAPI.CreateUnitorderOrder(param) + if err == nil { + var result2 tonglianpayapi.PayInfo + json.Unmarshal([]byte(result.PayInfo), &result2) + order.PrepayID = result2.Package[strings.LastIndex(result2.Package, "=")+1 : len(result2.Package)] + order.TransactionID = result.TrxID + err = dao.Update(db, order, "prepay_id", "transaction_id") + } + return err + }, + } +) + +func CreateOrder(tokenInfo *model.TokenInfo, orderType, origin, thingID, typeID string) (orderID string, err error) { + var ( + db = globals.GetDB() + now = time.Now() + payPrice int64 + ) + if payPrice, err = findOrderPayPriceMap[orderType](db, typeID); err != nil { + return "", err + } + orderID = utils.Int64ToStr(putils.GenOrderNo()) + payOrder := &model.PayOrder{ + CreatedAt: &now, + OrderID: orderID, + PayPrice: payPrice, + UserID: tokenInfo.User.UserID, + OrderType: orderType, + Origin: origin, + ThingID: thingID, + TypeID: typeID, + } + err = dao.Insert(db, payOrder) + return orderID, err +} + +func Pay(tokenInfo *model.TokenInfo, orderID, payType, vendorPayType string) (order *model.PayOrder, err error) { + var ( + db = globals.GetDB() + ) + order, _ = dao.GetOrder(db, orderID) + err = payFunc[payType](db, order, vendorPayType) + return order, err } diff --git a/services/print.go b/services/print.go index 889021f..e70d940 100644 --- a/services/print.go +++ b/services/print.go @@ -6,7 +6,7 @@ import ( "git.rosy.net.cn/jx-print/dao" "git.rosy.net.cn/jx-print/globals" "git.rosy.net.cn/jx-print/model" - putils "git.rosy.net.cn/jx-print/utils" + putils "git.rosy.net.cn/jx-print/putils" "github.com/gin-gonic/gin" "time" ) diff --git a/services/sim.go b/services/sim.go index c9278ba..400330b 100644 --- a/services/sim.go +++ b/services/sim.go @@ -6,8 +6,8 @@ import ( "git.rosy.net.cn/jx-print/dao" "git.rosy.net.cn/jx-print/globals" "git.rosy.net.cn/jx-print/model" + putils "git.rosy.net.cn/jx-print/putils" "git.rosy.net.cn/jx-print/services/api" - putils "git.rosy.net.cn/jx-print/utils" "time" ) @@ -68,7 +68,7 @@ func SimFlowDaySettle() (err error) { sumIncome, _ := dao.GetSimFlowIncomeSum(db, v.IccID, monthBegin, monthEnd) sumExpend, _ := dao.GetSimFlowExpendSum(db, v.IccID, monthBegin, monthEnd) if sumIncome != nil && sumExpend != nil { - if sumExpend.Flow-sumIncome.Flow <= 0 { + if sumIncome.Flow-sumExpend.Flow <= 0 { v.FlowFlag = 1 err = dao.Update(db, v, "flow_flag") } diff --git a/services/user.go b/services/user.go index 5b872b8..e7ed434 100644 --- a/services/user.go +++ b/services/user.go @@ -8,7 +8,7 @@ import ( "git.rosy.net.cn/jx-print/dao" "git.rosy.net.cn/jx-print/globals" "git.rosy.net.cn/jx-print/model" - putils "git.rosy.net.cn/jx-print/utils" + putils "git.rosy.net.cn/jx-print/putils" "github.com/gin-gonic/gin" "github.com/jmoiron/sqlx" "strings"