feat(iap): native Myket in-app billing plugin (AIDL) + wire purchase/consume
CI/CD / CI - API (dotnet build + engine sim) (push) Successful in 24s
CI/CD / CI - Web (tsc + next build) (push) Successful in 1m8s
CI/CD / Deploy - local stack (db + server + web) (push) Successful in 1m1s

Implements real Myket IAB for the Capacitor app (Myket has no purchase
deep-link like Bazaar — it uses the classic Google Play IAB v3 AIDL bound to
the Myket app):

- AIDL: com.android.vending.billing.IInAppBillingService (Myket-compatible).
- MyketBillingPlugin (Capacitor): binds ir.mservices.market via
  "ir.mservices.market.InAppBillingService.BIND", runs getBuyIntent →
  startIntentSenderForResult, verifies INAPP_DATA_SIGNATURE with the RSA key
  (Security.java, SHA1withRSA), returns the purchaseToken; consume() too.
- MainActivity registers the plugin + forwards the purchase activity result.
- Manifest: ir.mservices.market.BILLING permission + <queries> for Android 11+
  package visibility.
- build.gradle: enable buildFeatures.aidl (AGP 8 disables it by default).
- storeBilling: Myket goes through the plugin (RSA key embedded); after server
  verify, BuyCoins consumes the purchase so coins can be re-bought.

Bazaar (deep-link) and web (ZarinPal) paths unchanged. Needs on-device testing
with the Myket app installed + published products.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
soroush.asadi
2026-06-12 20:59:56 +03:30
parent 7dbadee406
commit d1bd279eba
8 changed files with 341 additions and 18 deletions
+4
View File
@@ -12,6 +12,10 @@ if (keystorePropsFile.exists()) {
android {
namespace = "com.bargevasat.app"
compileSdk = rootProject.ext.compileSdkVersion
// AGP 8 disables AIDL by default; the Myket billing service needs it.
buildFeatures {
aidl true
}
defaultConfig {
applicationId "com.bargevasat.app"
minSdkVersion rootProject.ext.minSdkVersion