蛋蛋星球-客户端
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.
 
 
 
 
 

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