小程序虚拟支付
This commit is contained in:
@@ -183,6 +183,18 @@ func prepareXpayOrder(
|
||||
for k, v := range orderFields {
|
||||
order[k] = v
|
||||
}
|
||||
// plan_key / level_key 是会员专有列,但老表把它们建成了 NOT NULL 且无默认值
|
||||
// (次数包订单没有这两个语义)→ 不补值会报
|
||||
// `Error 1364: Field 'plan_key' doesn't have a default value`。
|
||||
//
|
||||
// 这里统一兜底成空串,而不是去把库列改成 DEFAULT '':
|
||||
// level_key 一旦被静默填成空串,发货时 extendMembership 会把用户等级写成空,
|
||||
// 属于「无声降级」。保持列严格、由唯一的下单入口显式补齐,才是安全的做法。
|
||||
for _, k := range []string{"plan_key", "level_key"} {
|
||||
if _, ok := order[k]; !ok {
|
||||
order[k] = ""
|
||||
}
|
||||
}
|
||||
if _, err = g.Model(consts.TableMemberOrders).Data(order).Insert(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -423,6 +435,11 @@ func deliverOrder(ctx context.Context, outTradeNo, wxOrderId string) error {
|
||||
case consts.OrderTypeQuota:
|
||||
toolKey := row["tool_key"].String()
|
||||
times := row["times"].Int()
|
||||
// 空 toolKey 会写出一条挂在空工具上的额度记录,times<=0 则是「发了等于没发」,
|
||||
// 两者都属于数据异常,直接拒绝发货并告警,不要静默放过。
|
||||
if toolKey == "" || times <= 0 {
|
||||
return gerror.Newf("订单 %s 次数包信息异常: toolKey=%q times=%d", outTradeNo, toolKey, times)
|
||||
}
|
||||
expireAt, err := grantToolQuota(ctx, tx, userId, toolKey, times, days)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -431,6 +448,11 @@ func deliverOrder(ctx context.Context, outTradeNo, wxOrderId string) error {
|
||||
userId, outTradeNo, toolKey, times, expireAt.String())
|
||||
default:
|
||||
levelKey := row["level_key"].String()
|
||||
// 空等级会让 extendMembership 把 users.level_key 写成空串(等于无声降权),
|
||||
// 这里拦住:宁可发货失败留一条告警日志,也不要污染用户数据。
|
||||
if levelKey == "" {
|
||||
return gerror.Newf("订单 %s 缺少等级信息(level_key 为空),拒绝发货以免清空用户等级", outTradeNo)
|
||||
}
|
||||
expireAt, finalLevel, err := extendMembership(ctx, tx, userId, levelKey, days)
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
Reference in New Issue
Block a user