# CAM2 Pay (cam2.cc) API Documentation & Integration Specification
> Official Dynamic ABA KHQR Gateway & Merchant Integration Reference

## 1. Overview
CAM2 Pay (`cam2.cc`) is an ABA PayWay & KHQR payment gateway platform that generates real-time, dynamic EMVCo KHQR codes for merchants. It supports:
- Web Redirect (Hosted Checkout Page)
- JS Popup Modal Checkout
- Headless Raw QR API (Telegram Bots, Flutter / React Native Mobile Apps, POS Receipts)
- Server-to-Server Transaction Status Polling
- Instant Automated Webhooks with HMAC SHA-256 Signature Verification

---

## 2. Base URL & Authentication
- **Production Base URL:** `https://cam2.cc`
- **Sandbox / Local URL:** `http://localhost:3001`
- **Authentication Credentials:**
  - `Profile ID` (also called `api_key`): Public identifier passed in endpoint path or JSON body.
  - `Secret Key`: Private secret used ONLY on your backend server to calculate security hash signatures. NEVER expose this in frontend code!

---

## 3. Endpoints

### 3.1 Create Checkout (Web Redirect & Modal)
- **Method:** `POST`
- **Path:** `/api/payment/checkout/:profile_id?json=1`
- **Content-Type:** `application/json`

#### Request Parameters:
| Field | Type | Required | Description |
|---|---|---|---|
| `transaction_id` | String | Yes | Merchant unique invoice/order ID (e.g. `INV-10023`) |
| `amount` | String/Float | Yes | USD amount with 2 decimals (e.g. `1.00`, min `0.01`) |
| `success_url` | String | Yes | Return URL when customer completes payment |
| `cancel_url` | String | No | Return URL if customer cancels |
| `remark` | String | No | Order description (e.g. `Order #10023`) |
| `hash` | String | Yes | Security signature calculated using formula below |
| `custom_fields` | String | No | Base64-encoded custom JSON (e.g. user_id, game_id) |

#### Hash Formula (SHA-1):
```text
hash = sha1(secret_key + transaction_id + amount + success_url + remark)
```

#### Response (JSON):
```json
{
  "success": true,
  "status": "success",
  "checkout_url": "https://cam2.cc/pay/SES-1791614907485",
  "session_id": "SES-1791614907485",
  "data": {
    "qr": "00020101021229500016...",
    "qr_url": "https://cam2.cc/api/qr-image/SES-1791614907485",
    "deeplink": "https://link.payway.com.kh/ABAPAYwd542327q?amount=1.00"
  }
}
```

---

### 3.2 Headless Raw QR API (Telegram Bots & Mobile Apps)
- **Method:** `POST`
- **Path:** `/api/payment/qr-api/:profile_id`
- **Content-Type:** `application/x-www-form-urlencoded` or `application/json`

#### Response (JSON):
```json
{
  "responseCode": 0,
  "description": "Success",
  "data": {
    "qr": "00020101021229...",
    "qr_url": "https://cam2.cc/api/qr-image/SES-1791614907485",
    "deeplink": "https://link.payway.com.kh/ABAPAYwd542327q?amount=2.50",
    "session_id": "SES-1791614907485"
  }
}
```

---

### 3.3 Server-to-Server Transaction Status Polling
- **Method:** `POST`
- **Path:** `/api/payment/check-transaction/:profile_id`

#### Request Parameters:
| Field | Type | Description |
|---|---|---|
| `transaction_id` | String | Your order ID |
| `hash` | String | `sha1(secret_key + transaction_id)` |

#### Response (JSON):
```json
{
  "responseCode": 0,
  "data": {
    "status": "success", // 'pending' | 'success' | 'expired'
    "amount": "1.00",
    "tran_id": "APPR-9238102"
  }
}
```

---

### 3.4 Webhook Callback (Instant Notification)
When the customer scans the QR code and pays, CAM2 Pay immediately sends a `POST` request to your configured Webhook URL.

#### Incoming Payload:
```json
{
  "status": "SUCCESS",
  "transaction_id": "INV-10023",
  "amount": 1.00,
  "tran_id": "APPR-9238102",
  "req_time": "20261010234500",
  "custom_fields": "eyJ1c2VyX2lkIjoxMjM0NX0=",
  "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
}
```

#### Verification Formula (HMAC / SHA-256):
```text
expected_hash = hash('sha256', secret_key + req_time + transaction_id + amount + "SUCCESS")
```

#### Verification Code (PHP):
```php
$raw_json = file_get_contents('php://input');
$data     = json_decode($raw_json, true);

$expected_str  = $secret_key . $data['req_time'] . $data['transaction_id'] . $data['amount'] . "SUCCESS";
$expected_hash = hash('sha256', $expected_str);

if (hash_equals($expected_hash, $data['hash'])) {
    // Verified! Update order to PAID:
    // UPDATE orders SET status='PAID' WHERE id = $data['transaction_id'];
    http_response_code(200);
    echo json_encode(['status' => 'OK']);
} else {
    http_response_code(401);
    echo json_encode(['error' => 'Invalid signature']);
}
```

---

## 4. JS Popup Modal Plugin
Include the plugin on your frontend:
```html
<script src="https://cam2.cc/plugins/cam2-pay.js"></script>

<button onclick="payNow()">Pay with ABA KHQR</button>

<script>
function payNow() {
  Cam2Pay.checkout({
    apiKey: 'YOUR_PROFILE_ID',
    amount: 1.00,
    orderId: 'ORD-' + Date.now(),
    onSuccess: function(data) {
      alert('Payment Success! Tran ID: ' + data.tran_id);
    }
  });
}
</script>
```

---

## 5. Official Sample Project
Download ready-to-run PHP sample code:
- `https://cam2.cc/downloads/CAM2Pay_PHP_Sample.zip`
