Skip to main content

Form-Encoded Proxy Requests

Forward form-encoded requests to payment processors like Elavon.

Request Format

POST /proxy/transaction
Content-Type: application/x-www-form-urlencoded
X-Token: tok_a1b2c3d4e5f6
X-Proxy-URL: https://api.elavon.com/transaction
X-CVC-Session-ID: 550e8400-e29b-41d4-a716-446655440000

ssl_card_number=${cardNumber}&ssl_exp_date=${expirationMonth}${expirationYear}&ssl_cvv2cvc2=${cvv}&ssl_amount=10.00

Alternative: Headers

Pass all metadata via headers:
HeaderRequiredDescription
Content-TypeYesapplication/x-www-form-urlencoded
X-TokenYesToken to use
X-Proxy-URLYesTarget endpoint
X-CVC-Session-IDNoCVC session for CVV

Placeholders

Placeholders work in form data:
card_number=${cardNumber}&exp_month=${expirationMonth}&exp_year=${expirationYear}&cvv=${cvv}

Examples

Elavon/Converge

curl -X POST https://pci-vault-hrhwdgc4akhse3bs.eastus-01.azurewebsites.net/proxy/transaction \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -H "X-API-Key: YOUR_OZURA_API_KEY" \
  -H "X-Token: tok_a1b2c3d4e5f6" \
  -H "X-Proxy-URL: https://api.convergepay.com/VirtualMerchantDemo/processxml.do" \
  -H "X-CVC-Session-ID: session_xyz" \
  -d 'ssl_merchant_id=YOUR_MERCHANT_ID&ssl_user_id=YOUR_USER_ID&ssl_pin=YOUR_PIN&ssl_transaction_type=ccsale&ssl_card_number=${cardNumber}&ssl_exp_date=${expirationMonth}${expirationYear}&ssl_cvv2cvc2=${cvv}&ssl_amount=10.00'

Authorize.Net (AIM)

curl -X POST https://pci-vault-hrhwdgc4akhse3bs.eastus-01.azurewebsites.net/proxy/transaction \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -H "X-API-Key: YOUR_OZURA_API_KEY" \
  -H "X-Token: tok_a1b2c3d4e5f6" \
  -H "X-Proxy-URL: https://test.authorize.net/gateway/transact.dll" \
  -H "X-CVC-Session-ID: session_xyz" \
  -d 'x_login=YOUR_API_LOGIN&x_tran_key=YOUR_TRANS_KEY&x_type=AUTH_CAPTURE&x_amount=10.00&x_card_num=${cardNumber}&x_exp_date=${expirationMonth}/${expirationYear}&x_card_code=${cvv}&x_delim_data=TRUE&x_delim_char=|'

NMI

curl -X POST https://pci-vault-hrhwdgc4akhse3bs.eastus-01.azurewebsites.net/proxy/transaction \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -H "X-API-Key: YOUR_OZURA_API_KEY" \
  -H "X-Token: tok_a1b2c3d4e5f6" \
  -H "X-Proxy-URL: https://secure.networkmerchants.com/api/transact.php" \
  -H "X-CVC-Session-ID: session_xyz" \
  -d 'security_key=YOUR_SECURITY_KEY&type=sale&ccnumber=${cardNumber}&ccexp=${expirationMonth}${expirationYear}&cvv=${cvv}&amount=10.00'

Response

Form responses vary by gateway:

Delimited Response

{
  "success": true,
  "proxy_response": {
    "status_code": 200,
    "headers": {
      "content-type": "text/plain"
    },
    "body": "1|1|1|This transaction has been approved|ABC123|Y|1234567890||Test|10.00|CC|auth_capture"
  }
}

Name-Value Pair Response

{
  "success": true,
  "proxy_response": {
    "status_code": 200,
    "headers": {
      "content-type": "text/plain"
    },
    "body": "ssl_result=0&ssl_result_message=APPROVED&ssl_txn_id=123456789"
  }
}

Parsing Responses

Delimited

const response = await fetch('/proxy/transaction', { ... });
const data = await response.json();

if (data.success) {
  const parts = data.proxy_response.body.split('|');
  const approved = parts[0] === '1';
  const transactionId = parts[6];
}

Name-Value Pairs

const response = await fetch('/proxy/transaction', { ... });
const data = await response.json();

if (data.success) {
  const params = new URLSearchParams(data.proxy_response.body);
  const result = params.get('ssl_result');
  const message = params.get('ssl_result_message');
}

URL Encoding

Special characters in values are automatically URL-encoded:
CharacterEncoded
Space%20 or +
&%26
=%3D
+%2B
Card numbers don’t contain these, but other fields might.

Date Format Variations

Different gateways expect different expiration formats:
FormatExamplePlaceholder Combination
MMYY1225${expirationMonth}${expirationYear}
MM/YY12/25${expirationMonth}/${expirationYear}
MMYYYY122025${expirationMonth}${expirationYear} (4-digit year)
YYYY-MM2025-12${expirationYear}-${expirationMonth}
Check your gateway’s documentation for the expected format.

Best Practices

1. URL-Encode Properly

Ensure special characters in non-card fields are encoded:
const description = encodeURIComponent("Order #123 & extras");

2. Check Response Format

Gateways return different formats:
  • Delimited (pipe, comma)
  • Name-value pairs
  • XML
  • JSON

3. Handle Gateway-Specific Errors

// Elavon
if (result.ssl_result !== '0') {
  throw new Error(result.ssl_result_message);
}

// Authorize.Net
if (parts[0] !== '1') {
  throw new Error(parts[3]); // Response reason text
}

Next Steps