Skip to content
Back to skills

207 Real 15534c7c

ASecurity

Real-time payment notifications from SePay to your server.

  • 9 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added October 11, 2026
securityjavascriptgojavaphpnodeexpressapidatabasesecurity

Works with

  • cli
  • api

Security analysis

A100/100

Scanned October 11, 2026

npx -y skills add tools-only/X-Skills --skill 207-real_15534c7c --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of 207 Real 15534c7c?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for 207 Real 15534c7c
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/tools-only-207-real-15534c7c/badge)](https://www.skillsdirectory.com/skills/tools-only-207-real-15534c7c)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

SKILL.md
# SePay Webhooks

Real-time payment notifications from SePay to your server.

## Setup

1. Access WebHooks menu in dashboard
2. Click "+ Add webhooks"
3. Configure:
   - **Name:** Descriptive identifier
   - **Event Selection:** `All`, `In_only`, `Out_only`
   - **Conditions:** Bank accounts, VA filtering, payment code requirements
   - **Webhook URL:** Your callback endpoint (must be publicly accessible)
   - **Is Verify Payment:** Flag for validation
   - **Authentication:** `No_Authen`, `OAuth2.0`, or `Api_Key`
4. Click "Add" to finalize

## Payload Structure

```json
{
  "id": 92704,
  "gateway": "Vietcombank",
  "transactionDate": "2023-03-25 14:02:37",
  "accountNumber": "0123499999",
  "code": null,
  "content": "payment content",
  "transferType": "in",
  "transferAmount": 2277000,
  "accumulated": 19077000,
  "subAccount": null,
  "referenceCode": "MBVCB.3278907687"
}
```

**Fields:**
- `id` - Unique transaction ID (use for deduplication)
- `gateway` - Bank name
- `transactionDate` - Transaction timestamp
- `accountNumber` - Bank account number
- `code` - Payment code (if available)
- `content` - Transfer description/content
- `transferType` - "in" (incoming) or "out" (outgoing)
- `transferAmount` - Transaction amount
- `accumulated` - Account balance after transaction
- `subAccount` - Sub-account identifier
- `referenceCode` - Bank transaction reference

## Authentication

**API Key:**
```
Authorization: Apikey YOUR_KEY
Content-Type: application/json
```

**OAuth 2.0:**
Provide token endpoint, client ID, and client secret in dashboard.

**No Authentication:**
Available but not recommended for production. Consider IP whitelisting.

## Response Requirements

**Success Response:**
```json
HTTP/1.1 200 OK
{
  "success": true
}
```

**Accepted:** Any 2xx status code (200-201)
**Timeout:** Respond within 5 seconds

## Auto-Retry Mechanism

**Policy:**
- Retries up to 7 times over ~5 hours
- Fibonacci sequence intervals (1, 1, 2, 3, 5, 8, 13... minutes)

**Duplicate Prevention:**
```javascript
// Primary: Use transaction ID
const exists = await db.transactions.findOne({ sepay_id: data.id });
if (exists) return { success: true };

// Alternative: Composite key
const key = `${data.referenceCode}-${data.transferType}-${data.transferAmount}`;
```

## Implementation Examples

### Node.js/Express
```javascript
app.post('/webhook/sepay', async (req, res) => {
  const transaction = req.body;

  // Check duplicates
  if (await isDuplicate(transaction.id)) {
    return res.json({ success: true });
  }

  // Process transaction
  if (transaction.transferType === 'in') {
    await processPayment({
      amount: transaction.transferAmount,
      content: transaction.content,
      referenceCode: transaction.referenceCode
    });
  }

  // Save to database
  await db.transactions.insert(transaction);

  res.json({ success: true });
});
```

### PHP
```php
<?php
$data = json_decode(file_get_contents('php://input'), true);

// Check duplicates
$exists = $db->query("SELECT id FROM transactions WHERE sepay_id = ?", [$data['id']]);
if ($exists) {
    echo json_encode(['success' => true]);
    exit;
}

// Process payment
if ($data['transferType'] == 'in') {
    processPayment($data['transferAmount'], $data['content']);
}

// Save to database
$db->insert('transactions', [
    'sepay_id' => $data['id'],
    'amount' => $data['transferAmount'],
    'content' => $data['content'],
    'reference_code' => $data['referenceCode']
]);

header('Content-Type: application/json');
echo json_encode(['success' => true]);
```

## Security Best Practices

1. **IP Whitelisting:** Restrict endpoint to SePay IPs
2. **API Key Verification:** Validate authorization header
3. **HTTPS Only:** Use SSL/TLS
4. **Duplicate Detection:** Prevent double processing
5. **Logging:** Maintain webhook logs
6. **Timeout Handling:** Respond quickly (<5s)
7. **Idempotency:** Same webhook multiple times = same result

## Monitoring

**Dashboard Features:**
- View webhook attempts
- Check response status
- Review retry history
- Manual retry option

**Application Monitoring:**
- Log all webhook receipts
- Track processing time
- Alert on failures
- Monitor duplicate rate

## OAuth2 Webhook Management API

**Available Scopes:** `webhook:read`, `webhook:write`, `webhook:delete`

**List Webhooks:**
```
GET /api/v1/webhooks
```

**Get Details:**
```
GET /api/v1/webhooks/{id}
```

**Create:**
```
POST /api/v1/webhooks
{
  "bank_account_id": 123,
  "name": "My Webhook",
  "event_type": "All",
  "authen_type": "Api_Key",
  "webhook_url": "https://example.com/webhook",
  "is_verify_payment": true
}
```

**Update:**
```
PATCH /api/v1/webhooks/{id}
```

**Delete:**
```
DELETE /api/v1/webhooks/{id}
```

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.