feat(ui): wire the chip-pack purchase to Robokassa
Replace the disabled "Soon" pack action with a real purchase: the Wallet opens a money order (wallet.order) and sends the player to the provider's hosted-payment page (window.open via openExternalUrl); the chips are credited later by the verified server callback. Add a public-offer link under the packs (paying accepts the offer). Codec order round-trip unit test + a mock-e2e purchase test; the Google Play stub and the chip-spend paths are unchanged.
This commit is contained in:
@@ -6,6 +6,7 @@
|
||||
import { t, i18n, type MessageKey } from '../lib/i18n/index.svelte';
|
||||
import { executionContext, formatAmount, needsWebSpendWarning, type SpendContext } from '../lib/wallet';
|
||||
import { isGooglePlayBuild } from '../lib/distribution';
|
||||
import { openExternalUrl } from '../lib/links';
|
||||
import type { Wallet, Catalog, CatalogProduct } from '../lib/model';
|
||||
|
||||
// The Wallet section: the context-visible chip balances, the active benefits, and the storefront.
|
||||
@@ -78,6 +79,22 @@
|
||||
busy = false;
|
||||
}
|
||||
}
|
||||
|
||||
// onOrder funds a chip pack with money: it opens a pending order and sends the player to the
|
||||
// provider's hosted-payment page. The chips are credited later, by the verified server callback;
|
||||
// paying accepts the public offer (linked below the packs).
|
||||
async function onOrder(p: CatalogProduct) {
|
||||
if (busy) return;
|
||||
busy = true;
|
||||
try {
|
||||
const order = await gateway.walletOrder(p.productId);
|
||||
openExternalUrl(order.redirectUrl);
|
||||
} catch (e) {
|
||||
handleError(e);
|
||||
} finally {
|
||||
busy = false;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="wallet" data-testid="wallet">
|
||||
@@ -120,9 +137,14 @@
|
||||
<div class="row product" data-testid="product" data-kind="pack" data-pid={p.productId}>
|
||||
<span class="name">{p.title}</span>
|
||||
<span class="price">{formatAmount(p.moneyAmount, p.moneyCurrency)} {currencyLabel(p.moneyCurrency)}</span>
|
||||
<button class="buy" disabled>{t('wallet.soon')}</button>
|
||||
<button class="buy" data-testid="buy-pack" disabled={busy} onclick={() => onOrder(p)}>{t('wallet.buy')}</button>
|
||||
</div>
|
||||
{/each}
|
||||
{#if packs.length > 0}
|
||||
<p class="offer" data-testid="offer">
|
||||
<a href="/offer/" target="_blank" rel="noopener noreferrer">{t('wallet.offer')}</a>
|
||||
</p>
|
||||
{/if}
|
||||
{/if}
|
||||
|
||||
{#if !loading && values.length === 0 && (gpBuild || packs.length === 0)}
|
||||
@@ -207,6 +229,14 @@
|
||||
border: 1px dashed var(--border);
|
||||
border-radius: var(--radius-sm);
|
||||
}
|
||||
.offer {
|
||||
margin: 2px 0 0;
|
||||
text-align: center;
|
||||
font-size: 0.85rem;
|
||||
}
|
||||
.offer a {
|
||||
color: var(--text-muted);
|
||||
}
|
||||
.warn-body {
|
||||
margin: 0 0 14px;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user