修复:发货创建队列与补全接口透传 h5_prefix 和商品信息,解决上游报错缺少渠道标识

- 上游 /public/users/orders-queue (POST/PATCH) 补充传递 h5_prefix、goods_no 和 goods_name
- delivery.go submit 流程透传商品 SKU 与商品名称至队列相关方法
- 解决上游创建订单报"缺少渠道标识 h5_prefix,无法校验第三方订单状态"的故障
This commit is contained in:
yml2213
2026-09-08 12:44:45 +08:00
parent 114dcdf7d8
commit a314f3f51b
3 changed files with 72 additions and 11 deletions
+11 -2
View File
@@ -357,7 +357,16 @@ func (s *DeliveryService) submit(orderNo, gameAccount, bindUUID string, apiClien
s.markDeliverySubmissionFailed(claimed, apiClientID, deliveryStageBindMismatch, err.Error())
return nil, err
}
queueOrderID, err := s.createOrderQueue(goodID, order.OrderNo)
goodsNo := ""
goodsName := ""
if info != nil && info.Product != nil {
goodsNo = info.Product.SKU
goodsName = info.Product.Name
} else if openOrder != nil && openOrder.Product != nil {
goodsNo = openOrder.Product.SKU
goodsName = openOrder.Product.Name
}
queueOrderID, err := s.createOrderQueue(goodID, order.OrderNo, goodsNo)
if err != nil {
s.markDeliverySubmissionFailed(claimed, apiClientID, deliveryStageCreateQueue, err.Error())
return nil, err
@@ -369,7 +378,7 @@ func (s *DeliveryService) submit(orderNo, gameAccount, bindUUID string, apiClien
}); err != nil {
return nil, err
}
if err := s.patchOrderQueue(queueOrderID, gameAccount, bindUUID); err != nil {
if err := s.patchOrderQueue(queueOrderID, gameAccount, bindUUID, goodsNo, goodsName); err != nil {
s.markDeliverySubmissionFailed(claimed, apiClientID, deliveryStagePatchQueue, err.Error())
return nil, err
}
+22 -9
View File
@@ -44,15 +44,20 @@ func (s *DeliveryService) accountBound(bindUUID, goodID string) (map[string]inte
return out.GameAccount, nil
}
func (s *DeliveryService) createOrderQueue(goodID, orderNo string) (string, error) {
func (s *DeliveryService) createOrderQueue(goodID, orderNo, goodsNo string) (string, error) {
var out struct {
Orders []map[string]interface{} `json:"orders"`
}
if err := s.signProxy("/public/users/orders-queue", "POST", map[string]interface{}{
"good_id": goodID,
"quantity": 1,
"order_sn": orderNo,
}, &out); err != nil {
payload := map[string]interface{}{
"good_id": goodID,
"quantity": 1,
"order_sn": orderNo,
"h5_prefix": s.channel,
}
if goodsNo != "" {
payload["goods_no"] = goodsNo
}
if err := s.signProxy("/public/users/orders-queue", "POST", payload, &out); err != nil {
return "", err
}
if len(out.Orders) == 0 {
@@ -65,13 +70,21 @@ func (s *DeliveryService) createOrderQueue(goodID, orderNo string) (string, erro
return orderID, nil
}
func (s *DeliveryService) patchOrderQueue(orderID, gameAccount, bindUUID string) error {
func (s *DeliveryService) patchOrderQueue(orderID, gameAccount, bindUUID, goodsNo, goodsName string) error {
var out map[string]interface{}
return s.signProxy("/public/users/orders-queue", "PATCH", map[string]interface{}{
payload := map[string]interface{}{
"order_id": orderID,
"game_account": gameAccount,
"bind_uuid": bindUUID,
}, &out)
"h5_prefix": s.channel,
}
if goodsNo != "" {
payload["goods_no"] = goodsNo
}
if goodsName != "" {
payload["goods_name"] = goodsName
}
return s.signProxy("/public/users/orders-queue", "PATCH", payload, &out)
}
func (s *DeliveryService) createUpstreamOrder(orderID, gameAccount, goodID, orderNo string) (map[string]interface{}, error) {
+39
View File
@@ -531,3 +531,42 @@ func TestUsernameCanBeReusedAfterMerchantAccountSoftDelete(t *testing.T) {
t.Fatalf("expected a new account record, got id=%d", recreated.ID)
}
}
// TestRemoveMemberDoesNotReleaseUsername 固化行为:商户侧"移除成员"只删除成员关系,
// 登录账号(含用户名)保留,同名用户名仍被占用,无法新建。
func TestRemoveMemberDoesNotReleaseUsername(t *testing.T) {
db := newServiceTestDB(t)
merchant := model.Merchant{Code: "remove-member-keep", Name: "移除成员保留账号", Status: model.MerchantStatusActive}
actor := model.User{Username: "remove-member-actor", PasswordHash: "hash", Role: model.RoleMerchant, Status: 1}
staff := model.User{Username: "kf-2", PasswordHash: "hash", Role: model.RoleMerchant, Status: 1}
for _, entity := range []interface{}{&merchant, &actor, &staff} {
if err := db.Create(entity).Error; err != nil {
t.Fatalf("create fixture: %v", err)
}
}
if err := createDefaultMerchantRoles(db, merchant.ID); err != nil {
t.Fatalf("create default roles: %v", err)
}
merchantSvc := NewMerchantService(db, nil, NewTenantService(db))
member, err := merchantSvc.AddMember(merchant.ID, AddMemberInput{
UserID: staff.ID,
Role: model.MemberRoleOperator,
}, actor.ID)
if err != nil {
t.Fatalf("add member: %v", err)
}
if err := merchantSvc.RemoveMember(merchant.ID, member.ID, actor.ID); err != nil {
t.Fatalf("remove member: %v", err)
}
// 登录账号仍在(未被删除),用户名继续占用。
var kept model.User
if err := db.First(&kept, staff.ID).Error; err != nil {
t.Fatalf("login account should be retained after member removal: %v", err)
}
userSvc := NewUserService(db, nil)
if _, err := userSvc.Create("kf-2", "password123", "新员工", model.RoleMerchant, 0); err == nil {
t.Fatalf("username should still be occupied after member removal")
}
}