worker.go 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302
  1. package seller
  2. import (
  3. "Wine-Server/utils"
  4. "Wine-Server/utils/tables"
  5. "encoding/json"
  6. "errors"
  7. "github.com/gin-gonic/gin"
  8. "github.com/gorilla/websocket"
  9. "github.com/wechatpay-apiv3/wechatpay-go/core/auth/verifiers"
  10. "github.com/wechatpay-apiv3/wechatpay-go/core/downloader"
  11. "github.com/wechatpay-apiv3/wechatpay-go/core/notify"
  12. )
  13. func VersionHandler(ctx *gin.Context) {
  14. version := tables.VersionTable{}
  15. err := version.GetLatest()
  16. if err != nil {
  17. ctx.JSON(utils.HttpError, utils.Fail("Get latest version failed"))
  18. return
  19. }
  20. ctx.JSON(utils.HttpOk, utils.Success(version))
  21. }
  22. func updateWineInfo(trade *tradeRedis) (uint16, error) {
  23. wine := tables.WineTable{Id: trade.Wine}
  24. err := wine.Get()
  25. if err != nil {
  26. utils.Logger.Println("wine get error:", err)
  27. return 0, err
  28. }
  29. wine.Income += uint64(trade.Cash)
  30. wine.Order++
  31. err = wine.UpdateSelf()
  32. if err != nil {
  33. utils.Logger.Println("wine update error:", err)
  34. return 0, err
  35. }
  36. return uint16(50*float64(trade.Weight)/float64(wine.Density)/1000 + 0.5), nil
  37. }
  38. func updateDeviceInfo(trade *tradeRedis, volume uint16) (string, error) {
  39. table := tables.DeviceTable{Id: trade.Device}
  40. err := table.Get()
  41. if err != nil {
  42. utils.Logger.Println("device get error:", err)
  43. return "", err
  44. }
  45. table.Order++
  46. table.Income += uint64(trade.Cash)
  47. table.Wines[trade.Cell].Remain -= volume
  48. err = table.UpdateSelf()
  49. if err != nil {
  50. utils.Logger.Println("device update error:", err)
  51. return "", err
  52. }
  53. return table.Manager, nil
  54. }
  55. func updateManagerInfo(mid string, trade *tradeRedis) error {
  56. if mid == "" {
  57. utils.Logger.Println("blank manager id")
  58. return errors.New("blank manager id")
  59. }
  60. table := tables.ManagerTable{Id: mid}
  61. err := table.Get()
  62. if err != nil {
  63. utils.Logger.Println("manager get error:", err)
  64. return err
  65. }
  66. table.Order++
  67. table.Income += uint64(trade.Cash)
  68. err = table.UpdateSelf()
  69. if err != nil {
  70. utils.Logger.Println("manager update error:", err)
  71. return err
  72. }
  73. return nil
  74. }
  75. func WxPayHandler(ctx *gin.Context) {
  76. err := downloader.MgrInstance().RegisterDownloaderWithPrivateKey(
  77. utils.WxPayCli, utils.WxPrivateKey, utils.WxCertSeq, utils.WxMchId, utils.WxV3Key,
  78. )
  79. visitor := downloader.MgrInstance().GetCertificateVisitor(utils.WxMchId)
  80. handler, _ := notify.NewRSANotifyHandler(utils.WxV3Key, verifiers.NewSHA256WithRSAVerifier(visitor))
  81. var wxNotify notifyParam
  82. _, err = handler.ParseNotifyRequest(utils.WxPayCli, ctx.Request, &wxNotify)
  83. if wxNotify.TradeState != "SUCCESS" {
  84. utils.Logger.Printf("trade[%s] status[%s]\n", wxNotify.TradeNo, wxNotify.TradeState)
  85. ctx.JSON(utils.HttpOk, utils.Success(nil))
  86. return
  87. }
  88. dbKey := utils.Format("WxPay_%s", wxNotify.TradeNo)
  89. exist, err := utils.Redis.Exists(utils.WxPayCli, dbKey).Result()
  90. if exist != 1 {
  91. utils.Logger.Println("re-notified or expire of:", wxNotify.TradeNo)
  92. ctx.JSON(utils.HttpOk, utils.Success(nil))
  93. return
  94. }
  95. res, err := utils.Redis.Get(utils.WxPayCli, dbKey).Result()
  96. var dbTrade tradeRedis
  97. err = json.Unmarshal([]byte(res), &dbTrade)
  98. utils.Redis.Del(utils.WxPayCli, dbKey)
  99. volume, err := updateWineInfo(&dbTrade)
  100. manager, err := updateDeviceInfo(&dbTrade, volume)
  101. err = updateManagerInfo(manager, &dbTrade)
  102. table := tables.TradeTable{
  103. Id: wxNotify.TransactionId, Trade: wxNotify.TradeNo, Device: dbTrade.Device, Payer: wxNotify.Payer.Openid,
  104. Wine: dbTrade.Wine, Weight: dbTrade.Weight, Cash: dbTrade.Cash, Manager: manager,
  105. }
  106. err = table.Insert()
  107. if err != nil {
  108. ctx.JSON(utils.HttpError, utils.Fail("server error"))
  109. return
  110. }
  111. if device, din := utils.SellerDevices[dbTrade.Device]; din {
  112. if device.Online {
  113. _ = device.Conn.WriteJSON(utils.WsEvent("qrcodeScanned", nil))
  114. utils.Sleep(1)
  115. _ = device.Conn.WriteJSON(utils.WsEvent("orderPayed", volume))
  116. ctx.JSON(utils.HttpOk, utils.Success(nil))
  117. }
  118. }
  119. ctx.JSON(utils.HttpError, utils.Fail("server error"))
  120. }
  121. func infoOfDevice(device *tables.DeviceTable, conn *websocket.Conn) {
  122. var err error
  123. for i := 0; i < 4; i++ {
  124. err = device.Wines[i].Get()
  125. if err != nil {
  126. utils.Logger.Println("Query wine info failed:", err)
  127. _ = conn.WriteJSON(utils.WsError("Query wine info failed"))
  128. return
  129. }
  130. }
  131. _ = conn.WriteJSON(utils.WsEvent("wineResult", device.Wines))
  132. var advList []tables.AdvertiseTable
  133. advList, err = tables.AdvListAll()
  134. if err != nil {
  135. utils.Logger.Println("Query advertise failed:", err)
  136. _ = conn.WriteJSON(utils.WsError("Query advertise failed"))
  137. return
  138. }
  139. _ = conn.WriteJSON(utils.WsEvent("advResult", advList))
  140. var runParams []tables.ParamsTable
  141. runParams, err = tables.ParamsListAll()
  142. if err != nil {
  143. utils.Logger.Println("Query running params failed:", err)
  144. _ = conn.WriteJSON(utils.WsError("Query running params failed"))
  145. return
  146. }
  147. _ = conn.WriteJSON(utils.WsEvent("runParamResult", runParams))
  148. _ = conn.WriteJSON(utils.WsEvent("initFinish", nil))
  149. }
  150. func keepAlive(conn *websocket.Conn, data any) {
  151. _ = conn.WriteJSON(utils.WsEvent("pon", data))
  152. }
  153. func getQrcode(device *tables.DeviceTable, conn *websocket.Conn, data any) {
  154. var param qrcodeParam
  155. err := utils.AnyTrans(data, &param)
  156. if err != nil {
  157. _ = conn.WriteJSON(utils.WsError("param error"))
  158. return
  159. }
  160. wine := tables.WineTable{Id: param.Id}
  161. err = wine.Get()
  162. if err != nil {
  163. utils.Logger.Printf("Query wine[%d] failed: %s\n", param.Id, err)
  164. _ = conn.WriteJSON(utils.WsError(utils.Format("no such wine: %d", param.Id)))
  165. return
  166. }
  167. cash := int(param.Weight) * int(wine.Price)
  168. if cash != param.Cash {
  169. utils.Logger.Printf("got a wrong cash[user: %d, need: %d]\n", param.Cash, cash)
  170. _ = conn.WriteJSON(utils.WsError(utils.Format("got a wrong cash[you: %d, real: %d]", param.Cash, cash)))
  171. return
  172. }
  173. _ = device.Get()
  174. trade := device.Id + utils.TimeString()
  175. store := tradeRedis{Device: device.Id, Cell: param.Cell, Wine: wine.Id, Weight: param.Weight, Cash: cash}
  176. marshal, err := json.Marshal(store)
  177. if err != nil {
  178. utils.Logger.Println("marshal trade failed:", err)
  179. _ = conn.WriteJSON(utils.WsError("marshal trade failed"))
  180. return
  181. }
  182. err = utils.Redis.Set(utils.WxPayCli, utils.Format("WxPay_%s", trade), marshal, utils.Duration(1800)).Err()
  183. if err != nil {
  184. utils.Logger.Println("store trade failed:", err)
  185. _ = conn.WriteJSON(utils.WsError("store trade failed"))
  186. return
  187. }
  188. var img []byte
  189. img, err = utils.TryWxPay(trade, wine.Name, cash)
  190. if err != nil {
  191. utils.Logger.Println("access to wxpay failed:", err)
  192. _ = conn.WriteJSON(utils.WsError("access to Wechat Pay failed"))
  193. return
  194. }
  195. _ = conn.WriteJSON(utils.WsEvent("qrcodeOkayed", img))
  196. }
  197. func checkAuthCode(did string, conn *websocket.Conn, data any) {
  198. var param authParam
  199. err := utils.AnyTrans(data, &param)
  200. if err != nil {
  201. _ = conn.WriteJSON(utils.WsError("params error"))
  202. return
  203. }
  204. if param.Code != "284655" {
  205. _ = conn.WriteJSON(utils.WsEvent("authCodeResult", utils.JsonType{
  206. "type": param.Type, "ok": false,
  207. }))
  208. return
  209. }
  210. switch param.Type {
  211. case "Changing":
  212. // TODO: check redis `${did}_${param.who}_Change` === param.code, query real work
  213. _ = conn.WriteJSON(utils.WsEvent("authCodeResult", utils.JsonType{
  214. "type": param.Type, "ok": true, "work": []utils.JsonType{
  215. {
  216. "cell": 1,
  217. "old": utils.JsonType{"id": 13026, "name": "某一款酒名-1", "remain": 300},
  218. "new": utils.JsonType{"id": 13026, "name": "某一款酒名-1", "remain": 15000},
  219. },
  220. {
  221. "cell": 2,
  222. "old": utils.JsonType{"id": 13027, "name": "某一款酒名-2", "remain": 286},
  223. "new": utils.JsonType{"id": 13029, "name": "某一款酒名-3", "remain": 15000},
  224. },
  225. {
  226. "cell": 3,
  227. "old": utils.JsonType{"id": 13027, "name": "某一款酒名-2", "remain": 286},
  228. "new": utils.JsonType{"id": 13029, "name": "某一款酒名-3", "remain": 15000},
  229. },
  230. {
  231. "cell": 4,
  232. "old": utils.JsonType{"id": 13027, "name": "某一款酒名-2", "remain": 286},
  233. "new": utils.JsonType{"id": 13029, "name": "某一款酒名-3", "remain": 15000},
  234. },
  235. },
  236. }))
  237. break
  238. case "Fixing":
  239. // TODO: check redis `${did}_${param.who}_Fix` === param.code
  240. _ = conn.WriteJSON(utils.WsEvent("authCodeResult", utils.JsonType{
  241. "type": param.Type, "ok": true,
  242. }))
  243. break
  244. default:
  245. _ = conn.WriteJSON(utils.WsError("unrecognized open type"))
  246. }
  247. }
  248. func openResult(conn *websocket.Conn, data any) {
  249. var param resultParam
  250. err := utils.AnyTrans(data, &param)
  251. if err != nil {
  252. _ = conn.WriteJSON(utils.WsError("params error"))
  253. return
  254. }
  255. if worker, win := utils.WorkerWss[param.Who]; win {
  256. _ = worker.WriteJSON(utils.WsEvent("openResult", utils.JsonType{
  257. "type": param.Type, "result": param.Result,
  258. }))
  259. return
  260. }
  261. if debugger, din := utils.DebugWss[param.Who]; din {
  262. _ = debugger.WriteJSON(utils.WsEvent("openResult", utils.JsonType{
  263. "type": param.Type, "result": param.Result,
  264. }))
  265. return
  266. }
  267. }
  268. func workFinished(conn *websocket.Conn, data any) {
  269. var param finishParam
  270. err := utils.AnyTrans(data, &param)
  271. if err != nil {
  272. _ = conn.WriteJSON(utils.WsError("params error"))
  273. return
  274. }
  275. if worker, win := utils.WorkerWss[param.Who]; win {
  276. _ = worker.WriteJSON(utils.WsEvent("workFinished", param.Type))
  277. return
  278. }
  279. if debugger, din := utils.DebugWss[param.Who]; din {
  280. _ = debugger.WriteJSON(utils.WsEvent("workFinished", param.Type))
  281. return
  282. }
  283. }