|
@@ -3,9 +3,13 @@ package seller
|
|
|
import (
|
|
|
"Wine-Server/utils"
|
|
|
"Wine-Server/utils/tables"
|
|
|
- "fmt"
|
|
|
+ "encoding/json"
|
|
|
+ "errors"
|
|
|
"github.com/gin-gonic/gin"
|
|
|
"github.com/gorilla/websocket"
|
|
|
+ "github.com/wechatpay-apiv3/wechatpay-go/core/auth/verifiers"
|
|
|
+ "github.com/wechatpay-apiv3/wechatpay-go/core/downloader"
|
|
|
+ "github.com/wechatpay-apiv3/wechatpay-go/core/notify"
|
|
|
)
|
|
|
|
|
|
func VersionHandler(ctx *gin.Context) {
|
|
@@ -18,15 +22,119 @@ func VersionHandler(ctx *gin.Context) {
|
|
|
ctx.JSON(utils.HttpOk, utils.Success(version))
|
|
|
}
|
|
|
|
|
|
-func infoOfDevice(device *tables.DeviceTable, conn *websocket.Conn) {
|
|
|
- _ = conn.WriteJSON(utils.WsEvent("locationResult", utils.JsonType{
|
|
|
- "val": device.Addr, "close": false,
|
|
|
- }))
|
|
|
+func updateWineInfo(trade *tradeRedis) (uint16, error) {
|
|
|
+ wine := tables.WineTable{Id: trade.Wine}
|
|
|
+ err := wine.Get()
|
|
|
+ if err != nil {
|
|
|
+ utils.Logger.Println("wine get error:", err)
|
|
|
+ return 0, err
|
|
|
+ }
|
|
|
+ wine.Income += uint64(trade.Cash)
|
|
|
+ wine.Order++
|
|
|
+ err = wine.UpdateSelf()
|
|
|
+ if err != nil {
|
|
|
+ utils.Logger.Println("wine update error:", err)
|
|
|
+ return 0, err
|
|
|
+ }
|
|
|
+ return uint16(50*float64(trade.Weight)/float64(wine.Density)/1000 + 0.5), nil
|
|
|
+}
|
|
|
+
|
|
|
+func updateDeviceInfo(trade *tradeRedis, volume uint16) (string, error) {
|
|
|
+ table := tables.DeviceTable{Id: trade.Device}
|
|
|
+ err := table.Get()
|
|
|
+ if err != nil {
|
|
|
+ utils.Logger.Println("device get error:", err)
|
|
|
+ return "", err
|
|
|
+ }
|
|
|
+ table.Order++
|
|
|
+ table.Income += uint64(trade.Cash)
|
|
|
+ table.Wines[trade.Cell].Remain -= volume
|
|
|
+ err = table.UpdateSelf()
|
|
|
+ if err != nil {
|
|
|
+ utils.Logger.Println("device update error:", err)
|
|
|
+ return "", err
|
|
|
+ }
|
|
|
+
|
|
|
+ return table.Manager, nil
|
|
|
+}
|
|
|
+
|
|
|
+func updateManagerInfo(mid string, trade *tradeRedis) error {
|
|
|
+ if mid == "" {
|
|
|
+ utils.Logger.Println("blank manager id")
|
|
|
+ return errors.New("blank manager id")
|
|
|
+ }
|
|
|
+ table := tables.ManagerTable{Id: mid}
|
|
|
+ err := table.Get()
|
|
|
+ if err != nil {
|
|
|
+ utils.Logger.Println("manager get error:", err)
|
|
|
+ return err
|
|
|
+ }
|
|
|
+ table.Order++
|
|
|
+ table.Income += uint64(trade.Cash)
|
|
|
+ err = table.UpdateSelf()
|
|
|
+ if err != nil {
|
|
|
+ utils.Logger.Println("manager update error:", err)
|
|
|
+ return err
|
|
|
+ }
|
|
|
+ return nil
|
|
|
+}
|
|
|
|
|
|
+func WxPayHandler(ctx *gin.Context) {
|
|
|
+ err := downloader.MgrInstance().RegisterDownloaderWithPrivateKey(
|
|
|
+ utils.WxPayCli, utils.WxPrivateKey, utils.WxCertSeq, utils.WxMchId, utils.WxV3Key,
|
|
|
+ )
|
|
|
+ visitor := downloader.MgrInstance().GetCertificateVisitor(utils.WxMchId)
|
|
|
+ handler, _ := notify.NewRSANotifyHandler(utils.WxV3Key, verifiers.NewSHA256WithRSAVerifier(visitor))
|
|
|
+ var wxNotify notifyParam
|
|
|
+ _, err = handler.ParseNotifyRequest(utils.WxPayCli, ctx.Request, &wxNotify)
|
|
|
+ if wxNotify.TradeState != "SUCCESS" {
|
|
|
+ utils.Logger.Printf("trade[%s] status[%s]\n", wxNotify.TradeNo, wxNotify.TradeState)
|
|
|
+ ctx.JSON(utils.HttpOk, utils.Success(nil))
|
|
|
+ return
|
|
|
+ }
|
|
|
+ dbKey := utils.Format("WxPay_%s", wxNotify.TradeNo)
|
|
|
+ exist, err := utils.Redis.Exists(utils.WxPayCli, dbKey).Result()
|
|
|
+ if exist != 1 {
|
|
|
+ utils.Logger.Println("re-notified or expire of:", wxNotify.TradeNo)
|
|
|
+ ctx.JSON(utils.HttpOk, utils.Success(nil))
|
|
|
+ return
|
|
|
+ }
|
|
|
+ res, err := utils.Redis.Get(utils.WxPayCli, dbKey).Result()
|
|
|
+ var dbTrade tradeRedis
|
|
|
+ err = json.Unmarshal([]byte(res), &dbTrade)
|
|
|
+ utils.Redis.Del(utils.WxPayCli, dbKey)
|
|
|
+
|
|
|
+ volume, err := updateWineInfo(&dbTrade)
|
|
|
+ manager, err := updateDeviceInfo(&dbTrade, volume)
|
|
|
+ err = updateManagerInfo(manager, &dbTrade)
|
|
|
+
|
|
|
+ table := tables.TradeTable{
|
|
|
+ Id: wxNotify.TransactionId, Trade: wxNotify.TradeNo, Device: dbTrade.Device, Payer: wxNotify.Payer.Openid,
|
|
|
+ Wine: dbTrade.Wine, Weight: dbTrade.Weight, Cash: dbTrade.Cash, Manager: manager,
|
|
|
+ }
|
|
|
+ err = table.Insert()
|
|
|
+ if err != nil {
|
|
|
+ ctx.JSON(utils.HttpError, utils.Fail("server error"))
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if device, din := utils.SellerDevices[dbTrade.Device]; din {
|
|
|
+ if device.Online {
|
|
|
+ _ = device.Conn.WriteJSON(utils.WsEvent("qrcodeScanned", nil))
|
|
|
+ utils.Sleep(1)
|
|
|
+ _ = device.Conn.WriteJSON(utils.WsEvent("orderPayed", volume))
|
|
|
+
|
|
|
+ ctx.JSON(utils.HttpOk, utils.Success(nil))
|
|
|
+ }
|
|
|
+ }
|
|
|
+ ctx.JSON(utils.HttpError, utils.Fail("server error"))
|
|
|
+}
|
|
|
+
|
|
|
+func infoOfDevice(device *tables.DeviceTable, conn *websocket.Conn) {
|
|
|
var err error
|
|
|
for i := 0; i < 4; i++ {
|
|
|
err = device.Wines[i].Get()
|
|
|
if err != nil {
|
|
|
+ utils.Logger.Println("Query wine info failed:", err)
|
|
|
_ = conn.WriteJSON(utils.WsError("Query wine info failed"))
|
|
|
return
|
|
|
}
|
|
@@ -36,6 +144,7 @@ func infoOfDevice(device *tables.DeviceTable, conn *websocket.Conn) {
|
|
|
var advList []tables.AdvertiseTable
|
|
|
advList, err = tables.AdvListAll()
|
|
|
if err != nil {
|
|
|
+ utils.Logger.Println("Query advertise failed:", err)
|
|
|
_ = conn.WriteJSON(utils.WsError("Query advertise failed"))
|
|
|
return
|
|
|
}
|
|
@@ -44,6 +153,7 @@ func infoOfDevice(device *tables.DeviceTable, conn *websocket.Conn) {
|
|
|
var runParams []tables.ParamsTable
|
|
|
runParams, err = tables.ParamsListAll()
|
|
|
if err != nil {
|
|
|
+ utils.Logger.Println("Query running params failed:", err)
|
|
|
_ = conn.WriteJSON(utils.WsError("Query running params failed"))
|
|
|
return
|
|
|
}
|
|
@@ -51,95 +161,99 @@ func infoOfDevice(device *tables.DeviceTable, conn *websocket.Conn) {
|
|
|
_ = conn.WriteJSON(utils.WsEvent("initFinish", nil))
|
|
|
}
|
|
|
|
|
|
-func updateLocation(device *tables.DeviceTable, conn *websocket.Conn, data any) {
|
|
|
- if data == "" {
|
|
|
- _ = conn.WriteJSON(utils.WsError("Blank address is not allowed"))
|
|
|
+func keepAlive(conn *websocket.Conn, data any) {
|
|
|
+ _ = conn.WriteJSON(utils.WsEvent("pon", data))
|
|
|
+}
|
|
|
+
|
|
|
+func getQrcode(device *tables.DeviceTable, conn *websocket.Conn, data any) {
|
|
|
+ var param qrcodeParam
|
|
|
+ err := utils.AnyTrans(data, ¶m)
|
|
|
+ if err != nil {
|
|
|
+ _ = conn.WriteJSON(utils.WsError("param error"))
|
|
|
return
|
|
|
}
|
|
|
- if device.Addr != data {
|
|
|
- err := device.Update(utils.JsonType{"addr": data})
|
|
|
- if err != nil {
|
|
|
- _ = conn.WriteJSON(utils.WsError("Update location failed"))
|
|
|
- return
|
|
|
- }
|
|
|
- _ = conn.WriteJSON(utils.WsEvent("locationResult", utils.JsonType{
|
|
|
- "val": data, "close": true,
|
|
|
- }))
|
|
|
+ wine := tables.WineTable{Id: param.Id}
|
|
|
+ err = wine.Get()
|
|
|
+ if err != nil {
|
|
|
+ utils.Logger.Printf("Query wine[%d] failed: %s\n", param.Id, err)
|
|
|
+ _ = conn.WriteJSON(utils.WsError(utils.Format("no such wine: %d", param.Id)))
|
|
|
return
|
|
|
}
|
|
|
- _ = conn.WriteJSON(utils.WsError("same location"))
|
|
|
-}
|
|
|
-
|
|
|
-type wineParam struct {
|
|
|
- Id uint16 `json:"id"`
|
|
|
- Weight int `json:"weight"`
|
|
|
-}
|
|
|
-
|
|
|
-func getQrcode(conn *websocket.Conn, data any) {
|
|
|
- var list []wineParam
|
|
|
- err := utils.AnyTrans(data, &list)
|
|
|
+ cash := int(param.Weight) * int(wine.Price)
|
|
|
+ if cash != param.Cash {
|
|
|
+ utils.Logger.Printf("got a wrong cash[user: %d, need: %d]\n", param.Cash, cash)
|
|
|
+ _ = conn.WriteJSON(utils.WsError(utils.Format("got a wrong cash[you: %d, real: %d]", param.Cash, cash)))
|
|
|
+ return
|
|
|
+ }
|
|
|
+ _ = device.Get()
|
|
|
+ trade := device.Id + utils.TimeString()
|
|
|
+ store := tradeRedis{Device: device.Id, Cell: param.Cell, Wine: wine.Id, Weight: param.Weight, Cash: cash}
|
|
|
+ marshal, err := json.Marshal(store)
|
|
|
if err != nil {
|
|
|
- _ = conn.WriteJSON(utils.WsError("param error"))
|
|
|
+ utils.Logger.Println("marshal trade failed:", err)
|
|
|
+ _ = conn.WriteJSON(utils.WsError("marshal trade failed"))
|
|
|
return
|
|
|
}
|
|
|
- sum := 0
|
|
|
- for _, item := range list {
|
|
|
- wine := tables.WineTable{Id: item.Id}
|
|
|
- err = wine.Get()
|
|
|
- if err != nil {
|
|
|
- _ = conn.WriteJSON(utils.WsError(fmt.Sprintf("no such wine: %d", item.Id)))
|
|
|
- return
|
|
|
- }
|
|
|
- sum += item.Weight * int(wine.Price)
|
|
|
+ err = utils.Redis.Set(utils.WxPayCli, utils.Format("WxPay_%s", trade), marshal, utils.Duration(1800)).Err()
|
|
|
+ if err != nil {
|
|
|
+ utils.Logger.Println("store trade failed:", err)
|
|
|
+ _ = conn.WriteJSON(utils.WsError("store trade failed"))
|
|
|
+ return
|
|
|
}
|
|
|
- fmt.Println(sum)
|
|
|
- _ = conn.WriteJSON(utils.WsEvent("qrcodeOkayed", "/seller/icon/qrcode.svg"))
|
|
|
-}
|
|
|
|
|
|
-type authParam struct {
|
|
|
- Type string `json:"type"`
|
|
|
- Wid string `json:"wid"`
|
|
|
- Code string `json:"code"`
|
|
|
+ var img []byte
|
|
|
+ img, err = utils.TryWxPay(trade, wine.Name, cash)
|
|
|
+ if err != nil {
|
|
|
+ utils.Logger.Println("access to wxpay failed:", err)
|
|
|
+ _ = conn.WriteJSON(utils.WsError("access to Wechat Pay failed"))
|
|
|
+ return
|
|
|
+ }
|
|
|
+ _ = conn.WriteJSON(utils.WsEvent("qrcodeOkayed", img))
|
|
|
}
|
|
|
|
|
|
-func checkAuthCode(conn *websocket.Conn, did string, data any) {
|
|
|
+func checkAuthCode(did string, conn *websocket.Conn, data any) {
|
|
|
var param authParam
|
|
|
err := utils.AnyTrans(data, ¶m)
|
|
|
if err != nil {
|
|
|
_ = conn.WriteJSON(utils.WsError("params error"))
|
|
|
return
|
|
|
}
|
|
|
- fmt.Printf("checkAuthCode: device[%s], code[%s]\n", did, data)
|
|
|
+ if param.Code != "284655" {
|
|
|
+ _ = conn.WriteJSON(utils.WsEvent("authCodeResult", utils.JsonType{
|
|
|
+ "type": param.Type, "ok": false,
|
|
|
+ }))
|
|
|
+ return
|
|
|
+ }
|
|
|
switch param.Type {
|
|
|
case "Changing":
|
|
|
- // TODO: check redis `Change_${did}_${param.wid}` === param.code, query real work
|
|
|
+ // TODO: check redis `${did}_${param.who}_Change` === param.code, query real work
|
|
|
_ = conn.WriteJSON(utils.WsEvent("authCodeResult", utils.JsonType{
|
|
|
"type": param.Type, "ok": true, "work": []utils.JsonType{
|
|
|
{
|
|
|
"cell": 1,
|
|
|
- "old": utils.JsonType{"id": 13026, "name": "某一款酒名-1", "remain": 300},
|
|
|
- "new": utils.JsonType{"id": 13026, "name": "某一款酒名-1", "remain": 15000},
|
|
|
+ "old": utils.JsonType{"id": 13026, "name": "某一款酒名-1", "remain": 300},
|
|
|
+ "new": utils.JsonType{"id": 13026, "name": "某一款酒名-1", "remain": 15000},
|
|
|
},
|
|
|
{
|
|
|
"cell": 2,
|
|
|
- "old": utils.JsonType{"id": 13027, "name": "某一款酒名-2", "remain": 286},
|
|
|
- "new": utils.JsonType{"id": 13029, "name": "某一款酒名-3", "remain": 15000},
|
|
|
+ "old": utils.JsonType{"id": 13027, "name": "某一款酒名-2", "remain": 286},
|
|
|
+ "new": utils.JsonType{"id": 13029, "name": "某一款酒名-3", "remain": 15000},
|
|
|
},
|
|
|
{
|
|
|
"cell": 3,
|
|
|
- "old": utils.JsonType{"id": 13027, "name": "某一款酒名-2", "remain": 286},
|
|
|
- "new": utils.JsonType{"id": 13029, "name": "某一款酒名-3", "remain": 15000},
|
|
|
+ "old": utils.JsonType{"id": 13027, "name": "某一款酒名-2", "remain": 286},
|
|
|
+ "new": utils.JsonType{"id": 13029, "name": "某一款酒名-3", "remain": 15000},
|
|
|
},
|
|
|
{
|
|
|
"cell": 4,
|
|
|
- "old": utils.JsonType{"id": 13027, "name": "某一款酒名-2", "remain": 286},
|
|
|
- "new": utils.JsonType{"id": 13029, "name": "某一款酒名-3", "remain": 15000},
|
|
|
+ "old": utils.JsonType{"id": 13027, "name": "某一款酒名-2", "remain": 286},
|
|
|
+ "new": utils.JsonType{"id": 13029, "name": "某一款酒名-3", "remain": 15000},
|
|
|
},
|
|
|
},
|
|
|
}))
|
|
|
break
|
|
|
case "Fixing":
|
|
|
- // TODO: check redis `Fix_${did}_${param.wid}` === param.code
|
|
|
+ // TODO: check redis `${did}_${param.who}_Fix` === param.code
|
|
|
_ = conn.WriteJSON(utils.WsEvent("authCodeResult", utils.JsonType{
|
|
|
"type": param.Type, "ok": true,
|
|
|
}))
|
|
@@ -149,12 +263,6 @@ func checkAuthCode(conn *websocket.Conn, did string, data any) {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-type resultParam struct {
|
|
|
- Type string `json:"type"`
|
|
|
- Wid string `json:"wid"`
|
|
|
- Result bool `json:"result"`
|
|
|
-}
|
|
|
-
|
|
|
func openResult(conn *websocket.Conn, data any) {
|
|
|
var param resultParam
|
|
|
err := utils.AnyTrans(data, ¶m)
|
|
@@ -162,18 +270,18 @@ func openResult(conn *websocket.Conn, data any) {
|
|
|
_ = conn.WriteJSON(utils.WsError("params error"))
|
|
|
return
|
|
|
}
|
|
|
- if worker, win := utils.WorkerWss[param.Wid]; win {
|
|
|
+ if worker, win := utils.WorkerWss[param.Who]; win {
|
|
|
_ = worker.WriteJSON(utils.WsEvent("openResult", utils.JsonType{
|
|
|
"type": param.Type, "result": param.Result,
|
|
|
}))
|
|
|
return
|
|
|
}
|
|
|
- _ = conn.WriteJSON(utils.WsError("no such worker"))
|
|
|
-}
|
|
|
-
|
|
|
-type finishParam struct {
|
|
|
- Type string `json:"type"`
|
|
|
- Wid string `json:"wid"`
|
|
|
+ if debugger, din := utils.DebugWss[param.Who]; din {
|
|
|
+ _ = debugger.WriteJSON(utils.WsEvent("openResult", utils.JsonType{
|
|
|
+ "type": param.Type, "result": param.Result,
|
|
|
+ }))
|
|
|
+ return
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
func workFinished(conn *websocket.Conn, data any) {
|
|
@@ -183,9 +291,12 @@ func workFinished(conn *websocket.Conn, data any) {
|
|
|
_ = conn.WriteJSON(utils.WsError("params error"))
|
|
|
return
|
|
|
}
|
|
|
- if worker, win := utils.WorkerWss[param.Wid]; win {
|
|
|
+ if worker, win := utils.WorkerWss[param.Who]; win {
|
|
|
_ = worker.WriteJSON(utils.WsEvent("workFinished", param.Type))
|
|
|
- } else {
|
|
|
- _ = conn.WriteJSON(utils.WsError("no such worker"))
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if debugger, din := utils.DebugWss[param.Who]; din {
|
|
|
+ _ = debugger.WriteJSON(utils.WsEvent("workFinished", param.Type))
|
|
|
+ return
|
|
|
}
|
|
|
}
|