<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Buhgalter]]></title><description><![CDATA[Buhgalter]]></description><link>https://buhgalterapp.hashnode.dev</link><generator>RSS for Node</generator><lastBuildDate>Mon, 02 Nov 2026 08:50:27 GMT</lastBuildDate><atom:link href="https://buhgalterapp.hashnode.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Payment currency choices for small online services: RUB in, USDT or RUB out]]></title><description><![CDATA[When you build a small service for Russian speaking users (a VPN, a bot, a paid community), the payment question splits into two decisions that people…]]></description><link>https://buhgalterapp.hashnode.dev/payment-currency-choices-for-small-online-services-rub-in-usdt-or-rub-out</link><guid isPermaLink="true">https://buhgalterapp.hashnode.dev/payment-currency-choices-for-small-online-services-rub-in-usdt-or-rub-out</guid><category><![CDATA[payments]]></category><category><![CDATA[Startups]]></category><category><![CDATA[Cryptocurrency]]></category><category><![CDATA[webdev]]></category><dc:creator><![CDATA[Buhgalter]]></dc:creator><pubDate>Thu, 29 Oct 2026 11:17:51 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6ae32ac89c7392aa7e75ac23/fb05daaa-feb4-45fe-a470-681bba64e792.jpg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>When you build a small service for Russian speaking users (a VPN, a bot, a paid community), the payment question splits into two decisions that people often merge into one. What does the buyer pay in, and what do you get paid in. Treating them separately makes the architecture cleaner and the accounting less painful.</p>
<h2>What the buyer pays in</h2>
<p>With the Buhgalter API the payment itself is always in rubles. Amounts go from 1 to 100,000,000 RUB. The buyer chooses a familiar method: SBP, an NSPK QR code, or a transfer by card number. For crypto native audiences there is also invoicing in USDT, BTC, ETH or TON, where the coin and network are pinned to the invoice on the payment page.</p>
<p>From the buyer's side this is the right default. People pay in the currency they already hold, in the banking app they already trust.</p>
<h2>What you get paid in</h2>
<p>Your merchant balance defaults to USDT. You can switch it to rubles. The rate is locked at the moment the payment is created, not when it settles. That single rule removes a whole category of reconciliation bugs.</p>
<p>How to pick:</p>
<ul>
<li>your costs are mostly abroad (servers, domains, contractors paid in stablecoins): keep USDT;</li>
<li>your costs are mostly local (salaries, local suppliers, taxes): keep RUB;</li>
<li>mixed: run separate storefronts, each with its own balance logic, and keep revenue apart in reports.</li>
</ul>
<h2>Modeling it in your database</h2>
<p>Store three numbers per payment, not one:</p>
<pre><code class="language-sql">CREATE TABLE payments (
  id            text PRIMARY KEY,
  amount_rub    numeric(14,2) NOT NULL,
  credited      numeric(18,6),
  credited_ccy  text,
  created_at    timestamptz NOT NULL
);
</code></pre>
<p>amount_rub is what the buyer paid. credited is what landed on your balance, in credited_ccy. Never recompute credited from today's rate; take it from the payment data.</p>
<p>For display only, GET /api/fx returns the current USDT/RUB rate. Use it to show an estimated amount on a pricing page, not for bookkeeping.</p>
<h2>Payouts</h2>
<p>Withdrawals to yourself go to a bank account, a card, or a USDT TRC-20 wallet, manually or as an auto payout. Payouts to your users go through POST /api/payouts to a card, phone number or account. Keep these two flows in separate services with separate permissions.</p>
<h2>Time zones</h2>
<p>Daily reports use Moscow time. If your servers run on UTC, your daily totals will drift by three hours at the day boundary. Either convert when you compare or store a report_day column computed in Moscow time.</p>
<h2>Reports</h2>
<p>For month end, the dashboard exports Excel and CSV for 1C, plus a printable reconciliation statement with opening and closing balances and turnover. The payments report shows created, paid, conversion, turnover, fee, credited and refunds. Fees apply only to successful payments, so expired and cancelled invoices show up in counts but cost nothing.</p>
<h2>Summary</h2>
<p>Let buyers pay in rubles with methods they know. Decide your settlement currency from where your costs are. Store both amounts, lock to the rate at creation, and reconcile in Moscow time. More details and API docs at <a href="https://buhgalter.app">https://buhgalter.app</a>.</p>
<p>Alena Kotenkova, Buhgalter team</p>
]]></content:encoded></item></channel></rss>