蛋蛋星球-客户端
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

459 lines
12 KiB

  1. package hdl
  2. import (
  3. "applet/app/db"
  4. "applet/app/e"
  5. "applet/app/md"
  6. "applet/app/svc"
  7. "applet/app/utils"
  8. "applet/app/utils/cache"
  9. "code.fnuoos.com/EggPlanet/egg_models.git/src/implement"
  10. "code.fnuoos.com/EggPlanet/egg_models.git/src/model"
  11. "code.fnuoos.com/EggPlanet/egg_system_rules.git/enum"
  12. md2 "code.fnuoos.com/EggPlanet/egg_system_rules.git/md"
  13. "code.fnuoos.com/EggPlanet/egg_system_rules.git/rule"
  14. "errors"
  15. "fmt"
  16. "github.com/gin-gonic/gin"
  17. "time"
  18. )
  19. // GetAmountFlow
  20. // @Summary 蛋蛋星球-钱包-余额明细(获取)
  21. // @Tags 钱包
  22. // @Description 余额明细(获取)
  23. // @Accept json
  24. // @Produce json
  25. // @param Authorization header string true "验证参数Bearer和token空格拼接"
  26. // @Param limit query string true "每页大小"
  27. // @Param page query string true "页数"
  28. // @Param startAt query string false "开始时间"
  29. // @Param endAt query string false "结束时间"
  30. // @Param direction query string false "流水方向(1.收入 2.支出 0.全部)"
  31. // @Success 200 {object} md.GetAmountFlowResp "具体数据"
  32. // @Failure 400 {object} md.Response "具体错误"
  33. // @Router /api/v1/wallet/amountFlow [GET]
  34. func GetAmountFlow(c *gin.Context) {
  35. pageStr := c.DefaultQuery("page", "1")
  36. limitStr := c.DefaultQuery("limit", "10")
  37. startAt := c.Query("startAt")
  38. endAt := c.Query("endAt")
  39. directionStr := c.Query("direction")
  40. val, exists := c.Get("user")
  41. if !exists {
  42. e.OutErr(c, e.ERR_USER_CHECK_ERR, nil)
  43. return
  44. }
  45. user, ok := val.(*model.User)
  46. if !ok {
  47. e.OutErr(c, e.ERR_USER_CHECK_ERR, nil)
  48. return
  49. }
  50. direction := 0
  51. switch directionStr {
  52. case "1":
  53. direction = 1
  54. case "2":
  55. direction = 2
  56. }
  57. page := utils.StrToInt(pageStr)
  58. limit := utils.StrToInt(limitStr)
  59. flowDb := implement.NewUserWalletFlowDb(db.Db)
  60. flows, total, err := flowDb.UserWalletFlowFindByCoinAndUser(page, limit, user.Id, startAt, endAt, direction, false, 0, 0)
  61. if err != nil {
  62. e.OutErr(c, e.ERR_DB_ORM, err.Error())
  63. return
  64. }
  65. list := make([]md.WalletFlowNode, 0, len(flows))
  66. for _, flow := range flows {
  67. temp := md.WalletFlowNode{
  68. Id: flow.Id,
  69. Uid: flow.Uid,
  70. Direction: flow.Direction,
  71. Amount: flow.Amount,
  72. BeforeAmount: flow.BeforeAmount,
  73. AfterAmount: flow.AfterAmount,
  74. SysFee: flow.SysFee,
  75. OrdId: flow.OrdId,
  76. Title: flow.Title,
  77. Kind: flow.Kind,
  78. State: flow.State,
  79. Memo: flow.Memo,
  80. CreateTime: flow.CreateAt,
  81. UpdateTime: flow.UpdateAt,
  82. }
  83. list = append(list, temp)
  84. }
  85. resp := md.GetAmountFlowResp{
  86. List: list,
  87. Paginate: md.Paginate{
  88. Limit: limit,
  89. Page: page,
  90. Total: total,
  91. },
  92. }
  93. e.OutSuc(c, resp, nil)
  94. }
  95. // WithdrawGetAmount
  96. // @Summary 蛋蛋星球-钱包-提现余额(获取)
  97. // @Tags 钱包
  98. // @Description 提现余额(获取)
  99. // @Accept json
  100. // @Produce json
  101. // @param Authorization header string true "验证参数Bearer和token空格拼接"
  102. // @Success 200 {object} md.WithdrawGetAmountResp "具体数据"
  103. // @Failure 400 {object} md.Response "具体错误"
  104. // @Router /api/v1/wallet/withdraw/index [GET]
  105. func WithdrawGetAmount(c *gin.Context) {
  106. val, exists := c.Get("user")
  107. if !exists {
  108. e.OutErr(c, e.ERR_USER_CHECK_ERR, nil)
  109. return
  110. }
  111. user, ok := val.(*model.User)
  112. if !ok {
  113. e.OutErr(c, e.ERR_USER_CHECK_ERR, nil)
  114. return
  115. }
  116. walletDb := implement.NewUserWalletDb(db.Db)
  117. wallet, err := walletDb.GetUserVirtualWallet(user.Id)
  118. if err != nil {
  119. e.OutErr(c, e.ERR_DB_ORM, err.Error())
  120. return
  121. }
  122. resp := md.WithdrawGetAmountResp{
  123. Amount: wallet.Amount,
  124. }
  125. e.OutSuc(c, resp, nil)
  126. }
  127. // WithdrawApply
  128. // @Summary 蛋蛋星球-钱包-发起提现
  129. // @Tags 钱包
  130. // @Description 发起提现
  131. // @Accept json
  132. // @Produce json
  133. // @param Authorization header string true "验证参数Bearer和token空格拼接"
  134. // @Param req body md.WithdrawApplyReq true "具体参数"
  135. // @Success 200 {string} "success"
  136. // @Failure 400 {object} md.Response "具体错误"
  137. // @Router /api/v1/wallet/withdraw/apply [POST]
  138. func WithdrawApply(c *gin.Context) {
  139. var req md.WithdrawApplyReq
  140. err := c.ShouldBindJSON(&req)
  141. if err != nil {
  142. err = svc.HandleValidateErr(err)
  143. err1 := err.(e.E)
  144. e.OutErr(c, err1.Code, err1.Error())
  145. return
  146. }
  147. user := svc.GetUser(c)
  148. var userId, openId string
  149. //sysCfgDb := implement.NewSysCfgDb(db.Db, cache.GetPool().Get())
  150. //sysCfgMap := sysCfgDb.SysCfgFindWithDb(enum.AlipayAppId, enum.WxAppId)
  151. if req.Kind == int(enum.FinWithdrawApplyWithdrawKindForAli) {
  152. alipayUserInfoDb := implement.NewAlipayUserInfoDb(db.Db)
  153. aliInfo, err := alipayUserInfoDb.GetAlipayUserInfo(user.Id)
  154. if err != nil {
  155. e.OutErr(c, e.ERR, err.Error())
  156. return
  157. }
  158. if aliInfo == nil {
  159. e.OutErr(c, e.ERR, "支付宝用户信息未授权")
  160. return
  161. }
  162. //appId = sysCfgMap[enum.AlipayAppId]
  163. userId = aliInfo.UserId
  164. openId = aliInfo.OpenId
  165. } else if req.Kind == int(enum.FinWithdrawApplyWithdrawKindForWx) {
  166. wxUserInfoDb := implement.NewWxUserInfoDb(db.Db)
  167. wxInfo, err := wxUserInfoDb.GetWxUserInfo(user.Id)
  168. if err != nil {
  169. e.OutErr(c, e.ERR, err.Error())
  170. return
  171. }
  172. if wxInfo == nil {
  173. e.OutErr(c, e.ERR, "微信用户信息未授权")
  174. return
  175. }
  176. //appId = sysCfgMap[enum.WxAppId]
  177. userId = wxInfo.UserId
  178. openId = wxInfo.OpenId
  179. } else {
  180. e.OutErr(c, e.ERR, "未知的提现类型")
  181. return
  182. }
  183. //1、判断是否可以提现
  184. err, realAmount, fee, isAuto, isFirst := svc.CheckWithdraw(c, req.Amount)
  185. if err != nil {
  186. e.OutErr(c, e.ERR, err.Error())
  187. return
  188. }
  189. // 2、加锁 防止并发提取
  190. mutexKey := fmt.Sprintf("egg_app_withdraw_apply:%s", utils.Int64ToStr(user.Id))
  191. withdrawAvailable, err := cache.Do("SET", mutexKey, 1, "EX", 5, "NX")
  192. if err != nil {
  193. e.OutErr(c, e.ERR, err)
  194. return
  195. }
  196. if withdrawAvailable != "OK" {
  197. e.OutErr(c, e.ERR, e.NewErr(400000, "请求过于频繁,请稍后再试"))
  198. return
  199. }
  200. // 开启事务
  201. session := db.Db.NewSession()
  202. defer session.Close()
  203. err = session.Begin()
  204. if err != nil {
  205. session.Rollback()
  206. e.OutErr(c, e.ERR_DB_ORM, err)
  207. return
  208. }
  209. //3、处理用户余额
  210. dealUserWalletReq := md2.DealUserWalletReq{
  211. Direction: "sub",
  212. Kind: int(enum.UserWithdrawApply),
  213. Title: enum.UserWithdrawApply.String(),
  214. Uid: user.Id,
  215. Amount: utils.StrToFloat64(req.Amount),
  216. }
  217. err = rule.DealUserWallet(session, dealUserWalletReq)
  218. if err != nil {
  219. e.OutErr(c, e.ERR_DB_ORM, err.Error())
  220. session.Rollback()
  221. return
  222. }
  223. //4、新增提现记录
  224. now := time.Now()
  225. finWithdrawApplyDb := implement.NewFinWithdrawApplyDb(db.Db)
  226. insertAffected, err := finWithdrawApplyDb.FinWithdrawApplyInsertOneBySession(session, &model.FinWithdrawApply{
  227. Uid: user.Id,
  228. AdmId: 0,
  229. Amount: req.Amount,
  230. RealAmount: realAmount,
  231. Fee: fee,
  232. Type: func(isAuto bool) int {
  233. if isAuto {
  234. return 2
  235. }
  236. return 1
  237. }(isAuto),
  238. WithdrawAccount: userId,
  239. WithdrawName: openId,
  240. Reason: 0,
  241. PaymentDate: "",
  242. State: 0,
  243. WithdrawKind: req.Kind,
  244. IsFirst: func(isFirst bool) int {
  245. if isFirst {
  246. return 1
  247. }
  248. return 0
  249. }(isFirst),
  250. Memo: "",
  251. UpdateAt: now.Format("2006-01-02 15:04:05"),
  252. CreateAt: now.Format("2006-01-02 15:04:05"),
  253. })
  254. if err != nil {
  255. session.Rollback()
  256. e.OutErr(c, e.ERR_DB_ORM, err)
  257. return
  258. }
  259. if insertAffected <= 0 {
  260. session.Rollback()
  261. e.OutErr(c, e.ERR_DB_ORM, "生成提现单失败")
  262. return
  263. }
  264. err = session.Begin()
  265. if err != nil {
  266. session.Rollback()
  267. e.OutErr(c, e.ERR_DB_ORM, err)
  268. return
  269. }
  270. //5、推入mq
  271. if isAuto {
  272. }
  273. e.OutSuc(c, "success", nil)
  274. }
  275. // GetWithdrawCondition
  276. // @Summary 蛋蛋星球-钱包-提现条件(获取)
  277. // @Tags 钱包
  278. // @Description 提现条件(获取)
  279. // @Accept json
  280. // @Produce json
  281. // @param Authorization header string true "验证参数Bearer和token空格拼接"
  282. // @Success 200 {object} md.GetWithdrawConditionResp "具体数据"
  283. // @Failure 400 {object} md.Response "具体错误"
  284. // @Router /api/v1/wallet/withdraw/condition [GET]
  285. func GetWithdrawCondition(c *gin.Context) {
  286. user := svc.GetUser(c)
  287. alipayUserInfoDb := implement.NewAlipayUserInfoDb(db.Db)
  288. alipayInfo, err := alipayUserInfoDb.GetAlipayUserInfo(user.Id)
  289. if err != nil {
  290. e.OutErr(c, e.ERR_DB_ORM, err.Error())
  291. return
  292. }
  293. userInfoDb := implement.NewWxUserInfoDb(db.Db)
  294. wxUserInfo, err := userInfoDb.GetWxUserInfo(user.Id)
  295. if err != nil {
  296. e.OutErr(c, e.ERR_DB_ORM, err.Error())
  297. return
  298. }
  299. resp := md.GetWithdrawConditionResp{
  300. IsRealName: func(isRealName int) bool {
  301. switch isRealName {
  302. case 0:
  303. return false
  304. case 1:
  305. return true
  306. default:
  307. return false
  308. }
  309. }(user.IsRealName),
  310. IsBindAlipay: func(alipayInfo *model.AlipayUserInfo) bool {
  311. if alipayInfo == nil {
  312. return false
  313. } else {
  314. return true
  315. }
  316. }(alipayInfo),
  317. IsBindWx: func(wxUserInfo *model.WxUserInfo) bool {
  318. if wxUserInfo == nil {
  319. return false
  320. } else {
  321. return true
  322. }
  323. }(wxUserInfo),
  324. }
  325. e.OutSuc(c, resp, nil)
  326. }
  327. // BindAlipayAccount
  328. // @Summary 蛋蛋星球-钱包-绑定支付宝
  329. // @Tags 钱包
  330. // @Description 绑定支付宝
  331. // @Accept json
  332. // @Produce json
  333. // @param Authorization header string true "验证参数Bearer和token空格拼接"
  334. // @Param req body md.BindAlipayAccountReq true "具体参数"
  335. // @Success 200 {string} "success"
  336. // @Failure 400 {object} md.Response "具体错误"
  337. // @Router /api/v1/wallet/withdraw/bindAlipay [POST]
  338. func BindAlipayAccount(c *gin.Context) {
  339. var req md.BindAlipayAccountReq
  340. err := c.ShouldBindJSON(&req)
  341. if err != nil {
  342. err = svc.HandleValidateErr(err)
  343. err1 := err.(e.E)
  344. e.OutErr(c, err1.Code, err1.Error())
  345. return
  346. }
  347. user := svc.GetUser(c)
  348. alipayUserInfoDb := implement.NewAlipayUserInfoDb(db.Db)
  349. alipayUserInfo, err := alipayUserInfoDb.GetAlipayUserInfo(user.Id)
  350. if err != nil {
  351. e.OutErr(c, e.ERR_DB_ORM, err.Error())
  352. return
  353. }
  354. if alipayUserInfo != nil {
  355. e.OutErr(c, e.ERR, errors.New("用户已绑定支付宝").Error())
  356. return
  357. }
  358. now := time.Now()
  359. newAlipayUserInfo := model.AlipayUserInfo{
  360. Uid: user.Id,
  361. UserId: req.UserId,
  362. OpenId: req.OpenId,
  363. AppId: req.AppId,
  364. Ext: req.Ext,
  365. CreateAt: now.Format("2006-01-02 15:04:05"),
  366. UpdateAt: now.Format("2006-01-02 15:04:05"),
  367. }
  368. affected, err := alipayUserInfoDb.AlipayUserInfoInsert(&newAlipayUserInfo)
  369. if err != nil {
  370. e.OutErr(c, e.ERR_DB_ORM, err.Error())
  371. return
  372. }
  373. if affected <= 0 {
  374. e.OutErr(c, e.ERR, errors.New("绑定失败"))
  375. return
  376. }
  377. e.OutSuc(c, "success", nil)
  378. }
  379. // BindWxPayAccount
  380. // @Summary 蛋蛋星球-钱包-绑定微信支付
  381. // @Tags 钱包
  382. // @Description 绑定微信支付
  383. // @Accept json
  384. // @Produce json
  385. // @param Authorization header string true "验证参数Bearer和token空格拼接"
  386. // @Param req body md.BindWxPayAccountReq true "具体参数"
  387. // @Success 200 {string} "success"
  388. // @Failure 400 {object} md.Response "具体错误"
  389. // @Router /api/v1/wallet/withdraw/bindWxPay [POST]
  390. func BindWxPayAccount(c *gin.Context) {
  391. var req md.BindWxPayAccountReq
  392. err := c.ShouldBindJSON(&req)
  393. if err != nil {
  394. err = svc.HandleValidateErr(err)
  395. err1 := err.(e.E)
  396. e.OutErr(c, err1.Code, err1.Error())
  397. return
  398. }
  399. user := svc.GetUser(c)
  400. wxUserInfoDb := implement.NewWxUserInfoDb(db.Db)
  401. wxUserInfo, err := wxUserInfoDb.GetWxUserInfo(user.Id)
  402. if err != nil {
  403. e.OutErr(c, e.ERR_DB_ORM, err.Error())
  404. return
  405. }
  406. if wxUserInfo != nil {
  407. e.OutErr(c, e.ERR, errors.New("用户已绑定过微信").Error())
  408. return
  409. }
  410. now := time.Now()
  411. newWxUserInfo := model.WxUserInfo{
  412. Uid: user.Id,
  413. UserId: req.UserId,
  414. OpenId: req.OpenId,
  415. AppId: req.AppId,
  416. Ext: req.Ext,
  417. CreateAt: now.Format("2006-01-02 15:04:05"),
  418. UpdateAt: now.Format("2006-01-02 15:04:05"),
  419. }
  420. affected, err := wxUserInfoDb.WxUserInfoInsert(&newWxUserInfo)
  421. if err != nil {
  422. e.OutErr(c, e.ERR_DB_ORM, err.Error())
  423. return
  424. }
  425. if affected <= 0 {
  426. e.OutErr(c, e.ERR, errors.New("绑定失败"))
  427. }
  428. e.OutSuc(c, "success", nil)
  429. }