Developer Guides

Overview

Paystream provides a simple to use REST API. It is designed to be simple, have predictable URLs and uses HTTP response codes to indicate errors. In addition to this it uses HTTP features such as Basic Authentication and HTTP verbs (GET, PUT, POST etc). This means that it is highly compatible with most HTTP clients including Net::HTTP, cURL and System.Net.WebClient and httplib.

Paystream supports JSON for data transmitted and received to the API. It is recommended, if you are having problems, to test the well-formedness of your data against a lint tool, such as JSONLint (https://jsonlint.com/).

Note: It is important that you ensure no sensitive data is included in the data you are validating - this includes card numbers and CVV/CVN numbers. We also recommend that you replace card holder names with example data, however names with diacritics, umlauts or accents may cause validation issues, so remember this while you are testing.

Authentication

Authentication with the Paystream API is via HTTP Basic Authentication. When your account is setup you are provided with two sets of credentials - one for the test environment (also known as the Sandbox), and one for the live system. Your test username will always be prefixed with TEST

API request *must* be made over HTTPS - any requests over HTTP will fail. All requests require authentication.

It is important to note that your username is *not* case sensitive however your API token (password) is.

Example

$ curl https://gateway.sandbox.fatzebra.com.au/v1.0/purchases -u TEST:TEST

Errors

Paystream will return a HTTP response code to indicate whether the request was successful or failed.

The following HTTP response codes are used by Paystream:

  • HTTP 200 (OK) - This indicates the request was successfully completed.
  • HTTP 400 (Bad Data) - Indicates bad data was received.
  • HTTP 401 (Unauthorized) - Indicates your API credentials were not valid.
  • HTTP 403 (Forbidden) - The resource you were requesting is not available for your credentials. You will most commonly see this is you are attempting to fetch a payment or refund created by your live credentials with your test credentials.
  • HTTP 404 (Not Found) - This indicates that the requested object was not found.
  • HTTP 500 (Server Error) - A problem occurred processing your request.
  • HTTP 501 (Not Implemented) - This indicates there was a problem processing your request, possibly with your payload.

Responses

The response data from Paystream follows the following pattern:

  • successful: boolean (indicates if the operation was successful or failed)
  • response: hash (data from the operation if successful)
  • test: boolean (indicates if the gateway is in test mode or not)
  • errors: array (any errors from the operation - if the successful field is false this field should be checked)

Example

{
    "successful": false,
    "response": {
        "test": true
    },
    "errors": ["Invalid Card Number"]
} 

Test Card Numbers

In the test environment (sandbox, or sending test: true) there are a predefined set of cards and values you can use to receive an expected response:

Number Outcome
MasterCard 5123 4567 8901 2346 Approved
5313 5810 0012 3430 Declined
VISA 4005 5500 0000 0001 Approved
4557 0123 4567 8902 Declined
AMEX 3456 7890 1234 564 Approved
3714 4963 5398 431 Declined
JCB 3530 1113 3330 0000 Approved
3566 0020 2036 0505 Declined

What's the difference between Test and Sandbox?

There are two test modes in the Paystream system - one is a sandbox environment and the other is a test mode flag.

The Sandbox Environment is an identical copy of the live environment which is 100% functional except for communicating with the banks.

The Test Mode Flag is used to switch the live environment into test mode. If test: true is sent with your request your transactions will be executed in the live environment, but not communicate with the bank backends. This mode is useful for testing changes to your live website.

Purchases

Creating a Purchase

In order to create a purchase you must submit the following details:

Either
  • Card Holder (string)
  • Card Number (string, numerical, 13 to 16 digits)
  • Card Expiry (string, mm/yyyy format)
  • CVV (numerical, 3 or 4 digits)
Or
  • Card Token (String)

Definition

Authentication: Basic xxxxxxxxxxxxx
POST /v1.0/purchases HTTP/1.1

Example Request

$ curl https://gateway.sandbox.fatzebra.com.au/v1.0/purchases -u TEST:TEST -d" \
    { \
        \"card_holder\": \"Jim Smith\", \
        \"card_number\": \"5123456789012346\", \
        \"card_expiry\": \"05/2023\", \
        \"cvv\": \"987\", \
        \"amount\": 1000, \
        \"reference\": \"ORD98976\", \
        \"customer_ip\": \"111.222.111.123\" \
    }"

Responses

Successful — HTTP 200
{
  "successful": true,
  "response": {
    "authorization": 1384819815,
    "id": "071-P-HZGZ9C4U",
    "card_number": "512345XXXXXX2346",
    "card_holder": "Jim Smith",
    "card_expiry": "2023-05-31",
    "card_token": "1tyyuywf",
    "amount": 1000,
    "decimal_amount": 10.0,
    "successful": true,
    "message": "Approved",
    "reference": "ORD9897615716",
    "currency": "AUD",
    "settlement_date": "2013-11-20",
    "transaction_date": "2013-11-19T11:10:15+11:00",
  },
  "errors": [

  ],
  "test": true
}
Failed (bad data) — HTTP 400
{
    "successful": false,
    "response": {
        "test": true
    },
    "errors": ["Invalid Card Number"]
}
Failed (declined card) — HTTP 200
{
  "successful": true,
  "response": {
    "authorization": 1384819972,
    "id": "071-P-5BYLEA3E",
    "card_number": "444433XXXXXX1111",
    "card_holder": "Jim Smith",
    "card_expiry": "2023-05-31T23:59:59+10:00",
    "card_token": "v15njdgu",
    "amount": 1000,
    "decimal_amount": 10.0,
    "successful": false,
    "message": "Declined",
    "reference": "ORD9897622146",
    "currency": "AUD",
    "settlement_date": "2013-11-20",
    "transaction_date": "2013-11-19T11:12:52+11:00",
  },
  "errors": [

  ],
  "test": true
}

Retrieve a Purchase

Definition

Authentication: Basic xxxxxxxxxxxxx
GET /v1.0/purchases/{PURCHASE_ID} HTTP/1.1

Example Request

$ curl https://gateway.sandbox.fatzebra.com.au/v1.0/purchases/001-P-YH8JHU7 -u TEST:TEST

Responses

Successful — HTTP 200
{
    "successful": true,
    "response": {
        "authorization": "55355",
        "id": "001-P-YH8JHU7",
        "card_number": "444433XXXXXX1111",
        "card_holder": "John Smith",
        "card_expiry": "10/2011",
        "amount": 349,
        "authorized": true,
        "reference": "ABC123",
        "message": "Approved",
    },
    "test": true
    "errors": []
}
Failed (not found) — HTTP 404
{
    "successful": false,
    "response": null,
    "test": true
    "errors": ["Purchase not found"]
}
Failed (Permission Denied) — HTTP 403
{
  "successful": false,
  "response": null,
  "test": true,
  "errors": ["You do not have permissions to access this record"]
}
Direct Post allows merchants to host and fully customise the look and feel of their payment page while outsourcing much of their PCI DSS Compliance requirements to Paystream. The credit card details are posted from a form on the merchants website directly to the Paystream payment gateway server. The customer is then redirected back to a result page on the merchants website.

Payment URL's

Test: https://gateway.sandbox.fatzebra.com.au/v2/purchases/direct/[username]
Live: https://gateway.fatzebra.com.au/v2/purchases/direct/[username]

Transaction Fields
  • card_holder
  • card_number
  • expiry_month
  • expiry_year
  • cvv
Hidden Fields
  • reference - the purchase reference (e.g. invoice or order number)
  • amount - the purchase amount
  • currency - the currency for the transaction
  • return_path - the URL to return the customer to on completion
  • verification - please see below

About Verification

In order to ensure these values are not changed a verification value is also included, which is determined by the following:

hmac_md5(shared_secret, "reference:amount:currency:return_path")

View An Example

Return Values

Upon completion of the transaction (or in the event of an error) the customer will be returned to your return path URL with a number of parameters, including a verification code. Please see below.

  • r - the return code (see table in top right)
  • successful - indicates if the transaction was successful or not
  • amount - the amount of the transaction, as an integer
  • currency - the transaction currency
  • id - the transaction ID
  • token - the card token for future use (e.g. tokenized payments)
  • verification - the verification, detailed below
  • message - the transaction result message. If declined this will have details such as 'insufficient funds' or similar
  • card_holder - the card holders name
  • card_number - (masked - first 6 and last 4)
  • card_expiry - the credit card expiry date (mm/yyyy)
  • reference - the transaction reference

In order to ensure these values are not changed a verification value is also included, which is determined by the following:

hmac_md5(shared_secret, "r:successful:amount:currency:id:token")

Echo Parameters

In addition to the parameters mentioned above, merchants can pass additional information fields which they would like returned in the transaction response.

To use these simply include them in your form using the following format for the field name echo[your_param_name] and they will be included in the response URI.

Duplicate Transaction Attempts

When a Reference not unique (96) error is returned, the status of the original transaction will be returned. This is helpful for handling double-post situations and removes the need to query the Paystream API for the transaction details.

The transaction details returned include all the values listed above, however they are nested within the existing parameter. (For example: existing[id]=187-P-AJ8HY87K )

Token Payments

Tokenizing a Card

Definition

Authentication: Basic xxxxxxxxxxxxx
POST /v1.0/credit_cards HTTP/1.1

Example Request

$ curl https://gateway.sandbox.fatzebra.com.au/v1.0/credit_cards -u TEST:TEST -d" \
  {
    \"card_number\": \"5123456789012346\", \
    \"card_holder\": \"Bob Smith\", \
    \"card_expiry\": \"05/2023\", \
    \"cvv\": \"987\" \
  }"

Responses

Successful — HTTP 200
{
  "successful": true,
  "response": {
    "token": "e1q7dbj2",
    "card_holder": "Bob Smith",
    "card_number": "XXXXXXXXXXXX2346",
    "card_expiry": "2023-05-31T23:59:59+10:00",
    "authorized": true,
    "transaction_count": 0
  },
  "errors": [

  ],
  "test": true
}

Create a Purchase with a Token

If you have a token you may use this in lieu of the card details in order to complete a transaction. If you have the customer CVV (submitted for this transaction - note, you should never store the CVV) you should provide it, however if the card has previously been tokenised, you may proceed without it.

Definition

Authentication: Basic xxxxxxxxxxxxx
POST /v1.0/purchases HTTP/1.1

Example Request

$ curl https://gateway.sandbox.fatzebra.com.au/v1.0/purchases -u TEST:TEST -d" \
  {
    \"card_token\": \"a1bnhj76\", \
    \"amount\": 3490, \
    \"reference\": \"ORD98976\", \
    \"customer_ip\": \"111.222.111.123\" \
  }"

Responses

Successful — HTTP 200
{
    "successful": true,
    "response": {
        "authorization": "55355",
        "id": "001-P-12345AA",
        "card_number": "XXXXXXXXXXXX1111",
        "card_holder": "John Smith",
        "card_expiry": "10/2021",
        "card_token": "a1bhj98j",
        "amount": 349,
        "authorized": true,
        "reference": "ABC123",
        "message": "Approved",
    },
    "test": true
    "errors": []
}
Unsuccessful (Invalid Token) — HTTP 400
{
  "successful": false,
  "response": {},
  "errors": [
    "Card a1bhj98j could not be found"
  ],
  "test": true
}
Failed (declined card) — HTTP 200
{
    "successful": true, // This indicates that the API request was successful
    "response": {
        "authorization_id": null,
        "id": null,
        "card_number": "XXXXXXXXXXXX1111",
        "card_holder": "John Smith",
        "card_expiry": "10/2021",
        "amount": 100,
        "authorized": false,
        "reference": "ABC123",
        "message": "Card Declined - check with issuer",
    },
    "test": true
    "errors": [] 
}

Recurring Purchases

Creating a Plan

To create a new plan the following details are required:

  • Name
  • Reference (your internal reference - this will be used to look up the plan)
  • Description
  • Amount (this is the amount charged for each time the plan is billed)

Definition

Authentication: Basic xxxxxxxxxxxxx
POST /v1.0/plans HTTP/1.1

Example Request

$ curl https://sandbox.gateway.fatzebra.com.au/v1.0/plans -u TEST:TEST -d " \
  {
    \"name\": \"Gold Membership\",
    \"amount\": 2399,
    \"reference\": \"gold-1\",
    \"description\": \"Gold level membership\"
  }"

Responses

Successful — HTTP 201
  {
      "successful": true,
      "response": {
          "name": "Gold Membership",
          "id": "001-PL-VQPMB92P",
          "amount": 2399,
          "reference": "gold-1",
          "description": "Gold level membership"
      },
      "errors": [],
      "test": true
  }

Failed (bad data) — HTTP 400
{
  "successful": false,
  "response": {
    "name": "Gold Membership",
    "id": null,
    "amount": 2399,
    "reference": "gold-1",
    "description":""
  },
  "errors": [
    "Description can't be blank"
  ],
  "test": true
}

Retrieve all Plans

Definition

Authentication: Basic xxxxxxxxxxxxx
GET /v1.0/plans.json HTTP/1.1

Example Request

$ curl https://sandbox.gateway.fatzebra.com.au/v1.0/plans.json -u TEST:TEST

Responses

Successful — HTTP 200
{
  "successful": true,
  "response": [
    {
      "name": "Gold Membership",
      "id": "067-PL-KFG3OXX9",
      "amount": 2399,
      "reference" :"gold-1",
      "description" :"Gold level membership",
      "currency": "AUD",
      "subscription_count": 0
    }
  ],
  "errors": [],
  "test": false,
  "records": 1,
  "total_records": 1,
  "pages": 1,
  "current_page": 1
}

Retrieve a Plan

Definition

Authentication: Basic xxxxxxxxxxxxx
GET /v1.0/plans/{PLAN_ID} HTTP/1.1

Example Request

$ curl https://sandbox.gateway.fatzebra.com.au/v1.0/plans/001-PL-ZX8J9K.json -u TEST:TEST

Responses

Successful — HTTP 200
{
  "successful": true,
  "response": {
    "name": "Gold Membership",
    "id": "001-PL-VQPMB92P",
    "amount": 2399,
    "reference": "gold-1",
    "description": "Gold level membership"
  },
  "errors": [],
  "test": true
}
Failed (Not Found) — HTTP 404
{
    "successful": false,
    "response": null,
    "test": true
    "errors": ["Record not found"]
}

Update a Plan

Note: You can only update a plans name or description - the reference or amount can not be changed once the plan is in use.

Definition

Authentication: Basic xxxxxxxxxxxxx
PUT /v1.0/plans/{PLAN_ID} HTTP/1.1

Example Request

$ curl https://sandbox.gateway.fatzebra.com.au/v1.0/plans/001-PL-ZX8J9K.json -u TEST:TEST -d " \
  {
      \"name\": \"Silver Plan\",
      \"description\": \"Silver level membership\"
  }"

Responses

Successful — HTTP 200
{
  "successful": true,
  "response": {
    "name": "Silver Plan",
    "id": "067-PL-KFG3OXX9",
    "amount": 2399,
    "reference": "gold-1",
    "description":"Silver level membership",
    "currency": "AUD",
    "subscription_count": 0
  },
  "errors": [],
  "test":false
}
Failed (Invalid data or unable to process) — HTTP 501
{
  "successful": false,
  "response": {
    "name": "",
    "id": "067-PL-KFG3OXX9",
    "amount": 2399,
    "reference": "gold-1",
    "description": "Gold level membership",
    "currency": null,
    "subscription_count": 0
  },
  "errors": [
    "Name can't be blank"
  ],
  "test": false
}

Creating a Customer

To create a new customer the following details are required:

  • First Name
  • Last Name
  • Reference (such as your customer's ID number)
  • Email address (used to deliver email receipts if requested)
  • IP Address Optional
  • Card details
    • Card Holder (if different from the customer's name)
    • Card Number
    • Expiry Date
    • CVV
  • Address Details Optional
    • Address
    • City
    • State
    • Postcode
    • Country

Definition

Authentication: Basic xxxxxxxxxxxxx
POST /v1.0/customers HTTP/1.1

Example Request

$ curl https://gateway.sandbox.fatzebra.com.au/v1.0/customers -u TEST:TEST -d " \
  {
    \"first_name\": \"Harrold\",
    \"last_name\": \"Humphries\",
    \"reference\": \"Cust1234\",
    \"email\": \"hhump@gmail.com\",
    \"ip_address\": \"180.200.33.181\",
    \"card\": {
      \"card_holder\": \"Harrold Humphries Senior\",
      \"card_number\": \"5123456789012346\",
      \"expiry_date\": \"05/2023\",
      \"cvv\": \"123\"
    },
    \"address\": {
      \"address\": \"1 Harriet Road\",
      \"city\": "Kooliablin",
      \"state\": \"NSW\",
      \"postcode\": \"2222\",
      \"country\": \"Australia\"
    }  
  }"

Responses

Successful — HTTP 201
{
  "successful": true,
  "response": {
    "id": "067-C-EWMAAHMO",
    "email": "hhump@gmail.com",
    "reference": "Cust1234",
    "first_name": "Harrold",
    "last_name": "Humphries",
    "created_at": "2012-05-25T17:46:26+10:00",
    "card_token": "lhypjhrv",
    "address": {
      "address": "1 Harriet Road",
      "city": "Kooliablin",
      "state": "NSW",
      "postcode": "2222",
      "country": "Australia"
    }
  },
  "errors": [

  ],
  "test": false
}
Failed (Bad Data/Duplicate Reference) — HTTP 400
{
  "successful": false,
  "response": {
    "id": null,
    "email": "hhump@gmail.com",
    "reference": "Cust1234",
    "first_name": "Harrold",
    "last_name": "Humphries",
    "created_at": null
  },
  "errors": [
    "Reference has already been taken"
  ],
  "test": false
}
Failed (Bad Data/Missing Field) — HTTP 400
{
  "successful": false,
  "response": {
    "id": null,
    "email": "hhump@gmail.com",
    "reference": null,
    "first_name": "Harrold",
    "last_name": "Humphries",
    "created_at": null
  },
  "errors": [
    "Reference can't be blank"
  ],
  "test": false
}

Retrieve a Customer

Definition

Authentication: Basic xxxxxxxxxxxxx
GET /v1.0/customers/067-C-EWMAAHMO.json HTTP/1.1

Example Request

$ curl https://sandbox.gateway.fatzebra.com.au/v1.0/customers/067-C-EWMAAHMO.json -u TEST:TEST

Responses

Successful — HTTP 200
{
  "successful": true,
  "response": {
    "id": "067-C-EWMAAHMO",
    "email": "hhump@gmail.com",
    "reference": "Cust1234",
    "first_name": "Harrold",
    "last_name": "Humphries",
    "created_at": "2012-05-25T17:46:26+10:00",
    "card_token": "lhypjhrv"
  },
  "errors": [

  ],
  "test": false
}
Failed (Not Found) — HTTP 404
{
  "successful": false,
  "response": null,
  "errors": [
    "Record not found"
  ],
  "test": false
}

Update a Customer

Definition

Authentication: Basic xxxxxxxxxxxxx
PUT /v1.0/customers/067-C-EWMAAHMO.json HTTP/1.1

Example Request

$ curl https://sandbox.gateway.fatzebra.com.au/v1.0/customers/067-C-EWMAAHMO.json -u TEST:TEST -X PUT -d" \
  {
    \"first_name\": \"William\"
  }"

Responses

Successful — HTTP 200
{
  "successful": true,
  "response": {
    "id": "067-C-EWMAAHMO",
    "email": "hhump@gmail.com",
    "reference": "Cust1234",
    "first_name": "William",
    "last_name": "Humphries",
    "created_at": "2012-05-25T17:46:26+10:00",
    "card_token": "lhypjhrv"
  },
  "errors": [

  ],
  "test": false
}
Failed (Not Found) — HTTP 404
{
  "successful": false,
  "response": null,
  "errors": [
    "Record not found"
  ],
  "test": false
}
Failed (Bad Data) — HTTP 400
{
  "successful": false,
  "response": {
    "id": "067-C-EWMAAHMO",
    "email": "hhump@gmail.com",
    "reference": "Cust1234",
    "first_name": "",
    "last_name": "Humphries",
    "created_at": "2012-05-25T17:46:26+10:00",
    "card_token": "lhypjhrv"
  },
  "errors": [
    "First name can't be blank"
  ],
  "test": false
}

Delete a Customer

Definition

Authentication: Basic xxxxxxxxxxxxx
DELETE /v1.0/customers/067-C-EWMAAHMO.json HTTP/1.1

Example Request

$ curl https://sandbox.gateway.fatzebra.com.au/v1.0/customers/067-C-EWMAAHMO.json -u TEST:TEST -X DELETE

Responses

Successful — HTTP 200
{
  "successful": true,
  "response": {
    "id": "067-C-EWMAAHMO",
    "email": "hhump@gmail.com",
    "reference": "Cust1234",
    "first_name": "William",
    "last_name": "Humphries",
    "created_at": "2012-05-25T17:46:26+10:00",
    "card_token": "lhypjhrv"
  },
  "errors": [

  ],
  "test": false
}
Failed (Not Found) — HTTP 404
{
  "successful": false,
  "response": null,
  "errors": [
    "Record not found"
  ],
  "test": false
}

Creating a Subscription

Definition

Authentication: Basic xxxxxxxxxxxxx
POST /v1.0/subscriptions HTTP/1.1

Example Request

$ curl https://sandbox.gateway.fatzebra.com.au/v1.0/subscriptions -u TEST:TEST -d " \
  {
    \"customer\": \"001-C-80NCSQBE\",
    \"plan\": \"sbdt-1\",
    \"frequency\": \"Weekly\",
    \"start_date\": \"2014-05-09\",
    \"reference\": \"JSMITH1\",
    \"is_active\": true
  }"

Responses

Successful — HTTP 201
{
  "successful": true,
  "response": {
    "customer": "001-C-80NCSQBE",
    "plan": "001-PL-TDX67R1F",
    "frequency": "Weekly",
    "start_date": "2014-05-09",
    "end_date": null,
    "next_billing_date": "2014-05-09",
    "reference": "JSMITH1",
    "last_status": "Scheduled",
    "is_active": true
  },
  "errors": [],
  "test": false
}
Failed (Bad Data) — HTTP 400
{
  "successful": false,
  "response": {
    "id": null,
    "customer": "067-C-EWMAAHMO",
    "plan": "067-PL-KFG3OXX9",
    "frequency": "Daily",
    "start_date": "2012-06-02",
    "end_date": null,
    "next_billing_date": null,
    "reference": null,
    "last_status": "Scheduled",
    "is_active": false
  },
  "errors": [
    "Reference can't be blank"
  ],
  "test": false
}

Retrieving a Subscription

Definition

Authentication: Basic xxxxxxxxxxxxx
POST /v1.0/subscriptions HTTP/1.1

Example Request

$ curl https://sandbox.gateway.fatzebra.com.au/v1.0/subscriptions/JSMITH1.json -u TEST:TEST

Responses

Successful — HTTP 200
{
  "successful": true,
  "response": {
    "customer": "001-C-80NCSQBE",
    "plan": "001-PL-TDX67R1F",
    "frequency": "Weekly",
    "start_date": "2014-05-09",
    "end_date": null,
    "next_billing_date": "2014-05-09",
    "reference": "JSMITH1",
    "last_status": "Scheduled",
    "is_active": true
  },
  "errors": [],
  "test": false
}
Failed (Not Found) — HTTP 404
{
  "successful": false,
  "response": null,
  "errors": [
    "Record not found"
  ],
  "test": false
}

Updating a Subscription

A subscription can be updated to stop or pause it. If you wish to subscribe a customer to a new plan you should stop the current subscription and create a new one.

Definition

Authentication: Basic xxxxxxxxxxxxx
PUT /v1.0/subscriptions/067-S-R5TPVPHZ.json HTTP/1.1 

Example Request

  $ curl https://sandbox.gateway.fatzebra.com.au/v1.0/subscriptions/067-S-R5TPVPHZ.json -X PUT -u TEST:TEST -d " \
    {
      \"is_active\": false
    }"

Response

Successful — HTTP 200
{
  "successful": true,
  "response": {
    "id": "067-S-R5TPVPHZ",
    "customer": "067-C-EWMAAHMO",
    "plan": "067-PL-KFG3OXX9",
    "frequency": "Daily",
    "start_date": "2012-06-02",
    "end_date": null,
    "next_billing_date": "2012-06-02",
    "reference": "Hello1235",
    "last_status": "Scheduled",
    "is_active": false
  },
  "errors": [

  ],
  "test": false
}

Web Hooks

Paystream uses web hooks to notify your application of events relating to your recurring subscriptions. Web Hooks are triggered for the following events: charge:pending, charge:successful, charge:retry, charge:failed, card:expiring, card:expired.

Web Hooks are sent with a payload of the following format (in JSON):

  • event — the event name
  • payload — array of payload objects
    • These objects may include purchases, customers, cards or otherwise.

Web Hooks are also accompanied by an HTTP header, Mode, which will indicate the environment (Live or Sandbox)

charge:pending

Charge pending will be triggered when subscriptions are queued for processing each day.

Example Payload
{
  "event": "charge:pending",
  "payload": [
    {
      "id": "001-S-GMDS9GG9",
      "frequency": "Daily",
      "start_date": "2012-05-18",
      "end_date" :null,
      "reference": "MAG123",
      "customer": {
        "email": "wally@gmail.com",
        "first_name": "Wally",
        "last_name": "Kravitz",
        "reference": "WK123",
        "id": "001-C-RG3DCTR"
      }
    }
  ]
}

charge:successful

Charge successful will be triggered when subscription charges are successfully completed.

Example Payload
{
  "event": "charge:successful",
  "payload": [
    {
      "subscription": {
        "id": "067-S-R5TPVPHZ",
        "frequency": "Daily",
        "start_date": "2012-06-02",
        "end_date": null,
        "reference": "Hello1235",
        "customer": {
          "email": "hhump@gmail.com",
          "first_name": "Harrold Billy",
          "last_name": "Humphries",
          "reference": "Cust1234",
          "id": "067-C-EWMAAHMO"
        }
      },
      "response": {
        "successful": true,
        "response": {
          "authorization": 1339157688,
          "id": "067-P-4ERGWF0P",
          "card_number": "512345XXXXXX2346",
          "card_holder": "Harrold Humphries Senior",
          "card_expiry": "2012-08-08",
          "card_token": "lhypjhrv",
          "amount": 2399,
          "decimal_amount": 23.99,
          "successful": true,
          "message": "Approved",
          "reference": "HelloXXXX XXXXXXXX-XXXX47",
          "source": "Recurring",
          "currency": "AUD"
        },
        "errors": [

        ],
        "test": true
      }
    }
  ]
}

charge:retry

When a charge fails (e.g. declined or otherwise) it will be added to the retry queue and you will receive this notification.

Example Payload
{
  "event": "charge:retry",
  "payload": [
    {
      "subscription": {
        "id": "067-S-ZL1Q1YDM",
        "frequency": "Daily",
        "start_date": "2012-06-02",
        "end_date": null,
        "reference": "Hello123",
        "customer": {
          "email": "jsmith@gmail.com",
          "first_name": "John",
          "last_name": "Smith",
          "reference": "9cb09b54d987a3532cb79ff9bfc59eae",
          "id": "067-C-FGDZTYIA"
        },
        "last_status": "Failed (2), Pending"
      },
      "response": {
        "successful": true,
        "response": {
          "authorization": 1339160553,
          "id": "067-P-MDWU6LGH",
          "card_number": "455701XXXXXX8902",
          "card_holder": "John Smith",
          "card_expiry": "2012-09-08",
          "card_token": "g1r7y4wr",
          "amount": 2399,
          "decimal_amount": 23.99,
          "successful": false,
          "message": "Declined",
          "reference": "Hello123 XXXXXXXX-XXXXXX",
          "source": "Recurring",
          "currency": "AUD"
        },
        "errors": [

        ],
        "test": true
      }
    }
  ]
}

charge:failed

After three retries a charge will be abandoned and you will receive the charge:failed notification

Example Payload
{
  "event": "charge:failed",
  "payload": [
    {
      "subscription": {
        "id": "067-S-ZL1Q1YDM",
        "frequency": "Daily",
        "start_date": "2012-06-02",
        "end_date": null,
        "reference": "Hello123",
        "customer": {
          "email": "jsmith@gmail.com",
          "first_name": "John",
          "last_name": "Smith",
          "reference": "9cb09b54d987a3532cb79ff9bfc59eae",
          "id": "067-C-FGDZTYIA"
        },
        "last_status": "Failed (3), Aborted"
      },
      "response": {
        "successful": true,
        "response": {
          "authorization": 1339160258,
          "id": "067-P-5ZV92Y3K",
          "card_number": "455701XXXXXX8902",
          "card_holder": "John Smith",
          "card_expiry": "2012-09-08",
          "card_token": "g1r7y4wr",
          "amount": 2399,
          "decimal_amount": 23.99,
          "successful": false,
          "message": "Declined",
          "reference": "Hello123 XXXXXXXX-XXXXXX",
          "source": "Recurring",
          "currency": "AUD"
        },
        "errors": [

        ],
        "test": true
      }
    }
  ]
}

card:expiring

Card expiring will be triggered when a card is due to expire within 30 days.

Example Payload
{
  "event": "card:expiring",
  "payload": [
    {
      "email": "hhump@gmail.com",
      "first_name": "Harrold Billy",
      "last_name": "Humphries",
      "reference": "Cust1234",
      "id": "067-C-EWMAAHMO"
    }
  ]
}

card:expired

Card expired will be triggered when a credit card has expired for an active supscription. At this point the subscription will be set to inactive.

Example Payload
{
  "event": "card:expired",
  "payload": [
    {
      "email": "hhump@gmail.com",
      "first_name": "Harrold Billy",
      "last_name": "Humphries",
      "reference": "Cust1234",
      "id": "067-C-EWMAAHMO"
    }
  ]
}

Refunds

Refunding a Purchase

In order to refund a purchase the following details are required:

  • transaction_id (String) - The Transaction ID of the original transaction to be refunded (XXX-P-YYYYYY)
  • amount (Integer) - amount to be refunded
  • Reference (String) - the merchants reference for the refund

Definition

Authentication: Basic xxxxxxxxxxxxx
POST /v1.0/refunds HTTP/1.1

Example Request

  $ curl https://gateway.sandbox.fatzebra.com.au/v1.0/refunds -u TEST:TEST -d" \
  { \
    \"transaction_id\": \"55355\", \
    \"amount\": 349, \
    \"reference\": \"ABC123\" \
  }"

Responses

Successful — HTTP 200
{
  "successful": true,
  "response": {
    "authorization": "1392269829",
    "id": "001-R-D76NCBN8",
    "amount": -100,
    "refunded": "Approved",
    "message": "Approved",
    "card_holder": "James Smith",
    "card_number": "512345XXXXXX2346",
    "card_expiry": "2023-10-31",
    "card_type": "MasterCard",
    "successful": true,
    "transaction_date": "2014-02-13T16:37:08+11:00",
    "response_code": "00"
  },
  "errors": [

  ],
  "test": true
}
Failed (bad data) — HTTP 400
{
  "successful": false,
  "response": {
    "authorization": null,
    "id": null,
    "amount": null,
    "refunded": null,
    "message": null,
    "card_holder": "Harrold Smith",
    "card_number": "XXXXXXXXXXXX4444",
    "card_expiry": "2023-05-31",
    "card_type": "MasterCard",
    "successful": false
  },
  "errors": [
    "Reference can't be blank"
  ],
  "test": true
}

Retrieve a Refund

Definition

Authentication: Basic xxxxxxxxxxxxx
GET /v1.0/refunds/{REFUND_ID} HTTP/1.1

Example Request

$ curl https://gateway.sandbox.fatzebra.com.au/v1.0/refunds/001-R-ZX8J9K -u TEST:TEST

Responses

Successful — HTTP 200
{
    "successful": true,
    "response":     {
      "authorization": "1392269829",
      "id": "001-R-ZX8J9K",
      "amount": -100,
      "refunded": "Approved",
      "message": "Approved",
      "card_holder": "James Smith",
      "card_number": "512345XXXXXX2346",
      "card_expiry": "2023-10-31",
      "card_type": "MasterCard",
      "successful": true,
      "transaction_date": "2014-02-13T16:37:08+11:00",
      "response_code": "00"
    },
    "test": true
    "errors": []
}
Failed (Not Found) — HTTP 404
{
    "successful": false,
    "response": null,
    "test": true
    "errors": ["Purchase not found"]
}

Hosted Payments (Including IFrame)

Hosted Payments

Paystream provides a hosted payment page for merchants who wish to remove all PCI-DSS scope from their systems. Currently the hosted payment page supports two methods of implementation:
  • Standard Hosted Page (i.e. redirection from the merchants website to the payment page)
  • IFRAME embedded page

Usage

The data sent between the merchant and Paystream, and from Paystream to the merchant is sent in the request URL - to ensure that this has not been tampered with the payload includes a verification value, which is a signed-hash based on the payload values, using a shared secret between the merchant and Paystream. This process has been closely modelled on the Paystream Direct Post method - it is recommend you review this documentation for further details which may not be covered here.

URLs

There are two different URLs for the PayNow service - one for the Live environment and one for the Sandbox environment:

Environment URL
Sandbox https://paynow.sandbox.fatzebra.com.au/v2
Live https://paynow.fatzebra.com.au/v2

These URLs are for the PayNow hosted pages only - any Gateway requests (for example, querying a transaction, charging a tokenized card or performing a refund) should be performed against the Gateway URLs:

Environment URL
Sandbox https://gateway.sandbox.fatzebra.com.au/v2
Live https://gateway.fatzebra.com.au

Request

In order to direct the customer to the hosted payment page the merchants website should prepare the following URL and either use this as the redirect destination, or as the IFRAME source:

https://paynow.fatzebra.com.au/v2/[username]/[reference]/[currency]/[amount]/[hash]

URL Parameters

The following parameters are required and are used to build the URL which the user should be redirected to (or as the source for the IFRAME):

Name Type Description
username string The merchants Paystream username
reference string The invoice number or order reference
currency string (3 characters) The ISO-4217 3-letter currency code for the transaction
amount number The amount of the transaction, as a decimal value.
For currencies which do not make use of the decimal/cent value this should be omitted as 00 (e.g. 300.00 for ¥300)
hash string The hash is a MD5 hexdigest of a string compiled from the request parameters.
See below (Verification Value Calculation) for more details.

Options

Provide any of the following as query parameters to specify display options - these are optional parameters:

Name Type Description
iframe boolean Indicates whether to show the stripped-down iframe layout or not
show_email boolean Indicates whether to show and require the email field or not
show_extras boolean Indicates whether to display the invoice number and the amount to the customer
return_path string The return URL for the transaction success - if this is omitted the result will be displayed on screen to the customer
Note: if the a URL is specified it must be included in the verification hash. This may be a non-resolving URL for callback handling in mobile applications if required (e.g. paymentcallback://....)
tokenize_only boolean If this is set the card will not be charged, and will only be tokenized for future use - this option cannot currently be used with MasterPass
button_text string Specifies the text to be displayed for the submit button (e.g. Pay Now or Submit)
masterpass boolean Indicates whether to use the MasterCard MasterPass checkout process

Examples

Verification Value Calculation

There are two points of verification for requests - once when the request is received by Paystream (when the hosted page is rendered to the user), and once when the response is returned to the merchant - it is important that the response is verified by the merchant to ensure that the response has not been tampered with by malicious users.

Request Verification (Redirect to Paystream)

The request receive by Paystream will be verified with the following steps:

1. The reference, currency, amount, and if present, return_path will be concatenated into a string, joined by colons:

https://paynow.fatzebra.com.au/v2/samsbooks/INV1121/AUD/100.25/xxxxxxxxxxx?return_path=https://www.samsbooks.com/payment/callback -> "INV1121:100.25:AUD:https://www.samsbooks.com/payment/callback"

2. The value of this string will then be hashed with a HMAC-MD5, using the shared-secret known by Paystream and the merchant (please contact Paystream Support if you are unsure of where to find this shared secret).

shared_secret = "abc123ff12"
verification = hmac_md5(shared_secret, "INV1121:100.25:AUD:https://www.samsbooks.com/payment/callback")
Response Verification (Purchases)

For purchases the response verification will consist of the response code, success indicator, amount, currency, transaction ID and the card token:

https://www.samsbooks.com/payment/callback?r=1&successful=true&amount=10025¤cy=AUD&id=001-P-ABCDG1124&token=abcd1234&v=xxxxx....... -> "1:true:10025:AUD:001-P-ABCDG1123:abcd1234" shared_secret = "abc123ff12"
verification = hmac_md5(shared_secret, "1:true:10025:AUD:001-P-ABCDG1123:abcd1234")

# v == verification should be true

The response for purchases will also include the following:

Name Type Description
message string Any messages relating to the transaction
amount integer The amount, as an integer
reference string The transaction reference
id string The Paystream transaction ID
currency string The ISO-4217 3-letter currency code for the transaction
card_number string The masked credit card number (e.g. 512345XXXXXXXX2346)
card_holder string The card holders name
card_expiry date (mm/yyyy) The card expiry date
successful boolean Indicator of transaction success
Response Verification (Tokenization)

For tokenization the response verification will consist of the response code, and the card token:

https://www.samsbooks.com/payment/callback?r=1&token=abcd1234&v=xxxxxxxxx........ -> "1:abcd1234"
shared_secret = "abc123ff12"
verification = hmac_md5(shared_secret, "1:abcd1234")
# v == verification should be true

The response for tokenization will also include the following:

Name Type Description
card_number string The masked credit card number (e.g. 512345XXXXXXXX2346)
card_holder string The card holders name
card_expiry date (mm/yyyy) The card expiry date
token string The token representing the card in Paystream's systems

Response Codes

The following response codes are used when a redirect URL is provided:

Code Description
1 Successful
2 Declined - examine the message parameter for possible explanations
94 Cancelled - the merchant clicked the Cancel button on the payment or checkout form
95 Merchant Not Found - possible incorrect username
96 Reference not unique
97 Validation error - check the errors[] parameters for error messages
99 Invalid Verification - the verification value does not match the parameters supplied
999 Gateway error - an unknown error has occurred and the merchant should investigate with Paystream Support

IFRAME and postMessage Support

The Hosted Payment Page supports being embedded in an IFRAME and communicating back to the parent window via the postMessage function. In order to support this the following needs to be done:

  1. The postmessage=true parameter needs to be added to the URL
  2. The following code should be added to handle the messages from the IFRAME:
window.paymentHost = "https://paynow.sandbox.fatzebra.com.au";

var messageListener = function(e) {
if (e.origin !== window.paymentHost) {
return;
}
switch (e.data.message) {
case "transaction.complete":
// Handle the transaction complete message.
// Payload will be in e.data.data (eg. e.data.data.r == 1)
return true;
case "transaction.processing":
// Handle the processing of the transaction - implementation optional.
return true;
case "transaction.cancelled":
// Handle the transaction being cancelled (i.e. show message, re-display the window etc).
return true;
}
};

if (window.addEventListener) { window.addEventListener("message", messageListener); }
else { window.attachEvent("onmessage", messageListener); }

Return Codes

When the direct post redirects to your site one of the parameters to inspect is r which will contain the return code of the transaction.

The possible values for this code are:

Code Meaning
1 Successful Transaction
2 Declined Transaction
95 Merchant Not Found (incorrect username)
96 Reference not unique
97 Validation Error
98 Invalid Card Token
99 Invalid Verification
999 Gateway Error

Extra Fields

Paystream enables extended fields for merchants to allow advanced integrations where the need arises. This includes the ECM field to specify the card transaction type. If you require this functionality for your integration please contact Paystream support and detail your requirements so we can determine the best option for your needs.

The fields detailed below will only be accepted for merchants which are explicitly configured to support extra fields.
All fields should be included under the extra key in the request payload:

{ 
 "extra": { 
 "ecm": "32" 
  } 
}
The ECM describes the card transaction type. The field is two digits (mn) with the possible values being:
Digit 1 (m) Digit 2 (n)
Telephone order - 1 Single - 1
Recurring - 2
Instalment - 3
Mail order - 2 Single - 1
Recurring - 2
Instalment - 3
Internet order - 3 Single - 1
Recurring - 2
Instalment - 3