PCI Payments IVR API

Customer Backend Integration Guide


Table of Contents

  1. Overview
  2. Integration Architecture
  3. API Endpoints (You Implement)
  4. Call Flow
  5. Request Formats (From TelcoEdge)
  6. Response Formats (You Return)
  7. Configuration
  8. Integration Examples
  9. Troubleshooting

Overview

The PCI Payments IVR API enables integration between TelcoEdge's IVR payment system and your backend systems. During a payment call, TelcoEdge's IVR calls your backend endpoints to validate payment identifiers, retrieve payment amounts, and post transaction results.

What This API Does

When a caller phones your payment service number:

  1. IVR answers and prompts for payment IDs (customer number, invoice number, etc.)
  2. TelcoEdge calls YOUR Backend to validate the payment IDs and get the amount owing
  3. IVR collects credit card details securely
  4. Payment processes through the gateway
  5. TelcoEdge posts results to your callback endpoint (success or failure)

What This API Does NOT Do

  • ❌ This is NOT for web-based payments
  • ❌ This is NOT an API you call to trigger payments
  • ❌ This is NOT for direct card processing

This is specifically for IVR phone calls where TelcoEdge acts as the API client calling your backend.


Integration Architecture

Who Implements What?

YOU (Customer) Implement:

  • Backend API server with up to 4 endpoints
  • Database lookups for payment validation
  • Receipt/failure callback handlers

TelcoEdge Provides:

  • IVR system that handles the phone call
  • Secure credit card collection (PCI compliant)
  • Gateway integration for card processing
  • API client that calls YOUR backend endpoints

API Call Direction

How it works:

  1. Customer calls your payment number ↓
  2. TelcoEdge IVR answers the call ↓
  3. TelcoEdge → Your Backend (Optional alive check)
    • TelcoEdge calls: /api/payment/check
  4. TelcoEdge IVR prompts caller for payment IDs ↓
  5. TelcoEdge → Your Backend (Validate IDs & get amount)
    • TelcoEdge calls: /api/payment/validate
    • Your backend returns: amount, status, surcharges ↓
  6. TelcoEdge IVR collects credit card details ↓
  7. TelcoEdge processes payment through gateway ↓
  8. TelcoEdge → Your Backend (Post result)
    • Success: TelcoEdge calls /api/payment/receipt
    • Failure: TelcoEdge calls /api/payment/failure
  9. Your Backend updates database, sends emails, etc.

Call Sequence

  1. Customer dials your payment number
  2. IVR answers and checks if your backend is alive (checkurl)
  3. IVR prompts for payment IDs (1-3 identifiers)
  4. TelcoEdge calls your validation endpoint (validateurl) with the IDs
  5. Your backend returns amount owing, surcharges, min/max amounts
  6. IVR collects credit card number, expiry, CVN
  7. IVR processes payment through gateway
  8. TelcoEdge posts success to receipturl OR failure to failurl
  9. Your system updates database (mark invoice paid, log transaction, etc.)

Backend Endpoints (You Implement)

You implement up to 4 endpoints on your backend. All are optional but recommended for full integration.

Quick Reference

Endpoint Method Purpose Example URL
Alive Check GET Confirm API is responding https://yourdomain.com/api/payment/check
Validation GET/POST Validate IDs and return payment amount https://yourdomain.com/api/payment/validate
Receipt GET/POST Receive successful payment details https://yourdomain.com/api/payment/receipt
Failure GET/POST Receive failed payment details https://yourdomain.com/api/payment/failure

Note: URLs support placeholders like {id1}, {id2}, {amount}, etc. which are substituted with actual values.

Example with placeholders:

https://yourdomain.com/api/payment/validate?customer={id1}&invoice={id2}&amount={amount}

1. Check/Alive Endpoint (Optional)

Purpose: Health check - verifies your backend is available before starting the payment process.

When Called: At the start of every payment call (before prompting for payment IDs).

Configuration: Set checkurl in payment service config.

Request from TelcoEdge:

GET https://yourdomain.com/api/payment/check?indial=1300123456&cli=0412345678&callid=1737590123_2038_1

Query Parameters:

  • indial: Payment service number called

    • Example: 1300123456
  • cli: Caller's phone number

    • Example: 0412345678
  • callid: Unique call identifier

    • Example: 1737590123_2038_1
  • svcref: Service reference ID

    • Example: PAYSERVICE01
  • tstamp: Timestamp (configurable format)

    • Example: 2026-01-22 14:30:45

Your Response:

HTTP 200 OK

Any HTTP 2xx response indicates success. Non-2xx stops the call.


2. Validation Endpoint (Recommended)

Purpose: Validate payment identifiers and return the amount owing.

When Called: After caller enters payment ID(s), before collecting card details.

Configuration: Set validateurl in payment service config.

Request from TelcoEdge:

The request format depends on your apitype configuration:

GET Request (default):

GET https://yourdomain.com/api/payment/validate?id1=CUST12345&id2=INV98765&id3=REF001&indial=1300123456&cli=0412345678&callid=1737590123_2038_1

POST Request with JSON (apitype=POST+JSON):

POST https://yourdomain.com/api/payment/validate
Content-Type: application/json

{
  "voffice": {
    "validate": {
      "indial": "1300123456",
      "cli": "0412345678",
      "callid": "1737590123_2038_1",
      "svcref": "PAYSERVICE01",
      "tstamp": "2026-01-22 14:30:45",
      "id1": "CUST12345",
      "id2": "INV98765",
      "id3": "REF001"
    }
  }
}

POST Request with XML (apitype=POST+XML):

POST https://yourdomain.com/api/payment/validate
Content-Type: application/xml

<?xml version="1.0" encoding="UTF-8"?>
<voffice>
  <validate>
    <indial>1300123456</indial>
    <cli>0412345678</cli>
    <callid>1737590123_2038_1</callid>
    <svcref>PAYSERVICE01</svcref>
    <tstamp>2026-01-22 14:30:45</tstamp>
    <id1>CUST12345</id1>
    <id2>INV98765</id2>
    <id3>REF001</id3>
  </validate>
</voffice>

Request Parameters:

  • id1: Payment ID 1 (if enabled)

    • Example: CUST12345
  • id2: Payment ID 2 (if enabled)

    • Example: INV98765
  • id3: Payment ID 3 (if enabled)

    • Example: REF001
  • indial: Payment service number

    • Example: 1300123456
  • cli: Caller's phone number

    • Example: 0412345678
  • callid: Unique call identifier

    • Example: 1737590123_2038_1
  • svcref: Service reference

    • Example: PAYSERVICE01
  • tstamp: Timestamp

    • Example: 2026-01-22 14:30:45

Your Response Options:

Option 1: Fixed Amount (most common)

Return a single fixed amount to charge:

{
  "amount": 15000,
  "status": 1
}

Option 2: Amount Range

Return minimum and maximum allowed amounts (IVR will prompt caller for amount):

{
  "minamount": 1000,
  "maxamount": 50000,
  "status": 1
}

Option 3: No Amount (use configured value)

If amount is already configured in the IVR:

{
  "status": 1
}

Option 4: Error/Decline

Payment ID not found or invalid:

{
  "status": 0,
  "error": "Invoice not found"
}

Response Fields:

  • status (integer, required)

    • 1 = valid, 0 = invalid
  • amount (integer, conditional)

    • Fixed amount in cents (or dollars if units=dollars)
  • minamount (integer, conditional)

    • Minimum amount (if range-based)
  • maxamount (integer, conditional)

    • Maximum amount (if range-based)
  • error (string, optional)

    • Error message if status=0

3. Receipt Endpoint (Recommended)

Purpose: Receive successful payment transaction details.

When Called: Immediately after successful payment processing.

Configuration: Set receipturl in payment service config.

Request from TelcoEdge:

Format depends on apitype configuration:

POST JSON (apitype=POST+JSON):

POST https://yourdomain.com/api/payment/receipt
Content-Type: application/json

{
  "voffice": {
    "payment": {
      "indial": "1300123456",
      "cli": "0412345678",
      "callid": "1737590123_2038_1",
      "svcref": "PAYSERVICE01",
      "tstamp": "2026-01-22 14:30:45",
      "id1": "CUST12345",
      "id2": "INV98765",
      "id3": "REF001",
      "reference": "TXN2026012201",
      "summarycode": "0",
      "summary": "Approved",
      "responsecode": "00",
      "response": "Transaction Approved",
      "receipt": "ABC123456789",
      "transactionid": "TX-20260122-001",
      "refnum": "REF123456",
      "amount": "15000",
      "ccnum": "XXXXXXXXXXXX1234",
      "ccexp": "12/28",
      "token": "TKN_ABC123_XYZ789",
      "order": "ORD-20260122-001"
    }
  }
}

POST XML (apitype=POST+XML):

POST https://yourdomain.com/api/payment/receipt
Content-Type: application/xml

<?xml version="1.0" encoding="UTF-8"?>
<voffice>
  <payment>
    <indial>1300123456</indial>
    <cli>0412345678</cli>
    <callid>1737590123_2038_1</callid>
    <svcref>PAYSERVICE01</svcref>
    <tstamp>2026-01-22 14:30:45</tstamp>
    <id1>CUST12345</id1>
    <id2>INV98765</id2>
    <id3>REF001</id3>
    <reference>TXN2026012201</reference>
    <summarycode>0</summarycode>
    <summary>Approved</summary>
    <responsecode>00</responsecode>
    <response>Transaction Approved</response>
    <receipt>ABC123456789</receipt>
    <transactionid>TX-20260122-001</transactionid>
    <refnum>REF123456</refnum>
    <amount>15000</amount>
    <ccnum>XXXXXXXXXXXX1234</ccnum>
    <ccexp>12/28</ccexp>
    <token>TKN_ABC123_XYZ789</token>
    <order>ORD-20260122-001</order>
  </payment>
</voffice>

GET (apitype=GET):

GET https://yourdomain.com/api/payment/receipt?indial=1300123456&cli=0412345678&id1=CUST12345&id2=INV98765&amount=15000&receipt=ABC123456789&...

Payment Fields:

  • indial: Payment service number Example: 1300123456

  • cli: Caller's phone number Example: 0412345678

  • callid: Unique call identifier Example: 1737590123_2038_1

  • svcref: Service reference Example: PAYSERVICE01

  • tstamp: Transaction timestamp Example: 2026-01-22 14:30:45

  • id1, id2, id3: Payment identifiers Example: CUST12345, INV98765, REF001

  • reference: Transaction reference Example: TXN2026012201

  • summarycode: Summary code 0 = approved, 1 = declined, 2 = error Example: 0

  • summary: Summary text Example: Approved

  • responsecode: Gateway response code Example: 00

  • response: Gateway response text Example: Transaction Approved

  • receipt: Gateway receipt number Example: ABC123456789

  • transactionid: Transaction ID Example: TX-20260122-001

  • refnum: Reference number Example: REF123456

  • amount: Amount charged (cents or dollars) Example: 15000

  • ccnum: Masked card number Example: XXXXXXXXXXXX1234

  • ccexp: Card expiry Example: 12/28

  • token: Tokenised card reference (if tokenisation enabled) Example: TKN_ABC123_XYZ789

  • order: Order number Example: ORD-20260122-001

Your Response:

HTTP 200 OK

Any HTTP 2xx response is considered acknowledgment.


4. Failure Endpoint (Recommended)

Purpose: Receive failed payment transaction details.

When Called: Immediately after payment decline or failure.

Configuration: Set failurl in payment service config.

Request from TelcoEdge:

Same format options as receipt endpoint (JSON/XML/GET), but with failure details:

{
  "voffice": {
    "failure": {
      "indial": "1300123456",
      "cli": "0412345678",
      "callid": "1737590123_2038_1",
      "svcref": "PAYSERVICE01",
      "tstamp": "2026-01-22 14:30:45",
      "id1": "CUST12345",
      "id2": "INV98765",
      "id3": "REF001",
      "reference": "TXN2026012201",
      "summarycode": "1",
      "summary": "Declined",
      "responsecode": "05",
      "response": "Do Not Honour",
      "amount": "15000",
      "ccnum": "XXXXXXXXXXXX1234",
      "ccexp": "12/28"
    }
  }
}

Failure Fields:

  • summarycode: Summary code 1 = Declined, 2 = Error, etc. Example: 1

  • summary: Summary text Example: Declined

  • responsecode: Gateway response code Example: 05

  • response: Decline reason Example: Do Not Honour

(Other fields same as receipt endpoint)

Your Response:

HTTP 200 OK

Call Flow

Complete Payment Call Flow

1. CALL STARTS

  • Customer dials payment number

2. IVR ANSWERS

  • TelcoEdge IVR system answers the call

3. API ALIVE CHECK (Optional)

  • TelcoEdge calls: GET /api/payment/check?indial=...&cli=...
  • Only if checkurl is configured
  • If non-200 response: Play unavailable message, hangup

4. PLAY WELCOME

  • IVR plays welcome message: "Welcome to XYZ Payment Service..."

5. GET PAYMENT IDs

  • Prompt: "Please enter your customer number"
  • Collect: id1 (e.g., customer number)
  • If enabled:
    • Prompt: "Please enter your invoice number"
    • Collect: id2 (e.g., invoice number)
  • If enabled:
    • Prompt: "Please enter your reference number"
    • Collect: id3 (e.g., reference)
  • Validation: Length check, regex check

6. VALIDATE PAYMENT IDs & GET AMOUNT

  • TelcoEdge → Your Backend: POST /api/payment/validate
  • Sends: {id1, id2, id3, indial, cli, callid, ...}
  • Your Backend → TelcoEdge: Returns {amount, status, ...}
    • Your backend validates IDs and looks up amount
  • If status=0 or error: Play error, retry or transfer
  • If status=1: Continue with returned amount

7. CONFIRM AMOUNT

  • IVR announces: "The amount owing is $150 dollars"
  • Prompt: "Press 1 to continue or 2 to speak to an operator"

8. COLLECT CARD DETAILS

  • Prompt: "Please enter your card number"
  • Collect: Card number (validated with Luhn check)
  • Prompt: "Please enter expiry month and year"
  • Collect: Expiry MMYY (validated, not expired)
  • Prompt: "Please enter CVN"
  • Collect: CVN (3-4 digits)
  • Note: All card data collected via secure DTMF

9. CONFIRM DETAILS

  • IVR announces: "You have entered a card ending in 1234"
  • IVR announces: "The amount is $150 dollars"
  • Prompt: "Press 1 to confirm or 2 to re-enter"

10. PROCESS PAYMENT

  • TelcoEdge sends card data to gateway
  • Gateway processes transaction
  • Response: Approved or Declined

11A. POST SUCCESS (If payment approved)

  • TelcoEdge → Your Backend: POST /api/payment/receipt
  • Sends: Payment details (receipt, transactionid, amount, etc.)

12A. PLAY SUCCESS

  • IVR announces: "Your payment has been processed. Receipt number ABC123"

13A. EMAIL RECEIPT (If configured)

  • TelcoEdge sends email receipt

14A. CALL ENDS


11B. POST FAILURE (If payment declined)

  • TelcoEdge → Your Backend: POST /api/payment/failure
  • Sends: Failure details (responsecode, response, amount, etc.)

12B. PLAY FAILURE

  • IVR announces: "We were unable to process your payment. Please try again"

13B. RETRY OR TRANSFER

  • Offer retry or transfer to operator

14B. CALL ENDS


Request Formats (From TelcoEdge)

TelcoEdge can call your backend using different formats. Configure via apitype setting.

Format Options

  • GET (default)

    • HTTP Method: GET
    • Content-Type: N/A
    • Description: Query string parameters
  • POST

    • HTTP Method: POST
    • Content-Type: application/x-www-form-urlencoded
    • Description: Form parameters
  • POST+JSON

    • HTTP Method: POST
    • Content-Type: application/json
    • Description: JSON in request body
  • POST+XML

    • HTTP Method: POST
    • Content-Type: application/xml
    • Description: XML in request body

GET Format

GET /api/payment/validate?id1=CUST12345&id2=INV98765&indial=1300123456&cli=0412345678&callid=1737590123_2038_1&svcref=PAYSERVICE01&tstamp=2026-01-22%2014%3A30%3A45

POST Form Format

POST /api/payment/validate
Content-Type: application/x-www-form-urlencoded

id1=CUST12345&id2=INV98765&indial=1300123456&cli=0412345678&callid=1737590123_2038_1&svcref=PAYSERVICE01&tstamp=2026-01-22+14%3A30%3A45

POST JSON Format

POST /api/payment/validate
Content-Type: application/json

{
  "voffice": {
    "validate": {
      "indial": "1300123456",
      "cli": "0412345678",
      "callid": "1737590123_2038_1",
      "svcref": "PAYSERVICE01",
      "tstamp": "2026-01-22 14:30:45",
      "id1": "CUST12345",
      "id2": "INV98765",
      "id3": "REF001"
    }
  }
}

POST XML Format

POST /api/payment/validate
Content-Type: application/xml

<?xml version="1.0" encoding="UTF-8"?>
<voffice>
  <validate>
    <indial>1300123456</indial>
    <cli>0412345678</cli>
    <callid>1737590123_2038_1</callid>
    <svcref>PAYSERVICE01</svcref>
    <tstamp>2026-01-22 14:30:45</tstamp>
    <id1>CUST12345</id1>
    <id2>INV98765</id2>
    <id3>REF001</id3>
  </validate>
</voffice>

Response Formats (You Return)

Your backend can respond in JSON, XML, or plain text. TelcoEdge will parse all formats.

Validation Response Examples

JSON Response:

{
  "amount": 15000,
  "status": 1
}

XML Response:

<?xml version="1.0" encoding="UTF-8"?>
<response>
  <amount>15000</amount>
  <status>1</status>
</response>

Plain Text Response:

amount=15000
status=1

Receipt/Failure Response

For receipt and failure endpoints, any HTTP 2xx response is sufficient:

HTTP 200 OK

Or with body:

{
  "status": "received",
  "message": "Transaction recorded"
}

Configuration

Configure your backend endpoints in the payment service settings.

Basic Configuration

  • checkurl: Alive/health check endpoint Example: https://api.example.com/payment/check Example with placeholders: https://api.example.com/payment/check?service={indial}

  • validateurl: Validation endpoint Example: https://api.example.com/payment/validate Example with placeholders: https://api.example.com/payment/validate?customer={id1}&invoice={id2}

  • receipturl: Success callback Example: https://api.example.com/payment/receipt Example with placeholders: https://api.example.com/payment/receipt?ref={reference}&amount={amount}

  • failurl: Failure callback Example: https://api.example.com/payment/failure Example with placeholders: https://api.example.com/payment/failure?ref={reference}

Available placeholders: {id1}, {id2}, {id3}, {indial}, {cli}, {callid}, {svcref}, {tstamp}, {reference}, {amount}, {dollars}, {cents}, {receipt}, {transactionid}, {ccnum}, {ccexp}, etc.

  • apitype: Request format Values: POST+JSON, POST+XML, or GET

  • dformat: Timestamp format Example: %Y-%m-%d %H:%M:%S

Advanced Configuration

  • webuser: HTTP Basic Auth username Example: apiuser

  • webpass: HTTP Basic Auth password Example: secretpassword

  • apiuser: API-level auth username Example: api_username

  • apipass: API-level auth password Example: api_password

  • apiextra: Extra options (see below) Example: noproxy=1\nheaders=X-API-Version: 2.0

  • units: Amount units Values: cents (default) or dollars

API Extra Options

The apiextra field supports additional HTTP options (newline-separated).

Common Options

useragent=MyCompany Payment System
noproxy=1
headers=X-API-Version: 2.0
headers=X-Client-ID: ABC123

Option Descriptions:

  • useragent: Custom User-Agent string in HTTP requests
  • noproxy: Bypass proxy server (set to 1)
  • headers: Additional HTTP headers (can specify multiple times)

Payment ID Configuration

  • payidenabled_1: Enable payment ID 1 Default: 0

  • payidenabled_2: Enable payment ID 2 Default: 0

  • payidenabled_3: Enable payment ID 3 Default: 0

  • payidminlen_1: Minimum length for ID 1 Default: 1

  • payidmaxlen_1: Maximum length for ID 1 Default: 20

  • payidregex_1: Regex validation for ID 1 Default: (empty)

  • payidattempts_1: Retry attempts for ID 1 Default: 3

(Repeat for _2 and _3)

Amount Configuration

  • amountmode: How amount is determined Values: api, fixed, input

  • amountvalue: Fixed amount (if mode=fixed) Example: 15000

  • amountmin: Minimum amount (if mode=input) Example: 1000

  • amountmax: Maximum amount (if mode=input) Example: 50000

Amount Modes:

  • api - Get amount from validation endpoint response
  • fixed - Use configured fixed amount
  • input - Prompt caller to enter amount (within min/max range)

Integration Examples

Example 1: PHP Validation Endpoint

<?php
// /api/payment/validate.php

header('Content-Type: application/json');

// Get input (handle both JSON and query string)
$input = [];
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $json = file_get_contents('php://input');
    $data = json_decode($json, true);
    if (isset($data['voffice']['validate'])) {
        $input = $data['voffice']['validate'];
    }
} else {
    $input = $_GET;
}

$customerId = $input['id1'] ?? '';
$invoiceId = $input['id2'] ?? '';

// Lookup invoice in database
$pdo = new PDO('mysql:host=localhost;dbname=billing', 'user', 'pass');
$stmt = $pdo->prepare("
    SELECT amount_cents, status
    FROM invoices
    WHERE customer_id = ? AND invoice_id = ?
");
$stmt->execute([$customerId, $invoiceId]);
$invoice = $stmt->fetch(PDO::FETCH_ASSOC);

if (!$invoice) {
    // Invoice not found
    echo json_encode([
        'status' => 0,
        'error' => 'Invoice not found'
    ]);
    exit;
}

if ($invoice['status'] === 'paid') {
    // Already paid
    echo json_encode([
        'status' => 0,
        'error' => 'Invoice already paid'
    ]);
    exit;
}

// Return amount
echo json_encode([
    'status' => 1,
    'amount' => $invoice['amount_cents']
]);
?>

Example 2: Node.js Receipt Handler

// /api/payment/receipt
const express = require('express');
const app = express();

app.use(express.json());
app.use(express.urlencoded({ extended: true }));

app.post('/api/payment/receipt', async (req, res) => {
  try {
    // Extract payment data (handle both JSON and form data)
    let payment;
    if (req.body.voffice && req.body.voffice.payment) {
      payment = req.body.voffice.payment;
    } else {
      payment = req.body;
    }

    console.log('Payment received:', payment);

    // Update database
    await db.query(`
      UPDATE invoices
      SET
        status = 'paid',
        paid_amount = ?,
        payment_receipt = ?,
        payment_date = NOW(),
        gateway_response = ?,
        gateway_code = ?
      WHERE customer_id = ? AND invoice_id = ?
    `, [
      payment.amount,
      payment.receipt,
      payment.response,
      payment.responsecode,
      payment.id1,
      payment.id2
    ]);

    // Log transaction
    await db.query(`
      INSERT INTO payment_transactions
      (customer_id, invoice_id, amount, receipt, card_last4, cli, callid, tstamp)
      VALUES (?, ?, ?, ?, ?, ?, ?, ?)
    `, [
      payment.id1,
      payment.id2,
      payment.amount,
      payment.receipt,
      payment.ccnum.slice(-4),
      payment.cli,
      payment.callid,
      payment.tstamp
    ]);

    // Send confirmation email
    await sendEmail({
      to: getCustomerEmail(payment.id1),
      subject: 'Payment Confirmation',
      template: 'payment-success',
      data: payment
    });

    // Return acknowledgment
    res.status(200).json({
      status: 'received',
      message: 'Payment recorded successfully'
    });

  } catch (error) {
    console.error('Error processing payment:', error);
    res.status(500).json({
      status: 'error',
      message: 'Internal server error'
    });
  }
});

app.listen(3000);

Example 3: Python Validation with Amount Range

from flask import Flask, request, jsonify
import mysql.connector

app = Flask(__name__)

@app.route('/api/payment/validate', methods=['GET', 'POST'])
def validate_payment():
    # Get input data
    if request.method == 'POST':
        if request.is_json:
            data = request.json
            if 'voffice' in data and 'validate' in data['voffice']:
                input_data = data['voffice']['validate']
            else:
                input_data = data
        else:
            input_data = request.form.to_dict()
    else:
        input_data = request.args.to_dict()

    customer_id = input_data.get('id1')
    invoice_id = input_data.get('id2')

    # Database lookup
    conn = mysql.connector.connect(
        host='localhost',
        database='billing',
        user='user',
        password='pass'
    )
    cursor = conn.cursor(dictionary=True)

    cursor.execute("""
        SELECT
            amount_cents,
            min_payment_cents,
            status,
            due_date
        FROM invoices
        WHERE customer_id = %s AND invoice_id = %s
    """, (customer_id, invoice_id))

    invoice = cursor.fetchone()
    cursor.close()
    conn.close()

    if not invoice:
        return jsonify({
            'status': 0,
            'error': 'Invoice not found'
        })

    if invoice['status'] == 'paid':
        return jsonify({
            'status': 0,
            'error': 'Invoice already paid'
        })

    # Allow partial payments
    if invoice['min_payment_cents'] and invoice['min_payment_cents'] < invoice['amount_cents']:
        # Return range for caller to choose amount
        return jsonify({
            'status': 1,
            'minamount': invoice['min_payment_cents'],
            'maxamount': invoice['amount_cents']
        })
    else:
        # Fixed amount
        return jsonify({
            'status': 1,
            'amount': invoice['amount_cents']
        })

if __name__ == '__main__':
    app.run(port=5000)

Example 4: Alive/Health Check

@app.route('/api/payment/check', methods=['GET'])
def check_alive():
    """Simple health check endpoint"""
    try:
        # Check database connectivity
        conn = mysql.connector.connect(
            host='localhost',
            database='billing',
            user='user',
            password='pass',
            connect_timeout=5
        )
        conn.close()

        return ('OK', 200)
    except Exception as e:
        return ('Service Unavailable', 503)

Troubleshooting

API Not Being Called

Problem: TelcoEdge not calling your validation endpoint

Solutions:

  1. Verify validateurl is configured in payment service settings
  2. Check URL is accessible from TelcoEdge servers (not behind firewall)
  3. Test manually: curl -I https://yourdomain.com/api/payment/validate
  4. Review IVR logs for API call attempts and errors

Invalid Response

Problem: "API validation failed" message in IVR

Solutions:

  1. Ensure response includes status field (1=valid, 0=invalid)
  2. Check response format matches expected (JSON/XML/text)
  3. Verify HTTP response code is 200
  4. Test response with: curl https://yourdomain.com/api/payment/validate?id1=TEST

Timeout Errors

Problem: API calls timing out

Solutions:

  1. Optimize database queries (add indexes on customer_id, invoice_id)
  2. Cache frequently-accessed data
  3. Ensure response time < 5 seconds (10 second timeout)
  4. Use connection pooling for database
  5. Consider async processing for non-critical tasks

Authentication Failures

Problem: HTTP 401/403 errors

Solutions:

  1. Verify webuser and webpass configured correctly
  2. Check HTTP Basic Auth header format
  3. Test authentication: curl -u username:password https://...
  4. Whitelist TelcoEdge server IPs if using IP-based auth

Wrong Amount

Problem: IVR announces incorrect amount

Solutions:

  1. Verify units configuration (cents vs dollars)
  2. Check your backend returns amount in correct units
  3. Default is cents: 15000 = $150.00
  4. If using dollars: 150.00 = $150.00
  5. Test: Call with known invoice, verify amount announced

Receipt Not Received

Problem: Not receiving success/failure callbacks

Solutions:

  1. Verify receipturl and failurl configured
  2. Check URLs are publicly accessible (not localhost)
  3. Ensure endpoint returns HTTP 2xx response
  4. Check firewall allows incoming connections from TelcoEdge
  5. Monitor your endpoint logs during test call

Appendix

Summary Codes

  • 0: Approved - Payment successful
  • 1: Declined - Payment declined by issuer
  • 2: Error - System or gateway error
  • 95: Merchant Error - Merchant configuration error
  • 96: Duplicate - Duplicate transaction
  • 97: Validation Error - Card validation failed
  • 99: Verification Error - Data verification failed
  • 999: Gateway Error - Gateway communication error

Gateway Response Codes

  • 00: Approved - Payment successful
  • 01: Refer to card issuer - Contact bank
  • 05: Do not honour - Try different card
  • 12: Invalid transaction - Check details
  • 14: Invalid card number - Check card number
  • 51: Insufficient funds - Insufficient funds
  • 54: Expired card - Card expired
  • 91: Issuer unavailable - Try again later