2026-06-04 14:31:14 +03:30
|
|
|
# برگ وسط — Android (Capacitor) build
|
|
|
|
|
|
|
|
|
|
The app is packaged with **Capacitor** for Cafe Bazaar / Myket.
|
|
|
|
|
|
|
|
|
|
## Layout
|
|
|
|
|
- `next.config.ts` → `output: "export"` (static site in `out/`)
|
|
|
|
|
- `capacitor.config.ts` → appId `com.bargevasat.app`, appName «برگ وسط», webDir `out`
|
|
|
|
|
- `android/` → generated native project (committed; build outputs are git-ignored)
|
|
|
|
|
- Hardware **back button** handled by `src/components/CapacitorBack.tsx` (`@capacitor/app`)
|
|
|
|
|
|
|
|
|
|
## Build the web + sync native
|
|
|
|
|
```bash
|
|
|
|
|
npm run cap:sync # next build (export) + cap sync android
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## Build the APK
|
|
|
|
|
```bash
|
|
|
|
|
npm run android:apk # → android/app/build/outputs/apk/debug/app-debug.apk
|
|
|
|
|
# or open in Android Studio:
|
|
|
|
|
npm run android:open
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
> Point the app at the live server at build time:
|
|
|
|
|
> `NEXT_PUBLIC_USE_SERVER=1 NEXT_PUBLIC_SERVER_URL=https://api.example.com npm run cap:sync`
|
|
|
|
|
|
2026-06-04 15:22:34 +03:30
|
|
|
## ⚠️ Maven mirror (Iran) — VERIFIED WORKING
|
2026-06-04 14:31:14 +03:30
|
|
|
|
2026-06-04 15:22:34 +03:30
|
|
|
Gradle pulls the Android Gradle Plugin from **dl.google.com** + **Maven Central**,
|
|
|
|
|
blocked in Iran. The **Myket** mirror proxies both — at the **root** (no `/maven2`):
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
https://maven.myket.ir
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Copy `android/gradle-mirror.init.gradle.example` → `android/gradle-mirror.init.gradle`,
|
|
|
|
|
then build with the init script. (The `gradlew.bat` wrapper has a CLASSPATH quirk on
|
|
|
|
|
this setup, so invoke the wrapper jar with `java` directly):
|
2026-06-04 14:31:14 +03:30
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
cd android
|
2026-06-04 15:22:34 +03:30
|
|
|
java -classpath gradle\wrapper\gradle-wrapper.jar org.gradle.wrapper.GradleWrapperMain \
|
|
|
|
|
assembleDebug --init-script gradle-mirror.init.gradle --no-daemon
|
|
|
|
|
# → app/build/outputs/apk/debug/app-debug.apk (≈4.5 MB)
|
2026-06-04 14:31:14 +03:30
|
|
|
```
|
|
|
|
|
|
2026-06-04 15:22:34 +03:30
|
|
|
The init script also pins **build-tools 36.0.0** and **Java 17** compatibility,
|
|
|
|
|
which are the versions installed here (Capacitor 8 defaults to build-tools 35 / JDK 21).
|
|
|
|
|
On a CI box with JDK 21 + build-tools 35 you can drop those overrides.
|
|
|
|
|
|
|
|
|
|
> For Nexus instead of Myket directly: create a **maven2 (proxy)** repo with
|
|
|
|
|
> Remote storage URL `https://maven.myket.ir`, add it to a **maven2 (group)**,
|
|
|
|
|
> and point `MIRROR` at the group URL.
|
2026-06-04 14:31:14 +03:30
|
|
|
|
2026-06-04 17:59:30 +03:30
|
|
|
## 💳 Payments — ZarinPal (web) vs store billing (Android)
|
|
|
|
|
|
|
|
|
|
- **Web / PWA**: buying coins uses **ZarinPal** (sandbox now). Flow:
|
|
|
|
|
`POST /api/coins/pay/request` → redirect to `StartPay` → ZarinPal →
|
|
|
|
|
`GET /api/coins/pay/callback` (server verifies + credits) → back to the app
|
|
|
|
|
with `?pay=success`. Merchant id is config-driven (`Zarinpal:MerchantId`,
|
|
|
|
|
swap in the admin panel / appsettings; `Sandbox: true`).
|
|
|
|
|
- **Cafe Bazaar / Myket (APK)**: app stores in Iran **require their own
|
|
|
|
|
in-app billing** — do NOT use ZarinPal inside the store build. Use:
|
|
|
|
|
- **Cafe Bazaar**: Poolakey (`ir.cafebazaar.poolakey`) — define in-app products in the Bazaar panel.
|
|
|
|
|
- **Myket**: Myket IAB SDK — define products in the Myket panel.
|
|
|
|
|
Wire a Capacitor plugin that detects the store build and routes `buyCoins`
|
|
|
|
|
to the store SDK; verify the purchase token on the server, then credit coins
|
|
|
|
|
via the same `ProfileService.BuyCoins`. (TODO — needs store accounts + product SKUs.)
|
|
|
|
|
|
2026-06-04 14:31:14 +03:30
|
|
|
## Release (Cafe Bazaar / Myket)
|
|
|
|
|
1. Generate a keystore: `keytool -genkey -v -keystore bargevasat.keystore -alias bargevasat -keyalg RSA -keysize 2048 -validity 10000`
|
|
|
|
|
2. Configure signing in `android/app/build.gradle` (release `signingConfig`).
|
|
|
|
|
3. `gradlew.bat assembleRelease` (or `bundleRelease` for AAB) → upload to Cafe Bazaar / Myket.
|
|
|
|
|
4. App icon/splash: replace `android/app/src/main/res/**` (use `@capacitor/assets` to generate).
|