# eCash in the app (API contract)

eCash is a second online payment method next to Paymera. It works like Paymera's app checkout: **no order exists until eCash confirms the payment**, and eCash confirms it to our server directly, so the order is created even when the app is closed or offline after paying. Server side: `docs/codebase/features/online-payments.md`.

All endpoints are under `/api/v2`, with the usual `System-Key` and `App-Language` headers. Those marked 🔒 need the customer's bearer token. Old endpoints are unchanged; new keys are additive.

## 1. Which online methods to show

`GET prepaid-gateways?amount=<total in SYP>` (optional `amount`):

```json
{"result": true, "data": [
  {"gateway": "paymera", "name": "Paymera", "min_amount": null, "max_amount": null, "note": null, "available": true, "unavailable_reason": null},
  {"gateway": "ecash", "name": "إي كاش", "min_amount": 15, "max_amount": 250000,
   "note": "الدفع الإلكتروني حتى 250,000 ل.س للطلب الواحد", "available": false,
   "unavailable_reason": "أقصى مبلغ يمكن دفعه عبر إي كاش هو 250,000 ل.س. اختر الدفع عند الاستلام أو احذف بعض المنتجات."}
]}
```

- **eCash missing from the list** = switched off. Don't show it.
- **`note`:** show it under the method.
- **`available: false`:** show it greyed out with `unavailable_reason`.
- **Limits apply to Paymera too** once staff set them, so read `available` for both methods.

## 2. Pay

🔒 `POST ecash/create` (no body; takes the cart like `paymera/create`):

```json
{"result": true, "paid": false, "combined_order_id": 812, "payment_ref": "KP812A1",
 "payment_url": "https://checkout.ecash-pay.com/Checkout/CardCheckout?...",
 "return_url": "https://kapitano.shop/api/v2/ecash/return/KP812A1", "amount": 14500}
```

1. Open `payment_url` in a web view.
2. On eCash's page the customer picks the bank, card or account, and confirms with the SMS code. The page's language follows `App-Language`.
3. When the web view reaches an address starting with `return_url`, close it and go to §3.
4. If the customer closes the web view instead, go to §3 as well. Nothing needs cancelling; an unfinished attempt expires on its own after an hour.
5. eCash's own "Cancel" button tells our server nothing and does not open `return_url` (on the website it went back to the page that opened eCash). If the web view leaves eCash's site for anything other than `return_url`, close it and go to §3.

`amount` is what eCash charges: the total the app shows, in SYP, to the store's 5-pound step.

Other answers:
- **`result: false`:** show `message`. For example: cart empty, coupon no longer valid, no address, over the limit, eCash off.
- **`paid: true` with no `payment_url`:** a coupon covered everything. The order is placed and paid; show the success screen.

## 3. Was it paid?

🔒 `POST ecash/status` `{"payment_ref": "KP812A1"}`:

```json
{"result": true, "payment_ref": "KP812A1", "state": "pending", "paid": false,
 "message": "نتأكد من دفعتك مع إي كاش. يستغرق ذلك بضع ثوانٍ.", "combined_order_id": 812}
```

| `state` | Show |
|---|---|
| `pending` | A waiting screen. Ask again every 3 s for up to ~2 minutes. If still pending after that: "if money was taken your order will appear once eCash confirms it, do not pay again", plus a link to My Orders |
| `paid` | Success. The orders exist (open the order with `combined_order_id`) |
| `review` | "Payment received, our team is checking it" (wrong amount or a second payment). No retry button |
| `failed` | `message`, plus "Try again", which calls `ecash/create` again |
| `expired` / `superseded` | "Payment not completed", plus "Try again" |

## 4. Pay later for an unpaid eCash order

The combined-order endpoints add `pay_gateway` next to `can_pay_online` / `pay_order_id`:
- `ecash` → 🔒 `POST ecash/re-pay {"order_id": <pay_order_id>}`. Same answer as §2.
- `paymera` → `paymera/re-pay` as before.

## 5. Refund

The combined-order endpoints add `refund_gateway` next to `can_refund` / `refund_order_id`:
- `ecash` → 🔒 `POST ecash/refund {"order_id": <refund_order_id>}`.
- `paymera` → `paymera/refund` as before. If `paymera/refund` is called for an eCash order, it handles it too.

```json
{"result": true, "refund_status": "requested", "message": "أُلغي طلبك ووصلنا طلب الاسترجاع. يعود المبلغ إلى حسابك البنكي خلال ساعات."}
```

- **When it's offered:** `can_refund` is true only for the first 5 hours after paying, while no seller has confirmed. eCash itself refunds only within 6 hours, and only the whole amount.
- **What happens:** the whole order is cancelled.
- **`refund_status`:** `reversed` = already back; `requested` = our team cancels it at eCash within the hour.
- **`result: false`:** show `message`.

## 6. Don't

- **Don't place an eCash order with `order/store`.** `payment_type = ecash` is refused there with a message to update the app.
- **Don't decide "paid" from the web view's address.** Only `ecash/status` says it.
