Merge remote-tracking branch 'origin/mark' into lcw

This commit is contained in:
renyutian
2019-04-28 15:36:24 +08:00
44 changed files with 914 additions and 245 deletions

View File

@@ -49,8 +49,9 @@ func (a *Auther) SendVerifyCode(mobileNumber string) error {
response, err := smsClient.Execute(globals.AliKey, globals.AliSecret, mobileNumber, "京西菜市", "SMS_84655036", string(utils.MustMarshal(map[string]interface{}{ response, err := smsClient.Execute(globals.AliKey, globals.AliSecret, mobileNumber, "京西菜市", "SMS_84655036", string(utils.MustMarshal(map[string]interface{}{
"code": code, "code": code,
}))) })))
a.SaveVerifyCode(mobileNumber, code)
if err == nil && response.Code == aliyunsmsclient.ResponseCodeOk { if err == nil && response.Code == aliyunsmsclient.ResponseCodeOk {
a.SaveVerifyCode(mobileNumber, code) // a.SaveVerifyCode(mobileNumber, code)
} else { } else {
if err == nil { if err == nil {
if warningMap[response.Code] == 1 { if warningMap[response.Code] == 1 {

View File

@@ -87,7 +87,7 @@ func GetWeiXinUserInfo(code string, state string) (userInfo *UserInfoExt, err er
SNSUserInfo: *wxUserinfo, SNSUserInfo: *wxUserinfo,
TempPassword: utils.GetUUID(), TempPassword: utils.GetUUID(),
} }
globals.SugarLogger.Debugf("GetUserInfo code:%s, pwd:%s", code, userInfo.TempPassword) globals.SugarLogger.Debugf("GetUserInfo code:%s, userInfo:%s", code, utils.Format4Output(userInfo, true))
cacheSNSInfo(wxUserinfo, userInfo.TempPassword, DefTempPasswordDuration) cacheSNSInfo(wxUserinfo, userInfo.TempPassword, DefTempPasswordDuration)
user, err2 := dao.GetWeiXinUserByIDs(dao.GetDB(), "", wxUserinfo.UnionID, wxUserinfo.OpenID, "") user, err2 := dao.GetWeiXinUserByIDs(dao.GetDB(), "", wxUserinfo.UnionID, wxUserinfo.OpenID, "")
if err = err2; err == nil { if err = err2; err == nil {

View File

@@ -346,6 +346,7 @@ func (c *OrderManager) updateOrderOtherInfo(order *model.GoodsOrder, db *dao.Dao
} }
func (c *OrderManager) addOrderStatus(orderStatus *model.OrderStatus, db *dao.DaoDB) (isDuplicated bool, order *model.GoodsOrder, err error) { func (c *OrderManager) addOrderStatus(orderStatus *model.OrderStatus, db *dao.DaoDB) (isDuplicated bool, order *model.GoodsOrder, err error) {
globals.SugarLogger.Debugf("addOrderStatus refOrderID:%s, orderID:%s", orderStatus.RefVendorOrderID, orderStatus.VendorOrderID)
if db == nil { if db == nil {
db = dao.GetDB() db = dao.GetDB()
} }
@@ -359,24 +360,30 @@ func (c *OrderManager) addOrderStatus(orderStatus *model.OrderStatus, db *dao.Da
if (model.IsOrderLockStatus(orderStatus.Status) || model.IsOrderUnlockStatus(orderStatus.Status)) || if (model.IsOrderLockStatus(orderStatus.Status) || model.IsOrderUnlockStatus(orderStatus.Status)) ||
(model.IsOrderMainStatus(orderStatus.Status) && orderStatus.Status >= order.Status) { // todo 要求status不能回绕 (model.IsOrderMainStatus(orderStatus.Status) && orderStatus.Status >= order.Status) { // todo 要求status不能回绕
order.VendorStatus = orderStatus.VendorStatus order.VendorStatus = orderStatus.VendorStatus
order.StatusTime = orderStatus.StatusTime
updateFields := []string{ updateFields := []string{
"VendorStatus", "StatusTime", "VendorStatus",
} }
if model.IsOrderMainStatus(orderStatus.Status) { if model.IsOrderMainStatus(orderStatus.Status) {
order.LockStatus = model.OrderStatusUnknown
order.Status = orderStatus.Status order.Status = orderStatus.Status
updateFields = append(updateFields, "Status", "LockStatus") order.StatusTime = orderStatus.StatusTime
updateFields = append(updateFields, "Status", "StatusTime")
if order.LockStatus != model.OrderStatusUnknown {
order.LockStatus = model.OrderStatusUnknown
order.LockStatusTime = orderStatus.StatusTime
updateFields = append(updateFields, "LockStatus", "LockStatusTime")
}
} else { } else {
if model.IsOrderUnlockStatus(orderStatus.Status) { if model.IsOrderUnlockStatus(orderStatus.Status) {
order.LockStatus = model.OrderStatusUnknown order.LockStatus = model.OrderStatusUnknown
updateFields = append(updateFields, "LockStatus") } else {
} else if model.IsOrderLockStatus(orderStatus.Status) { if order.LockStatus != model.OrderStatusUnknown {
globals.SugarLogger.Warnf("addOrderStatus refOrderID:%s, orderID:%s, order.LockStatus:%d, status.LockStatus:%d", orderStatus.RefVendorOrderID, orderStatus.VendorOrderID, order.LockStatus, orderStatus.Status)
}
order.LockStatus = orderStatus.Status order.LockStatus = orderStatus.Status
updateFields = append(updateFields, "LockStatus")
} }
order.LockStatusTime = orderStatus.StatusTime
updateFields = append(updateFields, "LockStatus", "LockStatusTime")
} }
// orderStatus.LockStatus = order.LockStatus
if model.IsOrderFinalStatus(orderStatus.Status) { if model.IsOrderFinalStatus(orderStatus.Status) {
order.OrderFinishedAt = orderStatus.StatusTime order.OrderFinishedAt = orderStatus.StatusTime
updateFields = append(updateFields, "OrderFinishedAt") updateFields = append(updateFields, "OrderFinishedAt")

View File

@@ -133,6 +133,13 @@ func (c *BaseScheduler) AcceptOrRefuseFailedGetOrder(ctx *jxcontext.Context, ord
if c.IsReallyCallPlatformAPI { if c.IsReallyCallPlatformAPI {
err = partner.GetPurchasePlatformFromVendorID(order.VendorID).AcceptOrRefuseFailedGetOrder(ctx, order, isAcceptIt) err = partner.GetPurchasePlatformFromVendorID(order.VendorID).AcceptOrRefuseFailedGetOrder(ctx, order, isAcceptIt)
} }
if err == nil {
flag := int8(model.OrderFlagAgreeFailedGetGoods)
if !isAcceptIt {
flag = model.OrderFlagRefuseFailedGetGoods
}
dao.SetOrderFlag(dao.GetDB(), ctx.GetUserName(), order.VendorOrderID, order.VendorID, flag)
}
return err return err
} }
@@ -140,6 +147,9 @@ func (c *BaseScheduler) CallPMCourier(ctx *jxcontext.Context, order *model.Goods
if c.IsReallyCallPlatformAPI { if c.IsReallyCallPlatformAPI {
err = partner.GetPurchasePlatformFromVendorID(order.VendorID).CallCourier(ctx, order) err = partner.GetPurchasePlatformFromVendorID(order.VendorID).CallCourier(ctx, order)
} }
if err == nil {
dao.SetOrderFlag(dao.GetDB(), ctx.GetUserName(), order.VendorOrderID, order.VendorID, model.OrderFlagMaskCallPMCourier)
}
return err return err
} }
@@ -147,6 +157,9 @@ func (c *BaseScheduler) ConfirmReceiveGoods(ctx *jxcontext.Context, order *model
if c.IsReallyCallPlatformAPI { if c.IsReallyCallPlatformAPI {
err = partner.GetPurchasePlatformFromVendorID(order.VendorID).ConfirmReceiveGoods(ctx, order) err = partner.GetPurchasePlatformFromVendorID(order.VendorID).ConfirmReceiveGoods(ctx, order)
} }
if err == nil {
dao.SetOrderFlag(dao.GetDB(), ctx.GetUserName(), order.VendorOrderID, order.VendorID, model.OrderFlagMaskFailedDeliver)
}
return err return err
} }
@@ -154,5 +167,12 @@ func (c *BaseScheduler) AgreeOrRefuseCancel(ctx *jxcontext.Context, order *model
if c.IsReallyCallPlatformAPI { if c.IsReallyCallPlatformAPI {
err = partner.GetPurchasePlatformFromVendorID(order.VendorID).AgreeOrRefuseCancel(ctx, order, isAcceptIt, reason) err = partner.GetPurchasePlatformFromVendorID(order.VendorID).AgreeOrRefuseCancel(ctx, order, isAcceptIt, reason)
} }
if err == nil {
flag := int8(model.OrderFlagAgreeUserApplyCancel)
if !isAcceptIt {
flag = model.OrderFlagRefuseUserApplyCancel
}
dao.SetOrderFlag(dao.GetDB(), ctx.GetUserName(), order.VendorOrderID, order.VendorID, flag)
}
return err return err
} }

View File

@@ -113,11 +113,12 @@ func (s *WatchOrderInfo) updateOrderStoreFeature(order *model.GoodsOrder) (err e
} }
s.autoPickupTimeoutMinute = int(storeMap.AutoPickup) s.autoPickupTimeoutMinute = int(storeMap.AutoPickup)
s.storeDeliveryType = FixedScheduler.GetStoreDeliveryType(order, storeMap) s.storeDeliveryType = FixedScheduler.GetStoreDeliveryType(order, storeMap)
if s.storeDeliveryType == scheduler.StoreDeliveryTypeByStore && (order.DeliveryFlag&model.OrderDeliveryFlagMaskPurcahseDisabled) == 0 { globals.SugarLogger.Debugf("updateOrderStoreFeature orderID:%s, s.storeDeliveryType:%d", order.VendorOrderID, s.storeDeliveryType)
order.DeliveryFlag |= model.OrderDeliveryFlagMaskPurcahseDisabled // if s.storeDeliveryType == scheduler.StoreDeliveryTypeByStore && (order.DeliveryFlag&model.OrderDeliveryFlagMaskPurcahseDisabled) == 0 {
err = partner.CurOrderManager.UpdateOrderStatusAndFlag(order) // order.DeliveryFlag |= model.OrderDeliveryFlagMaskPurcahseDisabled
} // err = partner.CurOrderManager.UpdateOrderStatusAndFlag(order)
globals.SugarLogger.Debugf("updateOrderStoreFeature orderID:%s, s.storeDeliveryType:%d, order.DeliveryFlag:%d", order.VendorOrderID, s.storeDeliveryType, order.DeliveryFlag) // }
// globals.SugarLogger.Debugf("updateOrderStoreFeature orderID:%s, s.storeDeliveryType:%d, order.DeliveryFlag:%d", order.VendorOrderID, s.storeDeliveryType, order.DeliveryFlag)
} }
return err return err
} }
@@ -409,20 +410,7 @@ func (s *DefScheduler) OnWaybillStatusChanged(bill *model.Waybill, isPending boo
// s.ProxyCancelWaybill(order, bill, partner.CancelWaybillReasonNotAcceptIntime, partner.CancelWaybillReasonStrNotAcceptIntime) // s.ProxyCancelWaybill(order, bill, partner.CancelWaybillReasonNotAcceptIntime, partner.CancelWaybillReasonStrNotAcceptIntime)
globals.SugarLogger.Infof("OnWaybillStatusChanged CourierArrived order(%d, %s) bill(%d, %s), bill:%v shouldn't get here", order.WaybillVendorID, order.VendorWaybillID, bill.WaybillVendorID, bill.VendorWaybillID, bill) globals.SugarLogger.Infof("OnWaybillStatusChanged CourierArrived order(%d, %s) bill(%d, %s), bill:%v shouldn't get here", order.WaybillVendorID, order.VendorWaybillID, bill.WaybillVendorID, bill.VendorWaybillID, bill)
} }
case model.WaybillStatusFailed: // todo WaybillStatusFailed理解成订单整个失败了不需要再尝试创建运单了注意这里应该加个zabbix日志的报警 case model.WaybillStatusCanceled, model.WaybillStatusFailed:
s.removeWaybillFromMap(savedOrderInfo, bill.WaybillVendorID)
if s.isBillCandidate(order, bill) {
s.resetTimer(savedOrderInfo, bill, isPending)
if !isPending {
globals.SugarLogger.Infof("OnWaybillStatusChanged WaybillStatusFailed, bill:%v", bill)
bill.WaybillVendorID = model.VendorIDUnknown
s.updateOrderByBill(order, bill, false)
}
} else {
// 创建运单失败时可能到这里来比如818874313000121
globals.SugarLogger.Infof("OnWaybillStatusChanged Failed bill:%v shouldn't got here, order details:%v", bill, order)
}
case model.WaybillStatusCanceled:
s.removeWaybillFromMap(savedOrderInfo, bill.WaybillVendorID) s.removeWaybillFromMap(savedOrderInfo, bill.WaybillVendorID)
if s.isBillCandidate(order, bill) || order.WaybillVendorID == model.VendorIDUnknown { if s.isBillCandidate(order, bill) || order.WaybillVendorID == model.VendorIDUnknown {
s.resetTimer(savedOrderInfo, nil, isPending) s.resetTimer(savedOrderInfo, nil, isPending)

View File

@@ -54,6 +54,7 @@ func InitServiceInfo(version string, buildTime time.Time, gitCommit string) {
"storeMsgSendStatusName": model.StoreMsgSendStatusName, "storeMsgSendStatusName": model.StoreMsgSendStatusName,
"shopChineseNames": model.ShopChineseNames, "shopChineseNames": model.ShopChineseNames,
"printerVendorInfo": model.PrinterVendorInfo, "printerVendorInfo": model.PrinterVendorInfo,
"purchaseVendorInfo": model.PurchaseVendorInfo,
}, },
} }
Init() Init()

View File

@@ -63,7 +63,7 @@ func (s *StoreManager) OnStoreStatusChanged(vendorStoreID string, vendorID int,
} }
}() }()
if storeKV != nil { if storeKV != nil {
globals.SugarLogger.Debugf("OnStoreStatusChanged venvendorStoreID:%s, storeKV:%d", vendorStoreID, utils.Format4Output(storeKV, true)) globals.SugarLogger.Debugf("OnStoreStatusChanged venvendorStoreID:%s, storeKV:%s", vendorStoreID, utils.Format4Output(storeKV, true))
store := &model.Store{} store := &model.Store{}
store.ID = storeDetail.Store.ID store.ID = storeDetail.Store.ID
if err = utils.CallFuncLogError(func() error { if err = utils.CallFuncLogError(func() error {
@@ -74,7 +74,7 @@ func (s *StoreManager) OnStoreStatusChanged(vendorStoreID string, vendorID int,
} }
} }
if storeMapKV != nil { if storeMapKV != nil {
globals.SugarLogger.Debugf("OnStoreStatusChanged venvendorStoreID:%s, storeMapKV:%d", vendorStoreID, utils.Format4Output(storeMapKV, true)) globals.SugarLogger.Debugf("OnStoreStatusChanged venvendorStoreID:%s, storeMapKV:%s", vendorStoreID, utils.Format4Output(storeMapKV, true))
if err = utils.CallFuncLogError(func() error { if err = utils.CallFuncLogError(func() error {
_, err = dao.UpdateEntityLogically(db, &model.StoreMap{}, storeMapKV, model.AdminName, map[string]interface{}{ _, err = dao.UpdateEntityLogically(db, &model.StoreMap{}, storeMapKV, model.AdminName, map[string]interface{}{
model.FieldStoreID: storeDetail.Store.ID, model.FieldStoreID: storeDetail.Store.ID,

View File

@@ -242,13 +242,28 @@ func (v *VendorSync) SyncStore(ctx *jxcontext.Context, db *dao.DaoDB, vendorID,
} }
func (v *VendorSync) SyncSku(ctx *jxcontext.Context, db *dao.DaoDB, nameID, skuID int, isAsync, isContinueWhenError bool, userName string) (hint string, err error) { func (v *VendorSync) SyncSku(ctx *jxcontext.Context, db *dao.DaoDB, nameID, skuID int, isAsync, isContinueWhenError bool, userName string) (hint string, err error) {
globals.SugarLogger.Debugf("SyncSku trackInfo:%s, nameID:%d, skuID:%d, userName:%s", ctx.GetTrackInfo(), nameID, skuID, userName) var (
return v.LoopMultiStoresVendors(ctx, db, fmt.Sprintf("同步商品信息, nameID:%d, skuID:%d", nameID, skuID), isAsync, userName, nameIDs []int
skuIDs []int
)
if nameID != -1 {
nameIDs = []int{nameID}
}
if skuID != -1 {
skuIDs = []int{skuID}
}
return v.SyncSkus(ctx, db, nameIDs, skuIDs, isAsync, isContinueWhenError, userName)
}
func (v *VendorSync) SyncSkus(ctx *jxcontext.Context, db *dao.DaoDB, nameIDs []int, skuIDs []int, isAsync, isContinueWhenError bool, userName string) (hint string, err error) {
globals.SugarLogger.Debugf("SyncSku trackInfo:%s, nameIDs:%v, skuIDs:%v, userName:%s", ctx.GetTrackInfo(), nameIDs, skuIDs, userName)
return v.LoopMultiStoresVendors(ctx, db, fmt.Sprintf("同步商品信息, nameIDs:%v, skuIDs:%v", nameIDs, skuIDs), isAsync, userName,
func(t *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (interface{}, error) { func(t *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (interface{}, error) {
vendorID := batchItemList[0].(int) vendorID := batchItemList[0].(int)
multiStoresHandler := v.GetMultiStoreHandler(vendorID) multiStoresHandler := v.GetMultiStoreHandler(vendorID)
syncStatusFieldName := dao.GetSyncStatusStructField(model.VendorNames[multiStoresHandler.GetVendorID()]) syncStatusFieldName := dao.GetSyncStatusStructField(model.VendorNames[multiStoresHandler.GetVendorID()])
dbField := dao.ConvertDBFieldPrefix(model.VendorNames[multiStoresHandler.GetVendorID()]) dbField := dao.ConvertDBFieldPrefix(model.VendorNames[multiStoresHandler.GetVendorID()])
skuMap := make(map[int]bool)
sql := fmt.Sprintf(` sql := fmt.Sprintf(`
SELECT DISTINCT t2.* SELECT DISTINCT t2.*
FROM sku t1 FROM sku t1
@@ -256,14 +271,23 @@ func (v *VendorSync) SyncSku(ctx *jxcontext.Context, db *dao.DaoDB, nameID, skuI
WHERE t1.%s_sync_status <> 0 WHERE t1.%s_sync_status <> 0
`, dbField) `, dbField)
sqlParams := []interface{}{} sqlParams := []interface{}{}
if nameID != -1 { if len(nameIDs) > 1 {
sql += " AND t1.name_id = ?" sql += " AND t1.name_id IN (" + dao.GenQuestionMarks(len(nameIDs)) + ")"
sqlParams = append(sqlParams, nameID) sqlParams = append(sqlParams, nameIDs)
} else if len(nameIDs) == 1 {
sql += " AND t1.name_id = ? "
sqlParams = append(sqlParams, nameIDs[0])
} }
if skuID != -1 { if len(skuIDs) > 0 {
sql += " AND t1.id = ?" sql += " AND t1.id IN(" + dao.GenQuestionMarks(len(skuIDs)) + ")"
sqlParams = append(sqlParams, skuID) sqlParams = append(sqlParams, skuIDs)
} else if len(skuIDs) == 1 {
sql += " AND t1.id = ? "
sqlParams = append(sqlParams, skuIDs[0])
}
for _, v := range skuIDs {
skuMap[v] = true
} }
sql += " ORDER BY t2.id" sql += " ORDER BY t2.id"
@@ -284,7 +308,7 @@ func (v *VendorSync) SyncSku(ctx *jxcontext.Context, db *dao.DaoDB, nameID, skuI
for _, sku := range skuList { for _, sku := range skuList {
syncStatus := refutil.GetObjFieldByName(sku, syncStatusFieldName).(int8) syncStatus := refutil.GetObjFieldByName(sku, syncStatusFieldName).(int8)
globals.SugarLogger.Debugf("SyncSku trackInfo:%s, skuID:%d, syncStatus:%d", ctx.GetTrackInfo(), sku.ID, syncStatus) globals.SugarLogger.Debugf("SyncSku trackInfo:%s, skuID:%d, syncStatus:%d", ctx.GetTrackInfo(), sku.ID, syncStatus)
if (skuID == -1 || skuID == sku.ID) && (syncStatus != 0) { if (len(skuIDs) == 0 || skuMap[sku.ID]) && (syncStatus != 0) {
updateFields := []string{syncStatusFieldName} updateFields := []string{syncStatusFieldName}
if syncStatus&model.SyncFlagDeletedMask != 0 { // 删除 if syncStatus&model.SyncFlagDeletedMask != 0 { // 删除
if syncStatus&model.SyncFlagNewMask == 0 { if syncStatus&model.SyncFlagNewMask == 0 {
@@ -543,3 +567,26 @@ func isSyncError(err error) bool {
_, ok := err.(*SyncError) _, ok := err.(*SyncError)
return ok return ok
} }
func (v *VendorSync) SyncSkuNames(ctx *jxcontext.Context, nameIDs []int, isForce, isAsync, isContinueWhenError bool) (hint string, err error) {
db := dao.GetDB()
if isForce {
sql := `
UPDATE sku t1
SET t1.jd_sync_status = t1.jd_sync_status | ?
WHERE t1.deleted_at = ?
`
sqlParams := []interface{}{
model.SyncFlagModifiedMask,
utils.DefaultTimeValue,
}
if len(nameIDs) > 0 {
sql += " AND t1.name_id IN(" + dao.GenQuestionMarks(len(nameIDs)) + ")"
sqlParams = append(sqlParams, nameIDs)
}
if _, err = dao.ExecuteSQL(db, sql, sqlParams...); err != nil {
return "", err
}
}
return v.SyncSkus(ctx, db, nameIDs, nil, isAsync, isContinueWhenError, ctx.GetUserName())
}

View File

@@ -46,7 +46,9 @@ func GetStoreUsers(ctx *jxcontext.Context, storeID int) (storeUserInfos []*dao.S
} }
func GetUserInfo(ctx *jxcontext.Context, mobile string) (storeUserInfo *dao.StoreUserInfo, err error) { func GetUserInfo(ctx *jxcontext.Context, mobile string) (storeUserInfo *dao.StoreUserInfo, err error) {
return dao.GetUserStoreInfo(dao.GetDB(), "tel", mobile) storeUserInfo, err = dao.GetUserStoreInfo(dao.GetDB(), "tel", mobile)
globals.SugarLogger.Debugf("GetUserInfo:%s, token:%s, mobile:%s, storeUserInfo:%s, err:%v", ctx.GetTrackInfo(), ctx.GetToken(), mobile, utils.Format4Output(storeUserInfo, true), err)
return storeUserInfo, err
} }
func GetSelfInfo(ctx *jxcontext.Context) (storeUserInfo *dao.StoreUserInfo, err error) { func GetSelfInfo(ctx *jxcontext.Context) (storeUserInfo *dao.StoreUserInfo, err error) {
@@ -58,7 +60,9 @@ func GetSelfInfo(ctx *jxcontext.Context) (storeUserInfo *dao.StoreUserInfo, err
if fieldName == "" { if fieldName == "" {
return nil, auth.ErrIllegalLoginType return nil, auth.ErrIllegalLoginType
} }
return dao.GetUserStoreInfo(dao.GetDB(), fieldName, loginInfo.GetAuthID()) storeUserInfo, err = dao.GetUserStoreInfo(dao.GetDB(), fieldName, loginInfo.GetAuthID())
globals.SugarLogger.Debugf("GetSelfInfo:%s, token:%s, storeUserInfo:%s, err:%v", ctx.GetTrackInfo(), ctx.GetToken(), utils.Format4Output(storeUserInfo, true), err)
return storeUserInfo, err
} }
func UnbindMobile(ctx *jxcontext.Context, mobile string) (num int64, err error) { func UnbindMobile(ctx *jxcontext.Context, mobile string) (num int64, err error) {

View File

@@ -73,14 +73,14 @@ func SendFilesToStores(ctx *jxcontext.Context, files []*multipart.FileHeader, ti
db := dao.GetDB() db := dao.GetDB()
billRec := &legacymodel.StoreBill{ billRec := &legacymodel.StoreBill{
Date: time.Now(), Date: time.Now(),
Url: jxutils.ComposeQiniuResURL(ret.Key), Url: jxutils.ComposeQiniuResURL(strings.Replace(ret.Key, "http://", "https://", -1)),
StoreId: storeID, StoreId: storeID,
BillName: fileHeader.Filename, BillName: fileHeader.Filename,
ShopName: shopName, ShopName: shopName,
BillTitle: title, BillTitle: title,
} }
if err = dao.CreateEntity(db, billRec); err == nil { if err = dao.CreateEntity(db, billRec); err == nil {
err = weixinmsg.NotifySaleBill(storeID, title, shopName, "http://www.jxc4.com/billshow/?path="+billRec.Url) err = weixinmsg.NotifySaleBill(storeID, title, shopName, fmt.Sprintf("%s/billshow/?path=%s", globals.BackstageHost, billRec.Url))
if err != nil { if err != nil {
globals.SugarLogger.Infof("SendFilesToStores NotifySaleBill file:%s error:%v", fileHeader.Filename, err) globals.SugarLogger.Infof("SendFilesToStores NotifySaleBill file:%s error:%v", fileHeader.Filename, err)
} }

View File

@@ -9,6 +9,8 @@ import (
"net/http" "net/http"
"strings" "strings"
"git.rosy.net.cn/baseapi/platformapi"
"git.rosy.net.cn/baseapi/platformapi/autonavi" "git.rosy.net.cn/baseapi/platformapi/autonavi"
"git.rosy.net.cn/baseapi/platformapi/jdapi" "git.rosy.net.cn/baseapi/platformapi/jdapi"
"git.rosy.net.cn/baseapi/utils" "git.rosy.net.cn/baseapi/utils"
@@ -153,11 +155,15 @@ func InitSkuName(ctx *jxcontext.Context, isForce, isAsync, isContinueWhenError b
response, err := http.Get(skuName.Img) response, err := http.Get(skuName.Img)
if err == nil { if err == nil {
defer response.Body.Close() defer response.Body.Close()
data, err2 := ioutil.ReadAll(response.Body) if response.StatusCode == http.StatusOK {
if err = err2; err == nil { data, err2 := ioutil.ReadAll(response.Body)
skuName.ImgHashCode = fmt.Sprintf("%X", md5.Sum(data)) if err = err2; err == nil {
db := dao.GetDB() skuName.ImgHashCode = fmt.Sprintf("%X", md5.Sum(data))
_, err = dao.UpdateEntity(db, skuName, "ImgHashCode") db := dao.GetDB()
_, err = dao.UpdateEntity(db, skuName, "ImgHashCode")
}
} else {
err = platformapi.ErrHTTPCodeIsNot200
} }
} }
} }
@@ -423,7 +429,7 @@ func BuildSkuFromEbaiStore(ctx *jxcontext.Context, baiduShopID int64, isAsync, i
err = nil err = nil
continue continue
} }
qiniuImgURL := "http://image.jxc4.com/" + key + "?imageMogr2/thumbnail/x800/gravity/Center/crop/800x800" qiniuImgURL := jxutils.ComposeQiniuResURL(key) + "?imageMogr2/thumbnail/x800/gravity/Center/crop/800x800"
for _, sku := range skuNameExt.Skus { for _, sku := range skuNameExt.Skus {
jdCatID := 22410 // 其他国产水果 jdCatID := 22410 // 其他国产水果
if cat.Name == "进口水果" { if cat.Name == "进口水果" {

View File

@@ -23,7 +23,6 @@ import (
"git.rosy.net.cn/jx-callback/business/partner/purchase/ebai" "git.rosy.net.cn/jx-callback/business/partner/purchase/ebai"
"git.rosy.net.cn/jx-callback/globals" "git.rosy.net.cn/jx-callback/globals"
"git.rosy.net.cn/jx-callback/globals/api" "git.rosy.net.cn/jx-callback/globals/api"
"github.com/astaxie/beego/orm"
) )
var innerDataPat *regexp.Regexp var innerDataPat *regexp.Regexp
@@ -605,8 +604,7 @@ func CreateOrderFromOriginal(ctx *jxcontext.Context, isAsync, isContinueWhenErro
WHERE t2.id IS NULL WHERE t2.id IS NULL
LIMIT ?; LIMIT ?;
` `
rawDB := orm.NewOrm() db := dao.GetDB()
db := dao.WrapDB(rawDB)
var orderList []*GoodsOrderOriginalEx var orderList []*GoodsOrderOriginalEx
if err = dao.GetRows(db, &orderList, sql, sqlBatchCount); err != nil { if err = dao.GetRows(db, &orderList, sql, sqlBatchCount); err != nil {
return nil, err return nil, err

View File

@@ -0,0 +1,262 @@
package eventhub
import (
"fmt"
"strings"
"sync"
"time"
"git.rosy.net.cn/jx-callback/globals"
"git.rosy.net.cn/baseapi/utils"
)
const (
cmdRegisterConsumer = 1
cmdUnregisterConsumer = 2
cmdNewEvent = 3
)
const (
maxGetOrderTimeDuration = 24 * time.Hour
minPollingDuration = 1 * time.Minute
defPollingDuration = 5 * time.Minute
maxPollingDuration = 10 * time.Minute
)
const (
cmdChanLen = 100
)
const (
allEventType = ""
)
type IEventProducer interface {
IsCriteriaMatch(eventInfo *EventInfo, criteria interface{}) bool
}
type EventInfo struct {
Type string
Data interface{}
}
type tRegisterInfo struct {
notifyChan chan *EventInfo
eventCategory string
eventTypeList []string
criteria interface{}
}
type tUnregisterInfo struct {
notifyChan chan *EventInfo
closeChan chan struct{}
}
type tCmd struct {
cmdType int
data interface{}
// regisgerInfo *RegisterInfo // CmdRegisterConsumer
// unregisterInfo *UnregisterInfo // CmdUnregisterConsumer
// eventInfo *EventInfo // CmdNewEvent
}
type EventHub struct {
cmdChan chan *tCmd
chanMap map[chan *EventInfo]*tRegisterInfo
typeChanMap map[string]map[chan *EventInfo]bool
eventCatMap map[string]IEventProducer
locker sync.RWMutex
}
func eventRoutine(eventHub *EventHub) {
eventHub.eventRoutine()
}
func New() (eventHub *EventHub) {
eventHub = &EventHub{
cmdChan: make(chan *tCmd, cmdChanLen),
chanMap: make(map[chan *EventInfo]*tRegisterInfo),
typeChanMap: make(map[string]map[chan *EventInfo]bool),
eventCatMap: make(map[string]IEventProducer),
}
utils.CallFuncAsync(func() {
eventRoutine(eventHub)
})
return eventHub
}
func (e *EventHub) eventRoutine() {
for {
cmd, ok := <-e.cmdChan
if ok {
switch cmd.cmdType {
case cmdRegisterConsumer:
regisgerInfo := cmd.data.(*tRegisterInfo)
e.chanMap[regisgerInfo.notifyChan] = regisgerInfo
for _, eventType := range regisgerInfo.eventTypeList {
if e.typeChanMap[eventType] == nil {
e.typeChanMap[eventType] = make(map[chan *EventInfo]bool)
}
e.typeChanMap[eventType][regisgerInfo.notifyChan] = true
}
case cmdUnregisterConsumer:
unregisgerInfo := cmd.data.(*tUnregisterInfo)
e.removeChan(unregisgerInfo.notifyChan)
close(unregisgerInfo.closeChan)
case cmdNewEvent:
eventInfo := cmd.data.(*EventInfo)
typeList := []string{allEventType, eventInfo.Type}
tmpChanMap := make(map[chan *EventInfo]*tRegisterInfo)
for _, eventType := range typeList {
for notifyChan := range e.typeChanMap[eventType] {
tmpChanMap[notifyChan] = e.chanMap[notifyChan]
}
}
for notifyChan, registerInfo := range tmpChanMap {
eventCategory, _ := splitEventType(eventInfo.Type)
if eventProducer := e.getEventProducer(eventCategory); eventProducer != nil {
if eventProducer.IsCriteriaMatch(eventInfo, registerInfo.criteria) {
notifyChan <- eventInfo
e.removeChan(notifyChan)
}
} else {
globals.SugarLogger.Warnf("eventRoutine, eventCategory:%s producer is nil", eventCategory)
}
}
}
} else {
break
}
}
}
func (e *EventHub) removeChan(notifyChann chan *EventInfo) {
typeList := e.chanMap[notifyChann].eventTypeList
for _, eventType := range typeList {
delete(e.typeChanMap[eventType], notifyChann)
}
delete(e.chanMap, notifyChann)
}
func (e *EventHub) Close() {
close(e.cmdChan)
}
func (e *EventHub) RegisterProducer(eventCategory string, producer IEventProducer) (err error) {
e.locker.Lock()
if e.eventCatMap[eventCategory] != nil {
err = fmt.Errorf("eventCategory:%s已经被注册了", eventCategory)
} else {
e.eventCatMap[eventCategory] = producer
}
e.locker.Unlock()
return err
}
// 正常不应该是动态的经常调用注册与反注册Producer只是退出进程前礼貌的调用
func (e *EventHub) UnregisterProducer(eventCategory string) (err error) {
e.locker.Lock()
if e.eventCatMap[eventCategory] == nil {
err = fmt.Errorf("eventCategory:%s没有注册", eventCategory)
} else {
delete(e.eventCatMap, eventCategory)
}
e.locker.Unlock()
return err
}
func (e *EventHub) registerConsumer(eventCategory string, eventTypeList []string, criteria interface{}) (notifyChan chan *EventInfo) {
if len(eventTypeList) == 0 {
eventTypeList = []string{allEventType}
}
realEventTypeList := make([]string, len(eventTypeList))
for index, eventType := range eventTypeList {
realEventTypeList[index] = composeEventType(eventCategory, eventType)
}
info := &tRegisterInfo{
eventCategory: eventCategory,
eventTypeList: eventTypeList,
notifyChan: make(chan *EventInfo, 1),
criteria: criteria,
}
e.cmdChan <- &tCmd{
cmdType: cmdRegisterConsumer,
data: info,
}
return info.notifyChan
}
func (e *EventHub) unregisterConsumer(notifyChan chan *EventInfo) {
info := &tUnregisterInfo{
notifyChan: notifyChan,
closeChan: make(chan struct{}),
}
e.cmdChan <- &tCmd{
cmdType: cmdUnregisterConsumer,
data: info,
}
<-info.closeChan
}
func (e *EventHub) PostNewEvent(eventCategory string, event *EventInfo) {
utils.CallFuncAsync(func() {
newEvent := *event
newEvent.Type = composeEventType(eventCategory, event.Type)
e.cmdChan <- &tCmd{
cmdType: cmdNewEvent,
data: &newEvent,
}
})
}
func (e *EventHub) GetEvent(eventCategory string, eventTypeList []string, criteria interface{}, waitTime time.Duration) (event *EventInfo, err error) {
notifyChan := e.registerConsumer(eventCategory, eventTypeList, criteria)
pollingDuration := defPollingDuration
if waitTime != 0 {
pollingDuration = waitTime
if globals.IsProductEnv() {
if pollingDuration > maxPollingDuration {
pollingDuration = maxPollingDuration
} else if pollingDuration < minPollingDuration {
pollingDuration = minPollingDuration
}
}
}
globals.SugarLogger.Debugf("GetEvent pollingDuration:%d seconds", pollingDuration/time.Second)
timer := time.NewTimer(pollingDuration)
select {
case tmpEvent, ok := <-notifyChan:
timer.Stop()
if ok {
event = tmpEvent
}
case <-timer.C:
e.unregisterConsumer(notifyChan)
}
close(notifyChan)
return event, err
}
func (e *EventHub) getEventProducer(eventCategory string) IEventProducer {
e.locker.RLock()
defer e.locker.RUnlock()
return e.eventCatMap[eventCategory]
}
func composeEventType(eventCategory, eventType string) string {
return eventCategory + "/" + eventType
}
func splitEventType(eventType string) (eventCategory, pureEventType string) {
typeList := strings.Split(eventType, "/")
eventCategory = typeList[0]
if len(typeList) > 1 {
pureEventType = typeList[1]
} else {
globals.SugarLogger.Warnf("splitEventType eventType:%s", eventType)
}
return eventCategory, pureEventType
}

View File

@@ -0,0 +1,76 @@
package syseventhub
import (
"time"
"git.rosy.net.cn/baseapi/utils"
"git.rosy.net.cn/jx-callback/globals"
"git.rosy.net.cn/jx-callback/business/jxutils/eventhub"
"git.rosy.net.cn/jx-callback/globals/api"
)
const (
EventCategory = "sys"
EventTypeWXToken = "wxtoken"
)
type Hub struct {
eventHub *eventhub.EventHub
}
type Criteria struct {
}
type WXTokenInfo struct {
IsNew bool `json:"isNew"`
Token string `json:"token"`
}
var (
SysEventHub *Hub
)
func init() {
SysEventHub = New()
}
func New() (hub *Hub) {
hub = &Hub{
eventHub: eventhub.New(),
}
hub.eventHub.RegisterProducer(EventCategory, hub)
return hub
}
func (h *Hub) IsCriteriaMatch(eventInfo *eventhub.EventInfo, criteria interface{}) bool {
return true
}
func (h *Hub) OnNewWXToken(token string) {
h.eventHub.PostNewEvent(EventCategory, &eventhub.EventInfo{
Type: EventTypeWXToken,
Data: token,
})
}
func (h *Hub) GetWXToken(oldToken string, waitTime time.Duration) (tokenInfo *WXTokenInfo) {
token := api.WeixinAPI.CBGetToken()
if token != oldToken {
tokenInfo = &WXTokenInfo{
IsNew: false,
Token: token,
}
} else {
eventInfo, err := h.eventHub.GetEvent(EventCategory, []string{EventTypeWXToken}, nil, waitTime)
if err == nil && eventInfo != nil {
tokenInfo = &WXTokenInfo{
IsNew: true,
Token: eventInfo.Data.(string),
}
}
}
globals.SugarLogger.Debugf("GetWXToken tokenInfo:%s", utils.Format4Output(tokenInfo, true))
return tokenInfo
}

View File

@@ -270,9 +270,7 @@ func (s SkuList) Swap(i, j int) {
func DownloadFileByURL(fileURL string) (bodyData []byte, fileMD5 string, err error) { func DownloadFileByURL(fileURL string) (bodyData []byte, fileMD5 string, err error) {
response, err := http.Get(fileURL) response, err := http.Get(fileURL)
if err == nil { if err == nil {
defer func() { defer response.Body.Close()
response.Body.Close()
}()
if response.StatusCode == http.StatusOK { if response.StatusCode == http.StatusOK {
if bodyData, err = ioutil.ReadAll(response.Body); err == nil { if bodyData, err = ioutil.ReadAll(response.Body); err == nil {
fileMD5 = fmt.Sprintf("%X", md5.Sum(bodyData)) fileMD5 = fmt.Sprintf("%X", md5.Sum(bodyData))

View File

@@ -54,10 +54,12 @@ func PrintOrderByOrder(ctx *jxcontext.Context, order *model.GoodsOrder) (printRe
return &partner.PrinterStatus{ return &partner.PrinterStatus{
PrintResult: partner.PrintResultNoPrinter, PrintResult: partner.PrintResultNoPrinter,
}, nil }, nil
} else { }
if globals.EnableStoreWrite { if globals.EnableStoreWrite {
printResult, err = handler.PrintOrder(ctx, store, order) printResult, err = handler.PrintOrder(ctx, store, order)
} }
if err == nil {
dao.SetOrderPrintFlag(db, ctx.GetUserName(), order.VendorOrderID, order.VendorID, true)
} }
} }
if err != nil { if err != nil {

View File

@@ -1,8 +1,14 @@
package tasks package tasks
import ( import (
"fmt"
"io/ioutil"
"net/http"
"time" "time"
"git.rosy.net.cn/baseapi/platformapi"
"git.rosy.net.cn/jx-callback/business/jxutils/eventhub/syseventhub"
"git.rosy.net.cn/jx-callback/business/model" "git.rosy.net.cn/jx-callback/business/model"
"git.rosy.net.cn/jx-callback/business/model/dao" "git.rosy.net.cn/jx-callback/business/model/dao"
"git.rosy.net.cn/jx-callback/business/model/legacymodel" "git.rosy.net.cn/jx-callback/business/model/legacymodel"
@@ -22,8 +28,11 @@ const (
dingdingTokenExpires = 7200 * time.Second dingdingTokenExpires = 7200 * time.Second
elmTokenExpires = 20 * 24 * 3600 * time.Second elmTokenExpires = 20 * 24 * 3600 * time.Second
weimobTokenExpires = 7200 * time.Second weimobTokenExpires = 7200 * time.Second
maxRefreshGap = 5 * 60 * time.Second
yilianyunTokenExpires = 30 * 24 * 3600 * time.Second yilianyunTokenExpires = 30 * 24 * 3600 * time.Second
maxRefreshGap = 5 * 60 * time.Second
errRefreshGap = 10 * time.Second
minRefreshGap = 1 * time.Second
) )
type ElmTokenForCompatible struct { type ElmTokenForCompatible struct {
@@ -36,13 +45,21 @@ type ElmTokenForCompatible struct {
Success bool `json:"success"` Success bool `json:"success"`
} }
type CallResult struct {
Code string `json:"code"`
Desc string `json:"desc"`
Data string `json:"data"`
}
func RefreshConfig(configKey string, expiresTime time.Duration, configGetter func() (string, string), configSetter func(value string)) error { func RefreshConfig(configKey string, expiresTime time.Duration, configGetter func() (string, string), configSetter func(value string)) error {
sleepGap := expiresTime / 10
needRefreshGap := expiresTime * 8 / 10 needRefreshGap := expiresTime * 8 / 10
sleepGap := expiresTime / 10
if sleepGap > maxRefreshGap { if sleepGap > maxRefreshGap {
sleepGap = maxRefreshGap sleepGap = maxRefreshGap
} }
refreshFunc := func() (string, error) {
refreshFunc := func() (sleepDuration time.Duration) {
sleepDuration = sleepGap
curConfig := &legacymodel.Config{ curConfig := &legacymodel.Config{
Thirdparty: configKey, Thirdparty: configKey,
} }
@@ -52,7 +69,7 @@ func RefreshConfig(configKey string, expiresTime time.Duration, configGetter fun
if err := db.Read(curConfig, "Thirdparty"); err != nil { if err := db.Read(curConfig, "Thirdparty"); err != nil {
if err != orm.ErrNoRows { if err != orm.ErrNoRows {
globals.SugarLogger.Errorf("db error:%v, curConfig:%v", err, curConfig) globals.SugarLogger.Errorf("db error:%v, curConfig:%v", err, curConfig)
return "", err return errRefreshGap
} }
handleType = 2 handleType = 2
} else { } else {
@@ -65,15 +82,17 @@ func RefreshConfig(configKey string, expiresTime time.Duration, configGetter fun
if curConfig.Token, curConfig.Date = configGetter(); curConfig.Token == "" { if curConfig.Token, curConfig.Date = configGetter(); curConfig.Token == "" {
if beego.BConfig.RunMode == "prod" { if beego.BConfig.RunMode == "prod" {
globals.SugarLogger.Errorf("RefreshConfig %s get empty token", configKey) globals.SugarLogger.Errorf("RefreshConfig %s get empty token", configKey)
sleepDuration = errRefreshGap
} else { } else {
globals.SugarLogger.Infof("RefreshConfig %s get empty token", configKey) globals.SugarLogger.Infof("RefreshConfig %s get empty token", configKey)
} }
return "", nil return sleepDuration
} }
globals.SugarLogger.Debugf("RefreshConfig refresh %s, value:%s", configKey, curConfig.Token) configSetter(curConfig.Token)
if curConfig.Date == "" { if curConfig.Date == "" {
curConfig.Date = utils.GetCurTimeStr() curConfig.Date = utils.GetCurTimeStr()
} else {
sleepDuration = expiresTime - time.Now().Sub(utils.Str2Time(curConfig.Date))
} }
var num int64 var num int64
var err error var err error
@@ -85,88 +104,103 @@ func RefreshConfig(configKey string, expiresTime time.Duration, configGetter fun
} }
if err != nil || num == 0 { if err != nil || num == 0 {
globals.SugarLogger.Errorf("db error:%v, num:%d, curConfig:%v", err, num, curConfig) globals.SugarLogger.Errorf("db error:%v, num:%d, curConfig:%v", err, num, curConfig)
return "", err
} }
configSetter(curConfig.Token)
} }
return curConfig.Token, nil if sleepDuration < minRefreshGap {
sleepDuration = minRefreshGap
} else if sleepDuration > maxRefreshGap {
sleepDuration = maxRefreshGap
}
return sleepDuration
} }
token, err := refreshFunc() // 这样写的目的是强制第一次调用时要刷新一次 utils.CallFuncAsync(func() {
if err == nil { for {
if token != "" { sleepGap := refreshFunc()
configSetter(token) time.Sleep(sleepGap)
} }
utils.CallFuncAsync(func() { })
for { return nil
time.Sleep(sleepGap) }
refreshFunc()
func RefreshWeixinToken() (err error) {
if api.WeixinAPI != nil {
err = RefreshConfig("wechat", weixinTokenExpires, func() (token string, expireTimeStr string) {
globals.SugarLogger.Debugf("RefreshWeixinToken RunMode:%s", beego.BConfig.RunMode)
if globals.IsProductEnv() {
if globals.IsMainProductEnv() {
if tokenInfo, err := api.WeixinAPI.CBRetrieveToken(); err == nil {
globals.SugarLogger.Debugf("RefreshWeixinToken tokenInfo:%s", utils.Format4Output(tokenInfo, true))
token = tokenInfo.AccessToken
} else {
globals.SugarLogger.Errorf("RefreshWeixinToken RefreshToken failed with error:%v", err)
}
} else {
if tokenInfo := getWXTokenFromRemote(api.WeixinAPI.CBGetToken()); tokenInfo != nil {
expireTimeStr = utils.Time2Str(time.Now().Add(-weixinTokenExpires))
token = tokenInfo.Token
}
}
}
return token, expireTimeStr
}, func(value string) {
globals.SugarLogger.Debugf("RefreshWeixinToken setter value:%s", value)
syseventhub.SysEventHub.OnNewWXToken(value)
api.WeixinAPI.CBSetToken(value)
})
}
return err
}
func RefreshElmToken() (err error) {
if api.ElmAPI != nil {
err = RefreshConfig("eleme", elmTokenExpires, func() (string, string) {
if beego.BConfig.RunMode == "prod" {
if tokenInfo, err := api.ElmAPI.RefreshTokenIndividual(); err == nil {
tokenInfo2 := &ElmTokenForCompatible{
Error: "",
ErrorDescription: "",
AccessToken: tokenInfo.AccessToken,
TokenType: tokenInfo.TokenType,
Expires: tokenInfo.ExpiresIn,
RefreshToken: "",
Success: true,
}
return string(utils.MustMarshal(tokenInfo2)), ""
}
}
return "", ""
}, func(value string) {
var tokenInfo ElmTokenForCompatible
err := utils.UnmarshalUseNumber([]byte(value), &tokenInfo)
if err == nil {
api.ElmAPI.SetToken(tokenInfo.AccessToken)
} }
}) })
} }
return err return err
} }
func RefreshWeixinToken() error { func RefreshWeimobToken() (err error) {
return RefreshConfig("wechat", weixinTokenExpires, func() (string, string) { if api.WeimobAPI != nil {
globals.SugarLogger.Debugf("RefreshWeixinToken RunMode:%s", beego.BConfig.RunMode) err = RefreshConfig("weimob", weimobTokenExpires, func() (string, string) {
if beego.BConfig.RunMode == "prod" { if beego.BConfig.RunMode == "prod" {
if tokenInfo, err := api.WeixinAPI.CBRetrieveToken(); err == nil { if tokenInfo, err := api.WeimobAPI.RefreshTokenByRefreshToken(); err == nil {
globals.SugarLogger.Debugf("RefreshWeixinToken tokenInfo:%s", utils.Format4Output(tokenInfo, true)) return string(utils.MustMarshal(tokenInfo)), utils.Time2Str(time.Now().Add((time.Duration(tokenInfo.ExpiresIn) - weimobTokenExpires/time.Second) * time.Second))
return tokenInfo.AccessToken, ""
} else {
globals.SugarLogger.Errorf("RefreshWeixinToken RefreshToken failed with error:%v", err)
}
}
return "", ""
}, func(value string) {
api.WeixinAPI.CBSetToken(value)
})
}
func RefreshElmToken() error {
return RefreshConfig("eleme", elmTokenExpires, func() (string, string) {
if beego.BConfig.RunMode == "prod" {
if tokenInfo, err := api.ElmAPI.RefreshTokenIndividual(); err == nil {
tokenInfo2 := &ElmTokenForCompatible{
Error: "",
ErrorDescription: "",
AccessToken: tokenInfo.AccessToken,
TokenType: tokenInfo.TokenType,
Expires: tokenInfo.ExpiresIn,
RefreshToken: "",
Success: true,
} }
return string(utils.MustMarshal(tokenInfo2)), ""
} }
} return "", ""
return "", "" }, func(value string) {
}, func(value string) { var tokenInfo *weimobapi.TokenInfo
var tokenInfo ElmTokenForCompatible err := utils.UnmarshalUseNumber([]byte(value), &tokenInfo)
err := utils.UnmarshalUseNumber([]byte(value), &tokenInfo) if err == nil {
if err == nil { api.WeimobAPI.SetToken(tokenInfo)
api.ElmAPI.SetToken(tokenInfo.AccessToken) }
} })
}) }
return err
} }
func RefreshWeimobToken() error { func RefreshDingDingToken() (err error) {
return RefreshConfig("weimob", weimobTokenExpires, func() (string, string) {
if beego.BConfig.RunMode == "prod" {
if tokenInfo, err := api.WeimobAPI.RefreshTokenByRefreshToken(); err == nil {
return string(utils.MustMarshal(tokenInfo)), utils.Time2Str(time.Now().Add((time.Duration(tokenInfo.ExpiresIn) - weimobTokenExpires/time.Second) * time.Second))
}
}
return "", ""
}, func(value string) {
var tokenInfo *weimobapi.TokenInfo
err := utils.UnmarshalUseNumber([]byte(value), &tokenInfo)
if err == nil {
api.WeimobAPI.SetToken(tokenInfo)
}
})
}
func RefreshDingDingToken() error {
api.DingDingAPI.RetrieveToken() api.DingDingAPI.RetrieveToken()
return RefreshConfig("dingding", dingdingTokenExpires, func() (string, string) { return RefreshConfig("dingding", dingdingTokenExpires, func() (string, string) {
globals.SugarLogger.Debugf("RefreshDingDingToken RunMode:%s", beego.BConfig.RunMode) globals.SugarLogger.Debugf("RefreshDingDingToken RunMode:%s", beego.BConfig.RunMode)
@@ -195,7 +229,7 @@ func SaveWeimobToken(token *weimobapi.TokenInfo) (err error) {
return dao.CreateOrUpdate(db, config) return dao.CreateOrUpdate(db, config)
} }
func RefreshYilianyunToken() error { func RefreshYilianyunToken() (err error) {
return RefreshConfig("yilianyun", yilianyunTokenExpires, func() (string, string) { return RefreshConfig("yilianyun", yilianyunTokenExpires, func() (string, string) {
globals.SugarLogger.Debugf("RefreshYilianyunToken RunMode:%s", beego.BConfig.RunMode) globals.SugarLogger.Debugf("RefreshYilianyunToken RunMode:%s", beego.BConfig.RunMode)
if beego.BConfig.RunMode == "prod" { if beego.BConfig.RunMode == "prod" {
@@ -214,3 +248,46 @@ func RefreshYilianyunToken() error {
} }
}) })
} }
func getWXTokenFromRemote(oldToken string) (tokenInfo *syseventhub.WXTokenInfo) {
if IsGetWXTokenFromRemote() {
for {
waitSecond := 5 * 60
globals.SugarLogger.Debugf("getWXTokenFromProd1")
response, err := http.Get(fmt.Sprintf("%s?accessKey=%s&oldToken=%s&waitSecond=%d", globals.GetWeixinTokenURL, globals.GetWeixinTokenKey, oldToken, waitSecond))
globals.SugarLogger.Debugf("getWXTokenFromProd2 error:%v", err)
if err == nil {
defer response.Body.Close()
if response.StatusCode == http.StatusOK {
data, err2 := ioutil.ReadAll(response.Body)
if err = err2; err == nil {
var result CallResult
if err = utils.UnmarshalUseNumber(data, &result); err == nil {
if result.Code == "0" {
if result.Data != "" {
if err = utils.UnmarshalUseNumber([]byte(result.Data), &tokenInfo); err == nil && tokenInfo != nil {
globals.SugarLogger.Debugf("getWXTokenFromProd:%s", utils.Format4Output(tokenInfo, false))
break
}
}
} else {
err = fmt.Errorf("return code is:%s", result.Code)
}
}
}
} else {
err = platformapi.ErrHTTPCodeIsNot200
}
}
globals.SugarLogger.Infof("getWXTokenFromProd failed with error:%v", err)
if err != nil {
time.Sleep(errRefreshGap)
}
}
}
return tokenInfo
}
func IsGetWXTokenFromRemote() bool {
return !globals.IsMainProductEnv() && globals.GetWeixinTokenKey != "" && globals.GetWeixinTokenURL != ""
}

View File

@@ -26,7 +26,7 @@ const (
) )
const ( const (
MaxTaskNameLen = 30 MaxTaskNameLen = 50
) )
var ( var (

View File

@@ -15,12 +15,10 @@ import (
) )
const ( const (
// WX_TO_ORDER_PAGE_URL = "http://www.jxc4.com/jx/h5/#/?jxStoreId=" WX_TO_ORDER_PAGE_URL = "/#/?jxStoreId="
// WX_TO_SHOW_COMMENTS_DETAIL_URL = "http://www.jxc4.com/jx/h5/#/assess-list?jxStoreId=" //展示差评详情的页面 WX_TO_STORE_SKU_PAGE_URL = "/#/shop?jxStoreId="
WX_TO_ORDER_PAGE_URL = "http://wx.jxc4.com/#/?jxStoreId=" WX_TO_SHOW_COMMENTS_DETAIL_URL = "/#/assess-list?jxStoreId=" //展示差评详情的页面
WX_TO_STORE_SKU_PAGE_URL = "http://wx.jxc4.com/#/shop?jxStoreId=" WX_TO_SHOW_MSG = "/#/message-detail?msgID=%d&msgStatusID=%d"
WX_TO_SHOW_COMMENTS_DETAIL_URL = "http://wx.jxc4.com/#/assess-list?jxStoreId=" //展示差评详情的页面
WX_TO_SHOW_MSG = "http://wx.jxc4.com/#/message-detail?msgID=%d&msgStatusID=%d"
WX_MINI_TO_ORDER_PAGE_URL = "pages/order-manager/main" WX_MINI_TO_ORDER_PAGE_URL = "pages/order-manager/main"
WX_MINI_TO_STORE_SKU_PAGE_URL = "pages/goods-manager/main" WX_MINI_TO_STORE_SKU_PAGE_URL = "pages/goods-manager/main"
@@ -205,7 +203,7 @@ func NotifyNewOrder(order *model.GoodsOrder) (err error) {
}, },
} }
storeID := jxutils.GetSaleStoreIDFromOrder(order) storeID := jxutils.GetSaleStoreIDFromOrder(order)
return SendMsgToStore(storeID, WX_NEWORDER_TEMPLATE_ID, fmt.Sprintf("%s%d", WX_TO_ORDER_PAGE_URL, storeID), WX_MINI_TO_ORDER_PAGE_URL, data) return SendMsgToStore(storeID, WX_NEWORDER_TEMPLATE_ID, globals.WxBackstageHost+fmt.Sprintf("%s%d", WX_TO_ORDER_PAGE_URL, storeID), WX_MINI_TO_ORDER_PAGE_URL, data)
} }
func NotifyWaybillStatus(bill *model.Waybill, order *model.GoodsOrder, isBillAlreadyCandidate bool) error { func NotifyWaybillStatus(bill *model.Waybill, order *model.GoodsOrder, isBillAlreadyCandidate bool) error {
@@ -340,7 +338,7 @@ func PushJDBadCommentToWeiXin(comment *legacymodel.JxBadComments) (err error) {
}, },
} }
storeID := int(utils.Str2Int64(comment.Jxstoreid)) storeID := int(utils.Str2Int64(comment.Jxstoreid))
return SendMsgToStore(storeID, WX_BAD_COMMENT_PUSH_TEMPLATE_ID, fmt.Sprintf("%s%d", WX_TO_SHOW_COMMENTS_DETAIL_URL, storeID), WX_MINI_TO_SHOW_COMMENTS_DETAIL_URL, data) return SendMsgToStore(storeID, WX_BAD_COMMENT_PUSH_TEMPLATE_ID, globals.WxBackstageHost+fmt.Sprintf("%s%d", WX_TO_SHOW_COMMENTS_DETAIL_URL, storeID), WX_MINI_TO_SHOW_COMMENTS_DETAIL_URL, data)
} }
func NotifySaleBill(storeID int, title, shopName, fileURL string) (err error) { func NotifySaleBill(storeID int, title, shopName, fileURL string) (err error) {
@@ -379,7 +377,7 @@ func NotifySaleBill(storeID int, title, shopName, fileURL string) (err error) {
func NotifyStoreOpRequestStatus(isAccepted bool, storeID, nameID int, spuName string, originalUnitPrice, unitPrice int, rejectReason string) (err error) { func NotifyStoreOpRequestStatus(isAccepted bool, storeID, nameID int, spuName string, originalUnitPrice, unitPrice int, rejectReason string) (err error) {
globals.SugarLogger.Debugf("NotifyStoreOpRequestStatus isAccepted:%t, storeID:%d, nameID:%d, spuName:%s, originalUnitPrice:%d, unitPrice:%d, rejectReason:%s", isAccepted, storeID, nameID, spuName, originalUnitPrice, unitPrice, rejectReason) globals.SugarLogger.Debugf("NotifyStoreOpRequestStatus isAccepted:%t, storeID:%d, nameID:%d, spuName:%s, originalUnitPrice:%d, unitPrice:%d, rejectReason:%s", isAccepted, storeID, nameID, spuName, originalUnitPrice, unitPrice, rejectReason)
templateID := "" templateID := ""
fileURL := fmt.Sprintf("%s%d", WX_TO_STORE_SKU_PAGE_URL, storeID) fileURL := globals.WxBackstageHost + fmt.Sprintf("%s%d", WX_TO_STORE_SKU_PAGE_URL, storeID)
data := make(map[string]interface{}) data := make(map[string]interface{})
if isAccepted { if isAccepted {
templateID = WX_CHANGE_APPROVED_TEMPLATE_ID templateID = WX_CHANGE_APPROVED_TEMPLATE_ID
@@ -426,7 +424,7 @@ func NotifyStoreOpRequestStatus(isAccepted bool, storeID, nameID int, spuName st
func NotifyStoreMessage(storeID, msgID, msgStatusID int, title, content string) (err error) { func NotifyStoreMessage(storeID, msgID, msgStatusID int, title, content string) (err error) {
globals.SugarLogger.Debugf("NotifyStoreMessage storeID:%d, msgID:%d, title:%s, content:%s", storeID, msgID, title, content) globals.SugarLogger.Debugf("NotifyStoreMessage storeID:%d, msgID:%d, title:%s, content:%s", storeID, msgID, title, content)
templateID := WX_NORMAL_STORE_MSG_TEMPLATE_ID templateID := WX_NORMAL_STORE_MSG_TEMPLATE_ID
fileURL := fmt.Sprintf(WX_TO_SHOW_MSG, msgID, msgStatusID) fileURL := globals.WxBackstageHost + fmt.Sprintf(WX_TO_SHOW_MSG, msgID, msgStatusID)
data := map[string]interface{}{ data := map[string]interface{}{
"first": map[string]interface{}{ "first": map[string]interface{}{
"value": content, "value": content,

View File

@@ -1,5 +1,11 @@
package model package model
import (
"git.rosy.net.cn/baseapi/platformapi/ebaiapi"
"git.rosy.net.cn/baseapi/platformapi/jdapi"
"git.rosy.net.cn/baseapi/platformapi/mtwmapi"
)
// VendorIDJD, VendorIDMTWM与VendorIDELM的定义和老系统是兼容的 // VendorIDJD, VendorIDMTWM与VendorIDELM的定义和老系统是兼容的
const ( const (
VendorIDUnknown = -1 VendorIDUnknown = -1
@@ -42,6 +48,7 @@ var (
VendorIDYiLianYun: "Yilianyun", VendorIDYiLianYun: "Yilianyun",
VendorIDZhongWu: "ZhongWu", VendorIDZhongWu: "ZhongWu",
} }
VendorChineseNames = map[int]string{ VendorChineseNames = map[int]string{
VendorIDJD: "京东到家", VendorIDJD: "京东到家",
VendorIDMTWM: "美团外卖", VendorIDMTWM: "美团外卖",
@@ -58,6 +65,21 @@ var (
VendorIDZhongWu: "中午云", VendorIDZhongWu: "中午云",
} }
PurchaseVendorInfo = map[int]map[string]interface{}{
VendorIDJD: map[string]interface{}{
"chineseName": VendorChineseNames[VendorIDJD],
"userApplyCancelWaitMinute": jdapi.UserApplyCancelWaitMinute,
},
VendorIDMTWM: map[string]interface{}{
"chineseName": VendorChineseNames[VendorIDMTWM],
"userApplyCancelWaitMinute": mtwmapi.UserApplyCancelWaitMinute,
},
VendorIDEBAI: map[string]interface{}{
"chineseName": VendorChineseNames[VendorIDEBAI],
"userApplyCancelWaitMinute": ebaiapi.UserApplyCancelWaitMinute,
},
}
ShopChineseNames = map[int]string{ ShopChineseNames = map[int]string{
VendorIDJD: "京西菜市", VendorIDJD: "京西菜市",
VendorIDMTWM: "美好菜市", VendorIDMTWM: "美好菜市",
@@ -215,7 +237,7 @@ const (
WaybillStatusEndBegin = 100 // 以下的状态就是结束状态 WaybillStatusEndBegin = 100 // 以下的状态就是结束状态
WaybillStatusDelivered = 105 // todo 这个应该改为110与订单对应 WaybillStatusDelivered = 105 // todo 这个应该改为110与订单对应
WaybillStatusCanceled = 115 WaybillStatusCanceled = 115
WaybillStatusFailed = 120 // todo 这个应该要去掉 WaybillStatusFailed = 120 // 这个状态存在的意义是区分于WaybillStatusCanceled比如达达平台在这种状态下再次创建运单的方式不一样
WaybillStatusNeverSend = 125 // 这个状态指的是平台方不愿意配送门店自己想办法。与WaybillStatusAcceptCanceled不一样WaybillStatusAcceptCanceled可能之后还会尝试配送 WaybillStatusNeverSend = 125 // 这个状态指的是平台方不愿意配送门店自己想办法。与WaybillStatusAcceptCanceled不一样WaybillStatusAcceptCanceled可能之后还会尝试配送
) )
@@ -240,8 +262,20 @@ const (
OrderDeliveryFlagMaskScheduleDisabled = 1 // 禁止三方配送调度 OrderDeliveryFlagMaskScheduleDisabled = 1 // 禁止三方配送调度
OrderDeliveryFlagMaskPurcahseDisabled = 2 // 购物平台已不配送(一般为门店配送类型本身为自配送,或已经转自配送) OrderDeliveryFlagMaskPurcahseDisabled = 2 // 购物平台已不配送(一般为门店配送类型本身为自配送,或已经转自配送)
) )
const ( const (
OrderFlagMaskPrinted = 1 // 已经打印 OrderFlagMaskPrinted = 1 // 已经打印
OrderFlagMaskUserApplyCancel = 6
OrderFlagAgreeUserApplyCancel = 2
OrderFlagRefuseUserApplyCancel = 6
OrderFlagMaskFailedGetGoods = 24
OrderFlagAgreeFailedGetGoods = 8
OrderFlagRefuseFailedGetGoods = 24
OrderFlagMaskFailedDeliver = 32
OrderFlagMaskCallPMCourier = 64 // 取货失败后召唤平台配送
) )
func IsPurchaseVendorExist(vendorID int) bool { func IsPurchaseVendorExist(vendorID int) bool {

View File

@@ -59,10 +59,6 @@ func GetDB() *DaoDB {
return &DaoDB{Db: orm.NewOrm()} return &DaoDB{Db: orm.NewOrm()}
} }
func WrapDB(ormDb orm.Ormer) *DaoDB {
return &DaoDB{Db: ormDb}
}
func Begin(db *DaoDB) (err error) { func Begin(db *DaoDB) (err error) {
if db.transactionLevel == 0 { if db.transactionLevel == 0 {
err = db.Db.Begin() err = db.Db.Begin()

View File

@@ -25,27 +25,29 @@ func GetStoreOrderAfterTime(db *DaoDB, storeID int, orderTime time.Time, lastOrd
return orderList, GetRows(db, &orderList, sql, sqlParams...) return orderList, GetRows(db, &orderList, sql, sqlParams...)
} }
func SetOrderPrintFlag(db *DaoDB, vendorOrderID string, vendorID int, isPrinted bool) (err error) { func SetOrderPrintFlag(db *DaoDB, userName string, vendorOrderID string, vendorID int, isPrinted bool) (err error) {
var (
sql string
sqlParams []interface{}
)
if isPrinted { if isPrinted {
sql = ` err = SetOrderFlag(db, userName, vendorOrderID, vendorID, model.OrderFlagMaskPrinted)
UPDATE goods_order
SET flag = flag | ?
WHERE vendor_order_id = ? AND vendor_id = ?
`
sqlParams = append(sqlParams, model.OrderFlagMaskPrinted)
} else { } else {
sql = ` err = SetOrderFlag(db, userName, vendorOrderID, vendorID, ^int8(model.OrderFlagMaskPrinted))
UPDATE goods_order
SET flag = flag & ?
WHERE vendor_order_id = ? AND vendor_id = ?
`
sqlParams = append(sqlParams, ^model.OrderFlagMaskPrinted)
} }
sqlParams = append(sqlParams, vendorOrderID, vendorID) return err
_, err = ExecuteSQL(db, sql, sqlParams...) }
func SetOrderFlag(db *DaoDB, userName string, vendorOrderID string, vendorID int, flag int8) (err error) {
_, err = ExecuteSQL(db, `
UPDATE goods_order
SET flag = flag | ?
WHERE vendor_order_id = ? AND vendor_id = ?
`, flag, vendorOrderID, vendorID)
return err
}
func ClearOrderFlag(db *DaoDB, userName string, vendorOrderID string, vendorID int, flag int8) (err error) {
_, err = ExecuteSQL(db, `
UPDATE goods_order
SET flag = flag & ?
WHERE vendor_order_id = ? AND vendor_id = ?
`, flag, vendorOrderID, vendorID)
return err return err
} }

View File

@@ -32,7 +32,8 @@ type GoodsOrder struct {
Status int `json:"status"` // 参见OrderStatus*相关的常量定义 Status int `json:"status"` // 参见OrderStatus*相关的常量定义
VendorStatus string `orm:"size(255)" json:"-"` VendorStatus string `orm:"size(255)" json:"-"`
LockStatus int `json:"lockStatus"` LockStatus int `json:"lockStatus"`
OrderSeq int `json:"orderSeq"` // 门店订单序号 LockStatusTime time.Time `orm:"type(datetime);null" json:"-"` // last lock status time
OrderSeq int `json:"orderSeq"` // 门店订单序号
BuyerComment string `orm:"size(255)" json:"buyerComment"` BuyerComment string `orm:"size(255)" json:"buyerComment"`
BusinessType int `json:"businessType"` BusinessType int `json:"businessType"`
ExpectedDeliveredTime time.Time `orm:"type(datetime)" json:"expectedDeliveredTime"` // 预期送达时间 ExpectedDeliveredTime time.Time `orm:"type(datetime)" json:"expectedDeliveredTime"` // 预期送达时间

View File

@@ -67,7 +67,7 @@ func routinueFunc() {
registerMsg := msg.MsgData.(*MsgOp) registerMsg := msg.MsgData.(*MsgOp)
delete(channelMap[registerMsg.StoreID], registerMsg.Chan2Listen) delete(channelMap[registerMsg.StoreID], registerMsg.Chan2Listen)
close(registerMsg.Chan2Close) close(registerMsg.Chan2Close)
case ServerMsgNewOrder: case ServerMsgNewOrder, ServerMsgKeyOrderStatusChanged:
globals.SugarLogger.Debugf("msghub routinueFunc, msg:%s", utils.Format4Output(msg, false)) globals.SugarLogger.Debugf("msghub routinueFunc, msg:%s", utils.Format4Output(msg, false))
utils.CallFuncAsync(func() { utils.CallFuncAsync(func() {
for chan2Send := range channelMap[msg.StoreID] { for chan2Send := range channelMap[msg.StoreID] {
@@ -125,10 +125,12 @@ func GetMsg(ctx *jxcontext.Context, storeID int, lastOrderTime time.Time, lastOr
pollingDuration := defPollingDuration pollingDuration := defPollingDuration
if waitingSecond != 0 { if waitingSecond != 0 {
pollingDuration = time.Duration(waitingSecond) * time.Second pollingDuration = time.Duration(waitingSecond) * time.Second
if pollingDuration > maxPollingDuration { if globals.IsProductEnv() {
pollingDuration = maxPollingDuration if pollingDuration > maxPollingDuration {
} else if pollingDuration < minPollingDuration { pollingDuration = maxPollingDuration
pollingDuration = minPollingDuration } else if pollingDuration < minPollingDuration {
pollingDuration = minPollingDuration
}
} }
} }
timer := time.NewTimer(pollingDuration) timer := time.NewTimer(pollingDuration)
@@ -171,7 +173,7 @@ func OnKeyOrderStatusChanged(order *model.GoodsOrder) {
msgChan <- &ServerMsg{ msgChan <- &ServerMsg{
Type: ServerMsgKeyOrderStatusChanged, Type: ServerMsgKeyOrderStatusChanged,
StoreID: jxutils.GetSaleStoreIDFromOrder(order), StoreID: jxutils.GetSaleStoreIDFromOrder(order),
MsgData: 1, MsgData: order,
// MsgData: []*model.GoodsOrderExt{ // MsgData: []*model.GoodsOrderExt{
// &model.GoodsOrderExt{ // &model.GoodsOrderExt{
// GoodsOrder: *order, // GoodsOrder: *order,

View File

@@ -15,7 +15,6 @@ import (
"git.rosy.net.cn/jx-callback/globals" "git.rosy.net.cn/jx-callback/globals"
"git.rosy.net.cn/jx-callback/globals/api" "git.rosy.net.cn/jx-callback/globals/api"
"github.com/astaxie/beego" "github.com/astaxie/beego"
"github.com/astaxie/beego/orm"
) )
const ( const (
@@ -70,9 +69,9 @@ func (c *DeliveryHandler) onWaybillMsg(msg *dadaapi.CallbackMsg) (retVal *dadaap
order.Status = model.WaybillStatusDelivering order.Status = model.WaybillStatusDelivering
case dadaapi.OrderStatusFinished: case dadaapi.OrderStatusFinished:
order.Status = model.WaybillStatusDelivered order.Status = model.WaybillStatusDelivered
case dadaapi.OrderStatusCanceled: case dadaapi.OrderStatusCanceled, dadaapi.OrderStatusExpired:
order.Status = model.WaybillStatusCanceled order.Status = model.WaybillStatusCanceled
case dadaapi.OrderStatusExpired, dadaapi.OrderStatusAddOrderFailed: case dadaapi.OrderStatusAddOrderFailed:
order.Status = model.WaybillStatusFailed order.Status = model.WaybillStatusFailed
default: default:
order.Status = model.WaybillStatusUnknown order.Status = model.WaybillStatusUnknown
@@ -102,7 +101,7 @@ func (c *DeliveryHandler) callbackMsg2Waybill(msg *dadaapi.CallbackMsg) (retVal
// IDeliveryPlatformHandler // IDeliveryPlatformHandler
func (c *DeliveryHandler) CreateWaybill(order *model.GoodsOrder, policy partner.CreateWaybillPolicy) (bill *model.Waybill, err error) { func (c *DeliveryHandler) CreateWaybill(order *model.GoodsOrder, policy partner.CreateWaybillPolicy) (bill *model.Waybill, err error) {
db := orm.NewOrm() db := dao.GetDB()
deliveryFee, addFee, err := delivery.CalculateOrderDeliveryFee(order, time.Now(), db) deliveryFee, addFee, err := delivery.CalculateOrderDeliveryFee(order, time.Now(), db)
if err != nil { if err != nil {
return nil, err return nil, err
@@ -133,17 +132,18 @@ func (c *DeliveryHandler) CreateWaybill(order *model.GoodsOrder, policy partner.
if globals.EnableStoreWrite { if globals.EnableStoreWrite {
// 达达要求第二次创建运单,调用函数不同。所以查找两天内有无相同订单号的运单 // 达达要求第二次创建运单,调用函数不同。所以查找两天内有无相同订单号的运单
var lists []orm.ParamsList var waybillList []*model.Waybill
num, err2 := db.Raw(` err2 := dao.GetRows(db, &waybillList, `
SELECT vendor_waybill_id SELECT *
FROM waybill FROM waybill
WHERE waybill_created_at > DATE_ADD(NOW(), interval -2 day) WHERE waybill_created_at > DATE_ADD(NOW(), interval -2 day)
AND vendor_order_id = ? AND vendor_order_id = ?
AND waybill_vendor_id = ? AND waybill_vendor_id = ?
`, jxutils.ComposeUniversalOrderID(order.VendorOrderID, order.VendorID), model.VendorIDDada).ValuesList(&lists) ORDER BY id DESC
`, jxutils.ComposeUniversalOrderID(order.VendorOrderID, order.VendorID), model.VendorIDDada)
var result *dadaapi.CreateOrderResponse var result *dadaapi.CreateOrderResponse
if err = err2; err == nil && num > 0 { if err = err2; err == nil && len(waybillList) > 0 && waybillList[0].Status != model.WaybillStatusFailed {
globals.SugarLogger.Debugf("CreateWaybill orderID:%s num=%d use ReaddOrder", order.VendorOrderID, num) globals.SugarLogger.Debugf("CreateWaybill orderID:%s len(waybillList)=%d use ReaddOrder", order.VendorOrderID, len(waybillList))
result, err = api.DadaAPI.ReaddOrder(billParams, addParams) result, err = api.DadaAPI.ReaddOrder(billParams, addParams)
} else { } else {
if err != nil { if err != nil {
@@ -192,7 +192,7 @@ func (c *DeliveryHandler) CancelWaybill(bill *model.Waybill, cancelReasonID int,
return err return err
} }
func (c *DeliveryHandler) getDataCityCodeFromOrder(order *model.GoodsOrder, db orm.Ormer) (retVal string, err error) { func (c *DeliveryHandler) getDataCityCodeFromOrder(order *model.GoodsOrder, db *dao.DaoDB) (retVal string, err error) {
jxStoreID := jxutils.GetSaleStoreIDFromOrder(order) jxStoreID := jxutils.GetSaleStoreIDFromOrder(order)
sql := ` sql := `
SELECT t2.tel_code SELECT t2.tel_code
@@ -200,11 +200,10 @@ func (c *DeliveryHandler) getDataCityCodeFromOrder(order *model.GoodsOrder, db o
JOIN place t2 on t1.city_code = t2.code JOIN place t2 on t1.city_code = t2.code
WHERE t1.id = ? WHERE t1.id = ?
` `
db2 := dao.WrapDB(db)
codeInfo := &struct { codeInfo := &struct {
TelCode string TelCode string
}{} }{}
if err = dao.GetRow(db2, codeInfo, sql, jxStoreID); err != nil { if err = dao.GetRow(db, codeInfo, sql, jxStoreID); err != nil {
globals.SugarLogger.Errorf("GetDataCityCodeFromOrder can not find store info for vendorID:%d, store:%s, error:%v", order.VendorID, order.VendorStoreID, err) globals.SugarLogger.Errorf("GetDataCityCodeFromOrder can not find store info for vendorID:%d, store:%s, error:%v", order.VendorID, order.VendorStoreID, err)
if err == nil { if err == nil {
err = ErrCanNotFindDadaCityCode err = ErrCanNotFindDadaCityCode
@@ -214,11 +213,10 @@ func (c *DeliveryHandler) getDataCityCodeFromOrder(order *model.GoodsOrder, db o
return codeInfo.TelCode, nil return codeInfo.TelCode, nil
} }
func (c *DeliveryHandler) getDadaShopID(order *model.GoodsOrder, db orm.Ormer) (retVal string, err error) { func (c *DeliveryHandler) getDadaShopID(order *model.GoodsOrder, db *dao.DaoDB) (retVal string, err error) {
saleStoreID := jxutils.GetSaleStoreIDFromOrder(order) saleStoreID := jxutils.GetSaleStoreIDFromOrder(order)
db2 := dao.WrapDB(db) storeCourierList, err2 := dao.GetOpenedStoreCouriersByStoreID(db, saleStoreID, model.VendorIDDada)
storeCourierList, err2 := dao.GetOpenedStoreCouriersByStoreID(db2, saleStoreID, model.VendorIDDada) if err = err2; err != nil && !dao.IsNoRowsError(err) {
if err = err2; err != nil && err != orm.ErrNoRows {
return "", err return "", err
} }
if len(storeCourierList) == 0 { if len(storeCourierList) == 0 {

View File

@@ -12,7 +12,6 @@ import (
"git.rosy.net.cn/jx-callback/business/model/dao" "git.rosy.net.cn/jx-callback/business/model/dao"
"git.rosy.net.cn/jx-callback/business/partner" "git.rosy.net.cn/jx-callback/business/partner"
"git.rosy.net.cn/jx-callback/globals" "git.rosy.net.cn/jx-callback/globals"
"github.com/astaxie/beego/orm"
) )
const ( const (
@@ -57,10 +56,10 @@ func CallCreateWaybillPolicy(policy partner.CreateWaybillPolicy, refDeliveryFee,
return nil return nil
} }
func CalculateOrderDeliveryFee(order *model.GoodsOrder, billTime time.Time, db orm.Ormer) (deliveryFee, addFee int64, err error) { func CalculateOrderDeliveryFee(order *model.GoodsOrder, billTime time.Time, db *dao.DaoDB) (deliveryFee, addFee int64, err error) {
globals.SugarLogger.Debugf("CalculateOrderDeliveryFee orderID:%s", order.VendorOrderID) globals.SugarLogger.Debugf("CalculateOrderDeliveryFee orderID:%s", order.VendorOrderID)
if db == nil { if db == nil {
db = orm.NewOrm() db = dao.GetDB()
} }
jxStoreID := jxutils.GetSaleStoreIDFromOrder(order) jxStoreID := jxutils.GetSaleStoreIDFromOrder(order)
var lng, lat float64 var lng, lat float64
@@ -69,8 +68,7 @@ func CalculateOrderDeliveryFee(order *model.GoodsOrder, billTime time.Time, db o
Lng int Lng int
Lat int Lat int
}{} }{}
db2 := dao.WrapDB(db) if err = dao.GetRow(db, priceInfo, `
if err = dao.GetRow(db2, priceInfo, `
SELECT t2.mtps_price price, t1.lng, t1.lat SELECT t2.mtps_price price, t1.lng, t1.lat
FROM store t1 FROM store t1
JOIN place t2 ON t1.city_code = t2.code JOIN place t2 ON t1.city_code = t2.code

View File

@@ -115,7 +115,7 @@ func (c *DeliveryHandler) callbackMsg2Waybill(msg *mtpsapi.CallbackOrderMsg) (re
// IDeliveryPlatformHandler // IDeliveryPlatformHandler
func (c *DeliveryHandler) CreateWaybill(order *model.GoodsOrder, policy partner.CreateWaybillPolicy) (bill *model.Waybill, err error) { func (c *DeliveryHandler) CreateWaybill(order *model.GoodsOrder, policy partner.CreateWaybillPolicy) (bill *model.Waybill, err error) {
db := orm.NewOrm() db := dao.GetDB()
deliveryFee, addFee, err := delivery.CalculateOrderDeliveryFee(order, time.Now(), db) deliveryFee, addFee, err := delivery.CalculateOrderDeliveryFee(order, time.Now(), db)
if err == nil { if err == nil {
if err = delivery.CallCreateWaybillPolicy(policy, deliveryFee, addFee, deliveryFee, order, model.VendorIDMTPS); err != nil { if err = delivery.CallCreateWaybillPolicy(policy, deliveryFee, addFee, deliveryFee, order, model.VendorIDMTPS); err != nil {
@@ -201,16 +201,15 @@ func (c *DeliveryHandler) CancelWaybill(bill *model.Waybill, cancelReasonID int,
return nil return nil
} }
func (c *DeliveryHandler) getDeliveryID(order *model.GoodsOrder, db orm.Ormer) (retVal int64, err error) { func (c *DeliveryHandler) getDeliveryID(order *model.GoodsOrder, db *dao.DaoDB) (retVal int64, err error) {
// jxorder表当前已经有50多万条记录了加100万避免冲突 // jxorder表当前已经有50多万条记录了加100万避免冲突
// 508505 // 508505
return order.ID + 1000000, nil return order.ID + 1000000, nil
} }
func (c *DeliveryHandler) getMTPSShopID(order *model.GoodsOrder, db orm.Ormer) (retVal string, err error) { func (c *DeliveryHandler) getMTPSShopID(order *model.GoodsOrder, db *dao.DaoDB) (retVal string, err error) {
saleStoreID := jxutils.GetSaleStoreIDFromOrder(order) saleStoreID := jxutils.GetSaleStoreIDFromOrder(order)
db2 := dao.WrapDB(db) storeCourierList, err2 := dao.GetOpenedStoreCouriersByStoreID(db, saleStoreID, model.VendorIDMTPS)
storeCourierList, err2 := dao.GetOpenedStoreCouriersByStoreID(db2, saleStoreID, model.VendorIDMTPS)
if err = err2; err != nil && err != orm.ErrNoRows { if err = err2; err != nil && err != orm.ErrNoRows {
return "", err return "", err
} }

View File

@@ -166,6 +166,7 @@ func (p *PurchaseHandler) UpdateStore(db *dao.DaoDB, storeID int, userName strin
shopID = store.ID shopID = store.ID
} }
store2, err2 := p.ReadStore(store.VendorStoreID) store2, err2 := p.ReadStore(store.VendorStoreID)
// globals.SugarLogger.Debugf("ebai UpdateStore2 store2:%s, err2:%v", utils.Format4Output(store2, true), err2)
if err = err2; err == nil { if err = err2; err == nil {
if store2.ID == store.ID { if store2.ID == store.ID {
shopID = -1 shopID = -1

View File

@@ -387,16 +387,13 @@ func (p *PurchaseHandler) RefreshStoresAllSkusID(ctx *jxcontext.Context, parentT
func genSkuParamsFromStoreSkuInfo(storeSku *tStoreSkuFullInfo) (params map[string]interface{}) { func genSkuParamsFromStoreSkuInfo(storeSku *tStoreSkuFullInfo) (params map[string]interface{}) {
price := jxutils.CaculateSkuVendorPrice(storeSku.Price, storeSku.PricePercentage) price := jxutils.CaculateSkuVendorPrice(storeSku.Price, storeSku.PricePercentage)
params = map[string]interface{}{ params = map[string]interface{}{
"name": jxutils.ComposeSkuName(storeSku.Prefix, storeSku.Name, storeSku.Comment, storeSku.Unit, storeSku.SpecQuality, storeSku.SpecUnit, 0), "name": jxutils.ComposeSkuName(storeSku.Prefix, storeSku.Name, storeSku.Comment, storeSku.Unit, storeSku.SpecQuality, storeSku.SpecUnit, 0),
"status": jxSkuStatus2Ebai(jxutils.MergeSkuStatus(storeSku.SkuStatus, storeSku.Status)), "left_num": model.MaxStoreSkuStockQty,
"left_num": model.MaxStoreSkuStockQty, "category_id": storeSku.CatEbaiID,
"sale_price": price, "cat1_id": getEbaiCat(storeSku.EbaiCat1ID, 1),
"market_price": price, "cat2_id": getEbaiCat(storeSku.EbaiCat2ID, 2),
"category_id": storeSku.CatEbaiID, "cat3_id": getEbaiCat(storeSku.EbaiCat3ID, 3),
"cat1_id": getEbaiCat(storeSku.EbaiCat1ID, 1), "weight": storeSku.Weight,
"cat2_id": getEbaiCat(storeSku.EbaiCat2ID, 2),
"cat3_id": getEbaiCat(storeSku.EbaiCat3ID, 3),
"weight": storeSku.Weight,
"photos": []map[string]interface{}{ "photos": []map[string]interface{}{
map[string]interface{}{ map[string]interface{}{
"is_master": true, "is_master": true,
@@ -404,6 +401,13 @@ func genSkuParamsFromStoreSkuInfo(storeSku *tStoreSkuFullInfo) (params map[strin
}, },
}, },
} }
if storeSku.EbaiSyncStatus&(model.SyncFlagPriceMask|model.SyncFlagNewMask) != 0 {
params["sale_price"] = price
params["market_price"] = price
}
if storeSku.EbaiSyncStatus&(model.SyncFlagSaleMask|model.SyncFlagNewMask) != 0 {
params["status"] = jxSkuStatus2Ebai(jxutils.MergeSkuStatus(storeSku.SkuStatus, storeSku.Status))
}
// todo 饿百如果给的UPC是空要报错但如果我要删除UPC怎么弄 // todo 饿百如果给的UPC是空要报错但如果我要删除UPC怎么弄
if storeSku.Upc != "" { if storeSku.Upc != "" {
params["upc"] = storeSku.Upc params["upc"] = storeSku.Upc

View File

@@ -15,11 +15,14 @@ import (
"git.rosy.net.cn/jx-callback/business/partner" "git.rosy.net.cn/jx-callback/business/partner"
"git.rosy.net.cn/jx-callback/globals" "git.rosy.net.cn/jx-callback/globals"
"git.rosy.net.cn/jx-callback/globals/api" "git.rosy.net.cn/jx-callback/globals/api"
"github.com/astaxie/beego"
) )
const ( const (
DefBrandID = 35247 DefBrandID = 35247
DefJdCategoryID = 20362
DefJdCategoryID = 20362
DefJdCategoryID4Jxgy = 22410 // 其他国产水果
) )
type tSkuInfoExt struct { type tSkuInfoExt struct {
@@ -36,6 +39,13 @@ var (
} }
) )
func getDefJdCategoryID() int {
if beego.BConfig.RunMode == "jxgy" {
return DefJdCategoryID4Jxgy
}
return DefJdCategoryID
}
func (p *PurchaseHandler) CreateCategory(db *dao.DaoDB, cat *model.SkuCategory, userName string) (err error) { func (p *PurchaseHandler) CreateCategory(db *dao.DaoDB, cat *model.SkuCategory, userName string) (err error) {
var jdPid int64 var jdPid int64
if cat.ParentID != 0 { if cat.ParentID != 0 {
@@ -134,7 +144,7 @@ func (p *PurchaseHandler) cuSku(db *dao.DaoDB, sku *model.Sku, handler func(skuE
// shopCategories = append(shopCategories, skuInfoExt.SkuCatID) // shopCategories = append(shopCategories, skuInfoExt.SkuCatID)
// } // }
if skuInfoExt.JdCategoryID == 0 { if skuInfoExt.JdCategoryID == 0 {
skuInfoExt.JdCategoryID = DefJdCategoryID skuInfoExt.JdCategoryID = getDefJdCategoryID()
} }
if skuInfoExt.BrandID == 0 { if skuInfoExt.BrandID == 0 {
skuInfoExt.BrandID = DefBrandID skuInfoExt.BrandID = DefBrandID
@@ -176,6 +186,12 @@ func (p *PurchaseHandler) CreateSku(db *dao.DaoDB, sku *model.Sku, userName stri
if skuExt.IsSpu == 0 { if skuExt.IsSpu == 0 {
if globals.EnableStoreWrite { if globals.EnableStoreWrite {
vendorSkuID, err = api.JdAPI.AddSku(utils.Int2Str(sku.ID), skuExt.JdCategoryID, shopCategories, skuExt.BrandID, skuName, price, jxutils.IntWeight2Float(sku.Weight), []string{skuExt.Img}, jxStatus2jdStatus(sku.Status), true, addParams) vendorSkuID, err = api.JdAPI.AddSku(utils.Int2Str(sku.ID), skuExt.JdCategoryID, shopCategories, skuExt.BrandID, skuName, price, jxutils.IntWeight2Float(sku.Weight), []string{skuExt.Img}, jxStatus2jdStatus(sku.Status), true, addParams)
if err != nil {
if jdSkuID := jdapi.GetJdSkuIDFromError(err); jdSkuID > 0 {
vendorSkuID = utils.Int64ToStr(jdSkuID)
err = nil
}
}
} }
} else { } else {
vendorSkuID, err = p.syncSkuNameAsSpu(db, sku, skuExt, price, skuName, shopCategories, addParams) vendorSkuID, err = p.syncSkuNameAsSpu(db, sku, skuExt, price, skuName, shopCategories, addParams)

View File

@@ -301,6 +301,7 @@ func (p *PurchaseHandler) GetStoreStatus(ctx *jxcontext.Context, vendorStoreID s
return storeStatus, err return storeStatus, err
} }
// 当前京东的storeCrud消息不会在门店状态改变时发送所以意义不大先放在这里
func (c *PurchaseHandler) onStoreMsg(msg *jdapi.CallbackOrderMsg) (response *jdapi.CallbackResponse) { func (c *PurchaseHandler) onStoreMsg(msg *jdapi.CallbackOrderMsg) (response *jdapi.CallbackResponse) {
var err error var err error
if msg.StatusID == jdapi.StatusIDUpdateStore { if msg.StatusID == jdapi.StatusIDUpdateStore {
@@ -308,6 +309,11 @@ func (c *PurchaseHandler) onStoreMsg(msg *jdapi.CallbackOrderMsg) (response *jda
vendorStoreID := msg.BillID vendorStoreID := msg.BillID
if storeStatus, err = c.GetStoreStatus(jxcontext.AdminCtx, vendorStoreID); err == nil { if storeStatus, err = c.GetStoreStatus(jxcontext.AdminCtx, vendorStoreID); err == nil {
err = partner.CurStoreManager.OnStoreStatusChanged(vendorStoreID, model.VendorIDJD, storeStatus) err = partner.CurStoreManager.OnStoreStatusChanged(vendorStoreID, model.VendorIDJD, storeStatus)
} else {
// 可能在门店删除的情况下会出查不到门店的错误
if errExt, ok := err.(*utils.ErrorWithCode); ok && errExt.IntCode() == 4 {
err = nil
}
} }
} }
return jdapi.Err2CallbackResponse(err, "") return jdapi.Err2CallbackResponse(err, "")

View File

@@ -3,6 +3,8 @@ package wsc
import ( import (
"testing" "testing"
"git.rosy.net.cn/jx-callback/business/jxutils/jxcontext"
"git.rosy.net.cn/baseapi/utils" "git.rosy.net.cn/baseapi/utils"
"git.rosy.net.cn/jx-callback/business/jxutils/tasks" "git.rosy.net.cn/jx-callback/business/jxutils/tasks"
"git.rosy.net.cn/jx-callback/globals" "git.rosy.net.cn/jx-callback/globals"
@@ -19,7 +21,7 @@ func init() {
} }
func TestGetVendorCategories(t *testing.T) { func TestGetVendorCategories(t *testing.T) {
vendorCatList, err := new(PurchaseHandler).GetVendorCategories() vendorCatList, err := new(PurchaseHandler).GetVendorCategories(jxcontext.AdminCtx)
if err != nil { if err != nil {
t.Fatal(err.Error()) t.Fatal(err.Error())
} }

View File

@@ -39,9 +39,15 @@ showAppSecret = "384f911735334bf7a150f3bd3bdf0c1e"
weixinMsgToken = "weixin" weixinMsgToken = "weixin"
weixinMsgKey = "duyaeVYUsz8LuKBqJeQO1NX6KmoC43yfMsbJybcRJ3e" weixinMsgKey = "duyaeVYUsz8LuKBqJeQO1NX6KmoC43yfMsbJybcRJ3e"
weixinPageAppID = "wx018dbe7daa3d5627"
weixinPageSecret = "c7a84ed3ef3ae04ac78e02fb593ffbe5"
weixinMiniAppID = "wx4b5930c13f8b1170" weixinMiniAppID = "wx4b5930c13f8b1170"
weixinMiniSecret = "2a57228a716ce991a52739f0ff41111d" weixinMiniSecret = "2a57228a716ce991a52739f0ff41111d"
backstageHost = "http://www.jxc4.com"
wxBackstageHost = "http://wx.jxc4.com"
jdStorePageCookie = "YYJV3NHVBPHLD36FWP6F3EM5PTXJ2XZQS7U4HWRIDPP4IWGUKUIB4XG5N26CZRDLDF7PKOXBPD6BNTUAJLETLZOIWMCVFI3K6MYZIY4QBIXIMXYDJNUKFGJVQTN5356SAD6WPCIHWNQAG7DDMF7L7S3SHBUOPCIUXDX4MQEAYEPUFFOAD4WJECT4R3K22T24MKC7OMIRDLX7S55243TDVXLO25PP4UYSPTTPMNRUFXDNP4WPE566Q6V4AH32F7HT" jdStorePageCookie = "YYJV3NHVBPHLD36FWP6F3EM5PTXJ2XZQS7U4HWRIDPP4IWGUKUIB4XG5N26CZRDLDF7PKOXBPD6BNTUAJLETLZOIWMCVFI3K6MYZIY4QBIXIMXYDJNUKFGJVQTN5356SAD6WPCIHWNQAG7DDMF7L7S3SHBUOPCIUXDX4MQEAYEPUFFOAD4WJECT4R3K22T24MKC7OMIRDLX7S55243TDVXLO25PP4UYSPTTPMNRUFXDNP4WPE566Q6V4AH32F7HT"
ebaiStorePageCookieWMUSS = "AADIBAABbDlEpGl47c1EyBFcJSidBTBJHFHZEXyMSdBllJTZ9AUNOKV0tZFB9FlRVM73gEAIHRjBVagwAAHh98X2oPJ34Gal0ofFJBYXZ2Xnc6LCEXWQVnVxs7LDlaKBlFNz9DPCogYyZxJQhoHGVfVRIBa2oFUkEfDm1YZxZwLEwvZMjpB18rjw%7E3CaMQAo" ebaiStorePageCookieWMUSS = "AADIBAABbDlEpGl47c1EyBFcJSidBTBJHFHZEXyMSdBllJTZ9AUNOKV0tZFB9FlRVM73gEAIHRjBVagwAAHh98X2oPJ34Gal0ofFJBYXZ2Xnc6LCEXWQVnVxs7LDlaKBlFNz9DPCogYyZxJQhoHGVfVRIBa2oFUkEfDm1YZxZwLEwvZMjpB18rjw%7E3CaMQAo"
ebaiStorePageCookieWMSTOKEN = "HwXAAB9SGxnTT8pbEwWRDQsNGB3Y09_PF5rO157QUcoLRQAAAoKlgUEiVTOhIf5LjkCoFpAwwCaAAAUr-GEu-yDBeNAQAAHNneF25-uRjhYtgX4rsAAGHurh8C5GAQAA" ebaiStorePageCookieWMSTOKEN = "HwXAAB9SGxnTT8pbEwWRDQsNGB3Y09_PF5rO157QUcoLRQAAAoKlgUEiVTOhIf5LjkCoFpAwwCaAAAUr-GEu-yDBeNAQAAHNneF25-uRjhYtgX4rsAAGHurh8C5GAQAA"
@@ -51,9 +57,6 @@ weimobAppSecret = "7267AA7F58261F6965599218F5A1D592"
weimobStateSecret = "87ae9570-92dc-4c01-bcd9-1a15d441df6b" weimobStateSecret = "87ae9570-92dc-4c01-bcd9-1a15d441df6b"
weimobCallbackURL = "http://callback.test.jxc4.com/weimob" weimobCallbackURL = "http://callback.test.jxc4.com/weimob"
weixinPageAppID = "wx018dbe7daa3d5627"
weixinPageSecret = "c7a84ed3ef3ae04ac78e02fb593ffbe5"
dingdingAgentID = 241047291 dingdingAgentID = 241047291
dingdingAppKey = "dingpx4hcf55zb4ubewg" dingdingAppKey = "dingpx4hcf55zb4ubewg"
dingdingSecret = "1zooB4bmEXPesdwb1ElWASVQ1vinOSZM-1XCUFrrSjHsNAId1UuVCT5tmHSmg5_V" dingdingSecret = "1zooB4bmEXPesdwb1ElWASVQ1vinOSZM-1XCUFrrSjHsNAId1UuVCT5tmHSmg5_V"
@@ -78,6 +81,8 @@ yilianyunClientSecret = "4885d07c2997b661102e4b6099c0bf3b"
zhongwuAppID = 8000192 zhongwuAppID = 8000192
zhongwuAppSecret = "29435497822f52f3cf659c65da548a79" zhongwuAppSecret = "29435497822f52f3cf659c65da548a79"
getWeixinTokenKey = "c928ed0d-87a3-441a-8517-f92f0167296f"
[dev] [dev]
jdToken = "df97f334-f7d8-4b36-9664-5784d8ae0baf" jdToken = "df97f334-f7d8-4b36-9664-5784d8ae0baf"
jdAppKey = "06692746f7224695ad4788ce340bc854" jdAppKey = "06692746f7224695ad4788ce340bc854"
@@ -104,6 +109,8 @@ weixinToken = "17_roSCZgkCxhRnyFVtei0KdfHwdGP8PmLzJFhCieka4_X4_d-lgfaTxF6oIS6FE5
dbConnectStr = "root:WebServer@1@tcp(127.0.0.1:3306)/jxd_dev_0?charset=utf8mb4&loc=Local&parseTime=true" dbConnectStr = "root:WebServer@1@tcp(127.0.0.1:3306)/jxd_dev_0?charset=utf8mb4&loc=Local&parseTime=true"
getWeixinTokenURL = "http://beta.jxc4.com/v2/sys/GetWXToken"
[prod] [prod]
EnableDocs = false EnableDocs = false
@@ -148,34 +155,48 @@ dingdingCallbackURL = "http://callback.jxc4.com/dingding/msg"
httpport = 8088 httpport = 8088
EnableDocs = false EnableDocs = false
dbConnectStr = "root:WebServer@1@tcp(db1.int.jxc4.com:3306)/jxgy?charset=utf8mb4&loc=Local&parseTime=true" dbConnectStr = "root:WebServer@1@tcp(127.0.0.1:3306)/jxgy?charset=utf8mb4&loc=Local&parseTime=true"
jdToken = "b9f98667-9856-45e9-a31c-9a8862b1bfde" jdToken = "84541069-fbe2-424b-b625-9b2ba1d4c9e6"
jdAppKey = "5d5577a2506f41b8b4ec520ba83490f5" jdAppKey = "5d5577a2506f41b8b4ec520ba83490f5"
jdSecret = "0b01b9eeb15b41dab1c3d05d95c17a26" jdSecret = "0b01b9eeb15b41dab1c3d05d95c17a26"
disableEbai = true ebaiSource = "35957"
ebaiSecret = "10013fbb7c2ddad7"
disableElm = true disableElm = true
disableMtwm = true disableMtwm = true
disableWeimob = true disableWeimob = true
enableStoreWrite = true enableStoreWrite = true
enableEbaiStoreWrite = true
mtpsAppKey = "3c0a05d464c247c19d7ec13accc78605" mtpsAppKey = "3c0a05d464c247c19d7ec13accc78605"
mtpsSecret = "b1M}9?:sTbsB[OF2gNORnN(|(iy9rB8(`7]|[wGLnbmt`evfM>E:A90DjHAW:UPE" mtpsSecret = "b1M}9?:sTbsB[OF2gNORnN(|(iy9rB8(`7]|[wGLnbmt`evfM>E:A90DjHAW:UPE"
dadaIsProd = true dadaIsProd = true
dadaCallbackURL = "http://callback.jxc4.com/dadadelivery/msg" dadaCallbackURL = "http://callback-jxgy.jxc4.com/dadadelivery/msg"
dadaSourceID = "6660" dadaSourceID = "6660"
dingdingAgentID = 239461075 weixinAppID = "wx2bb99eb5d2c9b82c"
dingdingAppKey = "ding7iu9cptairtcls0c" weixinSecret = "6bbbed1443cc062c20a015a64c07a531"
dingdingSecret = "LWrZAFeqUfuVv7n_tc8vPpCAx6PT4CwManx2XCVhJOqGsx2L5XCDuX1sAN_JtvsI"
weixinMiniAppID = "wx2d6949f724b2541d"
weixinMiniSecret = "11f3c380551c4683c149990b004d6df9"
backstageHost = "http://www-jxgy.jxc4.com"
wxBackstageHost = "http://wx-jxgy.jxc4.com"
dingdingAgentID = 258707199
dingdingAppKey = "dingtozhutfr98qgwc7d"
dingdingSecret = "7EJ0HDbkxQri-O2RSaYUu7_ZwvvMKtRVHT8cpyfvIvK6A9n9HRwPNCNRJFuEDeT_"
dingdingQRCodeAppKey = "dingoaw990o1jm9jswvwib" dingdingQRCodeAppKey = "dingoaw990o1jm9jswvwib"
dingdingQRCodeSecret = "N9dyC9qB84sauQPs4_JYrILMsG5Krqm9-PSSVJ8t9hb87rrHiFUirISxGF5G57RV" dingdingQRCodeSecret = "N9dyC9qB84sauQPs4_JYrILMsG5Krqm9-PSSVJ8t9hb87rrHiFUirISxGF5G57RV"
dingdingCallbackURL = "http://callback.jxgy.jxc4.com/dingding/msg" dingdingCallbackURL = "http://callback-jxgy.jxc4.com/dingding/msg"
getWeixinTokenURL = "http://www.jxc4.com/v2/sys/GetWXToken"
[prod2] [prod2]
httpport = 8082 httpport = 8082

View File

@@ -139,3 +139,23 @@ func (c *SyncController) DeleteRemoteStoreSkus() {
return retVal, "", err return retVal, "", err
}) })
} }
// @Title 同步SkuName多门店平台
// @Description 同步SkuName多门店平台
// @Param token header string true "认证token"
// @Param nameIDs formData string false "name ID列表"
// @Param isForce formData bool false "是否强制(设置修改标志)"
// @Param isAsync formData bool false "是否异步"
// @Param isContinueWhenError formData bool false "单个同步失败是否继续缺省false"
// @Success 200 {object} controllers.CallResult
// @Failure 200 {object} controllers.CallResult
// @router /SyncSkuNames [put]
func (c *SyncController) SyncSkuNames() {
c.callSyncSkuNames(func(params *tSyncSyncSkuNamesParams) (retVal interface{}, errCode string, err error) {
var nameIDs []int
if err = jxutils.Strings2Objs(params.NameIDs, &nameIDs); err == nil {
retVal, err = cms.CurVendorSync.SyncSkuNames(params.Ctx, nameIDs, params.IsForce, params.IsAsync, params.IsContinueWhenError)
}
return retVal, "", err
})
}

View File

@@ -3,6 +3,7 @@ package controllers
import ( import (
"net/http" "net/http"
"git.rosy.net.cn/baseapi/platformapi/ebaiapi"
"git.rosy.net.cn/jx-callback/business/partner/purchase/ebai" "git.rosy.net.cn/jx-callback/business/partner/purchase/ebai"
"git.rosy.net.cn/jx-callback/globals/api" "git.rosy.net.cn/jx-callback/globals/api"
"github.com/astaxie/beego" "github.com/astaxie/beego"
@@ -19,7 +20,7 @@ func (c *EbaiController) Msg() {
callbackResponse = ebai.OnCallbackMsg(obj) callbackResponse = ebai.OnCallbackMsg(obj)
} }
if callbackResponse == nil { if callbackResponse == nil {
callbackResponse = api.EbaiAPI.Err2CallbackResponse(obj.Cmd, nil, nil) callbackResponse = api.EbaiAPI.Err2CallbackResponse(ebaiapi.GetCmd(c.Ctx.Request), nil, nil)
} }
c.Data["json"] = callbackResponse c.Data["json"] = callbackResponse
c.ServeJSON() c.ServeJSON()

View File

@@ -145,6 +145,9 @@ func (c *DjswController) StoreCrud() {
} }
func (c *DjswController) transferResponse(inCallbackResponse *jdapi.CallbackResponse) (outCallbackResponse *jdapi.CallbackResponse) { func (c *DjswController) transferResponse(inCallbackResponse *jdapi.CallbackResponse) (outCallbackResponse *jdapi.CallbackResponse) {
if globals.IsCallbackAlwaysReturnSuccess() {
return jdapi.SuccessResponse
}
if inCallbackResponse == nil { if inCallbackResponse == nil {
return jdapi.SuccessResponse return jdapi.SuccessResponse
} }

View File

@@ -309,7 +309,7 @@ func (c *OrderController) RefreshOrderRealMobile() {
// @router /SetOrderPrintStatus [put] // @router /SetOrderPrintStatus [put]
func (c *OrderController) SetOrderPrintStatus() { func (c *OrderController) SetOrderPrintStatus() {
c.callSetOrderPrintStatus(func(params *tOrderSetOrderPrintStatusParams) (retVal interface{}, errCode string, err error) { c.callSetOrderPrintStatus(func(params *tOrderSetOrderPrintStatusParams) (retVal interface{}, errCode string, err error) {
err = dao.SetOrderPrintFlag(dao.GetDB(), params.VendorOrderID, params.VendorID, params.IsPrinted) err = dao.SetOrderPrintFlag(dao.GetDB(), params.Ctx.GetUserName(), params.VendorOrderID, params.VendorID, params.IsPrinted)
return retVal, "", err return retVal, "", err
}) })
} }
@@ -362,7 +362,7 @@ func skuList2Map(skuList []*model.OrderSku) (skuMap map[int]*model.OrderSku) {
// @Param vendorOrderID formData string true "订单ID" // @Param vendorOrderID formData string true "订单ID"
// @Param vendorID formData int true "订单所属厂商ID" // @Param vendorID formData int true "订单所属厂商ID"
// @Param removedSkuInfo formData string true "要去除的商品信息只有skuID与Count字段有效" // @Param removedSkuInfo formData string true "要去除的商品信息只有skuID与Count字段有效"
// @Param reason formData string false "调整原因" // @Param reason formData string true "调整原因"
// @Success 200 {object} controllers.CallResult // @Success 200 {object} controllers.CallResult
// @Failure 200 {object} controllers.CallResult // @Failure 200 {object} controllers.CallResult
// @router /AdjustOrder [put] // @router /AdjustOrder [put]
@@ -371,7 +371,8 @@ func (c *OrderController) AdjustOrder() {
var skuList []*model.OrderSku var skuList []*model.OrderSku
err = jxutils.Strings2Objs(params.RemovedSkuInfo, &skuList) err = jxutils.Strings2Objs(params.RemovedSkuInfo, &skuList)
if err == nil { if err == nil {
order, err := partner.CurOrderManager.LoadOrder(params.VendorOrderID, params.VendorID) var order *model.GoodsOrder
order, err = partner.CurOrderManager.LoadOrder(params.VendorOrderID, params.VendorID)
if err == nil { if err == nil {
orderSkuMap := skuList2Map(order.Skus) orderSkuMap := skuList2Map(order.Skus)
removeSkuMap := skuList2Map(skuList) removeSkuMap := skuList2Map(skuList)

31
controllers/sys.go Normal file
View File

@@ -0,0 +1,31 @@
package controllers
import (
"time"
"git.rosy.net.cn/jx-callback/globals"
"git.rosy.net.cn/jx-callback/business/jxutils/eventhub/syseventhub"
"github.com/astaxie/beego"
)
type SysController struct {
beego.Controller
}
// @Title 得到京西门店信息
// @Description 得到京西门店信息,如下条件之间是与的关系
// @Param accessKey query string true "假token"
// @Param oldToken query string false "之前的token"
// @Param waitSecond query int false "等待秒数"
// @Success 200 {object} controllers.CallResult
// @Failure 200 {object} controllers.CallResult
// @router /GetWXToken [get]
func (c *SysController) GetWXToken() {
c.callGetWXToken(func(params *tSysGetWXTokenParams) (retVal interface{}, errCode string, err error) {
if params.AccessKey == globals.GetWeixinTokenKey {
retVal = syseventhub.SysEventHub.GetWXToken(params.OldToken, time.Duration(params.WaitSecond)*time.Second)
}
return retVal, "", err
})
}

View File

@@ -33,9 +33,9 @@ var (
MtpsAPI *mtpsapi.API MtpsAPI *mtpsapi.API
DadaAPI *dadaapi.API DadaAPI *dadaapi.API
MtwmAPI *mtwmapi.API MtwmAPI *mtwmapi.API
WeixinAPI *weixinapi.API WeixinAPI *weixinapi.API // 微信公众号
WeixinMiniAPI *weixinapi.API WeixinMiniAPI *weixinapi.API // 小程序
WeixinPageAPI *weixinapi.API WeixinPageAPI *weixinapi.API // 用户微信扫码登录
AutonaviAPI *autonavi.API AutonaviAPI *autonavi.API
QiniuAPI *qbox.Mac QiniuAPI *qbox.Mac

View File

@@ -36,15 +36,15 @@ func Init() {
orm.RegisterModel(&model.Promotion{}, &model.PromotionStore{}, &model.PromotionSku{}) orm.RegisterModel(&model.Promotion{}, &model.PromotionStore{}, &model.PromotionSku{})
orm.RegisterModel(&model.AuthBind{}, &model.User{}) orm.RegisterModel(&model.AuthBind{}, &model.User{})
orm.RegisterModel(&model.OrderFinancial{}, &model.AfsOrder{}, &model.OrderDiscountFinancial{}, &model.OrderSkuFinancial{})
// orm.RegisterModel(&model.ActivityForSku{}) // orm.RegisterModel(&model.ActivityForSku{})
// orm.RegisterModel(&legacymodel.JxBadComments2{}) // orm.RegisterModel(&legacymodel.JxBadComments2{})
if globals.EnablePendingChange { if globals.EnablePendingChange {
orm.RegisterModel(&model.StoreOpRequest{}) orm.RegisterModel(&model.StoreOpRequest{})
} }
// 如下语句建表时要出错INDEX名字太长了暂时放一下必须放最后一句
orm.RegisterModel(&model.OrderFinancial{}, &model.AfsOrder{}, &model.OrderDiscountFinancial{}, &model.OrderSkuFinancial{})
// create table // create table
orm.RunSyncdb("default", false, true) orm.RunSyncdb("default", false, true)
} }

View File

@@ -34,6 +34,12 @@ var (
QiniuBucket string QiniuBucket string
WeimobCallbackURL string WeimobCallbackURL string
WeimobStateSecret string WeimobStateSecret string
BackstageHost string
WxBackstageHost string
GetWeixinTokenURL string
GetWeixinTokenKey string
) )
func init() { func init() {
@@ -66,4 +72,22 @@ func Init() {
WeimobCallbackURL = beego.AppConfig.DefaultString("weimobCallbackURL", "") WeimobCallbackURL = beego.AppConfig.DefaultString("weimobCallbackURL", "")
WeimobStateSecret = beego.AppConfig.DefaultString("weimobStateSecret", "") WeimobStateSecret = beego.AppConfig.DefaultString("weimobStateSecret", "")
BackstageHost = beego.AppConfig.DefaultString("backstageHost", "")
WxBackstageHost = beego.AppConfig.DefaultString("wxBackstageHost", "")
GetWeixinTokenURL = beego.AppConfig.DefaultString("getWeixinTokenURL", "")
GetWeixinTokenKey = beego.AppConfig.DefaultString("getWeixinTokenKey", "")
}
func IsCallbackAlwaysReturnSuccess() bool {
return beego.BConfig.RunMode == "beta"
}
func IsMainProductEnv() bool {
return beego.BConfig.RunMode == "prod"
}
func IsProductEnv() bool {
return IsMainProductEnv() || beego.BConfig.RunMode == "jxgy"
} }

View File

@@ -120,7 +120,8 @@ func main() {
orderman.LoadPendingOrders() orderman.LoadPendingOrders()
// 延时的原因是等回调准备好 // 延时的原因是等回调准备好
if beego.BConfig.RunMode == "prod" { if beego.BConfig.RunMode == "prod" ||
beego.BConfig.RunMode == "jxgy" {
utils.AfterFuncWithRecover(2*time.Second, func() { utils.AfterFuncWithRecover(2*time.Second, func() {
api.DingDingAPI.DeleteCallback() api.DingDingAPI.DeleteCallback()
if err := api.DingDingAPI.RegisterCallback([]string{dingdingapi.CBTagUserAddOrg, dingdingapi.CBTagUserModifyOrg, dingdingapi.CBTagUserLeaveOrg}, beego.AppConfig.DefaultString("dingdingCallbackToken", ""), beego.AppConfig.DefaultString("dingdingCallbackAESKey", ""), beego.AppConfig.DefaultString("dingdingCallbackURL", "")); err != nil { if err := api.DingDingAPI.RegisterCallback([]string{dingdingapi.CBTagUserAddOrg, dingdingapi.CBTagUserModifyOrg, dingdingapi.CBTagUserLeaveOrg}, beego.AppConfig.DefaultString("dingdingCallbackToken", ""), beego.AppConfig.DefaultString("dingdingCallbackAESKey", ""), beego.AppConfig.DefaultString("dingdingCallbackURL", "")); err != nil {

View File

@@ -1240,6 +1240,15 @@ func init() {
Filters: nil, Filters: nil,
Params: nil}) Params: nil})
beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:SyncController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:SyncController"],
beego.ControllerComments{
Method: "SyncSkuNames",
Router: `/SyncSkuNames`,
AllowHTTPMethods: []string{"put"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:SyncController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:SyncController"], beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:SyncController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:SyncController"],
beego.ControllerComments{ beego.ControllerComments{
Method: "SyncStoresCategory", Method: "SyncStoresCategory",
@@ -1258,6 +1267,15 @@ func init() {
Filters: nil, Filters: nil,
Params: nil}) Params: nil})
beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:SysController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:SysController"],
beego.ControllerComments{
Method: "GetWXToken",
Router: `/GetWXToken`,
AllowHTTPMethods: []string{"get"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:TaskController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:TaskController"], beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:TaskController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:TaskController"],
beego.ControllerComments{ beego.ControllerComments{
Method: "CancelTask", Method: "CancelTask",

View File

@@ -101,6 +101,11 @@ func init() {
&controllers.TempOpController{}, &controllers.TempOpController{},
), ),
), ),
beego.NSNamespace("/sys",
beego.NSInclude(
&controllers.SysController{},
),
),
) )
beego.AddNamespace(ns) beego.AddNamespace(ns)