worker.go 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304
  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. wine := tables.WineTable{Id: dbTrade.Wine}
  103. _ = wine.Get()
  104. table := tables.TradeTable{
  105. Id: wxNotify.TransactionId, Trade: wxNotify.TradeNo, Device: dbTrade.Device, Payer: wxNotify.Payer.Openid,
  106. Wine: dbTrade.Wine, Price: wine.Price, Weight: dbTrade.Weight, Cash: dbTrade.Cash, Manager: manager,
  107. }
  108. err = table.Insert()
  109. if err != nil {
  110. ctx.JSON(utils.HttpError, utils.Fail("server error"))
  111. return
  112. }
  113. if device, din := utils.SellerDevices[dbTrade.Device]; din {
  114. if device.Online {
  115. _ = device.Conn.WriteJSON(utils.WsEvent("qrcodeScanned", nil))
  116. utils.Sleep(1)
  117. _ = device.Conn.WriteJSON(utils.WsEvent("orderPayed", volume))
  118. ctx.JSON(utils.HttpOk, utils.Success(nil))
  119. }
  120. }
  121. ctx.JSON(utils.HttpError, utils.Fail("server error"))
  122. }
  123. func infoOfDevice(device *tables.DeviceTable, conn *websocket.Conn) {
  124. var err error
  125. for i := 0; i < 4; i++ {
  126. err = device.Wines[i].Get()
  127. if err != nil {
  128. utils.Logger.Println("Query wine info failed:", err)
  129. _ = conn.WriteJSON(utils.WsError("Query wine info failed"))
  130. return
  131. }
  132. }
  133. _ = conn.WriteJSON(utils.WsEvent("wineResult", device.Wines))
  134. var advList []tables.AdvertiseTable
  135. advList, err = tables.AdvertiseListAll()
  136. if err != nil {
  137. utils.Logger.Println("Query advertise failed:", err)
  138. _ = conn.WriteJSON(utils.WsError("Query advertise failed"))
  139. return
  140. }
  141. _ = conn.WriteJSON(utils.WsEvent("advResult", advList))
  142. var runParams []tables.ParamsTable
  143. runParams, err = tables.ParamsListAll()
  144. if err != nil {
  145. utils.Logger.Println("Query running params failed:", err)
  146. _ = conn.WriteJSON(utils.WsError("Query running params failed"))
  147. return
  148. }
  149. _ = conn.WriteJSON(utils.WsEvent("runParamResult", runParams))
  150. _ = conn.WriteJSON(utils.WsEvent("initFinish", nil))
  151. }
  152. func keepAlive(conn *websocket.Conn, data any) {
  153. _ = conn.WriteJSON(utils.WsEvent("pon", data))
  154. }
  155. func getQrcode(device *tables.DeviceTable, conn *websocket.Conn, data any) {
  156. var param qrcodeParam
  157. err := utils.AnyTrans(data, &param)
  158. if err != nil {
  159. _ = conn.WriteJSON(utils.WsError("param error"))
  160. return
  161. }
  162. wine := tables.WineTable{Id: param.Id}
  163. err = wine.Get()
  164. if err != nil {
  165. utils.Logger.Printf("Query wine[%d] failed: %s\n", param.Id, err)
  166. _ = conn.WriteJSON(utils.WsError(utils.Format("no such wine: %d", param.Id)))
  167. return
  168. }
  169. cash := int(param.Weight) * int(wine.Price)
  170. if cash != param.Cash {
  171. utils.Logger.Printf("got a wrong cash[user: %d, need: %d]\n", param.Cash, cash)
  172. _ = conn.WriteJSON(utils.WsError(utils.Format("got a wrong cash[you: %d, real: %d]", param.Cash, cash)))
  173. return
  174. }
  175. _ = device.Get()
  176. trade := device.Id + utils.TimeString()
  177. store := tradeRedis{Device: device.Id, Cell: param.Cell, Wine: wine.Id, Weight: param.Weight, Cash: uint32(cash)}
  178. marshal, err := json.Marshal(store)
  179. if err != nil {
  180. utils.Logger.Println("marshal trade failed:", err)
  181. _ = conn.WriteJSON(utils.WsError("marshal trade failed"))
  182. return
  183. }
  184. err = utils.Redis.Set(utils.WxPayCli, utils.Format("WxPay_%s", trade), marshal, utils.Duration(1800)).Err()
  185. if err != nil {
  186. utils.Logger.Println("store trade failed:", err)
  187. _ = conn.WriteJSON(utils.WsError("store trade failed"))
  188. return
  189. }
  190. var img []byte
  191. img, err = utils.TryWxPay(trade, wine.Name, cash)
  192. if err != nil {
  193. utils.Logger.Println("access to wxpay failed:", err)
  194. _ = conn.WriteJSON(utils.WsError("access to Wechat Pay failed"))
  195. return
  196. }
  197. _ = conn.WriteJSON(utils.WsEvent("qrcodeOkayed", img))
  198. }
  199. func checkAuthCode(did string, conn *websocket.Conn, data any) {
  200. var param authParam
  201. err := utils.AnyTrans(data, &param)
  202. if err != nil {
  203. _ = conn.WriteJSON(utils.WsError("params error"))
  204. return
  205. }
  206. if param.Code != "284655" {
  207. _ = conn.WriteJSON(utils.WsEvent("authCodeResult", utils.JsonType{
  208. "type": param.Type, "ok": false,
  209. }))
  210. return
  211. }
  212. switch param.Type {
  213. case "Changing":
  214. // TODO: check redis `${did}_${param.who}_Change` === param.code, query real work
  215. _ = conn.WriteJSON(utils.WsEvent("authCodeResult", utils.JsonType{
  216. "type": param.Type, "ok": true, "work": []utils.JsonType{
  217. {
  218. "cell": 1,
  219. "old": utils.JsonType{"id": 13026, "name": "某一款酒名-1", "remain": 300},
  220. "new": utils.JsonType{"id": 13026, "name": "某一款酒名-1", "remain": 15000},
  221. },
  222. {
  223. "cell": 2,
  224. "old": utils.JsonType{"id": 13027, "name": "某一款酒名-2", "remain": 286},
  225. "new": utils.JsonType{"id": 13029, "name": "某一款酒名-3", "remain": 15000},
  226. },
  227. {
  228. "cell": 3,
  229. "old": utils.JsonType{"id": 13027, "name": "某一款酒名-2", "remain": 286},
  230. "new": utils.JsonType{"id": 13029, "name": "某一款酒名-3", "remain": 15000},
  231. },
  232. {
  233. "cell": 4,
  234. "old": utils.JsonType{"id": 13027, "name": "某一款酒名-2", "remain": 286},
  235. "new": utils.JsonType{"id": 13029, "name": "某一款酒名-3", "remain": 15000},
  236. },
  237. },
  238. }))
  239. break
  240. case "Fixing":
  241. // TODO: check redis `${did}_${param.who}_Fix` === param.code
  242. _ = conn.WriteJSON(utils.WsEvent("authCodeResult", utils.JsonType{
  243. "type": param.Type, "ok": true,
  244. }))
  245. break
  246. default:
  247. _ = conn.WriteJSON(utils.WsError("unrecognized open type"))
  248. }
  249. }
  250. func openResult(conn *websocket.Conn, data any) {
  251. var param resultParam
  252. err := utils.AnyTrans(data, &param)
  253. if err != nil {
  254. _ = conn.WriteJSON(utils.WsError("params error"))
  255. return
  256. }
  257. if worker, win := utils.WorkerWss[param.Who]; win {
  258. _ = worker.WriteJSON(utils.WsEvent("openResult", utils.JsonType{
  259. "type": param.Type, "result": param.Result,
  260. }))
  261. return
  262. }
  263. if debugger, din := utils.DebugWss[param.Who]; din {
  264. _ = debugger.WriteJSON(utils.WsEvent("openResult", utils.JsonType{
  265. "type": param.Type, "result": param.Result,
  266. }))
  267. return
  268. }
  269. }
  270. func workFinished(conn *websocket.Conn, data any) {
  271. var param finishParam
  272. err := utils.AnyTrans(data, &param)
  273. if err != nil {
  274. _ = conn.WriteJSON(utils.WsError("params error"))
  275. return
  276. }
  277. if worker, win := utils.WorkerWss[param.Who]; win {
  278. _ = worker.WriteJSON(utils.WsEvent("workFinished", param.Type))
  279. return
  280. }
  281. if debugger, din := utils.DebugWss[param.Who]; din {
  282. _ = debugger.WriteJSON(utils.WsEvent("workFinished", param.Type))
  283. return
  284. }
  285. }