Skip to main content

Batch Processing Integration Guide

Upload a CSV file to CommBank's SFTP service to process multiple payments in a single batch — ideal for recurring billing, bulk supplier payments, and scheduled transaction runs.

Icon
Before you begin

What you'll need:

  • SFTP credentials from Connected Payments (hostname, username, password or SSH key, directory path)
  • sharedSecret - Your shared secret for generating the hashedUserName authentication field
  • customerID - Your Connected Payments hierarchy ID
  • Existing card tokens for processing payments — see Tokenisation

IP whitelisting is required prior to using SFTP. Contact [email protected] to obtain access and request whitelisting if you haven't already.

Code samples: Code samples within this document are provided for reference purposes only and are not intended for production use.


How it works

Flow:

  1. Prepare a CSV file with your transactions following the naming and field rules below
  2. Generate hashedUserName using your shared secret (HMAC-SHA256)
  3. Upload the file to your assigned SFTP directory
  4. The batch service picks it up, validates it, and processes each row
  5. Results (approved/declined per transaction) appear in the Connected Payments dashboard

Quick start

Step 1: Name your file

Filenames must follow this exact pattern — files that don't match are rejected.

[customerID]-[yyyymmdd]-[suffix].csv
ComponentDescriptionExample
customerIDYour CommBank hierarchy IDdemoMerchant
yyyymmddProcessing date20260531
suffixUnique batch referencebatchDemo
info

Your assembled filename will look like this:

demoMerchant-20260531-batchDemo.csv

Rules:

  • The full filename must be unique — never reuse a filename
  • The suffix must be unique per customer — duplicate suffixes are rejected
  • The date cannot be in the past — use today or a future date
  • Future dates are valid — the file queues and processes on that date

Step 2: Generate hashedUserName

hashedUserName is an HMAC-SHA256 digest of your batch username using your shared secret. Calculate it once and reuse the same value on every row in the file.

Server-side only — Never expose sharedSecret in client code or CSV files stored in insecure locations.

Node.js
const crypto = require("crypto");

const hashedUserName = crypto
.createHmac("sha256", process.env.BATCH_SHARED_SECRET)
.update("your-batch-username")
.digest("hex");
PHP
$hashedUserName = hash_hmac(
'sha256',
'your-batch-username',
getenv('BATCH_SHARED_SECRET')
);
Python
import hmac, hashlib, os

hashed_username = hmac.new(
os.environ['BATCH_SHARED_SECRET'].encode(),
'your-batch-username'.encode(),
hashlib.sha256
).hexdigest()
C#
using System.Security.Cryptography;
using System.Text;

using (var hmac = new HMACSHA256(Encoding.UTF8.GetBytes(Environment.GetEnvironmentVariable("BATCH_SHARED_SECRET"))))
{
byte[] hash = hmac.ComputeHash(Encoding.UTF8.GetBytes("your-batch-username"));
string hashedUserName = BitConverter.ToString(hash).Replace("-", "").ToLower();
}

Step 3: Build your CSV

Every CSV requires a header row followed by one data row per transaction. Use stored card tokens for all batch processing.

cardToken,merchReference,amount,txnType,hashedUserName
token_abc123xyz,SUB-001,9900,1,abc123def456...
token_def456uvw,SUB-002,9900,1,abc123def456...

Required fields:

FieldDescriptionFormatExample
cardTokenStored card token or aliasToken stringtoken_abc123xyz
merchReferenceUnique reference per transactionAlphanumericSUB-001
amountAmount in centsInteger9900 (= $99.00)
txnTypeTransaction type (numeric)Integer1 (Purchase)
hashedUserNameHMAC-SHA256 of your batch usernameHex stringabc123def456...

Optional fields:

FieldDescriptionRequired when
cardHolderNameCardholder nameOptional but recommended
txnIdOriginal transaction IDRequired for refund and complete
metadata.*Custom key-value data (e.g. metadata.invoice)Never required
note

For merchReference, each row must have a unique value — duplicates will be rejected. Use a format like INV-{id} or SUB-{customerId}-{date} to guarantee uniqueness.

Step 4: Upload via SFTP

Connect to the SFTP server using the credentials provided by Connected Payments and place the file in your assigned directory.

Command line (Linux / macOS)
sftp [email protected]
cd /path/to/batch/directory
put demoMerchant-20260531-batchDemo.csv
quit
Node.js (automated)
const Client = require("ssh2-sftp-client");
const sftp = new Client();

await sftp.connect({
host: "sftp-host.com",
port: 22,
username: process.env.SFTP_USER,
password: process.env.SFTP_PASSWORD,
});

await sftp.put(
"demoMerchant-20260531-batchDemo.csv",
"/batch/dir/demoMerchant-20260531-batchDemo.csv",
);

await sftp.end();
Python (automated)
import paramiko, os

transport = paramiko.Transport(('sftp-host.com', 22))
transport.connect(
username=os.environ['SFTP_USER'],
password=os.environ['SFTP_PASSWORD']
)
sftp = paramiko.SFTPClient.from_transport(transport)
sftp.put('demoMerchant-20260531-batchDemo.csv', '/batch/dir/demoMerchant-20260531-batchDemo.csv')
sftp.close()
transport.close()
PHP (automated)
$connection = ssh2_connect('sftp-host.com', 22);
ssh2_auth_password($connection, getenv('SFTP_USER'), getenv('SFTP_PASSWORD'));
$sftp = ssh2_sftp($connection);

$localFile = 'demoMerchant-20260531-batchDemo.csv';
$remotePath = '/batch/dir/demoMerchant-20260531-batchDemo.csv';

$stream = fopen("ssh2.sftp://{$sftp}{$remotePath}", 'w');
fwrite($stream, file_get_contents($localFile));
fclose($stream);

GUI clients such as FileZilla or WinSCP also work — connect on port 22 using the SFTP protocol and drag the file to your directory.

Step 5: Check results

Log in to the Connected Payments dashboard, navigate to Batch Processing or Transactions, and filter by your batch reference. Each transaction row will show its status (Approved / Declined), response code, and transaction ID.


Complete examples

View full Node.js implementation — Automated recurring batch
const crypto = require("crypto");
const Client = require("ssh2-sftp-client");
const fs = require("fs");

const CONFIG = {
customerID: "demoMerchant",
batchUsername: "your-batch-username",
sharedSecret: process.env.BATCH_SHARED_SECRET,
sftpHost: "sftp-host.com",
sftpUser: process.env.SFTP_USER,
sftpPassword: process.env.SFTP_PASSWORD,
sftpDir: "/batch/dir/",
};

// Step 1: Generate hashedUserName
const hashedUserName = crypto
.createHmac("sha256", CONFIG.sharedSecret)
.update(CONFIG.batchUsername)
.digest("hex");

// Step 2: Build CSV from subscription data
function buildBatchCSV(subscriptions) {
const header = "cardToken,merchReference,amount,txnType,hashedUserName";
const rows = subscriptions.map(
(sub) => `${sub.token},${sub.reference},${sub.amount},1,${hashedUserName}`,
);
return [header, ...rows].join("\n");
}

// Step 3: Generate filename
const today = new Date().toISOString().slice(0, 10).replace(/-/g, "");
const suffix = `recurring-${Date.now()}`;
const filename = `${CONFIG.customerID}-${today}-${suffix}.csv`;

// Step 4: Write and upload
async function processBatch(subscriptions) {
const csv = buildBatchCSV(subscriptions);
fs.writeFileSync(filename, csv);

const sftp = new Client();
await sftp.connect({
host: CONFIG.sftpHost,
port: 22,
username: CONFIG.sftpUser,
password: CONFIG.sftpPassword,
});

await sftp.put(filename, `${CONFIG.sftpDir}${filename}`);
await sftp.end();

console.log(`Batch uploaded: ${filename}`);
}

// Example usage
processBatch([
{ token: "token_abc123xyz", reference: "SUB-001", amount: 9900 },
{ token: "token_def456uvw", reference: "SUB-002", amount: 9900 },
]);
View full Python implementation — Automated recurring batch
import hmac
import hashlib
import csv
import os
import paramiko
from datetime import datetime

CONFIG = {
'customer_id': 'demoMerchant',
'batch_username': 'your-batch-username',
'shared_secret': os.environ['BATCH_SHARED_SECRET'],
'sftp_host': 'sftp-host.com',
'sftp_user': os.environ['SFTP_USER'],
'sftp_password': os.environ['SFTP_PASSWORD'],
'sftp_dir': '/batch/dir/'
}

# Step 1: Generate hashedUserName
hashed_username = hmac.new(
CONFIG['shared_secret'].encode(),
CONFIG['batch_username'].encode(),
hashlib.sha256
).hexdigest()

# Step 2: Build CSV
def build_batch_csv(subscriptions, filename):
with open(filename, 'w', newline='') as f:
writer = csv.writer(f)
writer.writerow(['cardToken', 'merchReference', 'amount', 'txnType', 'hashedUserName'])
for sub in subscriptions:
writer.writerow([sub['token'], sub['reference'], sub['amount'], 1, hashed_username])

# Step 3: Generate filename
today = datetime.now().strftime('%Y%m%d')
suffix = f'recurring-{int(datetime.now().timestamp())}'
filename = f"{CONFIG['customer_id']}-{today}-{suffix}.csv"

# Step 4: Write and upload
def process_batch(subscriptions):
build_batch_csv(subscriptions, filename)

transport = paramiko.Transport((CONFIG['sftp_host'], 22))
transport.connect(username=CONFIG['sftp_user'], password=CONFIG['sftp_password'])
sftp = paramiko.SFTPClient.from_transport(transport)
sftp.put(filename, f"{CONFIG['sftp_dir']}{filename}")
sftp.close()
transport.close()

print(f'Batch uploaded: {filename}')

# Example usage
process_batch([
{'token': 'token_abc123xyz', 'reference': 'SUB-001', 'amount': 9900},
{'token': 'token_def456uvw', 'reference': 'SUB-002', 'amount': 9900},
])

Configuration reference

Transaction types

ValueDescriptionRequires txnId
1Purchase — Standard paymentNo
9Capture — Capture pre-authorized fundsYes
10Pre-Auth — Hold funds without chargingNo
20Refund — Refund against original transactionYes

Parameters

FieldTypeDescriptionExample
cardTokenStringStored card token or aliastoken_abc123xyz
merchReferenceStringUnique reference per transactionINV-12345
amountIntegerAmount in cents (e.g. 10000 = $100.00)10000
txnTypeIntegerTransaction type (numeric value)1
hashedUserNameStringHMAC-SHA256 of your batch usernameabc123def456...

File naming

ComponentDescriptionExample
customerIDYour CommBank hierarchy IDdemoMerchant
yyyymmddProcessing date (today or future)20260531
suffixUnique batch reference (unique per customer)batchDemo

Format: [customerID]-[yyyymmdd]-[suffix].csv


Security checklist

  • sharedSecret stored in environment variables — never hardcoded
  • SFTP credentials stored securely — prefer SSH keys over passwords
  • Batch files use card tokens only — never include raw card numbers
  • Uploaded files are archived and access is audited

Troubleshooting

For a full reference, see the Troubleshooting Guide in the FAQ & Support section.


Testing

Use the sandbox SFTP environment to test your batch files before processing live transactions. Never use real card numbers in test batches — use test cards and tokens instead.

Verification steps:

  1. Generate hashedUserName using your sandbox shared secret
  2. Build a CSV with test card tokens and a small number of rows
  3. Upload to your sandbox SFTP directory
  4. Check results in the Connected Payments dashboard under Batch Processing

For full test details, see the Testing Guide.