移除摸大红支付后建群逻辑,仅保留扫码与复制

支付成功只固化客服二维码与订单文案;同步清理迁移、配置与前后端相关字段。
This commit is contained in:
yml2213
2026-07-16 19:52:40 +08:00
parent 094a91c985
commit e07532a188
17 changed files with 16 additions and 192 deletions
+1 -17
View File
@@ -12,10 +12,8 @@ import (
const (
configKeyDefaultQrcodeURL = "mohong.default_qrcode_url"
configKeyGroupWelcomeText = "mohong.group_welcome_text"
configKeyOrderCopyTemplate = "mohong.order_copy_template"
defaultGroupWelcomeText = "订单已支付,请扫码联系客服,并将下方订单信息复制发送给客服。"
defaultOrderCopyTemplate = "【摸大红订单】\n订单号:{{order_no}}\n下单时间:{{created_at}}\n商品:{{product_title}}\n数量:{{quantity}}\n金额:{{amount}}\n下单人:{{buyer_name}}{{buyer_phone}}"
)
@@ -23,7 +21,7 @@ func (r *Repository) GetConfig(ctx context.Context) (*ConfigDTO, error) {
if r.db == nil {
return nil, ErrDependencyUnavailable
}
keys := []string{configKeyDefaultQrcodeURL, configKeyGroupWelcomeText, configKeyOrderCopyTemplate}
keys := []string{configKeyDefaultQrcodeURL, configKeyOrderCopyTemplate}
var rows []model.SystemConfig
if err := r.db.WithContext(ctx).Where("`key` IN ?", keys).Find(&rows).Error; err != nil {
return nil, err
@@ -34,7 +32,6 @@ func (r *Repository) GetConfig(ctx context.Context) (*ConfigDTO, error) {
}
return &ConfigDTO{
DefaultQrcodeURL: strings.TrimSpace(values[configKeyDefaultQrcodeURL]),
GroupWelcomeText: firstNonEmpty(values[configKeyGroupWelcomeText], defaultGroupWelcomeText),
OrderCopyTemplate: firstNonEmpty(values[configKeyOrderCopyTemplate], defaultOrderCopyTemplate),
}, nil
}
@@ -49,11 +46,6 @@ func (r *Repository) UpdateConfig(ctx context.Context, req UpdateConfigRequest)
return err
}
}
if req.GroupWelcomeText != nil {
if err := upsertConfig(tx, configKeyGroupWelcomeText, strings.TrimSpace(*req.GroupWelcomeText), "摸大红订单群欢迎语"); err != nil {
return err
}
}
if req.OrderCopyTemplate != nil {
if err := upsertConfig(tx, configKeyOrderCopyTemplate, strings.TrimSpace(*req.OrderCopyTemplate), "摸大红订单一键复制文案模板"); err != nil {
return err
@@ -100,14 +92,6 @@ func (r *Repository) resolveQrcodeURL(tx *gorm.DB, productQrcode string) string
return ""
}
func (r *Repository) loadWelcomeText(tx *gorm.DB) string {
var cfg model.SystemConfig
if err := tx.Where("`key` = ?", configKeyGroupWelcomeText).First(&cfg).Error; err == nil && strings.TrimSpace(cfg.Value) != "" {
return strings.TrimSpace(cfg.Value)
}
return defaultGroupWelcomeText
}
func (r *Repository) loadCopyTemplate(tx *gorm.DB) string {
var cfg model.SystemConfig
if err := tx.Where("`key` = ?", configKeyOrderCopyTemplate).First(&cfg).Error; err == nil && strings.TrimSpace(cfg.Value) != "" {
-3
View File
@@ -108,7 +108,6 @@ type OrderDTO struct {
ProductUnit string `json:"product_unit"`
QrcodeURLSnapshot string `json:"qrcode_url_snapshot"`
CopyText string `json:"copy_text"`
ConversationID *uint64 `json:"conversation_id"`
BuyerNickname string `json:"buyer_nickname,omitempty"`
BuyerPhone string `json:"buyer_phone,omitempty"`
AdminRemark string `json:"admin_remark,omitempty"`
@@ -138,13 +137,11 @@ type AdminCancelOrderRequest struct {
type ConfigDTO struct {
DefaultQrcodeURL string `json:"default_qrcode_url"`
GroupWelcomeText string `json:"group_welcome_text"`
OrderCopyTemplate string `json:"order_copy_template"`
}
type UpdateConfigRequest struct {
DefaultQrcodeURL *string `json:"default_qrcode_url"`
GroupWelcomeText *string `json:"group_welcome_text"`
OrderCopyTemplate *string `json:"order_copy_template"`
}
+6 -98
View File
@@ -10,9 +10,7 @@ import (
"time"
"hfb_sys/backend/internal/model"
"hfb_sys/backend/internal/modules/chat"
"hfb_sys/backend/internal/modules/notification"
"hfb_sys/backend/internal/modules/supportgroup"
"hfb_sys/backend/internal/timeutil"
"hfb_sys/backend/pkg/money"
@@ -21,8 +19,6 @@ import (
"gorm.io/gorm/clause"
)
const ConversationTypeMohongOrder = "mohong_order"
func (r *Repository) CreateOrder(ctx context.Context, userID uint64, req CreateOrderRequest) (*OrderDTO, error) {
if userID == 0 || req.ProductID == 0 || req.Quantity < 1 || req.Quantity > 99 {
return nil, ErrInvalidRequest
@@ -257,7 +253,8 @@ func (r *Repository) AdminCompleteOrder(ctx context.Context, orderID uint64, rem
return r.AdminFindOrder(ctx, orderID)
}
// ConfirmPaidFromChannelTx 支付成功后推进摸大红订单:建群、发固定码、写复制文案。
// ConfirmPaidFromChannelTx 支付成功后推进摸大红订单:固化二维码快照与可复制文案。
// 返回值固定为 0,兼容支付模块会话通知签名(摸大红无订单群)。
func (r *Repository) ConfirmPaidFromChannelTx(tx *gorm.DB, orderID uint64) (uint64, error) {
var order model.MohongOrder
if err := tx.Clauses(clause.Locking{Strength: "UPDATE"}).First(&order, orderID).Error; err != nil {
@@ -265,9 +262,6 @@ func (r *Repository) ConfirmPaidFromChannelTx(tx *gorm.DB, orderID uint64) (uint
}
if order.Status == model.MohongOrderStatusPaid ||
order.Status == model.MohongOrderStatusCompleted {
if order.ConversationID != nil {
return *order.ConversationID, nil
}
return 0, nil
}
if order.Status != model.MohongOrderStatusPendingPayment {
@@ -283,34 +277,10 @@ func (r *Repository) ConfirmPaidFromChannelTx(tx *gorm.DB, orderID uint64) (uint
copyText := buildCopyText(r.loadCopyTemplate(tx), order, snap, user)
now := time.Now()
conv, err := ensureMohongOrderConversation(tx, order, user)
if err != nil {
return 0, err
}
welcome := r.loadWelcomeText(tx)
if err := chat.SendSystemMessageForTx(tx, conv.ID, welcome); err != nil {
return 0, err
}
if qrcodeURL != "" {
if err := chat.SendImageMessageForTx(tx, conv.ID, "👇 请扫码联系客服", qrcodeURL); err != nil {
return 0, err
}
} else {
if err := chat.SendSystemMessageForTx(tx, conv.ID, "固定二维码尚未配置,请将下方订单信息复制后联系客服。"); err != nil {
return 0, err
}
}
if copyText != "" {
if err := chat.SendSystemMessageForTx(tx, conv.ID, copyText+"\n\n(长按/复制后发送给客服)"); err != nil {
return 0, err
}
}
order.Status = model.MohongOrderStatusPaid
order.PaidAt = &now
order.QrcodeURLSnapshot = qrcodeURL
order.CopyText = copyText
order.ConversationID = &conv.ID
if err := tx.Save(&order).Error; err != nil {
return 0, err
}
@@ -320,20 +290,17 @@ func (r *Repository) ConfirmPaidFromChannelTx(tx *gorm.DB, orderID uint64) (uint
UserID: order.UserID,
Type: "order",
Title: "摸大红订单支付成功",
Content: "支付已完成,请在群内查看二维码与订单信息。",
Content: "支付已完成,请在订单详情扫码联系客服,并复制订单信息发送。",
BizType: "mohong_order",
BizID: &orderIDCopy,
}); err != nil {
return 0, err
}
return conv.ID, nil
return 0, nil
}
func (r *Repository) NotifyNewConversation(conversationID uint64) {
if conversationID > 0 && r.chatNotifier != nil {
r.chatNotifier.NotifyNewConversation(conversationID)
}
}
// NotifyNewConversation 兼容支付模块接口;摸大红不创建会话,空实现。
func (r *Repository) NotifyNewConversation(conversationID uint64) {}
func (r *Repository) cancelPendingOrderTx(tx *gorm.DB, order *model.MohongOrder, reason string) error {
// 归还预扣库存
@@ -367,65 +334,6 @@ func (r *Repository) orderDTO(ctx context.Context, row model.MohongOrder, includ
return &dto, nil
}
func ensureMohongOrderConversation(tx *gorm.DB, order model.MohongOrder, user model.User) (*model.ChatConversation, error) {
var existing model.ChatConversation
err := tx.Where("mohong_order_id = ?", order.ID).First(&existing).Error
if err == nil {
return &existing, nil
}
if err != gorm.ErrRecordNotFound {
return nil, err
}
now := time.Now()
title := "摸大红 " + order.OrderNo
if name := strings.TrimSpace(user.Nickname); name != "" {
title = "摸大红-" + name
}
conversation := model.ChatConversation{
MohongOrderID: &order.ID,
Type: ConversationTypeMohongOrder,
Title: title,
Status: "active",
}
if err := tx.Create(&conversation).Error; err != nil {
return nil, err
}
participants := []model.ChatParticipant{
{
ConversationID: conversation.ID,
ParticipantType: "user",
ParticipantID: order.UserID,
Role: "buyer",
JoinedAt: now,
LastReadAt: &now,
},
}
supportID, err := supportgroup.PickSupportAdmin(tx, supportgroup.GroupCodeRenterHandoff)
if err != nil {
return nil, err
}
if supportID <= 0 {
supportID = chat.DefaultSupportAdminID(tx)
}
if supportID > 0 {
participants = append(participants, model.ChatParticipant{
ConversationID: conversation.ID,
ParticipantType: "admin",
ParticipantID: supportID,
Role: "support",
JoinedAt: now,
})
}
for _, p := range participants {
if err := tx.Clauses(clause.OnConflict{DoNothing: true}).Create(&p).Error; err != nil {
return nil, err
}
}
return &conversation, nil
}
func buildCopyText(template string, order model.MohongOrder, snap productSnapshot, user model.User) string {
if strings.TrimSpace(template) == "" {
template = defaultOrderCopyTemplate
@@ -59,7 +59,6 @@ func toOrderDTO(row model.MohongOrder, snap productSnapshot, buyerNickname, buye
ProductUnit: snap.Unit,
QrcodeURLSnapshot: row.QrcodeURLSnapshot,
CopyText: row.CopyText,
ConversationID: row.ConversationID,
CancelReason: row.CancelReason,
PaidAt: row.PaidAt,
CompletedAt: row.CompletedAt,
@@ -2,18 +2,12 @@ package mohong
import "gorm.io/gorm"
// ChatNotifier 会话创建后的异步通知接口。
type ChatNotifier interface {
NotifyNewConversation(conversationID uint64)
}
// Repository 摸大红数据访问。
type Repository struct {
db *gorm.DB
chatNotifier ChatNotifier
db *gorm.DB
}
// NewRepository 创建仓库。
func NewRepository(db *gorm.DB, chatNotifier ChatNotifier) *Repository {
return &Repository{db: db, chatNotifier: chatNotifier}
func NewRepository(db *gorm.DB) *Repository {
return &Repository{db: db}
}