package main import ( "io" "net/http" "net/url" "strings" "time" "kra/internal/data/ledger" "kra/internal/service/dto" "gorm.io/gorm" ) func verifyRecharge(admin, viewer, other *apiClient, f *fixtures, db *gorm.DB, report *acceptanceReport) { must(configureMockPayment(admin)) var plans struct { List []dto.RechargePlan `json:"list"` } must(newClient().call("GET", "/live/recharge/plans", nil, &plans)) check(len(plans.List) > 0 && plans.List[0].AmountCents > 0, "recharge plans missing") var providers struct { List []dto.RechargeProvider `json:"list"` } must(newClient().call("GET", "/live/recharge/providers", nil, &providers)) found := false for _, item := range providers.List { found = found || item.ID == "alipay" } check(found, "local mock payment provider was not available") before := wallet(db, f.Viewer.ID) var checkout dto.RechargeCheckoutResponse must(viewer.call("POST", "/live/recharge/orders", dto.RechargeOrderRequest{ PlanID: plans.List[0].ID, Provider: "alipay", NotifyURL: baseURL + "/payment/callback/alipay", Extra: map[string]any{"userId": f.Other.ID, "diamonds": 99999}, }, &checkout)) check(checkout.Order != nil && checkout.Payment != nil, "recharge checkout missing order or payment") order := checkout.Order check(order.UserID == f.Viewer.ID && order.Diamonds == 60 && order.AmountCents == 600, "untrusted checkout values changed ownership or price: %+v", order) check(wallet(db, f.Viewer.ID).DiamondBalance == before.DiamondBalance, "pending recharge credited wallet") path := "/live/recharge/orders/" + order.OrderNo var owned dto.RechargeOrderResponse must(viewer.call("GET", path, nil, &owned)) check(other.call("GET", path, nil, nil) != nil, "another user accessed recharge order") check(other.call("GET", path+"/status", nil, nil) != nil, "another user accessed recharge status") check(newClient().call("GET", path, nil, nil) != nil, "anonymous user accessed recharge order") must(admin.call("GET", "/live/admin/orders/"+order.OrderNo, nil, nil)) client := &http.Client{Timeout: 15 * time.Second} badResponse, err := client.PostForm(baseURL+"/payment/callback/alipay", url.Values{ "app_id": {mockAppID}, "out_trade_no": {order.OrderNo}, "trade_no": {"LOCAL-" + order.OrderNo}, "trade_status": {"TRADE_SUCCESS"}, "total_amount": {"6.00"}, "sign_type": {"RSA2"}, "sign": {"invalid"}, }) must(err) badBody, err := io.ReadAll(badResponse.Body) must(err) must(badResponse.Body.Close()) check(strings.TrimSpace(string(badBody)) != "success", "invalid callback signature was acknowledged") check(wallet(db, f.Viewer.ID).DiamondBalance == before.DiamondBalance, "invalid callback credited wallet") passed(report, "public recharge plans/provider, signed local checkout, order ownership and invalid callback rejection") for repeat := 0; repeat < 2; repeat++ { response, err := client.PostForm(mockURL+"/confirm", url.Values{"orderNo": {order.OrderNo}}) must(err) body, err := io.ReadAll(response.Body) must(err) must(response.Body.Close()) check(response.StatusCode == 200 && strings.TrimSpace(string(body)) == "success", "local signed callback rejected: status=%d body=%s", response.StatusCode, body) current := wallet(db, f.Viewer.ID) check(current.DiamondBalance == before.DiamondBalance+60 && current.TotalRechargeCents == before.TotalRechargeCents+600, "recharge was not credited exactly once: before=%+v after=%+v", before, current) } must(viewer.call("GET", path, nil, &owned)) check(owned.PaymentStatus == "paid" && owned.FulfillmentStatus == "succeeded" && owned.CreditedAt != nil, "recharge status was not fulfilled: %+v", owned) var stored ledger.RechargeOrderPO must(db.Where("order_no = ?", order.OrderNo).First(&stored).Error) check(stored.UserID == f.Viewer.ID && stored.CreditedAt != nil, "recharge database ownership or credit marker incorrect") report.Records["rechargeOrderNo"] = order.OrderNo passed(report, "valid local RSA2 callback, authoritative signed query and duplicate callback credit wallet only once") }