Files
clinicpro/docs/api/payment.md
T

203 lines
5.2 KiB
Markdown

# Payment API
> **Prefix:** `/api/v1/payment`, `/api/v1/subscription-payment`
> **Supported Gateways:** `mellat` (Mellat Bank SOAP) | `sep` (SEP REST)
---
## GET `/api/v1/payment/config`
دریافت تنظیمات عمومی پرداخت — برای نمایش وضعیت درگاه آزمایشی در frontend.
**Permission:** `IS_AUTHENTICATED_FULLY`
### Response `200`
```json
{
"success": true,
"data": {
"test_mode": true
}
}
```
| Field | Type | Description |
|-------|------|-------------|
| `test_mode` | boolean | `true` = درگاه آزمایشی فعال است — backend از MockGateway استفاده می‌کند و پول واقعی کسر نمی‌شود |
**نکته:** این endpoint هیچ اطلاعات حساسی (terminal_id، password، ...) را expose نمی‌کند. تنها یک boolean برای مصرف frontend است.
---
## POST `/api/v1/payment/appointment`
Initiate payment for an appointment. Returns a redirect URL to the payment gateway.
**Permission:** `AUTH` — must be the appointment owner (patient)
### Request Body (`application/json`)
```json
{
"appointment_uuid": "appt-uuid-...",
"gateway": "mellat",
"frontend_address": "https://myapp.com/payment/result"
}
```
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `appointment_uuid` | string (UUID) | ✅ | Appointment to pay for |
| `gateway` | string | ✅ | `"mellat"` or `"sep"` |
| `frontend_address` | string | ❌ | Redirect URL after payment (overrides default) |
### Response `200`
```json
{
"success": true,
"data": {
"payment_uuid": "pay-uuid-...",
"redirect_url": "https://bpm.shaparak.ir/pgwchannel/...",
"order_id": "CLINICPRO-1717000000-ABC123"
}
}
```
### Errors
| Code | HTTP | Description |
|------|------|-------------|
| `ERR_AUTH_001` | 401 | Missing token |
| `ERR_FORBIDDEN_001` | 403 | Not the patient |
| `ERR_PAYMENT_003` | 422 | Appointment not in payable state |
| `ERR_PAYMENT_002` | 422 | Invalid amount |
| `ERR_PAYMENT_001` | 503 | Payment gateway unavailable |
---
## POST `/api/v1/payment/callback/{gateway}`
## GET `/api/v1/payment/callback/{gateway}`
Payment gateway callback. Called by the bank after user completes (or cancels) payment.
**Permission:** `PUBLIC` — called by the gateway, not the user
### Path Parameters
| Param | Type | Description |
|-------|------|-------------|
| `gateway` | string | `mellat` or `sep` |
### Request (varies by gateway)
**Mellat POST fields:**
```
ResCode=0&SaleOrderId=...&SaleReferenceId=...&RefId=...
```
**SEP POST fields:**
```
Status=2&RRN=...&RefNum=...&TerminalId=...&TraceNo=...
```
### Response
- If `ResCode=0` (success): appointment confirmed, redirect to `frontend_address?success=1&uuid=...`
- If failed: redirect to `frontend_address?success=0&error=...`
### Notes
- On success: appointment status → `confirmed`, wallet credited with doctor's share
- Payment record stored with: `order_id`, `amount_rials`, `status`, `gateway`, `ref_id`
---
## POST `/api/v1/subscription-payment`
Initiate a subscription / wallet top-up payment (not tied to a specific appointment).
**Permission:** `AUTH`
### Request Body
```json
{
"gateway": "mellat",
"amount_rials": 1000000,
"frontend_address": "https://myapp.com/wallet/result"
}
```
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `gateway` | string | ✅ | `"mellat"` or `"sep"` |
| `amount_rials` | integer | ✅ | Amount in Rials (min: 10,000) |
| `frontend_address` | string | ❌ | Redirect URL after payment |
### Response `200`
```json
{
"success": true,
"data": {
"payment_uuid": "pay-uuid-...",
"redirect_url": "https://bpm.shaparak.ir/pgwchannel/...",
"order_id": "CLINICPRO-SUB-1717000000-XYZ"
}
}
```
### Errors
| Code | HTTP | Description |
|------|------|-------------|
| `ERR_AUTH_001` | 401 | Missing token |
| `ERR_PAYMENT_002` | 422 | Invalid amount |
| `ERR_PAYMENT_001` | 503 | Gateway unavailable |
---
## POST/GET `/api/v1/subscription-payment/callback/{gateway}`
Callback for subscription payments. Same behavior as appointment callback but credits wallet instead.
**Permission:** `PUBLIC`
---
## GET `/api/v1/payment/{uuid}`
Get payment status and details.
**Permission:** `AUTH` — must be the payment owner or `ROLE_ADMIN`
### Path Parameters
| Param | Type | Description |
|-------|------|-------------|
| `uuid` | string (UUID) | Payment UUID |
### Response `200`
```json
{
"success": true,
"data": {
"uuid": "pay-uuid-...",
"order_id": "CLINICPRO-1717000000-ABC123",
"amount_rials": 500000,
"status": "paid",
"gateway": "mellat",
"ref_id": "123456789",
"appointment_uuid": "appt-uuid-...",
"created_at": 1717000000,
"paid_at": 1717000120
}
}
```
**Payment Status Values:**
| Value | Description |
|-------|-------------|
| `pending` | Created, not paid yet |
| `paid` | Successfully paid |
| `failed` | Gateway returned failure |
| `cancelled` | User cancelled at gateway |
| `refunded` | Refunded |
### Errors
| Code | HTTP | Description |
|------|------|-------------|
| `ERR_AUTH_001` | 401 | Missing token |
| `ERR_FORBIDDEN_001` | 403 | Not the owner |
| `ERR_NOT_FOUND_001` | 404 | Payment not found |