Process an Online Card Purchase

Learn how to accept card-not-present payments for your business. This guide shows you how to process a basic card payment, handle responses, and manage the payment lifecycle.

The Purchase Intent

A Purchase intent combines authorization and capture in a single step, immediately processing the payment. Use this when you need to charge a card immediately, like for e-commerce transactions or digital goods.

Quick Start Example

curl -X POST https://api.pxpfinancial.net/api/v1/transactions \
-H "Content-Type: application/json" \
-H "Authorization: Bearer {your-api-key}" \
-d '{
  "merchant": "MERCHANT-1",
  "site": "SITE-1",
  "merchantTransactionId": "tx_123",
  "transactionMethod": {
    "intent": "Purchase",
    "entryType": "Ecom",
    "fundingType": "Card"
  },
  "fundingData": {
    "card": {
      "primaryAccountNumber": "4111111111111111",
      "expiryMonth": "03",
      "expiryYear": "2025",
      "cardVerificationCode": "123"
    }
  },
  "amounts": {
    "transactionValue": 1999,
    "currencyCode": "EUR"
  }
}'

Required Parameters

The following parameters are required to process a payment:

Authentication

  • Your API key in the Authorization header

Business Information

  • merchant: Your merchant identifier
  • site: Your site identifier
  • merchantTransactionId: A unique identifier for this transaction

Payment Details

  • Card number
  • Expiry date (month and year)
  • Security code (CVV/CVC)
  • Transaction amount and currency

Build the Payment Request

Start by creating a payment with the minimum required information:

const payment = await pxp.payments.create({
  merchantTransactionId: generateUniqueId(),
  transactionMethod: {
    intent: 'Purchase',
    entryType: 'Ecom',
    fundingType: 'Card'
  },
  fundingData: {
    card: {
      primaryAccountNumber: '4111111111111111',
      expiryMonth: '03',
      expiryYear: '2025',
      cardVerificationCode: '123'
    }
  },
  amounts: {
    transactionValue: 1999,  // €19.99
    currencyCode: 'EUR'
  }
});

Handle the Response

if (payment.state === 'Authorised') {
  // Payment successful
  const transactionId = payment.systemTransactionId;
  // Store payment.systemTransactionId for future reference
} else {
  // Handle payment failure
  console.error(payment.stateData.message);
}

Payment Response Object

A successful payment returns the following information:

{
  "systemTransactionId": "1ed768bb-e88a-4636-91ae-67927ccbb02b",
  "merchantTransactionId": "tx_123",
  "state": "Authorised",
  "stateMessage": "Transaction Authorised",
  "approvalCode": "123456",
  "fundingSource": "Credit",
  "providerResponse": {
    "code": "1001",
    "message": "Transaction Authorised with Authority Code: 123456"
  }
}

Add Additional Payment Details

For better fraud prevention and higher approval rates, include additional information:

const payment = await pxp.payments.create({
  // ... basic payment details ...
  
  // Add customer information
  shopper: {
    firstName: 'Jenny',
    lastName: 'Rosen',
    email: '[email protected]'
  },
  
  // Add billing address for AVS checks
  addressVerification: {
    houseNumberOrName: '123',
    postalCode: 'SW1A 1AA',
    country: 'GB'
  },
  
  // Add security data
  shopperSecurityData: {
    ipAddress: '192.0.2.1',
    deviceFingerprint: 'your-device-fingerprint'
  }
});

Test the Integration

Use these test card numbers to simulate different scenarios:

// Successful payment
4111111111111111

// Payment declined
4000000000000002

// Card expired
4000000000000119

Next Steps

Now that you can process basic payments, you might want to:

  1. Add 3D Secure authentication
  2. Implement recurring payments
  3. Handle refunds
  4. Manage webhooks

Handling Errors

When a payment fails, you'll receive a state of "Refused" or "Error" along with additional details:

try {
  const payment = await pxp.payments.create({
    // payment details
  });
} catch (error) {
  if (error.state === 'Refused') {
    // Handle declined payment
    console.log(error.stateData.message);
  } else if (error.state === 'Error') {
    // Handle system error
    console.log(`Error ${error.stateData.code}: ${error.stateData.message}`);
  }
}

Best Practices

  1. Generate Unique References

    const merchantTransactionId = `tx_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
  2. Handle Timeouts

    const payment = await pxp.payments.create({
      // ... payment details
    }, {
      timeout: 10000 // 10 seconds
    });
  3. Implement Idempotency
    Always use the same merchantTransactionId when retrying failed requests.

  4. Verify Amounts

    // Amount should be in minor units (cents/pence)
    const amount = Math.round(19.99 * 100); // 1999

Support

Need help? We're here for you: