feat(payment): admin-editable ZarinPal settings + in-panel test payment
Lets the broker's ZarinPal merchant / sandbox / amount-unit be set from Admin → درگاه پرداخت (persisted in payment.settings) instead of env + redeploy, and adds a per-app "test payment" button that mints a real ZarinPal StartPay link straight from the panel — no site wiring needed. - migration 33_payment_settings.sql: singleton payment.settings + a transactions.is_test column. (33, not 32 — 32 is content_render_engine.) - broker read-path precedence: per-client override > DB settings > env. - POST /v1/admin/clients/:id/test-payment + GET/PUT /v1/admin/settings. - admin UI: «تنظیمات زرینپال» tab + «پرداخت آزمایشی» button. Adversarial-review fixes (2 confirmed HIGH): - do NOT pre-seed the settings row — a seeded sandbox=TRUE default would override a production ZARINPAL_SANDBOX=false env and silently route real payments to sandbox.zarinpal.com until an admin untouched the toggle. No row → env governs until an admin saves. - test transactions are tagged is_test and the webhook dispatcher skips them, so an admin smoke-test can never notify (or credit) a real client, regardless of metadata. Broker-authoritative, not consumer-dependent. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -13,6 +13,14 @@ type APIError struct {
|
||||
Message string `json:"message"`
|
||||
}
|
||||
|
||||
// Settings is the singleton global broker config (admin-editable ZarinPal default).
|
||||
type Settings struct {
|
||||
ZarinPalMerchantID string `json:"zarinpal_merchant_id"`
|
||||
ZarinPalSandbox bool `json:"zarinpal_sandbox"`
|
||||
ZarinPalAmountUnit string `json:"zarinpal_amount_unit"` // "rial" | "toman"
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
}
|
||||
|
||||
// ── Client apps (tenants of the broker — each site that pays through it) ───────
|
||||
|
||||
type ClientApp struct {
|
||||
@@ -39,6 +47,7 @@ type Transaction struct {
|
||||
ClientSlug string `json:"client_slug,omitempty"` // joined for admin views
|
||||
Status string `json:"status"`
|
||||
Gateway string `json:"gateway"`
|
||||
IsTest bool `json:"is_test"`
|
||||
AmountRial int64 `json:"amount_rial"`
|
||||
Currency string `json:"currency"`
|
||||
Description *string `json:"description,omitempty"`
|
||||
|
||||
Reference in New Issue
Block a user