Judopay Documentation

Web SDK

Our Web SDK is a JavaScript library which includes a fully customisable hosted iframe solution enabling you to collect sensitive card information.

You will not take on additional PCI scope, as sensitive card information:

  • card number (PAN)

  • expiry date

  • CV2 

will be submitted by your customers into fields hosted by Judopay.

WebSDK.png

A one-use token is provided, which is used by your backend server to complete the transaction. See Creating a One Use Token.

Caution

The one-use token is a different field to the cardtoken.

Web SDK Checkout Flow

The complete checkout flow:

WebSDK_Checkout_Flow.png

Step

Description

One.png

An iframe is loaded on your page, including an instance of a JudoPay JavaScript object.

Two.png

Consumer enters card details into the iframe fields:

  • Card number

  • CV2

  • Expiry date

  • Post code Optional

Three.png

Consumer clicks on the Pay button:

  • The createToken function from the JudoPay object is called. 

  • This sends a request to Judopay.

  • Judopay uses the card details to return a one-use token. 

This token will be valid for 30 minutes.

Four.png

You send the one-use token to your backend, to process the transaction.

Five.png

Your backend makes a second call to Judopay.

This call sends the one-use token for the operation such as: Payment or RegisterCard.

Six.png

Judopay returns the Receipt for the operation.

Caution

The one-use token is a different field to the cardtoken.

Web SDK Set Up

To set up the Web SDK on your payment page:

  1. Include Judopay's JavaScript page on your website by adding a script tag in your HTML code:

Note

To automatically receive non-breaking changes, you can pin to the minor version (0.0) rather than the current patch version (0.0.12).

<script 
    src="https://web.judopay.com/js/0.0.12/judopay.min.js">
</script>
  1. Include a div in the iframe page with a unique ID value:

<div id="payment-iframe" width="100%"></div>
  1. Create an instance of the JudoPay object to call the createCardDetails function

  2. Provide the iframe div ID as a parameter. This function will return a reference to the card fields.:

var judo = new JudoPay("api_token", true);
Var payment = judo.createCardDetails('payment-iframe');

Note

The second parameter is called useSandbox

Set to true to use the Sandbox environment.

Set to false to use the Production environment.

Creating a One Use Token

Warning

The one-use token does not authorise any transactions but generates a oneTimeUse token for you to issue a payment request to our API endpoints, or to use our Server SDKs to request payment.

To create a one-use token:

  1. Your consumer clicks the Pay button on your website.

  2. Use your JudoPay instance to generate a one-use token from the card details fields: judo.createToken(payment);

    1. An encrypted Payload is generated (Judopay will decrypt the payload).

A sample success response:

{    
"oneUseToken": "2uhOsi...8KZcn=",    
 "cardLastfour": "3436",    
   "endDate": "12/20",    
    "cardScheme": "Visa",    
      "cardFunding": "Debit",    
        "error": false,     
   "clientDetails": 0 }

A sample error response:

{
    "error": 
    {
        "message": "Sorry, we're unable to process your request. Please check your details and try again."
    }
}
  1. The one-use token will be valid for 30 minutes .

  2. Use this token to call our Payment API and process a transaction.

  3. You will need to include the one-use token as part of an encrypted card model instance.

Registering a Card for a One Use Token

  1. Using your Judopay API client instance, create a RegisterEncryptedCardModel to save the consumer's card to Judopay’s card vault:

var encryptedCard = new RegisterEncryptedCardModel
{
    OneUseToken = oneUseToken,
    JudoId = judoId,
    YourConsumerReference = yourConsumerReference,
};

var response = client.RegisterCards.Create(encryptedCard);
var receipt = response.Response as PaymentReceiptModel;

if(receipt.Result === "Success") {
    var cardToken = receipt.CardDetails.CardToken;  
}
  1. The response will include a card token, which does not expire.

  2. The card token can be used in a TokenPaymentModel for the next transaction.

Making a Transaction with a One Use Token

  1. Using your Judopay API client instance, create a OneTimePaymentCardModel and immediately process a payment with the one-use token.

  2. The response includes a Card token:

    var oneTimePayment = new OneTimePaymentModel
    {
        OneUseToken = oneUseToken,
        JudoId = judoId,
        YourConsumerReference = yourConsumerReference,
        YourPaymentReference = yourPaymentReference,
        Amount: 1.0,
        Currency: "GBP"
    };
    
    var response = client.Payments.Create(oneTimePayment);
    var receipt = response.Response as PaymentReceiptModel;
    
    if(receipt.Result === "Success") {
        var cardToken = receipt.CardDetails.CardToken;  
    }
  3. Save the card token for the next transaction

  4. If 3D Secure is enabled, the response message = Requires 3D Secure 

All fields required to run the 3D Secure check will be available in the receipt:

  • acsUrl

  • PaReq

  • MD

{
    "receiptId": "415874660497166336",
    "result": "Requires 3D Secure",
    "message": "Issuer authentication required",
    "acsUrl": "https://gw1.paymentsensegateway.com:4430/ACS/Default.aspx",
    "md": "1902...2484",
    "paReq": "eJxd...kqXcvg=="
}

To complete the transaction the 3D Secure form needs to be displayed to the consumer.

This can be achieved in any of the following ways: 

  • a redirect

  • pop-up window

  • iframe

For more details, see 3D Secure.

Form Customisation

The configuration file is key for customising the behaviour and look of the Iframe.

You can change the appearance, behaviour and language by passing a configuration JSON object into createCardDetails.

Tip

Wrap up your configuration in a separate js file and include it on your page.

Example 1. Passing your configuration into createCardDetails:
var styleOptions = {
    iframe {
        ...
    }
}
var judo = new JudoPay('Your Token', true);
var paymentFrame = judo.createCardDetails('', styleOptions)


Form Customisation Top Level Properties

The Web SDK has a default setting for all properties, you override these in the config file. 

The config file is a simple JSON object containing the following properties:

Property Name

Values

Default

language

language from supported list

en

showCardTypeIcons

boolean

true

backgroundColor

HTML colour ('red') or

Hex color ('#FF0000')

white

layout

vertical, horizontal or compact

vertical

styles

JSON object which is defined below

specified below

fonts

JSON array which is defined below

specified below

The configuration file is optional.

Styles Properties

Configuration to style fields is within the Styles object. 

Styles can be applied to all fields by placing the style attribute in the default object inside Styles. You can also apply styles individually to fields, directly to the field name.

The styles object has 6 properties:

  1. Default 

  2. Focus 

  3. Error 

  4. Valid 

  5. cv2 

  6. expiryDate 

Each of these properties has three properties:

  1. Field 

  2. Label 

  3. Container

The properties for field and label:

  • Mapped to the style objects of the input and label HTML elements. 

The properties for container:

  • Mapped to the div that contains both the input and label.

The properties for focus, error and valid:

  • Mapped on state transition allowing the functionality to be consistent with other forms on your site.

Any property defined in default will be applied to all the fields.

Any property defined in a field will take priority over a default property, the fields are expiryDate and cv2.

All valid style properties are supported and take the form of camel cased CSS properties, eg padding-bottom becomes paddingBottom.

styles: {
            default: {
                field: {
                    backgroundColor: '#0a0a0a',
                    color: '#EEE',
                    padding: '10px',
                    margin: '0 20px',
                    width: '90%',
                    borderRadius: '4px',
                    boxShadow: 'rgba(255, 255, 255, 0.8) 0px 0px 10px inset'
                },
                label: {
                    color: '#EEE',
                    padding: '10px 10px 0 25px',
                    fontWeight: 'bold',
                    textTransform: 'capitalize'
                }
            },
            focus: {
                field: {
                    backgroundColor: '#2a2a2a',
                    color: '#EEE'
                },
            },
            error: {
                field: {
                    backgroundColor: '#1a0a0a',
                    color: '#990000'
                }
            },
            valid: {
                field: {
                    color: '#CFC'
                }
            },
            cv2: {
                field: {
                    margin: "0 20px 10px;"
                },
                container: {
                    width: '47%',
                    paddingBottom: "20px"
                }
            },
            expiryDate: {
                field: {
                    marginBottom: "10px;"
                },
                container: {
                    width: '47%',
                    paddingBottom: "20px"
                }
            }

Form Layout

Three layout options are provided:

  • Vertical

  • Compact

  • Horizontal

WebSDK_Layout.png

Form Fonts

An array of JSON objects each representing a font, are added to the page.

They can be referenced from the Style object.

Each object can have the following properties:

Property Name

Values

Example Value

family

Specifies the name of the font face value properties.

Roboto

src

Specifies the resource containing the font data.

"/fonts/OpenSans-Regular-webfont.woff2"

display

Determines how a font face is displayed.

Based on whether and when it is downloaded and ready to use.

auto

style

Specifies the font styles.

italic

unicodeRange

The range of font Unicode code points to be used.

U+0025-00FF, U+4??

weight

Specifies the font weight, or boldness.

400

The following example loads Roboto from Google fonts and assigns it:

fonts: [
            {
                family: 'Roboto',
                src: 'https://fonts.gstatic.com/s/roboto/v18/KFOmCnqEu92Fr1Mu72xKOzY.woff2',
                display: 'auto',
                style: 'normal',
                unicodeRange: 'U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD',
                weight: '400'
            }
        ],
        styles: {
            default: {
                field: {
                    fontFamily: "'Roboto', sans-serif",
                },
                label: {
                    fontFamily: "'Roboto', sans-serif",
                }
            },

Adding a New Language

You can add any language you need.

To add a new language:

  1. Add the language in a customLanguages property in your Judopay configuration file. 

    This property can either be a single dictionary for one language, or an array of dictionaries for multiple languages. 

For the purpose of this exercise, the example shows how to add Romanian:

var customStyle = {
    iframe1 : {
        language : "ro",
        customLanguages : 
            {
                "ro" : {
                    fieldLabels: {
                        cardNumberLabel: "Număr de card",
                        expiryDateLabel: "Data Expirarii",
                        cardVerificationCodeLabel: "CVC"
                    },
                    fieldPlaceholders: {
                        cardNumberPlaceholder: "Număr de card",
                        expiryDatePlaceholder: "LL / AA ",
                        cardVerificationCodePlaceholder: "CVC"
                    },
                    errors : {
                        0: "Numărul cardului poate conține numai numere",
                        1: "Numărul cardului nu este valid",
                        2: "Tipul de card nu este recunoscut, verificați din nou numărul dvs",
                        3: "Numarul cardului este necesar",
                        4: "Cardul a expirat",
                        5: "Data expirării cardului nu este validă",
                        6: "Data expirării necesară",
                        7: "Codul {0} este prea scurt pentru cartea de {1}",
                        8: "Codul {0} este prea lung pentru carte de {1}",
                        9: "Codul {0} poate conține numai numere",
                        10: "Codul {0} necesar pentru cartea de {1}"
                    }
                }
            },
           ...
    }
};

Warning

It is important the language dictionary follows this structure with inner dictionaries and strings, so the translations can be applied.

Now all strings used in the application will be taken from the new language set.

As well as adding any language into the customLanguages property, also set the language for the error code (ro). 

It is recommended to copy this example and change the strings when defining your new language.

Language Translations

Judopay's Web SDK supports multiple languages.

Tip

The default property is English.

Language

Code

English

en

French

fr

Spanish

es

Portuguese

pt

German

de

Changing the Form Language

To change the language of the form:

1. Set a language variable in your configuration file. 

2. Pass in the language code as a string:

var customStyle = {
    iframe1 : {
        language : "es"
        ...
    }
}

3. For the purpose of this exercise, the iframe will now load using Spanish translations.

Change Form Language at Runtime

You can change the language used in the form at run time. This is useful for consumers running a Single Page Application (SPA).

The JudoPay object which initialises the form provides a method for updating a language. You can hook this method up to a button/event of your choice for dynamically changing the language. 

In the example below, a method is added to an anchor element on the checkout page, which will change the language used after the iframe is already initialised.

<script>
    var judo = new JudoPay('Your Token', true);
</script>
<a href="javascript:judo.changeIframeLanguage('de');">de</a>

Configuration Example

Below is an example config file which sets the styles for:

  • Layout

  • Background colour

  • Inputs

  • Labels

It also modifies the error and UI strings for the default language: English.

var exampleConfig = {
    iframe: {
        language: 'en',
        errorFieldId: 'judopay-errors-2',
        showCardTypeIcons: true,
        cardTypeIconRight: '10px',
        cardTypeIconTop: '-2px',
        backgroundColor: '#e5e5e5',
        layout: "compact",
        fonts: [
            {
                family: 'Roboto',
                src: 'https://fonts.gstatic.com/s/roboto/v18/KFOmCnqEu92Fr1Mu72xKOzY.woff2',
                display: 'auto',
                style: 'normal',
                unicodeRange:
                'U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD',
                weight: '400'
            }
        ],
        styles: {
            default: {
                field: {
                    fontFamily: "'Roboto', sans-serif",
                    fontSize: '17px',
                    backgroundColor: '#e5e5e5',
                    borderTop: 'none',
                    borderRight: 'none',
                    borderLeft: 'none',
                    boxShadow: 'none',
                    margin: '-10px 0 -5px',
                    padding: '6px 0'
                },
                label: {
                    color: '#F77',
                    fontFamily: "'Roboto', sans-serif",
                    opacity: '0',
                    height: '15px',
                    fontSize: '8px',
                    display: 'inline-block',
                    transition: 'opacity 0.6s',
                    marginLeft: '5px',
                    position: 'relative',
                    bottom: '-10px',
                    zIndex: '100'
                }
            },
            focus: {
                field: {
                    backgroundColor: '#F0F0F0',
                    color: 'rgb(130, 130, 130)',
                    padding: '12px 6px 0',
                    fontSize: '16px',
                },
                label: {
                    opacity: "1",
                    color: 'rgb(130, 130, 130)'
                }
            },
            error: {
                field: {
                    backgroundColor: '#e5ecff',
                    padding: '12px 6px 0',
                },
                label: {
                    opacity: "1"
                }
            },
            valid: {
                field: {
                    backgroundColor: '#e5ffec',
                    color: 'green',
                    padding: '12px 6px 0',
                },
                label: {
                    color: 'green',
                    opacity: "1"
                }
            },
            customLanguages: {
                "en": {
                    fieldLabels: {
                        cardNumberLabel: "Credit Card Number",
                        expiryDateLabel: "Expiration Date",
                        cardVerificationCodeLabel: "CVC"
                    },
                    fieldPlaceholders: {
                        cardNumberPlaceholder: "xxxx xxxx xxxx xxxx",
                        expiryDatePlaceholder: "MM / YY ",
                        cardVerificationCodePlaceholder: "xxx"
                    },
                    errors: {
                        0: "Card number must be numeric",
                        1: "Card number not valid",
                        2: "Card type not recognised",
                        3: "Card number required",
                        4: "Card is expired",
                        5: "Invalid expiry date",
                        6: "Expiry date required",
                        7: "{0} code too short",
                        8: "{0} code too long",
                        9: "{0} code must be numeric",
                        10: "{0} code required"
                    }
                }
            }
        }
    }
}

Overriding an Existing Language

You can also modify the language to change the phrasing, words and dialects used

For the purpose of this exercise, the Romanian language is added in this example, to illustrate how multiple dictionaries can be added if customLanguages is defined as an array:

var customStyle = {
    iframe1 : {
        language : "en",
        customLanguages : [
        {
                "en" : {
                    fieldLabels: {
                        cardNumberLabel: "Credit Card Number",
                        expiryDateLabel: "Expiration Date",
                        cardVerificationCodeLabel: "CVC"
                    },
                    fieldPlaceholders: {
                        cardNumberPlaceholder: "xxxx xxxx xxxx xxxx",
                        expiryDatePlaceholder: "MM / YY ",
                        cardVerificationCodePlaceholder: "xxx"
                    },
                    errors : {
                        0: "Card number must be numeric",
                        1: "Card number not valid",
                        2: "Card type not recognised",
                        3: "Card number required",
                        4: "Card is expired",
                        5: "Invalid expiry date",
                        6: "Expiry date required",
                        7: "{0} code too short",
                        8: "{0} code too long",
                        9: "{0} code must be numeric",
                        10: "{0} code required"
                    }
                }
            },
            {
                "ro" : {
                    fieldLabels: {
                        cardNumberLabel: "Număr de card",
                        expiryDateLabel: "Data Expirarii",
                        cardVerificationCodeLabel: "CVC"
                    },
                    fieldPlaceholders: {
                        cardNumberPlaceholder: "Număr de card",
                        expiryDatePlaceholder: "LL / AA ",
                        cardVerificationCodePlaceholder: "CVC"
                    },
                    errors : {
                        0: "Numărul cardului poate conține numai numere",
                        1: "Numărul cardului nu este valid",
                        2: "Tipul de card nu este recunoscut, verificați din nou numărul dvs",
                        3: "Numarul cardului este necesar",
                        4: "Cardul a expirat",
                        5: "Data expirării cardului nu este validă",
                        6: "Data expirării necesară",
                        7: "Codul {0} este prea scurt pentru cartea de {1}",
                        8: "Codul {0} este prea lung pentru carte de {1}",
                        9: "Codul {0} poate conține numai numere",
                        10: "Codul {0} necesar pentru cartea de {1}"
                    }
                }
            }
    ],
        ...        
    }
};

Configuration File Example

Below is an example config file which sets the layout, background colour, input and label styles.

It also modifies the error and UI strings for the default language: English.

Example 2. Configuration File
var exampleConfig = {
    iframe: {
        language: 'en',
        errorFieldId: 'judopay-errors-2',
        showCardTypeIcons: true,
        cardTypeIconRight: '10px',
        cardTypeIconTop: '-2px',
        backgroundColor: '#e5e5e5',
        layout: "compact",
        fonts: [
            {
                family: 'Roboto',
                src: 'https://fonts.gstatic.com/s/roboto/v18/KFOmCnqEu92Fr1Mu72xKOzY.woff2',
                display: 'auto',
                style: 'normal',
                unicodeRange:
                'U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD',
                weight: '400'
            }
        ],
        styles: {
            default: {
                field: {
                    fontFamily: "'Roboto', sans-serif",
                    fontSize: '17px',
                    backgroundColor: '#e5e5e5',
                    borderTop: 'none',
                    borderRight: 'none',
                    borderLeft: 'none',
                    boxShadow: 'none',
                    margin: '-10px 0 -5px',
                    padding: '6px 0'
                },
                label: {
                    color: '#F77',
                    fontFamily: "'Roboto', sans-serif",
                    opacity: '0',
                    height: '15px',
                    fontSize: '8px',
                    display: 'inline-block',
                    transition: 'opacity 0.6s',
                    marginLeft: '5px',
                    position: 'relative',
                    bottom: '-10px',
                    zIndex: '100'
                }
            },
            focus: {
                field: {
                    backgroundColor: '#F0F0F0',
                    color: 'rgb(130, 130, 130)',
                    padding: '12px 6px 0',
                    fontSize: '16px',
                },
                label: {
                    opacity: "1",
                    color: 'rgb(130, 130, 130)'
                }
            },
            error: {
                field: {
                    backgroundColor: '#e5ecff',
                    padding: '12px 6px 0',
                },
                label: {
                    opacity: "1"
                }
            },
            valid: {
                field: {
                    backgroundColor: '#e5ffec',
                    color: 'green',
                    padding: '12px 6px 0',
                },
                label: {
                    color: 'green',
                    opacity: "1"
                }
            },
            customLanguages: {
                "en": {
                    fieldLabels: {
                        cardNumberLabel: "Credit Card Number",
                        expiryDateLabel: "Expiration Date",
                        cardVerificationCodeLabel: "CVC"
                    },
                    fieldPlaceholders: {
                        cardNumberPlaceholder: "xxxx xxxx xxxx xxxx",
                        expiryDatePlaceholder: "MM / YY ",
                        cardVerificationCodePlaceholder: "xxx"
                    },
                    errors: {
                        0: "Card number must be numeric",
                        1: "Card number not valid",
                        2: "Card type not recognised",
                        3: "Card number required",
                        4: "Card is expired",
                        5: "Invalid expiry date",
                        6: "Expiry date required",
                        7: "{0} code too short",
                        8: "{0} code too long",
                        9: "{0} code must be numeric",
                        10: "{0} code required"
                    }
                }
            }
        }
    }
}


Web SDK Errors

The Web SDK is designed to provide feedback quickly and clearly to the consumer.

To display error messages:

Add a div with the id judopay-errors on your page, ideally below the iframe:

<div class="judopay-errors"></div>;

 

The table below displays all errors that can be returned:

ID

Error String

0

Card number can only contain numbers

1

Card number not valid

2

Card type not recognised, please recheck your number

3

Card number required

4

Card is expired

5

Card expiry date is not valid

6

Expiry date required

7

{0} code too short for {1} card

8

{0} code too long for {1} card

9

{0} code can only contain numbers

10

{0} code required for {1} card

For errors 7-10; the numbers appear in curly brackets. These will be changed into values depending on the current state of the iframe form.

For example:

{0} will change to the card verification code acronym. This is named differently depending on the card type (e.g. CVC, CVV).

{1} will refer to the detected card type, for example Visa, Mastercard or Discover.

 

If the iframe has detected a Visa number, the following error message transform would occur:

{0} code too long for {1} card" -> "CVC code to long for Visa card

A similar error with an American Express card, the message would appear as:

"CID code too long for American Express card"

Handling 3D Secure 1.0 Payment Flows

The following guide is a full working example for use with Judopay's Web SDK, including how to handle 3D Secure Version 1.0 payment flows.

Prerequisites

Judopay's Web SDK requires some additional processing steps, in order to achieve a successful 3D Secure version 1.0 transaction.

This guide assumes the following prerequisites:   

  • You are already using Judopay's Web SDK to process standard payments.

  • You have a Judopay Sandbox Account to process test transactions while developing your app.

Note

The sample code uses PHP to directly call our API, however this can also be used as a guide in understanding how to call our API's by other methods.

Payment Flow - 3D Secure 1.0

WEBSDK_3DS_v1_Flow.png

Step

Description

Payload Example

One.png

Customise and Create the iFrame to present a Pay Button.

The Web SDK Pay Button is clicked.

var paymentPromise = judo.createToken(payment);

Two.png

Payment promise received.

{oneUseToken:
"F4e7PxeRZLA31G98SfcQcIlxPR8LtC8nBpFt1CDUV1JcSOHK56…lDcJh6HEpWrjV1NFmNYnGxTi0b6uuLIq9+xsDPg9e29PqW4c=",
cardLastfour: "7521",
endDate: "12/21", 
cardScheme: "Visa", 
cardFunding: "Credit"}
Three.png

A oneUseToken  is sent to the merchant's server for processing the payment request.

Use any method you desire to send the token to your back end server to process the request.

Four.png

Merchant's server sends the payment request to Judopay's servers for processing.

Use any method you desire to send the payment request to Judopay.

Judopay has 3 available methods:

  • PHP SDK

  • .NET SDK

  • Direct API Rest calls

Five.png

Merchant's front end javascript, receives the result sent back to the merchant's server via Judopay.

{receiptId: "614040999953559552",
result: "Requires 3D Secure", 
message: "Issuer authentication
required", 
acsUrl:
"https://gw1.judocommerce.com:4430/ACS/Default.aspx", 
md: "200821101926255601402655",
paReq:
"encryptedPaReqMessageWillBeHere",
result: "Requires 3D Secure"}
Six.png

Merchant's front end redirects the consumer to:

  • Issuer Service ACS URL

with the supplied fields including the return URL, for the Issuer to return the 3D Secure result.

  • acsURL :  The URL to redirect to. Received from step 5.

  • MD : The md received from step 5.

  • paReq : The paReq received from step 5.

  • TermUrl : the return URL the Issuer 3DS service sends the result back to.  

Example TermURL:   https://www.mydomain.com/return3ds.php?receiptId =’ + receiptID (Received from step 5 ).  

The reason to include the receiptID in your TermURL, is so that upon returning from the Issuer's 3D Secure service, you are given the receipt ID in the URL header which you can receive back.

Note: You will need this to complete the transaction.

 The values above should be POSTED to the acsURL.

Seven.png

The Issuer's 3D Secure service will return a result of the 3D Secure attempt, from the consumer to the TermURL.

You will receive the following back from the Issuer Service:

  • POSTed Variable : PaRes

  • POSTed Variable : MD  

  • A URL variable in your TermURL of the receiptId.

Eight.png

Your TermURL should submit these values to our API for payment processing.

PHP Sample PUT to Judopay's API endpoint using Curl:

  $receiptId =
  $_GET['receiptId'];
   
  // Set the receiptID = the ID received back from the Issuer
  Service.
   
  $MD =
  $_POST['MD'];
   
  // Set $MD = MD Received from 3DS Issuer
   
  $PaRes =
  $_POST['PaRes'];
   
  // Set $PaRes = PaRes Received from 3DS Issuer
   
  $data =
  json_encode(array('Md' =>$MD,'PaRes' =>$PaRes));
   
  // Encode to JSON format
   
  $userEncode =
  base64_encode("yourAPIToken:yourAPISecret");
   
  // Setup base64 Encoded ID / Password for submission
   
  $headers =
  array(
              'Content-Type:application/json',
              'Authorization: Basic
  '.$userEncode,
              'API-Version: 5.7.1',
  );
   
  // Set curl headers for the correct format and API Version
   
  $ch =
  curl_init("https://gw1.judopay-sandbox.com/transactions/".$receiptId);
   
  // Initialise the Curl Options (this uses our sandbox endpoint,
  this will differ for production)
   
  curl_setopt($ch,
  CURLOPT_RETURNTRANSFER, true);
   
  // Raw return format
   
  curl_setopt($ch,
  CURLOPT_CUSTOMREQUEST, "PUT");
   
  // Set curl to PUT
   
  curl_setopt($ch,
  CURLOPT_POSTFIELDS,$data);
   
  // Set the PUT fields to the $data above
   
  curl_setopt($ch,
  CURLOPT_HTTPHEADER, $headers);
   
  // Setup Curl headers
   
  $response =
  curl_exec($ch);
   
  // Execute the curl against the Judo endpoint
Nine.png

Judopay's servers will return either:

  • a receipt Object with the state of the transaction.

  • an error state with details of the error.

Example Receipt Object for a Success:

  {
  "receiptId":"614047134823608320",
  "yourPaymentReference":"a0b1e12",
  "type":"PreAuth",
  "createdAt":"2020-08-21T11:43:49.2501+01:00",
  "result":"Success",
  "message":"AuthCode:
  214733",
  "judoId":100183086,
  "merchantName":"wayne
  lawrence",
  "appearsOnStatementAs":"APL*/waynelawrence
  ",
  "originalAmount":"1.01",
  "amountCollected":"0.00",
  "netAmount":"1.01",
  "amount":"1.01",
  "currency":"GBP",
  "cardDetails":
  {"cardLastfour":"6891",
  "endDate":"1220",
  "cardToken":
  "lT1AakP6IkLlu8IVUBr5VDx7gcPV9VA1",
  "cardType":1,
  "cardScheme":
  "Visa",
  "cardFunding":"Credit",
  "cardCategory":"",
  "cardQualifier":0,
  "cardCountry":"FR",
  "bank":"Credit
  Industriel Et Commercial"},
  "consumer":
  {"consumerToken":"eaw3rv5Xy7wajdNt",
  "yourConsumerReference":"665e37f"},
  "device":{"identifier":"0b7fae264ee04cfba082c764169f52a5"},
  "riskScore":0,"threeDSecure":
  {"attempted":true,
  "result":"PASSED"},
  "externalBankResponseCode":"",
  "billingAddress":{}
  }
Ten.png

Depending on the state received from the receipt object, the merchant can display a success, decline or failure message.

Step 1: Customise and Create the iframe to Present a Pay Button

To customise and create the Judopay WebSDK iframe:

  1. Add the code snippet in your web page <HEAD>:

    https://web.judopay.com/js/0.0.11/judopay.min.js"></script>

    1. This example will use jQuery for a promise, so include the following in your web page <HEAD> :

      <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>

  2. In your <BODY> add a <DIV> tag where you want the iframe to appear.

    <div id="payment-iframe" width="100%"></div>

Note

This example uses the id: payment-frame. You can use whatever id you wish.

  1. In your <BODY> add a <DIV> tag where you want the errors in form entry to appear.

    1. For the purpose of this exercise, the class is named judopay-errors, and sets a style to be red.

      You can add any custom style you wish in your .CSS file.

      <div class="judopay-errors" style="color:red">Error Location</div>

  2. In your <BODY> add a button call: submit-payment-button for the iframe submission to Judopay.

    1. Set this to disabled. The iframe will enable it when the input is valid. 

      You can apply any CSS styling you wish to this button.

    2. <button id="submit-payment-button" name="submit-payment" disabled> Pay Now </button>

  3. In your <BODY> add the following script for a minimum iframe. 

    1. This example names this style configMinimum which is used when calling the iframe:

<script>var configMinimum = {
iframe: {
language: "en",
    	errorFieldId: 'judopay-errors',
    	showCardTypeIcons: true,
    	cardTypeIconRight: "10px",
    	cardTypeIconTop: "-2px",
    	backgroundColor: "#FFFFFF",
    	layout: "compact",
    	enabledPaymentMethods: ['CARD'],
    	isCountryAndPostcodeVisible: false,
    	errorsDisplay: "HIDE_UNDER_FIELDS",
    	disableUnderline: false,
    }
}
</script>

For the purpose of this exercise, this sample config sets the following options for the iframe:

  • Default language will be English “en” 

  • iframe error field location set to “judopay-errors” as set in (4) above

  • Card Icons will display when the card entry is recognised 

  • iframe Background Colour is White “#FFFFFF” 

  • iframe layout set to compact

  • iframe accepts Credit Card Entry “[‘CARD’]”

  • iframe does not show Post Code entry

  • iframe Errors will not display under the fields

  • iframe will underline the fields and highlight during entry

  1. Create the iframe in a <SCRIPT> tag:

var judo = new JudoPay("yourAPIToken", true);
var payment = judo.createCardDetails('payment-iframe',configMinimum);

Note

The iframe is created in your <SCRIPT> location.

  1. Alter yourAPIToken to match your Sandbox API Token.

  2. true’ lets the iframe know it’s running on sandbox.

    Set this to ‘false’ when you wish to go live and use a ‘live’ API Token

  3. ‘payment-iframe’ is where the iframe will load as defined in step (3) above.

  4. ‘configMinimum’ uses the style called configMinimum as defined in step (5(a)) above.

iFrame.png

Complete customisation of the iframe settings and styles can be found here.

Step 2: Obtain the Payment Promise

Once you have an established Judopay WebSDK iframe and after the consumer has entered valid card details (the iframe handles the validation and errors of this entry), on clicking the Pay Now button (submit-payment-button) you will obtain a promise from Judopay's servers which will return a oneUseToken for use within 30 minutes to transact the payment.

Note

This is a happy path example, and you should enhance this code with try / catch surrounds.

 

The following script:

  1. Adds an action to the payment button.

  2. Checks if the payment method is valid.

  3. Calls Judopay to obtain a oneUseToken. 

  4. It then proceeds to validate the result as having received a oneUseToken.

To setup a payment promise on the Pay Now button:

var paymentPromise = "";
$("#submit-payment-button").click(function(){
   if (judo.getPaymentMethod()=="CARD") {
  	var paymentPromise = judo.createToken(payment);
  	paymentPromise.then(function(result) {
     	if (typeof result.error !== 'undefined') {
        	if (typeof result.oneUseToken !== 'undefined') {
 
            	  	// This is where the token is sent to your back office for payment
         	// request (expanded example below)
 
        	}
     	} 
  	}
   }
}

Step 3: A oneUseToken is sent to Merchant's Server

This example expands on Step 2: Obtain the Payment Promise above, with the source code to handle the oneUseToken and then submit this to the merchant’s server.

  1. Insert this quote into the sample above.

    This is where the token is sent to your back office for the payment request

  2. This sample jQuery calls a php file called handle3.php which will submit the request to Judo and return the result:

$.get("handle3.php",{myToken : result.oneUseToken}, function(data) {

// Code in here to handle the result from the oneUseToken Request will be inserted
// Here and handled in Step 5: Handle the Response from Judopay's Servers
}
);

Step 4: Merchant Server Sends Payment Request to Judopay

This example should be called handle3.php and is the receiving handler from the Step 3: A oneUseToken is sent to Merchant's Server section above.

This example:

  • Receives a oneUseToken from the promise handler step.

  • Submits a £1.00 payment request to Judopay for payment processing using API version 5.7.1

  • Uses gw1.judopay-sandbox.com as the endpoint.

  • For production use the production credentials (APIToken / APISecret) and the endpoint gw1.judopay.com

  • Will return the JSON response received from Judopay's Servers:

<?php
header('Access-Control-Allow-Origin: *');
header('Content-Type: application/json');
 
$OneUseToken = $_GET["myToken"];
 
$userEncode = base64_encode("yourAPIToken:yourAPISecret");
$data=json_encode(
array(
'oneUseToken' =>$OneUseToken,
'yourConsumerReference' =>substr(md5(rand()), 0, 7),
'yourPaymentReference' => substr(md5(rand()), 0, 7), 	
'judoId' => 'yourJudoId',
'amount' => 1.0,
'currency' => "GBP"
));
$headers = array(
Content-Type:application/json',
'Authorization: Basic '.$userEncode,
'API-Version: 5.7.1',
);
$ch = curl_init("https://gw1.judopay-sandbox.com/transactions/payments");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_POSTFIELDS,$data);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
$response = curl_exec($ch);
 
echo $response;
 
?>
  1. Change yourAPIToken:yourAPISecret for your API Token and your API Secret.

    Warning

    IMPORTANT: Do not omit the :

  2. Change yourJudoId for your JudoID.

Step 5: Handle the Response from Judopay's Servers

Extend the handler in Step 3: A oneUseToken is sent to Merchant's Server to handle the response.

Note

This example handles a 3D Secure request if required.

$.get("handle3.php",{myToken : result.oneUseToken}, function(data) {

   if (data.result=="Requires 3D Secure") {
      // Create a Hidden form to Submit to the 3DS Issuer
      const form = document.createElement('form');
      form.method = 'post';
      form.action = data.acsUrl;
      const hiddenField = document.createElement('input');
      document.createElement('input');
      hiddenField.type = 'hidden';
      hiddenField.name = 'MD';
      hiddenField.value = data.md;
      form.appendChild(hiddenField);
      const hiddenField2 = document.createElement('input');
      document.createElement('input');
      hiddenField2.type = 'hidden';
      hiddenField2.name = 'PaReq';
      hiddenField2.value = data.paReq;
      form.appendChild(hiddenField2);
      const hiddenField3 = document.createElement('input');
      document.createElement('input');
      hiddenField3.type = 'hidden';
      hiddenField3.name = 'TermUrl';
      hiddenField3.value = 'https://www.yourdomain.com/return3ds.php?receiptId='+data.receiptId;
      form.appendChild(hiddenField3);
      document.body.appendChild(form);

      // Submit the form to redirect the user to the 3DS Issuer
      form.submit();
   }
}
);
  • Checks if the result returned from Judopay's Servers is Requires 3D Secure.

  • Creates a Hidden Form to POST to the Issuer's acsURL.

  • Adds Hidden Fields required for the 3D Secure Post.

  • Declares a termURL (https://www.yourdomain.com) for the Issuer Service to return to.

    • For the purpose of this example, the termURL will call the return file: return3ds.php.

This is a return location on your server (the result of the 3D Secure Challenge will be POSTed to this location). You should change this to your own public facing domain.

Note

The termURL includes the current receiptID which is required later to complete the 3D Secure payment.

It is added to the termURL in order for the Issuer's 3D Secure service to return it back.

 

Caution

You will have no control over the Issuer Service 3D Secure screen and can only complete a transaction when the Issuer Service returns to you.

If the consumer abandons at this stage, you will have no return.

Step 6: Re-Direct to the Issuer Service Challenge Screen

The source code from Step 5: Handle the Response from Judopay's Servers, will automatically submit the 3D Secure parameters to the required Issuer Service.

The consumer will be re-directed to the Issuer Service 3D Secure Challenge Screen:

ACS_Simulator.png

Step 7: Issuer Service Return

If the consumer completes the 3D Secure challenge screen:

If the consumer chooses to abandon at this stage, you will receive a no reply POST.

Step 8: Handle the Issuer 3D Secure Result

This example is the return3ds.php file as declared in the sample code from Step 5: Handle the Response from Judopay's Servers.

The following sample POSTs the returned 3D Secure response back to Judopay via an API call to the /transactions endpoint, with the given receiptId.

<?php

$receiptId = $_GET['receiptId'];1

if (empty($receiptId))  {
  echo '<BR> Sorry there was an error - missing receiptId';2
} else {
  $MD = $_POST['MD'];
  $PaRes = $_POST['PaRes'];
  $data = json_encode(array('Md' =>$MD,'PaRes' =>$PaRes));3
  $userEncode = base64_encode("yourAPIToken:yourAPISecret");4
  $headers = array(
  'Content-Type:application/json',
  'Authorization: Basic '.$userEncode,
  'API-Version: 5.7.1',
  );
  $ch = curl_init("https://gw1.judopay-sandbox.com/transactions/".$receiptId);5
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);6
  curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
  curl_setopt($ch, CURLOPT_POSTFIELDS,$data);
  curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
  $response = curl_exec($ch);
  echo $response;7
}
?>

1

receiptId is received from the termURL (Sent back from the Issuer 3D Secure Service).

2

A simple check: If no receiptId is set = not proceed. It will just fail.

3

Sets the JSON payload to send to Judopay's Servers.

4

Replace: yourAPIToken:yourAPISecret with your Sandbox API Token and API Secret.

5

Curl Options sets the endpoint to:

For Sandbox: https://gw1.judopay-sandbox.com/transactions/

For Production change to: https://gw1.judopay.com/transactions/ including the Production API Token and Production API Secret.

6

This will complete or fail the transaction accordingly.

7

The sample just echo’s the response received from Judopay's Servers (JSON Payload). The response will either be:

SUCCESS | DECLINED | ERROR

Receipt Object - SUCCESS

From the Handle the Response from Judopay's Servers section above, the $response will either be a:

  • receiptobject or

  • an ERROR

which you should handle accordingly. This example just echo’s the result from Judopay's Servers.

Example: Receipt Object for a Successful Transaction:

{"receiptId":"615495218204119040",
"yourPaymentReference":"bbd5067",
"type":"Payment",
"createdAt":"2020-08-25T11:38:06.7811+01:00",
"result":"Success",
"message":"AuthCode: 058967",
"judoId":100183086,
"merchantName":"testmerchant",
"appearsOnStatementAs":"APL*/testmerchant ",
"originalAmount":"1.00",
"netAmount":"1.00",
"amount":"1.00",
"currency":"GBP",
"cardDetails":
{"cardLastfour":"6891",
   "endDate":"1220",
   "cardToken":"DgoimaGqpm8ngRKnAl7xgXvFS0zuf3JQ",
   "cardType":1,
   "cardScheme":"Visa",
   "cardFunding":"Credit",
   "cardCategory":"",
   "cardQualifier":0,
   "cardCountry":"FR",
   "bank":"Credit Industriel Et Commercial"},
"consumer":
{"consumerToken":"dQxfNBY5cddXeMhe",
   "yourConsumerReference":"3190912"
},
"riskScore":0,
"threeDSecure":
{"attempted":true,
   "result":"PASSED"},
"externalBankResponseCode":"",
"billingAddress":{}
}

Parameter

Description

receiptId

Unique 18 digit reference for the transaction.

yourPaymentReference

Unique payment reference you provided, or generated if not provided.

type

Type of transaction:

  • Payment

  • Refund

  • Void

createdAt

Date and Time stamp of the transaction.

result

Result of the transaction:

  • Success

  • Declined

  • Failed

  • Error

message

Further details of the result, for example:

  • Auth Code

  • reason for failure

judoId

The judoId the transaction was associated with.

merchantName

Merchant Name.

appearsOnStatementAs

The name the consumer will see on their statement.

originalAmount

Original amount of the transaction.

netAmount

Net amount of the transaction.

currency

Transaction currency.

cardDetails

Array of card details.

cardLastfour

Last 4 Digits of the consumer's card.

endDate

Expiry date of the consumer's card.

cardToken

Unique card token for this card, stored in Judopay's card vault.

Note: This can be used to make token payments in the future.

cardType

Card Type.

cardScheme

Card Scheme.

cardFunding

Card Funding Scheme.

cardCategory

Card Category.

cardQualifier

Card Qualifier.

cardCountry

Card Country of origin.

bank

Bank for the Card.

consumer

Consumer Array.

consumerToken

Unique consumer token to be used in conjunction with cardToken to make future payments.

yourConsumerReference

Unique consumer reference you provided in the originating transaction.

riskScore

JudoShield risk score for the transaction:

  • 0 = Low

  • 100 = High

threeDSecure

3D Secure Array.

attempted

If 3D Secure was attempted.

Boolean.

result

Result of the 3D Secure attempt.

externalBankResponseCode

Any other External Response Codes.

billingAddress

Billing Address.

(If provided in the originating transaction).

Step 9: Redirect the Consumer to the Appropriate Location

As a result of the receiptObject received in Step 5: Handle the Response from Judopay's Servers, you should redirect the consumer accordingly.

For example, if the result = SUCCESS redirect the consumer to the Success Page, else ERROR.

Note

You can store any of the receiptObject details in your own back office systems for recall later.

You could store the:

  1. cardToken

  2. consumerToken

  3. cardDetails

    against the consumer's record and offer a quick checkout option for future transactions.

Using those tokens bypasses the need to enter any card details if required.