Checkout: Zarinpal is the default; Bazaar tile shows the price Bazaar itself has (Poolakey getSkuDetails bridge)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-12 18:21:48 +03:30
parent fffdeac3ed
commit d440986b88
4 changed files with 115 additions and 11 deletions

View File

@@ -12,6 +12,8 @@ import { store } from './storage';
* productType «inapp» (بسته، purchaseProduct) یا «subscription» (subscribeProduct)؛
* orderId همان payloadِ خرید است؛ dynamicPriceToken رشته‌ی خالی یعنی قیمتِ پیشخان.
* JS → اندروید TadrisinoAndroid.bazaarConsume(purchaseToken) فقط بسته، بعد از تأییدِ سرور.
* JS → اندروید TadrisinoAndroid.bazaarPrices(skusJson, productType) قیمتِ پیشخان؛ جواب با رویدادِ
* «tadrisino:bazaar-prices» و detail‌ِ { productType, prices: { sku: «۷۹۸,۰۰۰ تومان» } } یا { productType, error }
* اندروید → JS رویدادِ window به نامِ «tadrisino:bazaar» با detail:
* { orderId, purchaseToken } خرید انجام شد
* { orderId, error: 'canceled' | 'failed', message? }
@@ -28,6 +30,7 @@ interface AndroidBridge {
/** APKِ قدیمی؛ فقط برای این‌که بدانیم داخلِ اپیم ولی خرید از بازار در آن ممکن نیست. */
bazaarPurchase?: (sku: string, orderId: string) => void;
bazaarConsume?: (purchaseToken: string) => void;
bazaarPrices?: (skusJson: string, productType: BazaarProductType) => void;
/** اولین صفحه‌ی واقعی کشیده شد؛ اسپلشِ سیستم می‌تواند برود (APKهای قدیمی‌تر این را ندارند). */
appReady?: () => void;
}
@@ -87,6 +90,47 @@ export function bazaarBuy(sku: string, orderId: string, productType: BazaarProdu
});
}
type PricesResult = { productType: BazaarProductType; prices?: Record<string, string>; error?: string };
function askPrices(skus: string[], productType: BazaarProductType): Promise<Record<string, string>> {
const bridge = window.TadrisinoAndroid;
if (!bridge?.bazaarPrices || !skus.length) return Promise.resolve({});
return new Promise((resolve, reject) => {
const timer = window.setTimeout(() => done(() => reject(new Error('timeout'))), 8000);
function done(settle: () => void) {
window.clearTimeout(timer);
window.removeEventListener('tadrisino:bazaar-prices', onResult);
settle();
}
function onResult(event: Event) {
const detail = (event as CustomEvent<PricesResult>).detail;
if (!detail || detail.productType !== productType) return;
if (detail.prices) done(() => resolve(detail.prices!));
else done(() => reject(new Error(detail.error || 'failed')));
}
window.addEventListener('tadrisino:bazaar-prices', onResult);
bridge.bazaarPrices!(JSON.stringify(skus), productType);
});
}
/**
* قیمتِ ثبت‌شده در پیشخانِ بازار برای هر SKU، از خودِ بازار روی گوشی (API سرور قیمت نمی‌دهد). اتصالِ Poolakey
* چند لحظه بعد از باز شدنِ اپ برقرار می‌شود، پس یک بار دوباره امتحان می‌شود. خطا یعنی قیمتی نشان داده نمی‌شود.
*/
export async function bazaarPrices(skus: string[], productType: BazaarProductType): Promise<Record<string, string>> {
try {
return await askPrices(skus, productType);
} catch {
await new Promise((r) => setTimeout(r, 1500));
try {
return await askPrices(skus, productType);
} catch (err) {
console.error('bazaarPrices failed', err);
return {};
}
}
}
export function bazaarConsume(purchaseToken: string) {
try {
window.TadrisinoAndroid?.bazaarConsume?.(purchaseToken);