package robokassa // Shops is a set of Robokassa merchant shops keyed by channel — the subtype of the trusted // X-Platform signal for the direct rail ("web", "android"; "ios" later). The direct rail routes a // payment to the per-channel shop for separate merchant accounts, accounting and receipts, while // every shop still credits the one direct wallet (docs/PAYMENTS_DECISIONS_ru.md D42). An empty set // leaves the direct order and Result-callback endpoints unregistered. type Shops map[string]Config // Channel constants name the direct-rail X-Platform subtypes a shop is keyed by. ChannelWeb is the // default: an unknown or empty channel routes here on the order side, and the legacy single-shop // configuration seeds it. const ( ChannelWeb = "web" ChannelAndroid = "android" ) // Shop returns the shop that issues an order for channel, falling back to the web shop when channel // is unknown, empty or not configured. The fallback is safe: routing only chooses the merchant // account and receipt, never the credited wallet (always direct, D42), so a mis-attributed channel // costs at most accounting accuracy, not money. The second result is false when neither the channel // nor the web shop has a merchant login (the rail is unconfigured). func (s Shops) Shop(channel string) (Config, bool) { if channel != "" { if c, ok := s[channel]; ok && c.MerchantLogin != "" { return c, true } } if c, ok := s[ChannelWeb]; ok && c.MerchantLogin != "" { return c, true } return Config{}, false } // Verifier returns the shop whose Password2 verifies a Result callback delivered to channel's // dedicated Result route. Unlike Shop it does not fall back to web: each shop's callback is verified // only by that shop's own credentials, so a route with no configured shop reports false (and its // handler answers as unregistered). The second result is false when channel has no merchant login. func (s Shops) Verifier(channel string) (Config, bool) { if c, ok := s[channel]; ok && c.MerchantLogin != "" { return c, true } return Config{}, false } // Configured reports whether at least one shop has a merchant login (the direct rail is live). func (s Shops) Configured() bool { for _, c := range s { if c.MerchantLogin != "" { return true } } return false }