You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

476 lines
13 KiB
Go

7 months ago
package service
import (
6 months ago
"encoding/base64"
7 months ago
e "errors"
6 months ago
"fmt"
7 months ago
"github.com/xuri/excelize/v2"
7 months ago
"gold-shop/errors"
"gold-shop/global"
"gold-shop/model"
"gold-shop/request"
7 months ago
"gold-shop/request/manage"
7 months ago
"gold-shop/utils"
7 months ago
"gold-shop/utils/excel"
7 months ago
"gold-shop/utils/payment"
"gold-shop/utils/result"
6 months ago
"gold-shop/utils/tlpay"
6 months ago
"gold-shop/utils/tlpay/notify"
6 months ago
"gold-shop/utils/tlpay/param"
7 months ago
"gorm.io/gorm"
6 months ago
"strconv"
7 months ago
"time"
7 months ago
)
var PaymentService = paymentService{}
type paymentService struct {
}
7 months ago
func (paymentService) GetUserPayments(userID, page, pageSize int) ([]model.Payment, int64) {
7 months ago
payments := make([]model.Payment, pageSize)
offset := (page - 1) * pageSize
var total int64
6 months ago
global.DB.Where("user_id", userID).Order("id desc").Offset(offset).Limit(pageSize).Find(&payments)
7 months ago
global.DB.Model(&model.Payment{}).Where("user_id", userID).Count(&total)
return payments, total
}
func (s paymentService) Payment(userID int, paymentRequest request.PaymentRequest) (result.Data, error) {
7 months ago
p, err := s.createPayment(userID, paymentRequest)
if err != nil {
return nil, err
}
data := result.Data{}
6 months ago
if paymentRequest.PayType == "wxgzh" {
6 months ago
data, err = s.wxPayment(paymentRequest, p.PaymentNo)
5 months ago
} else if paymentRequest.PayType == "alishh" {
data, err = s.aliPayment(paymentRequest, p.PaymentNo)
7 months ago
} else if paymentRequest.PayType == "transfer" {
data, err = s.transferPayment(paymentRequest, p)
6 months ago
} else if paymentRequest.PayType == "binding" {
data, err = s.bindingPayment(paymentRequest, p)
6 months ago
} else if paymentRequest.PayType == "gateway" {
data, err = s.getGatewayPayUrl(p)
5 months ago
} else if paymentRequest.PayType == "union" {
data, err = s.getUnionPayUrl(p)
7 months ago
} else {
err = errors.NewBusinessError("payType参数错误")
}
if err != nil {
p.Status = 2
p.ErrorMessage = err.Error()
global.DB.Save(p)
return nil, err
}
6 months ago
p.PayOrderID = data["orderId"].(string)
7 months ago
global.DB.Save(p)
6 months ago
fmt.Println(data)
7 months ago
return data, nil
}
6 months ago
func (s paymentService) wxPayment(paymentRequest request.PaymentRequest, orderID string) (result.Data, error) {
7 months ago
param := payment.WxPayParam{}
param.Remark = "payment"
6 months ago
param.OrderId = orderID
7 months ago
param.OpenId = paymentRequest.OpenID
param.Amount = paymentRequest.Amount
6 months ago
param.NotifyUrl = "http://api.wrtcjt.com/h5/payment-notify"
7 months ago
res, err := payment.PayApi.WxPay(param)
if err != nil {
return nil, err
}
7 months ago
7 months ago
if res.Status != payment.Success {
return nil, errors.NewBusinessError(res.Message)
}
data := result.Data{
6 months ago
"orderId": res.OrderID,
7 months ago
"paySign": res.PaySign,
"package": res.Package,
"signType": res.PaySignType,
"nonceStr": res.NonceStr,
"appId": res.AppId,
"timeStamp": res.Timestamp,
}
return data, nil
}
5 months ago
func (s paymentService) aliPayment(paymentRequest request.PaymentRequest, orderID string) (result.Data, error) {
param := payment.AliPayParam{}
param.Remark = "payment"
param.OrderId = orderID
param.BuyerId = paymentRequest.OpenID
param.Amount = paymentRequest.Amount
param.NotifyUrl = "http://api.wrtcjt.com/h5/payment-notify"
res, err := payment.PayApi.AliPay(param)
if err != nil {
return nil, err
}
if res.Status != payment.Success {
return nil, errors.NewBusinessError(res.Message)
}
data := result.Data{
"orderId": res.OrderID,
"tradeNo": res.TradeNo,
"paymentNo": orderID,
}
return data, nil
}
7 months ago
func (s paymentService) transferPayment(paymentRequest request.PaymentRequest, p *model.Payment) (result.Data, error) {
param := payment.TransferPayParam{}
param.Remark = "payment"
param.OrderId = utils.GenerateNo("payment")
param.Amount = paymentRequest.Amount
param.NotifyUrl = ""
res, err := payment.PayApi.TransferPay(param)
if err != nil {
return nil, err
}
if res.Status != payment.Success {
return nil, errors.NewBusinessError(res.Message)
}
data := result.Data{
"payeeAccountName": res.PayeeAccountName,
"payeeBankName": res.PayeeBankName,
"payeeCardNo": res.PayeeCardNo,
"orderID": res.OrderID,
6 months ago
"paymentNo": p.PaymentNo,
}
return data, nil
}
func (s paymentService) bindingPayment(paymentRequest request.PaymentRequest, p *model.Payment) (result.Data, error) {
payParam := param.PayApplyAgreeParam{}
payParam.Amount = strconv.FormatFloat(paymentRequest.Amount*100, 'f', 0, 64)
payParam.AgreeID = paymentRequest.AgreeID
payParam.ReqSn = p.PaymentNo
payParam.Currency = "CNY"
payParam.Subject = "充值"
payParam.TrxReserve = "充值"
6 months ago
payParam.NotifyUrl = "http://api.wrtcjt.com/h5/binding-pay-notify"
6 months ago
res, err := tlpay.TLPay.PayApplyAgree(payParam)
if err != nil {
return nil, err
}
if err != nil {
return nil, err
}
if res.RetCode != "SUCCESS" {
return nil, errors.NewBusinessError(res.RetMsg)
}
if res.TrxStatus != "1999" {
return nil, errors.NewBusinessError(res.ErrMsg)
}
data := result.Data{
"paymentNo": p.PaymentNo,
"orderId": res.TrxID,
"thpInfo": base64.StdEncoding.EncodeToString([]byte(res.ThpInfo)),
}
return data, nil
}
func (s paymentService) ConfirmBindingPayment(req request.BindingPayConfirmRequest, user *model.User) (result.Data, error) {
pm := &model.Payment{}
err := global.DB.Where("user_id", user.ID).Where("payment_no", req.PaymentNo).Where("status", 0).First(&pm).Error
if err != nil {
return nil, err
}
thpInfo, err := base64.StdEncoding.DecodeString(req.ThpInfo)
if err != nil {
return nil, err
}
payParam := param.PayAgreeConfirmParam{}
payParam.AgreeID = req.AgreeID
payParam.ThpInfo = string(thpInfo)
payParam.ReqSn = req.PaymentNo
payParam.SmsCode = req.SmsCode
res, err := tlpay.TLPay.PayAgreeConfirm(payParam)
if err != nil {
return nil, err
}
if err != nil {
return nil, err
}
if res.RetCode != "SUCCESS" {
return nil, errors.NewBusinessError(res.RetMsg)
}
6 months ago
if res.TrxStatus != "0000" {
6 months ago
return nil, errors.NewBusinessError(res.ErrMsg)
}
data := result.Data{
"paymentNo": pm.PaymentNo,
"orderId": res.TrxID,
7 months ago
}
return data, nil
}
6 months ago
func (s paymentService) SmsBindingPayment(req request.BindingPaySmsRequest, user *model.User) (result.Data, error) {
pm := &model.Payment{}
err := global.DB.Where("user_id", user.ID).Where("payment_no", req.PaymentNo).Where("status", 0).First(&pm).Error
if err != nil {
return nil, err
}
thpInfo, err := base64.StdEncoding.DecodeString(req.ThpInfo)
if err != nil {
return nil, err
}
smsParam := param.PaySmsAgreeParam{}
smsParam.AgreeID = req.AgreeID
smsParam.ThpInfo = string(thpInfo)
smsParam.OrderID = req.PaymentNo
res, err := tlpay.TLPay.PaySmsAgree(smsParam)
if err != nil {
return nil, err
}
if err != nil {
return nil, err
}
if res.RetCode != "SUCCESS" {
return nil, errors.NewBusinessError(res.RetMsg)
}
data := result.Data{
"paymentNo": pm.PaymentNo,
}
return data, nil
}
7 months ago
func (paymentService) createPayment(userID int, paymentRequest request.PaymentRequest) (*model.Payment, error) {
7 months ago
p := model.Payment{}
p.PaymentNo = utils.GenerateNo("payment")
7 months ago
p.Amount = paymentRequest.Amount
p.OpenID = paymentRequest.OpenID
p.PayType = paymentRequest.PayType
7 months ago
p.Status = 0
p.UserID = userID
err := global.DB.Save(&p).Error
if err != nil {
return nil, errors.NewBusinessError("保存数据失败")
}
return &p, nil
}
7 months ago
func (s *paymentService) buildQuery(req manage.PaymentQueryRequest) *gorm.DB {
tx := global.DB
if req.Mobile != "" {
var userIds []int
global.DB.Model(&model.User{}).Where("mobile", req.Mobile).Pluck("id", &userIds)
tx = tx.Where("user_id", userIds)
}
if req.PaymentNo != "" {
tx = tx.Where("payment_no", req.PaymentNo)
}
if req.Status != "" {
tx = tx.Where("status", req.Status)
}
if req.UserID != 0 {
tx = tx.Where("user_id", req.UserID)
}
return tx
}
func (s *paymentService) GetPayments(req manage.PaymentQueryRequest) ([]model.Payment, int64) {
payments := make([]model.Payment, req.PageSize)
offset := (req.Page - 1) * req.PageSize
var total int64
tx := s.buildQuery(req)
tx.Preload("User").Order("id desc").Offset(offset).Limit(req.PageSize).Find(&payments)
tx.Model(&model.Order{}).Count(&total)
return payments, total
}
func (s *paymentService) GeneratePaymentsExcel(req manage.PaymentQueryRequest) *excelize.File {
pageSize := 200
lastID := 0
tx := s.buildQuery(req)
f := excel.NewFile()
headers := []string{"支付订单号", "用户手机号", "金额", "支付状态", "支付时间"}
excel.SetSimpleHeaders(headers, "Sheet1", f)
for {
payments := make([]model.Payment, pageSize)
tx.Preload("User").Where("id > ?", lastID).Limit(pageSize).Find(&payments)
count := len(payments)
if count == 0 {
break
}
s.buildPaymentsExcel(payments, "Sheet1", f)
lastIndex := count - 1
lastID = payments[lastIndex].ID
}
return f
}
func (paymentService) buildPaymentsExcel(payments []model.Payment, sheet string, f *excelize.File) {
row := 2
for _, p := range payments {
col := 0
f.SetCellValue(sheet, excel.CellKey(row, &col), p.PaymentNo)
f.SetCellValue(sheet, excel.CellKey(row, &col), p.User.Mobile)
f.SetCellValue(sheet, excel.CellKey(row, &col), p.Amount)
f.SetCellValue(sheet, excel.CellKey(row, &col), p.GetStatusText())
f.SetCellValue(sheet, excel.CellKey(row, &col), p.CreatedAt.Format(time.DateTime))
row++
}
}
func (s paymentService) AfterTransferPayNotify(req request.TransferPayNotifyRequest) error {
pm := &model.Payment{}
6 months ago
err := global.DB.Where("payment_no", req.OutOrderID).Where("status", 0).First(&pm).Error
7 months ago
if err != nil && e.Is(err, gorm.ErrRecordNotFound) {
return errors.NewBusinessError("记录不存在")
}
6 months ago
user := model.User{}
global.DB.Model(&model.User{}).Where("id", pm.UserID).Find(&user)
7 months ago
if req.PayStatus == "1" {
pm.Status = 1
pm.PayerCardNo = req.PayerCardNo
pm.PayerAccountName = req.PayerAccountName
6 months ago
global.DB.Save(&user)
7 months ago
} else {
pm.Status = 2
}
err = global.DB.Save(&pm).Error
return err
}
6 months ago
func (s paymentService) AfterPaymentNotify(req request.PaymentNotifyRequest) error {
pm := &model.Payment{}
6 months ago
err := global.DB.Where("payment_no", req.MchOrderID).Where("status", 0).First(&pm).Error
6 months ago
if err != nil && e.Is(err, gorm.ErrRecordNotFound) {
return errors.NewBusinessError("记录不存在")
}
6 months ago
user := model.User{}
global.DB.Model(&model.User{}).Where("id", pm.UserID).Find(&user)
6 months ago
if req.PayStatus == 1 {
pm.Status = 1
6 months ago
global.DB.Model(&user).UpdateColumn("balance", gorm.Expr("balance + ?", pm.Amount))
6 months ago
} else {
pm.Status = 2
}
err = global.DB.Save(&pm).Error
return err
}
6 months ago
func (s paymentService) AfterBindingPayNotify(req notify.PayAgreeNotify) error {
pm := &model.Payment{}
err := global.DB.Where("payment_no", req.CusOrderID).Where("status", 0).First(&pm).Error
if err != nil && e.Is(err, gorm.ErrRecordNotFound) {
return errors.NewBusinessError("记录不存在")
}
user := model.User{}
global.DB.Model(&model.User{}).Where("id", pm.UserID).Find(&user)
if req.TrxStatus == "0000" {
pm.Status = 1
global.DB.Model(&user).UpdateColumn("balance", gorm.Expr("balance + ?", pm.Amount))
} else {
pm.Status = 2
}
err = global.DB.Save(&pm).Error
return err
}
func (s paymentService) GatewayPay(token string) (string, error) {
pm := &model.Payment{}
err := global.DB.Where("token", token).Where("status", 0).First(&pm).Error
if err != nil {
return "", err
}
p := param.GatewayPayParam{}
p.OrderID = pm.PaymentNo
p.PayType = "B2B,B2C"
p.TrxAmt = strconv.FormatFloat(pm.Amount*100, 'f', 0, 64)
p.LimitPay = "no_credit"
p.RetUrl = "http://api.wrtcjt.com/h5/gateway-pay-ret"
5 months ago
//p.RetUrl = "https://www.baidu.com"
6 months ago
p.NotifyUrl = "http://api.wrtcjt.com/h5/binding-pay-notify"
p.GoodsID = "1"
p.GoodsInf = "充值"
p.Charset = "UTF-8"
str := tlpay.TLPay.GatewayPay(p)
return str, nil
}
func (s paymentService) GatewayPayRet(ret notify.GatewayPayRet) (string, error) {
return "", nil
}
func (s paymentService) GatewayPayApply(userID int, paymentRequest request.PaymentRequest) (result.Data, error) {
pm, err := s.createPayment(userID, paymentRequest)
if err != nil {
return nil, err
}
return s.getGatewayPayUrl(pm)
}
func (s paymentService) getGatewayPayUrl(pm *model.Payment) (result.Data, error) {
token := utils.Md5(pm.PaymentNo + strconv.Itoa(pm.UserID) + "_gateway")
pm.Token = token
err := global.DB.Save(pm).Error
if err != nil {
return nil, err
}
data := result.Data{"url": "http://api.wrtcjt.com/h5/gateway-pay?token=" + token, "orderId": ""}
return data, nil
}
5 months ago
func (s paymentService) getUnionPayUrl(pm *model.Payment) (result.Data, error) {
token := utils.Md5(pm.PaymentNo + strconv.Itoa(pm.UserID) + "_union")
pm.Token = token
err := global.DB.Save(pm).Error
if err != nil {
return nil, err
}
data := result.Data{"url": "http://api.wrtcjt.com/h5/union-pay?token=" + token, "orderId": ""}
return data, nil
}
func (s paymentService) UnionPay(token string) (string, error) {
pm := &model.Payment{}
err := global.DB.Where("token", token).Where("status", 0).First(&pm).Error
if err != nil {
return "", err
}
p := param.UnionOrderParam{}
p.ReqSn = pm.PaymentNo
p.TrxAmt = strconv.FormatFloat(pm.Amount*100, 'f', 0, 64)
p.LimitPay = "no_credit"
p.RetUrl = "http://api.wrtcjt.com/h5/gateway-pay-ret"
p.NotifyUrl = "http://api.wrtcjt.com/h5/binding-pay-notify"
p.Body = "充值"
p.Charset = "UTF-8"
p.PayType = "VSP511"
str := tlpay.TLPay.UnionPay(p)
return str, nil
}