|
- package hdl
-
- import (
- "applet/app/cfg"
- "applet/app/db"
- "applet/app/e"
- alipay "applet/app/lib/gopay"
- "applet/app/md"
- "applet/app/svc"
- "applet/app/svc/sys_cfg"
- "applet/app/utils"
- "applet/app/utils/cache"
- "code.fnuoos.com/EggPlanet/egg_models.git/src/implement"
- "code.fnuoos.com/EggPlanet/egg_models.git/src/model"
- rule2 "code.fnuoos.com/EggPlanet/egg_system_rules.git"
- "code.fnuoos.com/EggPlanet/egg_system_rules.git/enum"
- enum2 "code.fnuoos.com/EggPlanet/egg_system_rules.git/enum"
- md2 "code.fnuoos.com/EggPlanet/egg_system_rules.git/md"
- "code.fnuoos.com/EggPlanet/egg_system_rules.git/rule"
- md3 "code.fnuoos.com/EggPlanet/egg_system_rules.git/rule/egg_energy/md"
- "code.fnuoos.com/go_rely_warehouse/zyos_go_mq.git/rabbit"
- "errors"
- "fmt"
- "github.com/gin-gonic/gin"
- "github.com/go-pay/gopay"
- alipay2 "github.com/go-pay/gopay/alipay"
- "github.com/jinzhu/copier"
- "github.com/tidwall/gjson"
- "time"
- )
-
- // GetAmountFlow
- // @Summary 蛋蛋星球-钱包-余额明细(获取)
- // @Tags 钱包
- // @Description 余额明细(获取)
- // @Accept json
- // @Produce json
- // @param Authorization header string true "验证参数Bearer和token空格拼接"
- // @Param limit query string true "每页大小"
- // @Param page query string true "页数"
- // @Param startAt query string false "开始时间"
- // @Param endAt query string false "结束时间"
- // @Param direction query string false "流水方向(1.收入 2.支出 0.全部)"
- // @Success 200 {object} md.GetAmountFlowResp "具体数据"
- // @Failure 400 {object} md.Response "具体错误"
- // @Router /api/v1/wallet/amountFlow [GET]
- func GetAmountFlow(c *gin.Context) {
- pageStr := c.DefaultQuery("page", "1")
- limitStr := c.DefaultQuery("limit", "10")
- startAt := c.Query("startAt")
- endAt := c.Query("endAt")
- directionStr := c.Query("direction")
-
- val, exists := c.Get("user")
- if !exists {
- e.OutErr(c, e.ERR_USER_CHECK_ERR, nil)
- return
- }
- user, ok := val.(*model.User)
- if !ok {
- e.OutErr(c, e.ERR_USER_CHECK_ERR, nil)
- return
- }
-
- direction := 0
- switch directionStr {
- case "1":
- direction = 1
- case "2":
- direction = 2
- }
-
- page := utils.StrToInt(pageStr)
- limit := utils.StrToInt(limitStr)
-
- flowDb := implement.NewUserWalletFlowDb(db.Db)
- flows, total, err := flowDb.UserWalletFlowFindByCoinAndUser(page, limit, user.Id, startAt, endAt, direction, false, 0, 0)
- if err != nil {
- e.OutErr(c, e.ERR_DB_ORM, err.Error())
- return
- }
-
- list := make([]md.WalletFlowNode, 0, len(flows))
- for _, flow := range flows {
- temp := md.WalletFlowNode{
- Id: flow.Id,
- Uid: flow.Uid,
- Direction: flow.Direction,
- Amount: flow.Amount,
- BeforeAmount: flow.BeforeAmount,
- AfterAmount: flow.AfterAmount,
- SysFee: flow.SysFee,
- OrdId: flow.OrdId,
- Title: flow.Title,
- Kind: flow.Kind,
- State: flow.State,
- Memo: flow.Memo,
- CreateTime: flow.CreateAt,
- UpdateTime: flow.UpdateAt,
- }
- list = append(list, temp)
- }
-
- resp := md.GetAmountFlowResp{
- List: list,
- Paginate: md.Paginate{
- Limit: limit,
- Page: page,
- Total: total,
- },
- }
- e.OutSuc(c, resp, nil)
- }
-
- // WithdrawGetAmount
- // @Summary 蛋蛋星球-钱包-提现余额(获取)
- // @Tags 钱包
- // @Description 提现余额(获取)
- // @Accept json
- // @Produce json
- // @param Authorization header string true "验证参数Bearer和token空格拼接"
- // @Success 200 {object} md.WithdrawGetAmountResp "具体数据"
- // @Failure 400 {object} md.Response "具体错误"
- // @Router /api/v1/wallet/withdraw/index [GET]
- func WithdrawGetAmount(c *gin.Context) {
- val, exists := c.Get("user")
- if !exists {
- e.OutErr(c, e.ERR_USER_CHECK_ERR, nil)
- return
- }
- user, ok := val.(*model.User)
- if !ok {
- e.OutErr(c, e.ERR_USER_CHECK_ERR, nil)
- return
- }
-
- walletDb := implement.NewUserWalletDb(db.Db)
- wallet, err := walletDb.GetUserVirtualWallet(user.Id)
- if err != nil {
- e.OutErr(c, e.ERR_DB_ORM, err.Error())
- return
- }
-
- resp := md.WithdrawGetAmountResp{
- Amount: wallet.Amount,
- }
- e.OutSuc(c, resp, nil)
- }
-
- // WithdrawApply
- // @Summary 蛋蛋星球-钱包-发起提现
- // @Tags 钱包
- // @Description 发起提现
- // @Accept json
- // @Produce json
- // @param Authorization header string true "验证参数Bearer和token空格拼接"
- // @Param req body md.WithdrawApplyReq true "具体参数"
- // @Success 200 {string} "success"
- // @Failure 400 {object} md.Response "具体错误"
- // @Router /api/v1/wallet/withdraw/apply [POST]
- func WithdrawApply(c *gin.Context) {
- var req md.WithdrawApplyReq
- err := c.ShouldBindJSON(&req)
- if err != nil {
- err = svc.HandleValidateErr(err)
- err1 := err.(e.E)
- e.OutErr(c, err1.Code, err1.Error())
- return
- }
- user := svc.GetUser(c)
- var userId, openId string
- var kind int
- //sysCfgDb := implement.NewSysCfgDb(db.Db, cache.GetPool().Get())
- //sysCfgMap := sysCfgDb.SysCfgFindWithDb(enum.AlipayAppId, enum.WxAppId)
- if req.Kind == enum.FinWithdrawApplyWithdrawKindForAli.String() {
- alipayUserInfoDb := implement.NewAlipayUserInfoDb(db.Db)
- aliInfo, err := alipayUserInfoDb.GetAlipayUserInfo(user.Id)
- if err != nil {
- e.OutErr(c, e.ERR, err.Error())
- return
- }
- if aliInfo == nil {
- e.OutErr(c, e.ERR, "支付宝用户信息未授权")
- return
- }
- if aliInfo.OpenId == "" {
- e.OutErr(c, e.ERR, "支付宝用户授权信息有误")
- return
- }
- //appId = sysCfgMap[enum.AlipayAppId]
- userId = aliInfo.UserId
- openId = aliInfo.OpenId
- kind = int(enum.FinWithdrawApplyWithdrawKindForAli)
- } else if req.Kind == enum.FinWithdrawApplyWithdrawKindForWx.String() {
- wxUserInfoDb := implement.NewWxUserInfoDb(db.Db)
- wxInfo, err := wxUserInfoDb.GetWxUserInfo(user.Id)
- if err != nil {
- e.OutErr(c, e.ERR, err.Error())
- return
- }
- if wxInfo == nil {
- e.OutErr(c, e.ERR, "微信用户信息未授权")
- return
- }
- //appId = sysCfgMap[enum.WxAppId]
- userId = wxInfo.UserId
- openId = wxInfo.OpenId
- kind = int(enum.FinWithdrawApplyWithdrawKindForWx)
- } else {
- e.OutErr(c, e.ERR, "未知的提现类型")
- return
- }
-
- //1、判断是否可以提现
- err, realAmount, fee, isAuto, isFirst := svc.CheckWithdraw(c, req.Amount)
- if err != nil {
- e.OutErr(c, e.ERR, err.Error())
- return
- }
-
- // 2、加锁 防止并发提取
- mutexKey := fmt.Sprintf("egg_app_withdraw_apply:%s", utils.Int64ToStr(user.Id))
- withdrawAvailable, err := cache.Do("SET", mutexKey, 1, "EX", 5, "NX")
- if err != nil {
- e.OutErr(c, e.ERR, err)
- return
- }
- if withdrawAvailable != "OK" {
- e.OutErr(c, e.ERR, e.NewErr(400000, "请求过于频繁,请稍后再试"))
- return
- }
-
- // 开启事务
- session := db.Db.NewSession()
- defer session.Close()
- err = session.Begin()
- if err != nil {
- session.Rollback()
- e.OutErr(c, e.ERR_DB_ORM, err)
- return
- }
-
- //3、处理用户余额
- dealUserWalletReq := md2.DealUserWalletReq{
- Direction: "sub",
- Kind: int(enum.UserWithdrawApply),
- Title: enum.UserWithdrawApply.String(),
- Uid: user.Id,
- Amount: utils.StrToFloat64(req.Amount),
- }
- rule2.Init(cfg.RedisAddr)
- err = rule.DealUserWallet(session, dealUserWalletReq)
- if err != nil {
- e.OutErr(c, e.ERR_DB_ORM, err.Error())
- session.Rollback()
- return
- }
-
- //4、新增提现记录
- now := time.Now()
- id := utils.StrToInt64(utils.OrderUUID(int(user.Id)))
- finWithdrawApplyDb := implement.NewFinWithdrawApplyDb(db.Db)
- finWithdrawApply := &model.FinWithdrawApply{
- Id: id,
- Uid: user.Id,
- AdmId: 0,
- Amount: req.Amount,
- RealAmount: realAmount,
- Fee: fee,
- Type: func(isAuto bool) int {
- if isAuto {
- return 2
- }
- return 1
- }(isAuto),
- WithdrawAccount: userId,
- WithdrawName: openId,
- Reason: 0,
- PaymentDate: "",
- State: 0,
- WithdrawKind: kind,
- IsFirst: func(isFirst bool) int {
- if isFirst {
- return 1
- }
- return 0
- }(isFirst),
- Memo: "",
- UpdateAt: now.Format("2006-01-02 15:04:05"),
- CreateAt: now.Format("2006-01-02 15:04:05"),
- }
- insertAffected, err := finWithdrawApplyDb.FinWithdrawApplyInsertOneBySession(session, finWithdrawApply)
- if err != nil {
- session.Rollback()
- e.OutErr(c, e.ERR_DB_ORM, err)
- return
- }
- if insertAffected <= 0 {
- session.Rollback()
- e.OutErr(c, e.ERR_DB_ORM, "生成提现单失败")
- return
- }
- err = session.Begin()
- if err != nil {
- session.Rollback()
- e.OutErr(c, e.ERR_DB_ORM, err)
- return
- }
- err = session.Commit()
- if err != nil {
- _ = session.Rollback()
- e.OutErr(c, e.ERR_DB_ORM, err)
- return
- }
-
- //5、推入mq
- if isAuto {
- //更改提现单记录状态
- finWithdrawApply.State = int(enum.FinWithdrawApplyStateForIng)
- updateAffected, err1 := finWithdrawApplyDb.UpdateFinWithdrawApply(finWithdrawApply, "state")
- if err1 != nil {
- e.OutErr(c, e.ERR_DB_ORM, err1.Error())
- return
- }
- if updateAffected <= 0 {
- e.OutErr(c, e.ERR_DB_ORM, "更新提现单状态失败")
- return
- }
-
- ch, err1 := rabbit.Cfg.Pool.GetChannel()
- if err1 != nil {
- e.OutErr(c, e.ERR_INIT_RABBITMQ, err1.Error())
- return
- }
- defer ch.Release()
- var data md3.EggFinWithdrawApplyData
- err = copier.Copy(&data, &finWithdrawApply)
- if err != nil {
- e.OutErr(c, e.ERR, err.Error())
- return
- }
-
- ch.Publish(md3.EggAppExchange, data, md3.EggFinWithdrawApply)
- }
-
- e.OutSuc(c, "success", nil)
- }
-
- // GetWithdrawCondition
- // @Summary 蛋蛋星球-钱包-提现条件(获取)
- // @Tags 钱包
- // @Description 提现条件(获取)
- // @Accept json
- // @Produce json
- // @param Authorization header string true "验证参数Bearer和token空格拼接"
- // @Success 200 {object} md.GetWithdrawConditionResp "具体数据"
- // @Failure 400 {object} md.Response "具体错误"
- // @Router /api/v1/wallet/withdraw/condition [GET]
- func GetWithdrawCondition(c *gin.Context) {
- user := svc.GetUser(c)
-
- settingDb := implement.NewFinWithdrawSettingDb(db.Db)
- setting, err := settingDb.FinWithdrawSettingGetOne()
- if err != nil {
- e.OutErr(c, e.ERR_DB_ORM, err)
- return
- }
-
- //1. 判断是否为第一次提现
- isFirst := false
- has, err := db.Db.Where("uid = ?", user.Id).Get(&model.FinWithdrawApply{})
- if !has { //第一次提现
- isFirst = true
- }
- resp := svc.GetWithdrawCondition(user, setting, isFirst)
- alipayUserInfoDb := implement.NewAlipayUserInfoDb(db.Db)
- alipayInfo, err := alipayUserInfoDb.GetAlipayUserInfo(user.Id)
- if err != nil {
- e.OutErr(c, e.ERR_DB_ORM, err.Error())
- return
- }
- if alipayInfo != nil {
- resp.IsBindAlipay = true
- }
-
- userInfoDb := implement.NewWxUserInfoDb(db.Db)
- wxUserInfo, err := userInfoDb.GetWxUserInfo(user.Id)
- if err != nil {
- e.OutErr(c, e.ERR_DB_ORM, err.Error())
- return
- }
- if wxUserInfo != nil {
- resp.IsBindWx = true
- }
-
- e.OutSuc(c, resp, nil)
- }
-
- // LaunchBindAlipayAccount
- // @Summary 蛋蛋星球-钱包-发起绑定支付宝获得URL
- // @Tags 钱包
- // @Description 发起绑定支付宝获得URL
- // @Accept json
- // @Produce json
- // @param Authorization header string true "验证参数Bearer和token空格拼接"
- // @Success 200 {string} "Url"
- // @Failure 400 {object} md.Response "具体错误"
- // @Router /api/v1/wallet/withdraw/launchBindAlipay [GET]
- func LaunchBindAlipayAccount(c *gin.Context) {
- client, err := alipay.InitAlipay(nil)
- if err != nil {
- e.OutErr(c, e.ERR, err.Error())
- return
- }
- appId := client.AppId
- scope := "auth_user"
-
- sysCfgDb := sys_cfg.NewSysCfgDb(db.Db)
- sysCfgs, err := sysCfgDb.SysCfgGetAll()
- if err != nil {
- e.OutErr(c, e.ERR_DB_ORM, err.Error())
- return
- }
- if sysCfgs == nil {
- e.OutErr(c, e.ERR_CFG_CACHE, nil)
- return
- }
-
- cfgMap := make(map[string]string, len(*sysCfgs))
- for _, cfg := range *sysCfgs {
- cfgMap[cfg.Key] = cfg.Val
- }
- targetId := utils.UUIDHexString()
-
- alipayPrivateKey := cfgMap[enum2.AlipayPrivateKey]
- pid := cfgMap[enum2.AlipayPid]
- bm := make(gopay.BodyMap)
- bm.Set("apiname", "com.alipay.account.auth")
- bm.Set("app_id", appId)
- bm.Set("app_name", "mc")
- bm.Set("auth_type", "AUTHACCOUNT")
- bm.Set("biz_type", "openservice")
- bm.Set("pid", pid)
- bm.Set("product_id", "APP_FAST_LOGIN")
- bm.Set("scope", scope)
- bm.Set("sign_type", "RSA2")
- bm.Set("method", "alipay.open.auth.sdk.code.get")
- bm.Set("target_id", targetId)
- privateKey, err := utils.StringToPrivateKey(alipayPrivateKey)
- if err != nil {
- e.OutErr(c, e.ERR, err.Error())
- return
- }
- sign, err := alipay2.GetRsaSign(bm, alipay2.RSA2, privateKey)
- if err != nil {
- e.OutErr(c, e.ERR, err.Error())
- return
- }
-
- resUrl := fmt.Sprintf("apiname=com.alipay.account.auth&app_id=%s&app_name=mc&"+
- "auth_type=AUTHACCOUNT&biz_type=openservice&method=alipay.open.auth.sdk.code.get"+
- "&pid=%s&product_id=APP_FAST_LOGIN&scope=%s&sign_type=RSA2&"+
- "target_id=%s&sign=%s", appId, pid, scope, targetId, sign)
-
- e.OutSuc(c, resUrl, nil)
- }
-
- // BindAlipayAccount
- // @Summary 蛋蛋星球-钱包-绑定支付宝
- // @Tags 钱包
- // @Description 绑定支付宝
- // @Accept json
- // @Produce json
- // @param Authorization header string true "验证参数Bearer和token空格拼接"
- // @Param req body md.BindAlipayAccountReq true "具体参数"
- // @Success 200 {string} "success"
- // @Failure 400 {object} md.Response "具体错误"
- // @Router /api/v1/wallet/withdraw/bindAlipay [POST]
- func BindAlipayAccount(c *gin.Context) {
- var req md.BindAlipayAccountReq
- err := c.ShouldBindJSON(&req)
- if err != nil {
- err = svc.HandleValidateErr(err)
- err1 := err.(e.E)
- e.OutErr(c, err1.Code, err1.Error())
- return
- }
-
- user := svc.GetUser(c)
-
- var alipayStruct *alipay.InitAlipayStruct
- client, err := alipay.InitAlipay(alipayStruct)
- if err != nil {
- e.OutErr(c, e.ERR, err.Error())
- return
- }
-
- bm := make(gopay.BodyMap)
- bm = bm.Set("grant_type", "authorization_code")
- bm = bm.Set("code", req.AuthCode)
-
- systemOauthToken, err := client.SystemOauthToken(c, bm)
- if err != nil {
- e.OutErr(c, e.ERR, err.Error())
- return
- }
-
- info, err := client.UserInfoShare(c, systemOauthToken.Response.AccessToken)
- if err != nil {
- e.OutErr(c, e.ERR, err.Error())
- return
- }
- fmt.Println("BindAlipayAccount>>>>>>>>", info)
- utils.FilePutContents("BindAlipayAccount", utils.SerializeStr(map[string]interface{}{
- "info": info,
- "systemOauthToken": systemOauthToken,
- "req": req,
- }))
-
- infoDb := implement.NewAlipayUserInfoDb(db.Db)
- userInfo, err := infoDb.GetAlipayUserInfo(user.Id)
- if err != nil {
- e.OutErr(c, e.ERR, err.Error())
- return
- }
- now := time.Now()
- if userInfo == nil {
- m := model.AlipayUserInfo{
- Uid: user.Id,
- UserId: info.Response.UserId,
- OpenId: systemOauthToken.Response.OpenId,
- AppId: client.AppId,
- UserName: info.Response.NickName,
- Ext: "",
- CreateAt: now.Format("2006-01-02 15:04:05"),
- UpdateAt: now.Format("2006-01-02 15:04:05"),
- }
- _, err = infoDb.AlipayUserInfoInsert(&m)
- if err != nil {
- e.OutErr(c, e.ERR_DB_ORM, err.Error())
- return
- }
- } else {
- cols := []string{"open_id", "app_id", "user_id", "user_name"}
- m := model.AlipayUserInfo{
- Id: userInfo.Id,
- Uid: userInfo.Uid,
- UserId: info.Response.UserId,
- OpenId: info.Response.OpenId,
- AppId: client.AppId,
- UserName: info.Response.NickName,
- Ext: "",
- CreateAt: userInfo.CreateAt,
- UpdateAt: now.Format("2006-01-02 15:04:05"),
- }
- _, err := infoDb.UpdateAlipayUserInfo(&m, cols...)
- if err != nil {
- e.OutErr(c, e.ERR_DB_ORM, err.Error())
- return
- }
- }
-
- e.OutSuc(c, "success", nil)
- }
-
- // BindWxPayAccount
- // @Summary 蛋蛋星球-钱包-绑定微信支付
- // @Tags 钱包
- // @Description 绑定微信支付
- // @Accept json
- // @Produce json
- // @param Authorization header string true "验证参数Bearer和token空格拼接"
- // @Param req body md.BindWxPayAccountReq true "具体参数"
- // @Success 200 {string} "success"
- // @Failure 400 {object} md.Response "具体错误"
- // @Router /api/v1/wallet/withdraw/bindWxPay [POST]
- func BindWxPayAccount(c *gin.Context) {
- var req md.BindWxPayAccountReq
- err := c.ShouldBindJSON(&req)
- if err != nil {
- err = svc.HandleValidateErr(err)
- err1 := err.(e.E)
- e.OutErr(c, err1.Code, err1.Error())
- return
- }
-
- user := svc.GetUser(c)
- wxUserInfoDb := implement.NewWxUserInfoDb(db.Db)
- wxUserInfo, err := wxUserInfoDb.GetWxUserInfo(user.Id)
- if err != nil {
- e.OutErr(c, e.ERR_DB_ORM, err.Error())
- return
- }
- if wxUserInfo != nil {
- e.OutErr(c, e.ERR, errors.New("用户已绑定过微信").Error())
- return
- }
-
- appid := svc.GetSysCfgStr("wechat_appid")
- secret := svc.GetSysCfgStr("wechat_secret")
-
- wxUrl := fmt.Sprintf("https://api.weixin.qq.com/sns/oauth2/access_token?appid=%s&secret=%s&code=%s&grant_type=authorization_code", appid, secret, req.Code)
- wechatResp, err := utils.CurlGet(wxUrl, nil)
- if err != nil {
- e.OutErr(c, 400, e.NewErr(400, "获取微信信息失败"))
- return
- }
- utils.FilePutContents("WithdrawalBinding", utils.SerializeStr(wechatResp))
- openId := gjson.Get(string(wechatResp), "openid").String()
- wechatToken := gjson.Get(string(wechatResp), "access_token").String()
- wechatInfoUrl := "https://api.weixin.qq.com/sns/userinfo?access_token=%s&openid=%s"
- wechatInfoUrl = fmt.Sprintf(wechatInfoUrl, wechatToken, openId)
- wechatInfoResp, _ := utils.CurlGet(wechatInfoUrl, nil)
-
- now := time.Now()
- newWxUserInfo := model.WxUserInfo{
- Uid: user.Id,
- OpenId: openId,
- UserId: gjson.Get(string(wechatResp), "unionid").String(),
- UserName: gjson.Get(string(wechatInfoResp), "nickname").String(),
- AppId: appid,
- CreateAt: now.Format("2006-01-02 15:04:05"),
- UpdateAt: now.Format("2006-01-02 15:04:05"),
- }
- affected, err := wxUserInfoDb.WxUserInfoInsert(&newWxUserInfo)
- if err != nil {
- e.OutErr(c, e.ERR_DB_ORM, err.Error())
- return
- }
- if affected <= 0 {
- e.OutErr(c, e.ERR, errors.New("绑定失败"))
- }
- e.OutSuc(c, "success", nil)
- }
|