dongfeng-pay/agent/controllers/multi_withdraw.go

251 lines
6.8 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/***************************************************
** @Desc : This file for 批量提现
** @Time : 19.12.6 17:07
** @Author : Joker
** @File : multi_withdraw
** @Last Modified by : Joker
** @Last Modified time: 19.12.6 17:07
** @Software: GoLand
****************************************************/
package controllers
import (
"agent/common"
"agent/models"
"agent/sys/enum"
"agent/utils"
"fmt"
"github.com/rs/xid"
"github.com/tealeg/xlsx"
"path"
"regexp"
"strconv"
"strings"
"time"
)
type MultiWithdraw struct {
KeepSession
}
func (c *MultiWithdraw) ShowMultiWithdrawUI() {
us := c.GetSession(enum.UserSession)
u := us.(models.AgentInfo)
ranMd5 := encrypt.EncodeMd5([]byte(pubMethod.RandomString(46)))
c.Ctx.SetCookie(enum.UserCookie, ranMd5, enum.CookieExpireTime)
c.Ctx.SetSecureCookie(ranMd5, enum.UserCookie, ranMd5, enum.CookieExpireTime)
c.SetSession(enum.UserCookie, ranMd5)
c.Data["userName"] = u.AgentName
c.TplName = "withdraw/multi_withdraw.html"
}
// 申请批量提现
func (c *Withdraw) LaunchMultiWithdraw() {
mobileCode := strings.TrimSpace(c.GetString("mobileCode"))
file, header, err := c.GetFile("file")
us := c.GetSession(enum.UserSession)
u := us.(models.AgentInfo)
var (
msg = enum.FailedString
flag = enum.FailedFlag
b bool
url string
)
fileName := header.Filename
defer file.Close()
split := strings.Split(fileName, ".")
if len(split) < 2 {
msg = "请选择批量文件!"
goto stopRun
}
if strings.Compare(strings.ToLower(split[1]), "xls") != 0 &&
strings.Compare(strings.ToLower(split[1]), "xlsx") != 0 {
msg = "仅支持“xls”、“xlsx”格式文件!"
goto stopRun
}
if err != nil {
msg = "请上传批量文件! " + err.Error()
goto stopRun
}
if u.PayPassword == "" {
msg = "请设置支付密码!"
goto stopRun
}
if strings.Compare(strings.ToUpper(encrypt.EncodeMd5([]byte(mobileCode))), u.PayPassword) != 0 {
msg = "支付密码输入错误!"
goto stopRun
}
u = models.GetAgentInfoByAgentUid(u.AgentUid)
if strings.Compare(enum.ACTIVE, u.Status) != 0 {
msg = "商户状态异常,请联系管理人员!"
goto stopRun
}
b, msg = handleFileContent(split[0], u, c)
if b {
flag = enum.SuccessFlag
url = "/withdraw/show_list_ui"
}
stopRun:
c.Data["json"] = pubMethod.JsonFormat(flag, "", msg, url)
c.ServeJSON()
c.StopRun()
}
func handleFileContent(name string, u models.AgentInfo, c *Withdraw) (bool, string) {
// 重命名文件
fileName := name + " - " + pubMethod.GetNowTimeV2() + pubMethod.RandomString(4) + ".xlsx"
// 保存文件
_ = c.SaveToFile("file", path.Join(enum.ExcelPath, fileName))
// 读取文件内容
xlFile, err := xlsx.OpenFile(enum.ExcelPath + fileName)
if err != nil {
msg := "文件内容错误:" + err.Error()
utils.LogInfo(msg)
return false, msg
}
// 只读取文档中第一个工作表,忽略其他工作表
sheet := xlFile.Sheets[0]
line, err := sheet.Row(0).Cells[1].Int()
if err != nil {
msg := "请输入正确的总笔数:" + err.Error()
utils.LogInfo(msg)
return false, msg
}
if line <= 0 {
msg := "请输入正确的总笔数!"
return false, msg
}
if line > 300 {
line = 300
}
ac := models.GetAccountByUid(u.AgentUid)
if strings.Compare(enum.ACTIVE, ac.Status) != 0 {
msg := "账户状态异常,请联系管理人员!"
return false, msg
}
// 后台处理文件,不让用户等待
go func() {
for k, row := range sheet.Rows {
if k == 0 || k == 1 {
continue
}
// 数据行数不得超过指定行数
if k == line+2 || k == 301 {
break
}
// 出现空行,则忽略后面记录
if row.Cells[0].String() == "" || row.Cells[4].String() == "" {
break
}
bankAccountType := row.Cells[3].String()
ac := models.GetAccountByUid(u.AgentUid)
b, msg, code := verifyFileContent(row.Cells[0].String(), row.Cells[1].String(), row.Cells[2].String(), bankAccountType,
row.Cells[4].String(), ac)
if !b {
utils.LogInfo(fmt.Sprintf("用户:%s 批量代付中,第 %d 行记录出现错误:%s", u.AgentName, k+1, msg))
// 账户可用余额不足,终止读取记录
if code == 5009 {
break
}
continue
}
if strings.Compare("对公", bankAccountType) == 0 {
bankAccountType = enum.PublicAccount
} else {
bankAccountType = enum.PrivateDebitAccount
}
money, _ := strconv.ParseFloat(row.Cells[4].String(), 10)
payFor := models.PayforInfo{
PayforUid: "pppp" + xid.New().String(),
MerchantUid: u.AgentUid,
MerchantName: u.AgentName,
PhoneNo: u.AgentPhone,
MerchantOrderId: xid.New().String(),
BankOrderId: "4444" + xid.New().String(),
PayforFee: common.PAYFOR_FEE,
Type: common.SELF_MERCHANT,
PayforAmount: money,
PayforTotalAmount: money + common.PAYFOR_FEE,
BankCode: "C",
BankName: row.Cells[2].String(),
IsSend: common.NO,
BankAccountName: row.Cells[0].String(),
BankAccountNo: row.Cells[1].String(),
BankAccountType: bankAccountType,
BankAccountAddress: row.Cells[2].String(),
Status: common.PAYFOR_COMFRIM,
CreateTime: pubMethod.GetNowTime(),
UpdateTime: pubMethod.GetNowTime(),
}
models.InsertPayfor(payFor)
time.Sleep(500 * time.Millisecond)
}
}()
return true, "提交成功,等待审核中,请在结算信息中查询状态!"
}
// 验证文件内容是否规范
func verifyFileContent(accountName, cardNo, bankAccountAddress, bankAccountType, amount string, ac models.AccountInfo) (bool, string, int) {
if accountName == "" || cardNo == "" {
msg := "账户名或卡号不能为空!"
return false, msg, 5001
}
// 账户类型
if strings.Compare("对公", bankAccountType) == 0 {
if bankAccountAddress == "" {
msg := "收款方开户机构名称不能为空!"
return false, msg, 5002
}
}
if amount == "" {
msg := "金额不能为空!"
return false, msg, 5003
}
matched, _ := regexp.MatchString(enum.MoneyReg, amount)
if !matched {
msg := "请输入正确的金额!"
return false, msg, 5004
}
f, err := strconv.ParseFloat(amount, 10)
if err != nil {
msg := "请输入正确的金额! " + err.Error()
return false, msg, 5007
}
if f > enum.WithdrawalMaxAmount || f < enum.WithdrawalMinAmount || f+enum.SettlementFee > ac.WaitAmount {
msg := fmt.Sprintf("单笔提现金额超出限制,提现金额:%f账户可结算余额%f提现最小额%d最大额%d手续费%d",
f, ac.WaitAmount, enum.WithdrawalMinAmount, enum.WithdrawalMaxAmount, enum.SettlementFee)
return false, msg, 5008
}
if f+enum.SettlementFee > ac.Balance || ac.Balance <= 0 {
msg := fmt.Sprintf("账户金额不足,提现金额:%f账户余额%f手续费%d",
f, ac.Balance, enum.SettlementFee)
return false, msg, 5009
}
return true, "", 5000
}