# Testing Your Implementation (/docs/products/ussd-flows/developers/security/testing)

The [ussd-flow-exchange-examples](https://github.com/monimesl/ussd-flow-exchange-examples) repository has a complete exchange server in five languages, and a test flow to import into the dashboard. Deploy one, point the test flow at it, and compare its behaviour with your own server.

## Reference servers

- [**Node.js**](https://github.com/monimesl/ussd-flow-exchange-examples/tree/main/nodejs)

  Built-in `crypto` module. No dependencies.

- [**Python**](https://github.com/monimesl/ussd-flow-exchange-examples/tree/main/python)

  Flask and the `cryptography` library. Deploys to Vercel.

- [**Go**](https://github.com/monimesl/ussd-flow-exchange-examples/tree/main/go)

  Standard library only. Deploys to Vercel.

- [**Java**](https://github.com/monimesl/ussd-flow-exchange-examples/tree/main/java)

  JDK standard library, in Docker. Deploys to Railway, Render or Fly.io.

- [**PHP**](https://github.com/monimesl/ussd-flow-exchange-examples/tree/main/php)

  phpseclib v3 for RSA, OpenSSL for AES. Deploys to Vercel.

- [**Test flow**](https://github.com/monimesl/ussd-flow-exchange-examples/tree/main/flow)

  The flow JSON to import into the dashboard.

## How to test

### 1. Make a key pair

Follow [Key Setup](/docs/products/ussd-flows/developers/security/key-setup#make-a-key-pair). You need `private_key.pem` for the next step.

### 2. Deploy a reference server

Clone the repository, then deploy the language you want with the private key set as `MONIME_RSA_PRIVATE_KEY`:

```bash Node.js
git clone https://github.com/monimesl/ussd-flow-exchange-examples
cd ussd-flow-exchange-examples/nodejs
vercel env add MONIME_RSA_PRIVATE_KEY < /path/to/private_key.pem
vercel
```

```bash Python
git clone https://github.com/monimesl/ussd-flow-exchange-examples
cd ussd-flow-exchange-examples/python
vercel env add MONIME_RSA_PRIVATE_KEY < /path/to/private_key.pem
vercel
```

```bash Go
git clone https://github.com/monimesl/ussd-flow-exchange-examples
cd ussd-flow-exchange-examples/go
vercel env add MONIME_RSA_PRIVATE_KEY < /path/to/private_key.pem
vercel
```

```bash Java (Docker)
git clone https://github.com/monimesl/ussd-flow-exchange-examples
cd ussd-flow-exchange-examples/java
docker build -t exchange-java .
docker run -p 3000:3000 -e MONIME_RSA_PRIVATE_KEY="$(cat /path/to/private_key.pem)" exchange-java
```

```bash PHP
git clone https://github.com/monimesl/ussd-flow-exchange-examples
cd ussd-flow-exchange-examples/php
composer install
vercel env add MONIME_RSA_PRIVATE_KEY < /path/to/private_key.pem
vercel
```

### 3. Check the server is up

```bash
curl https://your-deployment-url/api/exchange
```

You should see:

```json
{
  "status": "ok",
  "language": "python",
  "key_loaded": true,
  "encryption": "RSA-OAEP-SHA256 + AES-128-GCM"
}
```

If `key_loaded` is `false`, the server can't read `MONIME_RSA_PRIVATE_KEY`. Check that it's set and holds the whole PEM file. On Vercel, run `vercel env ls`.

### 4. Connect the test flow

1. Import the [test flow JSON](https://github.com/monimesl/ussd-flow-exchange-examples/tree/main/flow) into a new flow in the dashboard.
2. Set its exchange URL to `https://your-deployment-url/api/exchange`.
3. Paste the contents of `public_key.pem` into the flow's Security section.
4. Run the flow in the Simulator, or publish it and dial it.

### 5. Send a plain request (optional)

The reference servers also accept unencrypted requests, so you can check their logic without encryption:

```bash
curl -X POST https://your-deployment-url/api/exchange \
  -H 'Content-Type: application/json' \
  -d '{
    "global": {
      "sessionId": "5f0c1e8a-2b7d-4c1e-9a43-7d2f8e6b1c90",
      "networkName": "Orange",
      "subscriberId": "c9b4e86f-a1d8-5056-8dc4-5d1aafc6994a",
      "subscriberMsisdn": "+23276****56"
    },
    "currentPage": "security_test_start",
    "flowData": {}
  }'
```

Expected reply:

```json
{
  "action": "navigate",
  "pageId": "security_test_menu",
  "pageData": {
    "items": [
      { "label": "Continue", "value": "continue" },
      { "label": "Cancel", "value": "cancel" }
    ],
    "message": "Security test flow (Python). Select an option."
  }
}
```

If plain requests work but encrypted ones fail, the problem is in the encryption. See [Troubleshooting](/docs/products/ussd-flows/developers/security/troubleshooting).
