- elm callback basic.

This commit is contained in:
gazebo
2018-06-14 17:50:58 +08:00
parent 4854395ef3
commit ad1a6ab5c4
12 changed files with 273 additions and 48 deletions

21
business/business.go Normal file
View File

@@ -0,0 +1,21 @@
package controller
import (
elmmodels "git.rosy.net.cn/jx-callback/business/elm/models"
"git.rosy.net.cn/jx-callback/business/jd/models"
"github.com/astaxie/beego/orm"
_ "github.com/go-sql-driver/mysql" // import your used driver
)
// 确定这个init是最先执行的
func init() {
// set default database
orm.RegisterDataBase("default", "mysql", "root:WebServer@1@tcp(127.0.0.1:3306)/jx-callback?charset=utf8&loc=Local", 30)
// register model
orm.RegisterModel(new(models.Jdorder))
orm.RegisterModel(new(elmmodels.ELMOrder))
// create table
orm.RunSyncdb("default", false, true)
}

View File

@@ -0,0 +1,40 @@
package controller
import (
"git.rosy.net.cn/baseapi/platform/elmapi"
"git.rosy.net.cn/baseapi/utils"
"git.rosy.net.cn/jx-callback/globals"
"github.com/astaxie/beego/orm"
"go.uber.org/zap"
)
const (
elmToken = "" //"bab2a27f99562f394b411dbb9a6214da"
elmAppKey = "KLRDcOZGrk"
elmSecret = "1fc221f8265506531da36fb613d5f5ad673f2e9a"
)
var (
gElmAPI *elmapi.ELMAPI
sugarLogger *zap.SugaredLogger
)
func init() {
sugarLogger = globals.SugarLogger
token := elmToken
if token == "" {
db := orm.NewOrm()
var tokenInfo []orm.Params
num, err := db.Raw("SELECT * FROM thirdpartytoken WHERE thirdparty='eleme'").Values(&tokenInfo)
if err != nil || num != 1 {
panic(err.Error())
}
var tokenInfo2 map[string]interface{}
if err := utils.UnmarshalUseNumber([]byte(tokenInfo[0]["token"].(string)), &tokenInfo2); err != nil {
panic(err.Error())
}
token = tokenInfo2["accessToken"].(string)
}
gElmAPI = elmapi.NewELMAPI(token, elmAppKey, elmSecret, sugarLogger, true)
}

View File

@@ -0,0 +1,86 @@
package controller
import (
"git.rosy.net.cn/baseapi/platform/elmapi"
"git.rosy.net.cn/baseapi/utils"
"git.rosy.net.cn/jx-callback/business/elm/models"
"git.rosy.net.cn/jx-callback/globals"
"github.com/astaxie/beego/orm"
)
var (
errResponseInternal = &elmapi.ELMCallbackResponse{Message: "internal error"}
errResponseDataError = &elmapi.ELMCallbackResponse{Message: "elm data error"}
errResponseDBError = &elmapi.ELMCallbackResponse{Message: "DB error"}
errResponseCallELMAPIError = &elmapi.ELMCallbackResponse{Message: "call ELM API error"}
)
type OrderController struct {
}
func (o *OrderController) OrderMessage(msg *elmapi.ELMCallbackMsg) *elmapi.ELMCallbackResponse {
var innerMsg map[string]interface{}
err := utils.UnmarshalUseNumber([]byte(msg.Message), &innerMsg)
if err != nil {
sugarLogger.Warnf("OrderMessage unmarshal %v error:%v", msg, err)
return errResponseDataError
}
if msg.Type == elmapi.OrderValid {
return o.NewOrder(msg, innerMsg["id"].(string))
} else if msg.Type >= elmapi.MerchantValid && msg.Type <= elmapi.OrderFinished {
return o.OrderStatusChanged(msg, innerMsg["orderId"].(string))
}
return elmapi.ELMResponseOK
}
func (o *OrderController) NewOrder(msg *elmapi.ELMCallbackMsg, orderId string) *elmapi.ELMCallbackResponse {
db := orm.NewOrm()
rec := &models.ELMOrder{
OrderId: orderId,
Type: msg.Type,
}
created, _, err := db.ReadOrCreate(rec, "OrderId")
if err != nil {
sugarLogger.Warnf("error when calling ReadOrCreate, error:%v", err)
return errResponseDBError
}
if created || rec.Type != msg.Type {
result, err := gElmAPI.GetOrder(orderId)
if err != nil {
sugarLogger.Warnf("call GetOrder error:%v", err)
return errResponseCallELMAPIError
}
err = globals.FreshFoodAPI.NewELMOrder(result)
if err != nil {
sugarLogger.Warnf("internal error:%v", err)
return errResponseInternal
}
} else {
sugarLogger.Infof("duplicate elm msg received:%v", msg)
}
return elmapi.ELMResponseOK
}
func (o *OrderController) OrderStatusChanged(msg *elmapi.ELMCallbackMsg, orderId string) *elmapi.ELMCallbackResponse {
db := orm.NewOrm()
rec := &models.ELMOrder{
OrderId: orderId,
}
err := db.Read(rec, "OrderId")
if err != nil {
sugarLogger.Warnf("error when calling ReadOrCreate, error:%v", err)
return errResponseDBError
}
if rec.Type != msg.Type {
err = globals.FreshFoodAPI.ELMOrderStatus(orderId, msg.Type, utils.GetCurTimestamp())
if err != nil {
sugarLogger.Warnf("internal error:%v", err)
return errResponseInternal
}
} else {
sugarLogger.Infof("duplicate elm msg received:%v", msg)
}
return elmapi.ELMResponseOK
}

View File

@@ -0,0 +1,12 @@
package models
type ELMOrder struct {
Id int
OrderId string `orm:"size(50);unique;null"`
Data string `orm:"type(text);null"`
Type int `orm:"null"`
}
func (e *ELMOrder) TableName() string {
return "elemeorder"
}

View File

@@ -27,29 +27,44 @@ const (
URL_FRESHFOOD_PARA_DELIVERYMANNO = "deliveryManNo" URL_FRESHFOOD_PARA_DELIVERYMANNO = "deliveryManNo"
URL_FRESHFOOD_PARA_DELIVERYMANNAME = "deliveryManName" URL_FRESHFOOD_PARA_DELIVERYMANNAME = "deliveryManName"
URL_FRESHFOOD_PARA_DELIVERYMANPHONE = "deliveryManPhone" URL_FRESHFOOD_PARA_DELIVERYMANPHONE = "deliveryManPhone"
URL_FRESHFOOD_PARA_ELEMEORDER = "elemeOrder"
)
const (
JD_VENDERID = 0
ELM_VENDERID = 2
)
const (
retryCount = 3
) )
type FreshFoodAPI struct { type FreshFoodAPI struct {
baseURL string baseURL string
sugarLogger *zap.SugaredLogger sugarLogger *zap.SugaredLogger
client http.Client client *http.Client
} }
func NewFreshFoodAPI(baseURL string, zapLogger *zap.Logger) *FreshFoodAPI { func NewFreshFoodAPI(baseURL string, sugarredLogger *zap.SugaredLogger) *FreshFoodAPI {
return &FreshFoodAPI{baseURL, zapLogger.Sugar(), http.Client{Timeout: time.Second * 5}} return &FreshFoodAPI{baseURL, sugarredLogger, &http.Client{Timeout: time.Second * 5}}
} }
func (f *FreshFoodAPI) AccessFreshFodd(apiStr string, params url.Values) error { func (f *FreshFoodAPI) AccessFreshFodd(apiStr string, params url.Values) error {
var err error
fullURL := f.baseURL + "/" + apiStr fullURL := f.baseURL + "/" + apiStr
// _, err := f.client.PostForm(fullURL, params) for i := 0; i < retryCount; i++ {
err := error(nil) // _, err := f.client.PostForm(fullURL, params)
f.sugarLogger.Debug(fullURL) err = error(nil)
if err != nil { f.sugarLogger.Debug(fullURL)
f.sugarLogger.Warnf("Call %s error:%v", fullURL, err) if err != nil {
f.sugarLogger.Warnf("Call %s error:%v", fullURL, err)
}
} }
return nil return err
} }
// jd api
func (f *FreshFoodAPI) NewJDOrder(jdorder *models.Jdorder) error { func (f *FreshFoodAPI) NewJDOrder(jdorder *models.Jdorder) error {
params := make(url.Values) params := make(url.Values)
params.Set(URL_FRESHFOOD_PARA_JDORDER, string(utils.MustMarshal(jdorder))) params.Set(URL_FRESHFOOD_PARA_JDORDER, string(utils.MustMarshal(jdorder)))
@@ -57,9 +72,9 @@ func (f *FreshFoodAPI) NewJDOrder(jdorder *models.Jdorder) error {
} }
// todo venderId // todo venderId
func (f *FreshFoodAPI) JDOrderStatus(jdorder *models.Jdorder, venderId string) error { func (f *FreshFoodAPI) JDOrderStatus(jdorder *models.Jdorder) error {
params := make(url.Values) params := make(url.Values)
params.Set(URL_FRESHFOOD_PARA_VENDERID, venderId) params.Set(URL_FRESHFOOD_PARA_VENDERID, utils.Int2Str(JD_VENDERID))
params.Set(URL_FRESHFOOD_PARA_ORDERID, utils.Int64ToStr(jdorder.JdOrderId)) params.Set(URL_FRESHFOOD_PARA_ORDERID, utils.Int64ToStr(jdorder.JdOrderId))
params.Set(URL_FRESHFOOD_PARA_ORDERSTATUS, utils.Int2Str(jdorder.OrderStatus)) params.Set(URL_FRESHFOOD_PARA_ORDERSTATUS, utils.Int2Str(jdorder.OrderStatus))
params.Set(URL_FRESHFOOD_PARA_ORDERSTATUSTIME, jdorder.OrderStatusTime) params.Set(URL_FRESHFOOD_PARA_ORDERSTATUSTIME, jdorder.OrderStatusTime)
@@ -68,11 +83,11 @@ func (f *FreshFoodAPI) JDOrderStatus(jdorder *models.Jdorder, venderId string) e
return f.AccessFreshFodd("order/status", params) return f.AccessFreshFodd("order/status", params)
} }
func (f *FreshFoodAPI) JDOrderDeliveryStatus(jdOrderDeliveryStatusMsg *jdapi.JDDeliveryStatusMsg, venderId string) error { func (f *FreshFoodAPI) JDOrderDeliveryStatus(jdOrderDeliveryStatusMsg *jdapi.JDDeliveryStatusMsg) error {
params := make(url.Values) params := make(url.Values)
cityName := "all" cityName := "all"
params.Set(URL_FRESHFOOD_PARA_VENDERID, venderId) params.Set(URL_FRESHFOOD_PARA_VENDERID, utils.Int2Str(JD_VENDERID))
params.Set(URL_FRESHFOOD_PARA_ORDERID, jdOrderDeliveryStatusMsg.OrderId) params.Set(URL_FRESHFOOD_PARA_ORDERID, jdOrderDeliveryStatusMsg.OrderId)
params.Set(URL_FRESHFOOD_PARA_DELIVERYSTATUS, utils.Int2Str(jdOrderDeliveryStatusMsg.DeliveryStatus)) params.Set(URL_FRESHFOOD_PARA_DELIVERYSTATUS, utils.Int2Str(jdOrderDeliveryStatusMsg.DeliveryStatus))
params.Set(URL_FRESHFOOD_PARA_DLIVERYSTATUSTIME, jdOrderDeliveryStatusMsg.DeliveryStatusTime) params.Set(URL_FRESHFOOD_PARA_DLIVERYSTATUSTIME, jdOrderDeliveryStatusMsg.DeliveryStatusTime)
@@ -87,3 +102,22 @@ func (f *FreshFoodAPI) JDOrderDeliveryStatus(jdOrderDeliveryStatusMsg *jdapi.JDD
return f.AccessFreshFodd("delivery/status", params) return f.AccessFreshFodd("delivery/status", params)
} }
// elm api
func (f *FreshFoodAPI) NewELMOrder(order map[string]interface{}) error {
str := string(utils.MustMarshal(order))
params := make(url.Values)
params.Set(URL_FRESHFOOD_PARA_ELEMEORDER, str)
return f.AccessFreshFodd("order/eleme", params)
}
func (f *FreshFoodAPI) ELMOrderStatus(orderId string, status int, timestamp int64) error {
params := make(url.Values)
params.Set(URL_FRESHFOOD_PARA_VENDERID, utils.Int2Str(ELM_VENDERID))
params.Set(URL_FRESHFOOD_PARA_ORDERID, orderId)
params.Set(URL_FRESHFOOD_PARA_ORDERSTATUS, utils.Int2Str(status))
params.Set(URL_FRESHFOOD_PARA_ORDERSTATUSTIME, utils.Timestamp2Str(timestamp))
return f.AccessFreshFodd("order/status", params)
}

View File

@@ -2,9 +2,7 @@ package controller
import ( import (
"git.rosy.net.cn/baseapi/platform/jdapi" "git.rosy.net.cn/baseapi/platform/jdapi"
"git.rosy.net.cn/jx-callback/business/jd/models"
"git.rosy.net.cn/jx-callback/globals" "git.rosy.net.cn/jx-callback/globals"
"github.com/astaxie/beego/orm"
"go.uber.org/zap" "go.uber.org/zap"
) )
@@ -16,18 +14,6 @@ var (
func init() { func init() {
sugarLogger = globals.SugarLogger sugarLogger = globals.SugarLogger
logger := sugarLogger.Desugar() gJdapi = jdapi.NewJDAPI("91633f2a-c5f5-4982-a925-a220d19095c3", "1dba76d40cac446ca500c0391a0b6c9d", "a88d031a1e7b462cb1579f12e97fe7f4", sugarLogger)
gJdapi = jdapi.NewJDAPI("91633f2a-c5f5-4982-a925-a220d19095c3", "1dba76d40cac446ca500c0391a0b6c9d", "a88d031a1e7b462cb1579f12e97fe7f4", logger)
// set default database
orm.RegisterDataBase("default", "mysql", "root:WebServer@1@tcp(127.0.0.1:3306)/jx-callback?charset=utf8&loc=Local", 30)
// register model
orm.RegisterModel(new(models.Jdorder))
// create table
orm.RunSyncdb("default", false, true)
initOrder() initOrder()
} }

View File

@@ -5,11 +5,10 @@ import (
"git.rosy.net.cn/baseapi/platform/jdapi" "git.rosy.net.cn/baseapi/platform/jdapi"
"git.rosy.net.cn/baseapi/utils" "git.rosy.net.cn/baseapi/utils"
"git.rosy.net.cn/jx-callback/business/freshfood"
"git.rosy.net.cn/jx-callback/business/jd/models" "git.rosy.net.cn/jx-callback/business/jd/models"
"git.rosy.net.cn/jx-callback/compat/corm" "git.rosy.net.cn/jx-callback/compat/corm"
"git.rosy.net.cn/jx-callback/globals"
"github.com/astaxie/beego/orm" "github.com/astaxie/beego/orm"
_ "github.com/go-sql-driver/mysql" // import your used driver
) )
const ( const (
@@ -19,18 +18,13 @@ const (
var ( var (
errChecker corm.DBErrorChecker errChecker corm.DBErrorChecker
orderMsgChan chan *jdapi.JDOrderMsg orderMsgChan chan *jdapi.JDOrderMsg
// freshFoodServerURL = "http://portal.jingxicaishi.com"
freshFoodServerURL = "http://test.jxc4.com"
freshFoodAPI *freshfood.FreshFoodAPI
) )
type OrderControler struct { type OrderController struct {
} }
func initOrder() { func initOrder() {
errChecker = new(corm.MysqlErrorChecker) errChecker = new(corm.MysqlErrorChecker)
freshFoodAPI = freshfood.NewFreshFoodAPI(freshFoodServerURL, sugarLogger.Desugar())
orderMsgChan = make(chan *jdapi.JDOrderMsg, 128) orderMsgChan = make(chan *jdapi.JDOrderMsg, 128)
go orderMsgHandlerRoutinue() go orderMsgHandlerRoutinue()
@@ -86,7 +80,7 @@ func handleOrderMsg(orderMsg *jdapi.JDOrderMsg) {
} }
// -------------- // --------------
func (c *OrderControler) OrderStatus(order *jdapi.JDOrderMsg) *jdapi.JDOrderMsgResponse { func (c *OrderController) OrderStatus(order *jdapi.JDOrderMsg) *jdapi.JDOrderMsgResponse {
if order.StatusId != jdapi.JdOrderStatusNew && order.StatusId != jdapi.JdOrderStatusAdjust { if order.StatusId != jdapi.JdOrderStatusNew && order.StatusId != jdapi.JdOrderStatusAdjust {
err := normalOrderStatus(order) err := normalOrderStatus(order)
if err != nil { if err != nil {
@@ -137,8 +131,8 @@ func (c *OrderControler) OrderStatus(order *jdapi.JDOrderMsg) *jdapi.JDOrderMsgR
return jdSuccessResponse return jdSuccessResponse
} }
func (c *OrderControler) OrderDeliveryStatus(jdOrderDeliveryStatusMsg *jdapi.JDDeliveryStatusMsg) *jdapi.JDOrderMsgResponse { func (c *OrderController) OrderDeliveryStatus(jdOrderDeliveryStatusMsg *jdapi.JDDeliveryStatusMsg) *jdapi.JDOrderMsgResponse {
err := freshFoodAPI.JDOrderDeliveryStatus(jdOrderDeliveryStatusMsg, "0") err := globals.FreshFoodAPI.JDOrderDeliveryStatus(jdOrderDeliveryStatusMsg)
if err != nil { if err != nil {
sugarLogger.Errorf("Error when calling JDOrderDeliveryStatus, error:%v", err) sugarLogger.Errorf("Error when calling JDOrderDeliveryStatus, error:%v", err)
@@ -159,7 +153,7 @@ func newOrder(order *jdapi.JDOrderMsg) error {
result, err := gJdapi.LegacyQuerySingleOrder(order.BillId) result, err := gJdapi.LegacyQuerySingleOrder(order.BillId)
acceptOrder(order) acceptOrder(order)
if err != nil { if err != nil {
sugarLogger.Warnf("error when query jd order:%s, error:%v", order.BillId, err) sugarLogger.Errorf("error when query jd order:%s, error:%v", order.BillId, err)
} else { } else {
rec := &models.Jdorder{ rec := &models.Jdorder{
Id: order.Id, Id: order.Id,
@@ -186,9 +180,9 @@ func newOrder(order *jdapi.JDOrderMsg) error {
rec.OrderStatus = int(orderStatus) rec.OrderStatus = int(orderStatus)
rec.OrderStatusTime = resultList0["orderStatusTime"].(string) rec.OrderStatusTime = resultList0["orderStatusTime"].(string)
resultByteArr, _ := json.Marshal(data) resultByteArr := utils.MustMarshal(data)
rec.Data = string(resultByteArr) rec.Data = string(resultByteArr)
err = freshFoodAPI.NewJDOrder(rec) err = globals.FreshFoodAPI.NewJDOrder(rec)
if err == nil { if err == nil {
db := orm.NewOrm() db := orm.NewOrm()
_, err = db.Update(rec, "Data", "Code", "Msg", "Success", "CityName", "OrderStatus", "OrderStatusTime") _, err = db.Update(rec, "Data", "Code", "Msg", "Success", "CityName", "OrderStatus", "OrderStatusTime")
@@ -228,9 +222,8 @@ func normalOrderStatus(order *jdapi.JDOrderMsg) error {
rec.OrderStatus = utils.Str2Int(order.StatusId) rec.OrderStatus = utils.Str2Int(order.StatusId)
rec.OrderStatusTime = order.Timestamp rec.OrderStatusTime = order.Timestamp
err = freshFoodAPI.JDOrderStatus(rec, "0") err = globals.FreshFoodAPI.JDOrderStatus(rec)
if err != nil { if err != nil {
// todo 这里应该要加一个重试机制
sugarLogger.Warnf("access freshfood failed, error:%v", err) sugarLogger.Warnf("access freshfood failed, error:%v", err)
return err return err
} }

40
controllers/elm_order.go Normal file
View File

@@ -0,0 +1,40 @@
package controllers
import (
"encoding/json"
"git.rosy.net.cn/baseapi/platform/elmapi"
"git.rosy.net.cn/jx-callback/business/elm/controller"
"git.rosy.net.cn/jx-callback/globals"
"github.com/astaxie/beego"
)
// Operations about ELMOrder
type ELMOrderController struct {
beego.Controller
}
func (c *ELMOrderController) URLMapping() {
c.Mapping("Msg", c.Msg)
}
// @Title all msg
// @Description create object
// @Param jd_param_json formData string true "应用级别输入参数"
// @Success 200 {string} models.Object.Id
// @Failure 403 body is empty
// @router /msg [post]
func (c *ELMOrderController) Msg() {
var obj elmapi.ELMCallbackMsg
jdParamJSON := c.Ctx.Input.RequestBody
err := json.Unmarshal([]byte(jdParamJSON), &obj)
if err != nil {
globals.SugarLogger.Warnf("error when Unmarshal data:%v, error:%v", jdParamJSON, err)
c.Data["json"] = elmapi.ELMCallbackResponse{Message: "failed"}
} else {
cc := &controller.OrderController{}
c.Data["json"] = cc.OrderMessage(&obj)
}
c.ServeJSON()
}

View File

@@ -43,7 +43,7 @@ func (c *JDOrderController) handleJDCallback(obj interface{}, needUnescape bool,
func (c *JDOrderController) orderStatus() { func (c *JDOrderController) orderStatus() {
var ob jdapi.JDOrderMsg var ob jdapi.JDOrderMsg
c.handleJDCallback(&ob, false, func() interface{} { c.handleJDCallback(&ob, false, func() interface{} {
cc := controller.OrderControler{} cc := controller.OrderController{}
return cc.OrderStatus(&ob) return cc.OrderStatus(&ob)
}) })
} }
@@ -147,7 +147,7 @@ func (c *JDOrderController) ApplyCancelOrder() {
func (c *JDOrderController) PushDeliveryStatus() { func (c *JDOrderController) PushDeliveryStatus() {
var ob jdapi.JDDeliveryStatusMsg var ob jdapi.JDDeliveryStatusMsg
c.handleJDCallback(&ob, true, func() interface{} { c.handleJDCallback(&ob, true, func() interface{} {
cc := controller.OrderControler{} cc := controller.OrderController{}
return cc.OrderDeliveryStatus(&ob) return cc.OrderDeliveryStatus(&ob)
}) })
} }

View File

@@ -1,14 +1,22 @@
package globals package globals
import ( import (
"git.rosy.net.cn/jx-callback/business/freshfood"
"go.uber.org/zap" "go.uber.org/zap"
) )
const (
freshFoodServerURL = "http://test.jxc4.com"
)
var ( var (
SugarLogger *zap.SugaredLogger SugarLogger *zap.SugaredLogger
// freshFoodServerURL = "http://portal.jingxicaishi.com"
FreshFoodAPI *freshfood.FreshFoodAPI
) )
func init() { func init() {
logger, _ := zap.NewDevelopment() logger, _ := zap.NewDevelopment()
SugarLogger = logger.Sugar() SugarLogger = logger.Sugar()
FreshFoodAPI = freshfood.NewFreshFoodAPI(freshFoodServerURL, SugarLogger)
} }

View File

@@ -1,8 +1,8 @@
package main package main
import ( import (
_ "git.rosy.net.cn/jx-callback/business"
_ "git.rosy.net.cn/jx-callback/routers" _ "git.rosy.net.cn/jx-callback/routers"
"github.com/astaxie/beego" "github.com/astaxie/beego"
) )

View File

@@ -19,5 +19,10 @@ func init() {
&controllers.JDOrderController{}, &controllers.JDOrderController{},
), ),
) )
beego.AddNamespace(ns) ns2 := beego.NewNamespace("/elem",
beego.NSInclude(
&controllers.ELMOrderController{},
),
)
beego.AddNamespace(ns, ns2)
} }