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

@@ -42,6 +42,7 @@ import org.json.JSONObject
*
* قراردادِ پل با `src/lib/bazaar.ts`ِ فرانت:
* JS → اینجا TadrisinoAndroid.bazaarBuy(sku, orderId, productType, dynamicPriceToken)
* TadrisinoAndroid.bazaarPrices(skusJson, productType) → رویدادِ «tadrisino:bazaar-prices»
* TadrisinoAndroid.bazaarConsume(purchaseToken)
* اینجا → JS window رویدادِ «tadrisino:bazaar» با { orderId, purchaseToken } یا
* { orderId, error: "canceled" | "failed", message }
@@ -261,6 +262,36 @@ class MainActivity : AppCompatActivity() {
if (subscription) p.getSubscribedProducts(query) else p.getPurchasedProducts(query)
}
/**
* قیمتِ ثبت‌شده در پیشخانِ بازار برای هر SKU (متنِ آماده‌ی نمایش، مثلِ «۷۹۸,۰۰۰ تومان»)، تا فرانت روی کاشیِ
* بازار همان را نشان دهد. API سرور-به-سرورِ بازار قیمت نمی‌دهد؛ فقط Poolakey روی گوشی.
* نتیجه: رویدادِ «tadrisino:bazaar-prices» با { productType, prices: { sku: price } } یا { productType, error }.
*/
private fun prices(skus: List<String>, productType: String) {
val p = payment ?: return sendPrices(productType, error = "bazaar not connected")
val callback: ir.cafebazaar.poolakey.callback.GetSkuDetailsCallback.() -> Unit = {
getSkuDetailsSucceed { list ->
val map = JSONObject()
list.forEach { map.put(it.sku, it.price) }
sendPrices(productType, prices = map)
}
getSkuDetailsFailed { sendPrices(productType, error = it.message ?: "failed") }
}
if (productType == "subscription") p.getSubscriptionSkuDetails(skus, callback)
else p.getInAppSkuDetails(skus, callback)
}
private fun sendPrices(productType: String, prices: JSONObject? = null, error: String? = null) {
val detail = JSONObject().put("productType", productType)
if (prices != null) detail.put("prices", prices)
if (error != null) detail.put("error", error)
runOnUiThread {
webView.evaluateJavascript(
"window.dispatchEvent(new CustomEvent('tadrisino:bazaar-prices', { detail: $detail }));", null,
)
}
}
private fun consume(purchaseToken: String) {
payment?.consumeProduct(purchaseToken) {
consumeSucceed { Log.i(TAG, "consumed") }
@@ -324,6 +355,22 @@ class MainActivity : AppCompatActivity() {
runOnUiThread { hideOffline() }
}
/** skusJson آرایه‌ی JSON از SKUها؛ productType «inapp» یا «subscription». */
@JavascriptInterface
fun bazaarPrices(skusJson: String, productType: String) {
val skus = try {
val arr = JSONArray(skusJson)
List(arr.length()) { i -> arr.getString(i) }
} catch (e: Exception) {
Log.w(TAG, "bad skus", e)
return
}
runOnUiThread {
if (!isOurPage(Uri.parse(webView.url ?: ""))) return@runOnUiThread
prices(skus, productType)
}
}
/** فرانت با این می‌فهمد درگاه داخلِ اپ باز می‌شود (isPaymentPage)، نه در مرورگرِ بیرونی. */
@JavascriptInterface
fun paysInApp(): Boolean = true