- 新增 internal/sitecode 包:FromRequest 头优先解析、FromQueryThenHeader 探测接口专用、ExtractHost/IsLocalHost 提取 Host 域名 - 替换 auth/order/listing/chat/notification/withdrawal/wallet/distribution 八模块 17 处各自内联的解析逻辑,统一优先级与 TrimSpace 行为 - 修复 notification 漏 TrimSpace、探测接口会话头压过显式 query、 GetPublicSiteInfo 把 localhost Host 当站点域名查库等不一致 - 顺手清理 auth 中无引用的 extractHost 死代码 - gofmt 修复 withdrawal/presenter、chat/file/payment 测试四个历史遗留格式问题
139 lines
4.0 KiB
Go
139 lines
4.0 KiB
Go
package withdrawal
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"net/url"
|
|
"strings"
|
|
|
|
"hfb_sys/backend/internal/model"
|
|
)
|
|
|
|
// 转换为用户DTO
|
|
func toDTO(w model.WithdrawalRequest) WithdrawalDTO {
|
|
return WithdrawalDTO{
|
|
ID: w.ID,
|
|
WithdrawNo: w.WithdrawNo,
|
|
UserID: w.UserID,
|
|
DistributionSiteID: w.DistributionSiteID,
|
|
AmountCent: w.AmountCent,
|
|
FeeCent: w.FeeCent,
|
|
ActualAmountCent: w.ActualAmountCent,
|
|
AccountType: w.AccountType,
|
|
AccountName: w.AccountName,
|
|
AccountNo: w.AccountNo,
|
|
BankName: w.BankName,
|
|
Status: w.Status,
|
|
ReviewRemark: w.ReviewRemark,
|
|
CreatedAt: w.CreatedAt,
|
|
UpdatedAt: w.UpdatedAt,
|
|
ReviewedAt: w.ReviewedAt,
|
|
PaidAt: w.PaidAt,
|
|
}
|
|
}
|
|
|
|
// 转换为管理员详细DTO
|
|
|
|
// 转换为管理员详细DTO
|
|
func (r *Repository) toDetailDTO(ctx context.Context, w model.WithdrawalRequest) (*WithdrawalDetailDTO, error) {
|
|
db := r.db.WithContext(ctx)
|
|
// 查询用户信息
|
|
var user model.User
|
|
db.Select("nickname, phone").First(&user, w.UserID)
|
|
|
|
// 查询审核人信息
|
|
var reviewedByName string
|
|
if w.ReviewedBy != nil {
|
|
var admin model.AdminUser
|
|
if err := db.Select("nickname").First(&admin, *w.ReviewedBy).Error; err == nil {
|
|
reviewedByName = admin.Nickname
|
|
}
|
|
}
|
|
|
|
// 查询打款人信息
|
|
var paidByName string
|
|
if w.PaidBy != nil {
|
|
var admin model.AdminUser
|
|
if err := db.Select("nickname").First(&admin, *w.PaidBy).Error; err == nil {
|
|
paidByName = admin.Nickname
|
|
}
|
|
}
|
|
|
|
// 获取完整账号和收款二维码(管理员可见)
|
|
fullAccountNo := w.AccountNo
|
|
var certificateURLs []string
|
|
if w.PaymentAccountID != nil {
|
|
var paymentAccount model.UserPaymentAccount
|
|
if err := db.First(&paymentAccount, *w.PaymentAccountID).Error; err == nil {
|
|
// 解密账号
|
|
decrypted, err := r.encryptor.Decrypt(paymentAccount.AccountNo)
|
|
if err == nil {
|
|
fullAccountNo = decrypted
|
|
}
|
|
// 解析收款二维码
|
|
if paymentAccount.CertificateURLs != nil {
|
|
json.Unmarshal(paymentAccount.CertificateURLs, &certificateURLs)
|
|
}
|
|
certificateURLs = privateCertificateURLs(certificateURLs)
|
|
}
|
|
}
|
|
|
|
var siteName, siteCode string
|
|
if w.DistributionSiteID > 0 {
|
|
var site model.DistributionSite
|
|
if err := db.Select("site_name, site_code").First(&site, w.DistributionSiteID).Error; err == nil {
|
|
siteName = site.SiteName
|
|
siteCode = site.SiteCode
|
|
}
|
|
}
|
|
|
|
return &WithdrawalDetailDTO{
|
|
ID: w.ID,
|
|
WithdrawNo: w.WithdrawNo,
|
|
UserID: w.UserID,
|
|
DistributionSiteID: w.DistributionSiteID,
|
|
DistributionSiteName: siteName,
|
|
DistributionSiteCode: siteCode,
|
|
UserNickname: user.Nickname,
|
|
UserPhone: user.Phone,
|
|
AmountCent: w.AmountCent,
|
|
FeeCent: w.FeeCent,
|
|
ActualAmountCent: w.ActualAmountCent,
|
|
PaymentAccountID: w.PaymentAccountID,
|
|
AccountType: w.AccountType,
|
|
AccountName: w.AccountName,
|
|
AccountNo: fullAccountNo,
|
|
BankName: w.BankName,
|
|
BankBranch: w.BankBranch,
|
|
CertificateURLs: certificateURLs,
|
|
Status: w.Status,
|
|
ReviewedBy: w.ReviewedBy,
|
|
ReviewedByName: reviewedByName,
|
|
ReviewedAt: w.ReviewedAt,
|
|
ReviewRemark: w.ReviewRemark,
|
|
PaidBy: w.PaidBy,
|
|
PaidByName: paidByName,
|
|
PaidAt: w.PaidAt,
|
|
PaymentProofURL: w.PaymentProofURL,
|
|
PaymentRemark: w.PaymentRemark,
|
|
CreatedAt: w.CreatedAt,
|
|
UpdatedAt: w.UpdatedAt,
|
|
}, nil
|
|
}
|
|
|
|
// privateCertificateURLs 兼容历史公开收款凭证 URL,统一经私有对象接口读取。
|
|
func privateCertificateURLs(values []string) []string {
|
|
for index, value := range values {
|
|
parsed, err := url.Parse(value)
|
|
if err != nil || parsed.Path != "/api/public/files/object" {
|
|
continue
|
|
}
|
|
if !strings.HasPrefix(parsed.Query().Get("key"), "payment-cert/") {
|
|
continue
|
|
}
|
|
parsed.Path = "/api/files/object"
|
|
values[index] = parsed.String()
|
|
}
|
|
return values
|
|
}
|