Files
kami_gateway/internal/service/pay_service.go
2024-09-03 21:52:44 +08:00

409 lines
14 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.

package service
import (
"errors"
"fmt"
"gateway/internal/config"
"gateway/internal/entities/supplier"
"gateway/internal/models/merchant"
"gateway/internal/models/merchant_deploy"
"gateway/internal/models/order"
"gateway/internal/models/road"
"gateway/internal/schema/request"
"gateway/internal/schema/response"
"gateway/internal/utils"
"strconv"
"time"
"github.com/beego/beego/v2/core/logs"
"github.com/rs/xid"
"github.com/shopspring/decimal"
)
// ChooseRoadV2 选择通道通过productCode选择对应的通道
func ChooseRoadV2(c *response.PayBaseResp) *response.PayBaseResp {
orderPrice, err := strconv.ParseFloat(c.Params["orderPrice"], 64)
if err != nil {
c.Code = -1
c.Msg = "输入金额错误!"
return c
}
roadInfo := road.GetRoadInfoByProductCode(c.Params["productCode"])
if roadInfo.Id == 0 {
c.Code = -1
c.Msg = "未配置支付通道!"
return c
}
if msg, ok := RoadIsValid(roadInfo, c); !ok {
c.Code = -1
c.Msg = msg
return c
}
merchantUid := c.MerchantInfo.MerchantUid
// 通道配置信息
deployInfo := merchant_deploy.GetMerchantDeployByUidAndRoadUid(merchantUid, roadInfo.RoadUid)
if deployInfo.MerchantUid == "" {
c.Code = -1
c.Msg = "该商户没有配置通道信息"
return c
}
rate, err2 := deployInfo.GetSingleRoadPlatformRateByPrice(orderPrice)
if err2 != nil {
c.Code = -1
c.Msg = "当前通道面额存在问题"
return c
}
if !deployInfo.CheckSingleRoadPlatformRate(orderPrice) {
c.Code = -1
c.Msg = "当前面额不被允许"
return c
}
c.RoadInfo = roadInfo
c.PlatformRate = rate
c.AgentRate = deployInfo.SingleRoadAgentRate
c.RoadPoolInfo = road.GetRoadPoolByRoadPoolCode(deployInfo.RollRoadCode)
return c
}
// RoadIsValid 判断通道是否是合法的
func RoadIsValid(roadInfo road.RoadInfo, c *response.PayBaseResp) (string, bool) {
if roadInfo.RoadUid == "" || len(roadInfo.RoadUid) == 0 {
return "参数缺失", false
}
FORMAT := fmt.Sprintf("该通道:%s;", roadInfo.RoadName)
if roadInfo.Status != "active" {
logs.Notice(FORMAT + "不是激活状态")
return "通道未激活", false
}
hour := time.Now().Hour()
s := roadInfo.StarHour
e := roadInfo.EndHour
if hour < s || hour > e {
logs.Notice(FORMAT)
return "当前未处在交易区间内", false
}
if roadInfo.SingleMinLimit > c.OrderAmount || roadInfo.SingleMaxLimit < c.OrderAmount {
logs.Error(FORMAT + "订单金额超限制")
return "订单金额超过交易限制", false
}
todayLimit := roadInfo.TodayLimit
totalLimit := roadInfo.TotalLimit
todayIncome := roadInfo.TodayIncome
totalIncome := roadInfo.TotalIncome
if (todayIncome + c.OrderAmount) > todayLimit {
logs.Error(FORMAT + "达到了每天金额上限")
return "订单金额超过金额限制", false
}
if (totalIncome + c.OrderAmount) > totalLimit {
logs.Error(FORMAT + "达到了总量限制")
return "订单金额达到总量限制", false
}
// 如果通道被选中,那么总请求数+1
roadInfo.RequestAll = roadInfo.RequestAll + 1
roadInfo.TodayRequestAll = roadInfo.RequestAll + 1
roadInfo.UpdateTime = time.Now()
road.UpdateRoadInfo(roadInfo)
return "", true
}
// GenerateOrderInfo 获取基本订单记录
func GenerateOrderInfo(c *response.PayBaseResp) order.OrderInfo {
// 6666是自己系统订单号
bankOrderNo := "6666" + xid.New().String()
// 获取支付类型的名称,例如支付宝扫码等
orderInfo := order.OrderInfo{
MerchantUid: c.MerchantInfo.MerchantUid,
MerchantName: c.MerchantInfo.MerchantName,
MerchantOrderId: c.Params["orderNo"],
BankOrderId: bankOrderNo,
OrderAmount: c.OrderAmount,
FactAmount: c.OrderAmount,
ShowAmount: c.OrderAmount,
RollPoolCode: c.RoadPoolInfo.RoadPoolCode,
RollPoolName: c.RoadPoolInfo.RoadPoolName,
RoadUid: c.RoadInfo.RoadUid,
RoadName: c.RoadInfo.RoadName,
PayProductName: c.RoadInfo.ProductName,
ShopName: c.Params["productName"],
Freeze: config.NO,
Refund: config.NO,
Unfreeze: config.NO,
Ip: c.ClientIP,
PayProductCode: c.RoadInfo.ProductUid,
Status: config.WAIT,
NotifyUrl: c.Params["notifyUrl"],
OrderPeriod: c.Params["orderPeriod"],
UpdateTime: time.Now(),
CreateTime: time.Now(),
ExValue: c.Params["exValue"],
}
if c.MerchantInfo.BelongAgentUid != "" || c.AgentRate > config.ZERO {
orderInfo.AgentUid = c.MerchantInfo.BelongAgentUid
orderInfo.AgentName = c.MerchantInfo.BelongAgentName
}
return orderInfo
}
// CreateOrderInfo 创建订单
func CreateOrderInfo(createdOrder request.CreatedOrder, info merchant.MerchantInfo, roadPoolInfo road.RoadPoolInfo, roadInfo road.RoadInfo) (orderInfo order.OrderInfo, err error) {
// 6666是自己系统订单号
orderInfo = order.OrderInfo{}
// 获取支付类型的名称,例如支付宝扫码等
orderInfo = order.OrderInfo{
MerchantUid: info.MerchantUid,
MerchantName: info.MerchantName,
MerchantOrderId: createdOrder.OrderNo,
BankOrderId: "6666" + xid.New().String(),
OrderAmount: createdOrder.OrderPrice,
FactAmount: createdOrder.OrderPrice,
ShowAmount: createdOrder.OrderPrice,
RollPoolCode: roadPoolInfo.RoadPoolCode,
RollPoolName: roadPoolInfo.RoadPoolName,
RoadUid: roadInfo.RoadUid,
RoadName: roadInfo.RoadName,
PayProductName: roadInfo.ProductName,
Freeze: config.NO,
Refund: config.NO,
Unfreeze: config.NO,
Ip: createdOrder.IP,
PayProductCode: roadInfo.ProductUid,
Status: config.Created,
NotifyUrl: createdOrder.NotifyUrl,
OrderPeriod: createdOrder.OrderPeriod,
CreateTime: time.Now(),
TransactionType: roadInfo.TransactionType,
}
return
}
// GenerateOrderProfit 计算收益,平台利润,代理利润
func GenerateOrderProfit(orderInfo order.OrderInfo, c *response.PayBaseResp) order.OrderProfitInfo {
// 因为所有的手续费率都是百分率所以需要除以100
supplierProfit := decimal.NewFromFloat(orderInfo.OrderAmount).
Div(decimal.NewFromInt(100)).
Mul(decimal.NewFromFloat(c.RoadInfo.BasicFee))
platformProfit := decimal.NewFromFloat(orderInfo.OrderAmount).
Div(decimal.NewFromInt(100)).
Mul(decimal.NewFromFloat(c.PlatformRate))
agentProfit := decimal.NewFromFloat(orderInfo.OrderAmount).
Div(decimal.NewFromInt(100)).
Mul(decimal.NewFromFloat(c.AgentRate))
// 如果用户没有设置代理那么代理利润为0.000
if c.MerchantInfo.BelongAgentUid == "" || len(c.MerchantInfo.BelongAgentUid) == 0 {
agentProfit = decimal.NewFromFloat(config.ZERO)
}
allProfit := supplierProfit.Add(platformProfit).Add(agentProfit)
if allProfit.GreaterThanOrEqual(decimal.NewFromFloat(orderInfo.OrderAmount)) {
logs.Error("手续费已经超过订单金额bankOrderId = %s", orderInfo.BankOrderId)
c.Msg = "手续费已经超过了订单金额"
c.Code = -1
}
orderProfit := order.OrderProfitInfo{
PayProductCode: c.RoadInfo.ProductUid,
PayProductName: c.RoadInfo.ProductName,
Status: config.WAIT,
MerchantOrderId: c.Params["orderNo"],
BankOrderId: orderInfo.BankOrderId,
OrderAmount: c.OrderAmount,
FactAmount: c.OrderAmount,
ShowAmount: c.OrderAmount,
AllProfit: allProfit.InexactFloat64(),
UserInAmount: decimal.NewFromFloat(orderInfo.OrderAmount).Sub(allProfit).InexactFloat64(),
SupplierProfit: supplierProfit.InexactFloat64(),
PlatformProfit: platformProfit.InexactFloat64(),
AgentProfit: agentProfit.InexactFloat64(),
UpdateTime: time.Now(),
CreateTime: time.Now(),
MerchantUid: c.MerchantInfo.MerchantUid,
MerchantName: orderInfo.MerchantName,
SupplierRate: c.RoadInfo.BasicFee,
PlatformRate: c.PlatformRate,
AgentRate: c.AgentRate,
AgentName: orderInfo.AgentName,
AgentUid: orderInfo.AgentUid,
}
// 如果该条订单设置了代理利率,并且设置了代理
if c.MerchantInfo.BelongAgentUid != "" || c.AgentRate > config.ZERO {
orderProfit.AgentUid = c.MerchantInfo.BelongAgentUid
orderProfit.AgentName = c.MerchantInfo.BelongAgentName
}
return orderProfit
}
func CreateOrderProfitInfo(createdOrder request.CreatedOrder, merchantInfo merchant.MerchantInfo, merchantDeployInfo merchant_deploy.MerchantDeployInfo, orderInfo order.OrderInfo, roadInfo road.RoadInfo) (orderProfitInfo order.OrderProfitInfo, err error) {
// 因为所有的手续费率都是百分率所以需要除以100
platFormRate, err := merchantDeployInfo.GetSingleRoadPlatformRateByPrice(createdOrder.OrderPrice)
if err != nil {
platFormRate = 0.0
}
supplierProfit := decimal.NewFromFloat(orderInfo.OrderAmount).
Div(decimal.NewFromInt(100)).
Mul(decimal.NewFromFloat(roadInfo.BasicFee))
platformProfit := decimal.NewFromFloat(orderInfo.OrderAmount).
Div(decimal.NewFromInt(100)).
Mul(decimal.NewFromFloat(platFormRate))
agentProfit := decimal.NewFromFloat(orderInfo.OrderAmount).
Div(decimal.NewFromInt(100)).
Mul(decimal.NewFromFloat(merchantDeployInfo.SingleRoadAgentRate))
// 如果用户没有设置代理那么代理利润为0.000
if merchantInfo.BelongAgentUid == "" || len(merchantInfo.BelongAgentUid) == 0 {
agentProfit = decimal.NewFromFloat(config.ZERO)
}
allProfit := supplierProfit.Add(platformProfit).Add(agentProfit)
if allProfit.GreaterThanOrEqual(decimal.NewFromFloat(orderInfo.OrderAmount)) {
logs.Error("手续费已经超过订单金额bankOrderId = %s", orderInfo.BankOrderId)
err = errors.New("手续费已经超过订单金额")
return
}
orderProfitInfo = order.OrderProfitInfo{
PayProductCode: roadInfo.ProductUid,
PayProductName: roadInfo.ProductName,
Status: config.Created,
MerchantOrderId: createdOrder.OrderNo,
BankOrderId: orderInfo.BankOrderId,
OrderAmount: orderInfo.OrderAmount,
FactAmount: orderInfo.FactAmount,
ShowAmount: orderInfo.ShowAmount,
AllProfit: allProfit.InexactFloat64(),
UserInAmount: decimal.NewFromFloat(orderInfo.OrderAmount).Sub(allProfit).InexactFloat64(),
SupplierProfit: supplierProfit.InexactFloat64(),
PlatformProfit: platformProfit.InexactFloat64(),
AgentProfit: agentProfit.InexactFloat64(),
UpdateTime: time.Now(),
CreateTime: time.Now(),
MerchantUid: merchantInfo.MerchantUid,
MerchantName: orderInfo.MerchantName,
SupplierRate: roadInfo.BasicFee,
PlatformRate: platFormRate,
AgentRate: merchantDeployInfo.SingleRoadAgentRate,
AgentName: orderInfo.AgentName,
AgentUid: orderInfo.AgentUid,
}
return
}
// GenerateRecord 生成订单一系列的记录
func GenerateRecord(c *response.PayBaseResp) (order.OrderInfo, order.OrderProfitInfo, error) {
// 获取订单和订单利润表
orderInfo := order.GetOrderByMerchantOrderId(c.Params["orderNo"])
orderProfitInfo := order.GetOrderProfitByMerchantOrderId(c.Params["orderNo"])
if orderProfitInfo.Id == 0 || orderInfo.MerchantOrderId == "" {
//生成订单记录,订单利润利润
orderInfo = GenerateOrderInfo(c)
orderProfit := GenerateOrderProfit(orderInfo, c)
if c.Code == -1 {
return orderInfo, orderProfit, errors.New("订单数据插入失败")
}
if !order.InsertOrderAndOrderProfit(orderInfo, orderProfit) {
c.Code = -1
return orderInfo, orderProfit, errors.New("订单数据插入失败")
}
logs.Info("插入支付订单记录和支付利润记录成功")
return orderInfo, orderProfit, nil
}
if orderInfo.Status != config.Created {
err := errors.New("当前订单已存在,请等待处理结果或手动查询")
return orderInfo, orderProfitInfo, err
}
if !order.InsertOrderExValue(c.Params["orderNo"], c.Params["exValue"]) {
err := errors.New("订单数据插入失败")
return orderInfo, orderProfitInfo, err
}
if !order.InsertPayTime(c.Params["orderNo"]) {
err := errors.New("订单数据插入失败")
return orderInfo, orderProfitInfo, err
}
if !order.SwitchOrderAndOrderProfitStatus(c.Params["orderNo"], config.WAIT) {
err := errors.New("订单状态转换失败")
return orderInfo, orderProfitInfo, err
}
orderInfo = order.GetOrderByMerchantOrderId(c.Params["orderNo"])
logs.Info("插入支付订单记录和支付利润记录成功")
return orderInfo, orderProfitInfo, nil
}
func GenerateSuccessData(scanData supplier.ScanData, c *response.PayBaseResp) *response.ScanSuccessData {
params := make(map[string]string)
params["statusCode"] = "00"
params["orderNo"] = scanData.BankNo
params["orderPrice"] = scanData.OrderPrice
params["statusCode"] = "00"
sign := utils.GetMD5SignMF(params, c.MerchantInfo.MerchantSecret)
scanSuccessData := new(response.ScanSuccessData)
scanSuccessData.StatusCode = "00"
scanSuccessData.OrderNo = scanData.OrderNo
scanSuccessData.OrderPrice = scanData.OrderPrice
scanSuccessData.Msg = "请求成功"
scanSuccessData.Sign = sign
if scanSuccessData.StatusCode == "00" {
scanSuccessData.Code = 0
} else {
scanSuccessData.Code = -1
}
return scanSuccessData
}
func CreateOrderInfoAndOrderProfitInfo(createdOrder request.CreatedOrder, info merchant.MerchantInfo) (roadInfo road.RoadInfo, err error) {
roadInfo = road.GetRoadInfoByProductCode(createdOrder.ProductCode)
if roadInfo.Id == 0 {
err = errors.New("未配置支付方式")
return
}
if msg, ok := RoadIsValid(roadInfo, &response.PayBaseResp{
OrderAmount: createdOrder.OrderPrice,
}); !ok {
err = errors.New(msg)
return
}
merchantDeploy := merchant_deploy.GetMerchantDeployByUidAndRoadUid(
info.MerchantUid,
roadInfo.RoadUid,
)
if merchantDeploy.Id == 0 {
err = errors.New("当前用户未配置支付方式")
return
}
roadPoolInfo := road.GetRoadPoolByRoadPoolCode(merchantDeploy.RollRoadCode)
if roadPoolInfo.Id == 0 {
err = errors.New("当前用户未配置支付方式")
return
}
orderInfo, err := CreateOrderInfo(createdOrder, info, roadPoolInfo, roadInfo)
if err != nil {
err = errors.Join(err, errors.New("创建订单失败"))
return
}
orderProfitInfo, err := CreateOrderProfitInfo(createdOrder, info, *merchantDeploy, orderInfo, roadInfo)
if err != nil {
err = errors.Join(err, errors.New("创建订单失败"))
return
}
if !order.InsertOrderAndOrderProfit(orderInfo, orderProfitInfo) {
err = errors.Join(err, errors.New("创建订单失败"))
return
}
return
}
func GerMerchantDeployInfoByUidAndProductCode(uid, productCode string) merchant_deploy.MerchantDeployInfo {
roadInfo := road.GetRoadInfoByProductCode(productCode)
merchantDeploy := merchant_deploy.GetMerchantDeployByUidAndRoadUid(uid, roadInfo.RoadUid)
return *merchantDeploy
}