123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302 |
- package seller
- import (
- "Wine-Server/utils"
- "Wine-Server/utils/tables"
- "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) {
- version := tables.VersionTable{}
- err := version.GetLatest()
- if err != nil {
- ctx.JSON(utils.HttpError, utils.Fail("Get latest version failed"))
- return
- }
- ctx.JSON(utils.HttpOk, utils.Success(version))
- }
- 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
- }
- }
- _ = conn.WriteJSON(utils.WsEvent("wineResult", device.Wines))
- 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
- }
- _ = conn.WriteJSON(utils.WsEvent("advResult", advList))
- 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
- }
- _ = conn.WriteJSON(utils.WsEvent("runParamResult", runParams))
- _ = conn.WriteJSON(utils.WsEvent("initFinish", nil))
- }
- 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
- }
- 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
- }
- 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 {
- utils.Logger.Println("marshal trade failed:", err)
- _ = conn.WriteJSON(utils.WsError("marshal trade failed"))
- return
- }
- 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
- }
- 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(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
- }
- 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 `${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},
- },
- {
- "cell": 2,
- "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},
- },
- {
- "cell": 4,
- "old": utils.JsonType{"id": 13027, "name": "某一款酒名-2", "remain": 286},
- "new": utils.JsonType{"id": 13029, "name": "某一款酒名-3", "remain": 15000},
- },
- },
- }))
- break
- case "Fixing":
- // TODO: check redis `${did}_${param.who}_Fix` === param.code
- _ = conn.WriteJSON(utils.WsEvent("authCodeResult", utils.JsonType{
- "type": param.Type, "ok": true,
- }))
- break
- default:
- _ = conn.WriteJSON(utils.WsError("unrecognized open type"))
- }
- }
- func openResult(conn *websocket.Conn, data any) {
- var param resultParam
- err := utils.AnyTrans(data, ¶m)
- if err != nil {
- _ = conn.WriteJSON(utils.WsError("params error"))
- return
- }
- if worker, win := utils.WorkerWss[param.Who]; win {
- _ = worker.WriteJSON(utils.WsEvent("openResult", utils.JsonType{
- "type": param.Type, "result": param.Result,
- }))
- return
- }
- 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) {
- var param finishParam
- err := utils.AnyTrans(data, ¶m)
- if err != nil {
- _ = conn.WriteJSON(utils.WsError("params error"))
- return
- }
- if worker, win := utils.WorkerWss[param.Who]; win {
- _ = worker.WriteJSON(utils.WsEvent("workFinished", param.Type))
- return
- }
- if debugger, din := utils.DebugWss[param.Who]; din {
- _ = debugger.WriteJSON(utils.WsEvent("workFinished", param.Type))
- return
- }
- }
|