77 lines
2.8 KiB
Go
77 lines
2.8 KiB
Go
package logic
|
||
|
||
import (
|
||
"context"
|
||
"net/http"
|
||
"testing"
|
||
|
||
"github.com/gogf/gf/v2/frame/g"
|
||
"github.com/gogf/gf/v2/net/ghttp"
|
||
"github.com/gogf/gf/v2/os/gcfg"
|
||
|
||
"tool-api/internal/consts"
|
||
)
|
||
|
||
// ============================================================================
|
||
// 订单越权回归(真库 IT,IT_DB 门控)
|
||
//
|
||
// 两步式(N1)下,订单归属校验必须发生在「详情」与「支付」两条链路:
|
||
// 访问**他人**订单的 out_trade_no → 一律 4015(订单不存在 / 不属于当前用户)。
|
||
// 运行:$env:IT_DB=1; go test ./internal/logic/ -run TestOrderOwnership4015 -count=1 -v
|
||
// ============================================================================
|
||
|
||
// ctxWithUser 构造带登录用户 id 的最小请求上下文(CtxUserId 依赖 g.RequestFromCtx)。
|
||
func ctxWithUser(userId int64) context.Context {
|
||
req := &ghttp.Request{Request: &http.Request{}}
|
||
req.SetCtxVar(consts.CtxUserId, userId)
|
||
return req.Context()
|
||
}
|
||
|
||
// ensureXPayConfig 注入最小可用的 wx.pay 配置,使 buildPayParams 越过「未配置」闸门,
|
||
// 从而真正走到「支付人 = 登录人」的越权校验(本用例的目的:验证 4015,而非支付配置)。
|
||
func ensureXPayConfig(t *testing.T) {
|
||
t.Helper()
|
||
if xpayConfig(context.Background()).Configured() {
|
||
return
|
||
}
|
||
adapter, err := gcfg.NewAdapterFile()
|
||
if err != nil {
|
||
t.Fatalf("创建配置适配器失败: %v", err)
|
||
}
|
||
adapter.SetContent(
|
||
"wx:\n appId: \"probe\"\n appSecret: \"probe\"\n pay:\n offerId: \"probe\"\n appKey: \"probe\"\n env: 0\n",
|
||
)
|
||
g.Cfg().SetAdapter(adapter)
|
||
if !xpayConfig(context.Background()).Configured() {
|
||
t.Fatalf("wx.pay 配置注入后仍未生效")
|
||
}
|
||
}
|
||
|
||
// TestOrderOwnership4015 越权访问他人订单:详情 / 支付均须 4015。
|
||
func TestOrderOwnership4015(t *testing.T) {
|
||
ctx := requireOrderIT(t)
|
||
p := setupOrderProbe(ctx, t)
|
||
defer p.cleanup(ctx)
|
||
|
||
res := createMemberOrder(ctx, t, p) // 属于 p.userId 的待支付单
|
||
|
||
other := ctxWithUser(p.userId + 1)
|
||
if _, err := MemberOrderDetail(other, res.OutTradeNo); err == nil {
|
||
t.Fatalf("/member/order/detail 他人订单应 4015,实得 nil")
|
||
} else if codeOf(err) != consts.CodeOrderInvalid {
|
||
t.Fatalf("/member/order/detail 他人订单应 4015,实得 code=%d err=%v", codeOf(err), err)
|
||
}
|
||
|
||
ensureXPayConfig(t)
|
||
if _, err := MemberOrderPay(other, res.OutTradeNo, "probe-code"); err == nil {
|
||
t.Fatalf("/member/order/pay 他人订单应 4015,实得 nil")
|
||
} else if codeOf(err) != consts.CodeOrderInvalid {
|
||
t.Fatalf("/member/order/pay 他人订单应 4015,实得 code=%d err=%v", codeOf(err), err)
|
||
}
|
||
|
||
// 反证:本人取详情应放行
|
||
if _, err := MemberOrderDetail(ctxWithUser(p.userId), res.OutTradeNo); err != nil {
|
||
t.Fatalf("本人订单详情应放行,实得 err=%v", err)
|
||
}
|
||
}
|