# Relworx Webhook Integration

## Overview

This integration handles status update webhooks from Relworx API. When a payment request changes from `pending` to either `failed` or `success`, Relworx sends a POST request to your configured webhook endpoint with the transaction details.

## Webhook Endpoint

**URL:** `POST /api/mobile-money/webhook/relworx`

**Full URL (configure this in Relworx):**
```
https://yourdomain.com/api/mobile-money/webhook/relworx
```

## Configuration in Relworx

1. Log into your Relworx business account
2. Navigate to **Business Account Settings**
3. Find the **Webhooks** section
4. Add your webhook endpoint URL:
   ```
   https://yourdomain.com/api/mobile-money/webhook/relworx
   ```
5. Save the configuration

## Webhook Payload from Relworx

Relworx will send the following JSON payload when a transaction status changes:

```json
{
  "status": "success",
  "message": "Request payment completed successfully.",
  "customer_reference": "MM_1728576000_a1b2c3d4e5f67890",
  "internal_reference": "fdd10a4c5d6b459d54ebc5f09d095101",
  "msisdn": "+256773454899",
  "amount": 500.0,
  "currency": "UGX",
  "provider": "mtn_mobile_money",
  "charge": 12.5,
  "completed_at": "2025-04-10T15:12:58.977+03:00"
}
```

### Payload Fields

| Field | Type | Description |
|-------|------|-------------|
| `status` | string | Transaction status: `"success"` or `"failed"` |
| `message` | string | Status message from Relworx |
| `customer_reference` | string | Your original reference (transaction_id) |
| `internal_reference` | string | Relworx's internal reference |
| `msisdn` | string | Customer phone number |
| `amount` | float | Transaction amount |
| `currency` | string | Currency code (e.g., "UGX") |
| `provider` | string | Payment provider (e.g., "mtn_mobile_money") |
| `charge` | float | Transaction charge/fee |
| `completed_at` | string | ISO 8601 timestamp of completion |

## How It Works

1. **Relworx sends webhook** → Your endpoint receives the POST request
2. **Webhook handler validates** → Checks required fields and logs the request
3. **Transaction lookup** → Finds transaction by `customer_reference` or `internal_reference`
4. **Database update** → Updates transaction status, metadata, and timestamps
5. **Forward to your webhooks** → Notifies your configured webhook endpoints
6. **Respond with 200 OK** → Acknowledges receipt to Relworx

## Retry Logic

- If your endpoint doesn't respond with **HTTP 200 OK**, Relworx will retry sending the webhook
- Retries happen **10 times** with **exponential backoff**
- Your endpoint **ALWAYS responds with 200 OK** to prevent unnecessary retries (even if transaction not found)

## What Gets Updated in Database

When webhook is received, the following fields are updated:

```php
[
    'status' => 'SUCCESS' or 'FAILED',
    'updated_at' => current timestamp,
    'processed_at' => completion timestamp,
    'gateway_reference' => internal_reference,
    'failure_reason' => message (if failed),
    'metadata' => includes full Relworx webhook data
]
```

## Metadata Storage

The webhook data is stored in the transaction's `metadata` field:

```json
{
  "relworx_webhook": {
    "received_at": "2025-10-10 15:12:58",
    "status": "success",
    "internal_reference": "fdd10a4c5d6b459d54ebc5f09d095101",
    "provider": "mtn_mobile_money",
    "charge": 12.5,
    "completed_at": "2025-04-10T15:12:58.977+03:00",
    "message": "Request payment completed successfully."
  }
}
```

## Forwarding to Your Webhooks

After processing, the webhook handler forwards the status update to your configured webhook endpoints (from the `webhooks` table in your database).

**Forwarded payload:**
```json
{
  "transaction_id": "MM_1728576000_a1b2c3d4e5f67890",
  "reference": "fdd10a4c5d6b459d54ebc5f09d095101",
  "msisdn": "+256773454899",
  "amount": 500.0,
  "currency": "UGX",
  "status": "SUCCESS",
  "provider": "mtn_mobile_money",
  "charge": 12.5,
  "completed_at": "2025-04-10T15:12:58.977+03:00",
  "message": "Request payment completed successfully.",
  "created_at": "2025-10-10 14:30:00",
  "updated_at": "2025-10-10 15:12:58"
}
```

## Logging

All webhook activity is logged for debugging:

```php
// Logs in: writable/logs/log-YYYY-MM-DD.log

// Webhook received
log_message('info', 'Relworx Webhook received: ' . $rawInput);

// Transaction updated
log_message('info', "Relworx Webhook: Transaction {$reference} updated to status: {$status}");

// Transaction not found (warning, but still returns 200 OK)
log_message('warning', "Relworx Webhook: Transaction not found - customer_ref: {$ref}");

// Errors
log_message('error', 'Relworx Webhook: Invalid JSON input');
```

## Testing the Webhook

You can test the webhook manually using curl:

```bash
curl -X POST http://localhost/api/mobile-money/webhook/relworx \
  -H "Content-Type: application/json" \
  -d '{
    "status": "success",
    "message": "Request payment completed successfully.",
    "customer_reference": "MM_1728576000_a1b2c3d4e5f67890",
    "internal_reference": "fdd10a4c5d6b459d54ebc5f09d095101",
    "msisdn": "+256773454899",
    "amount": 500.0,
    "currency": "UGX",
    "provider": "mtn_mobile_money",
    "charge": 12.5,
    "completed_at": "2025-04-10T15:12:58.977+03:00"
  }'
```

**Expected Response:**
```json
{
  "success": true,
  "message": "Webhook received and processed successfully"
}
```

## Webhook vs Callback Endpoints

Your system now has **two webhook endpoints**:

| Endpoint | Purpose |
|----------|---------|
| `/api/mobile-money/callback` | Generic callback (existing, kept intact) |
| `/api/mobile-money/webhook/relworx` | **Relworx-specific webhook (NEW)** |

Configure the **Relworx-specific endpoint** in your Relworx account settings.

## Security Considerations

1. **HTTPS Required:** Always use HTTPS in production for webhook endpoints
2. **IP Whitelisting:** Consider whitelisting Relworx's IP addresses
3. **Signature Verification:** If Relworx provides webhook signatures, implement verification
4. **Rate Limiting:** Consider rate limiting webhook endpoints to prevent abuse
5. **Log Monitoring:** Monitor logs for suspicious webhook activity

## Troubleshooting

### Webhook not being received
- Check that the URL is correctly configured in Relworx
- Verify your server is accessible from the internet
- Check firewall rules

### Transaction not found
- Verify the `customer_reference` matches your transaction IDs
- Check the transaction exists in your database
- Review logs for the exact reference being searched

### Status not updating
- Check database permissions
- Review error logs
- Verify transaction model and table structure

### Relworx keeps retrying
- Ensure your endpoint returns HTTP 200 OK
- Check for PHP errors that might cause 500 responses
- Verify JSON response format is correct

## Files Modified

- `app/Controllers/MobileMoney.php` - Added `relworxWebhook()` method
- `app/Config/Routes.php` - Added route for `/webhook/relworx`

## Related Endpoints

- `POST /api/mobile-money/pay` - Initiate payment
- `GET /api/mobile-money/status/{reference}` - Check local status
- `GET /api/mobile-money/check-status/{internal_reference}` - Check Relworx status
- `POST /api/mobile-money/webhook/relworx` - **Receive Relworx webhooks (NEW)**

