Hosted Payments Advanced Integration Guide

Change Log

2020-01-31

  • Added missing screenshots
  • Updated notes on “fingerprint” stating that it is only potentially useful for completely static payment forms. 
  • Added example of raw HTTP post-back to integrator
  • Miscellaneous spelling and grammar fixes

What is Hosted Payments?

Hosted Payments is a secure checkout service provided by PayJunction which allows merchants and integrators to collect card payments without directly touching the sensitive card information. This allows merchants and integrators to drastically lower the PCI-DSS audit requirements for their business or software on Card-Not-Present channels.

How It Works

Hosted Payments works by redirecting the end user’s browser to the secure checkout page provided by PayJunction. As the software is completely hosted and controlled by PayJunction, the sensitive card information never passes through the merchant or integrator’s software and servers. Arbitrary data can be passed through from initiation of the redirect to a custom URL allowing the automation of the payment workflow.

HTML Forms vs URL Links

A common question is, should I use an HTML form or a link? The short answer is that it depends on what your platform allows and what information you are collecting from the card holder. If you are taking payments for a specific, invariable amount and with an invariable quantity, a link is often the best choice. Otherwise an HTML form might be the better option.

The Basics

Sandbox vs Production Domains

For security, PayJunction completely separates the sandbox and production systems, including different URL domains. All test transactions during initial development should be sent to the sandbox domain, payjunctionlabs.com while production transactions must go to the payjunction.com domain. In this guide, all examples will use the payjunctionlabs.com sandbox domain. To use the production server, simply change the domain to payjunction.com along with the Shop Name used to identify the specific merchant’s account. 

Example

Sandbox

HTML Form
<form method="POST" action="https://www.payjunctionlabs.com/trinity/quickshop/add_to_cart_snap.action">
  <input type="hidden" name="store" value="mySandboxShopName">
  <input type="hidden" name="description" value="Widget Cleaning Service">
  <input type="hidden" name="price" value="100.00">
  <input type="hidden" name="quantity" value="1">
  <input type="hidden" name="need_to_tax" value="no">
  <input type="hidden" name="need_to_ship" value="no">
  <input type="submit" name="submit"value="Purchase Now">
</form>
Hyper Link / URL

https://www.payjunctionlabs.com/trinity/quickshop/add_to_cart_snap.action?store=mySandboxShopName&description=Widget+Cleaning+Service&price=100.00&quantity=1&need_to_tax=no&need_to_ship=no

Production

HTML Form
<form method="POST" action="https://www.payjunction.com/trinity/quickshop/add_to_cart_snap.action">
  <input type="hidden" name="store" value="mySandboxShopName">
  <input type="hidden" name="description" value="Widget Cleaning Service">
  <input type="hidden" name="price" value="100.00">
  <input type="hidden" name="quantity" value="1">
  <input type="hidden" name="need_to_tax" value="no">
  <input type="hidden" name="need_to_ship" value="no">
  <input type="submit" name="submit"value="Purchase Now">
</form>
Hyper Link / URL

https://www.payjunction.com/trinity/quickshop/add_to_cart_snap.action?store=mySandboxShopName&description=Widget+Cleaning+Service&price=100.00&quantity=1&need_to_tax=no&need_to_ship=no

Invoice Mode & Shopping Cart Mode

Depending on which endpoint is used in the URL, Hosted Payments can be used in either “Invoice Mode” or “Shopping Cart Mode”. The primary difference between these two modes is whether the end user is immediately sent to the checkout page upon clicking the link or button, or if they are taken to a cart to confirm the item and quantity of products/services they are purchasing. 

Invoice Mode

https://www.payjunctionlabs.com/trinity/quickshop/add_to_cart_snap.action

Shopping Cart Mode

https://www.payjunctionlabs.com/trinity/quickshop/add_to_cart.action

When using Hosted Payments in Shopping Cart mode, the Hosted Payment shop must have the method set to POST in the Shop Settings in order to receive the details on the individual line items added to the cart.

Additional URLs for Shopping Cart Mode

View Shopping Cart

https://www.payjunctionlabs.com/trinity/quickshop/view_cart_init.action

Go to Checkout

https://www.payjunctionlabs.com/trinity/quickshop/check_out_init.action

These two endpoints do not change the contents of the cart.

Required Fields

In order to initiate a Hosted Payments transaction, five fields with values are required:

  • Hosted Payments Shop name
  • Description of the item or service
  • Amount to charge per unit
  • Unit quantity
  • Tax indicator
  • Shipping indicator

Based on the above, the simple example of a Hosted Payments form might be:

<label>Widget Cleaning Service - $100</label>
<form method="POST" action="https://www.payjunction.com/trinity/quickshop/add_to_cart_snap.action">
  <input type="hidden" name="store" value="myShopName">
  <input type="hidden" name="description" value="Widget Cleaning Service">
  <input type="hidden" name="price" value="100.00">
  <input type="hidden" name="quantity" value="1">
  <input type="hidden" name="need_to_tax" value="no">
  <input type="hidden" name="need_to_ship" value="no">
  <input type="submit" name="submit" value="Purchase Now">
</form>

Without additional styling, the above will look similar to the following:

Or as a link:

https://www.payjunction.com/trinity/quickshop/add_to_cart_snap.action?store=myShopName&description=Widget+Cleaning+Service&price=100.00&quantity=1&need_to_tax=no&need_to_ship=no

If using a link, the values will need to be URL encoded. Web browsers automatically convert the values from an HTML form into URL encoded data before submission. 

Field

Format

Description

store

String (Case-sensitive)

Sets the Hosted Payments Shop to use. This tells the service which PayJunction account to process through.

description

String

A description of the item or service being paid for.

price

Number

Sets the amount to charge per unit. If submitted as a float value both the tenths and hundredths must be present. 


Valid: “1”, “1.00”

NOT valid: “1.0”

quantity

Number

An integer value indicating the number of units to charge for.

need_to_tax

“yes” or “no”

Indicates if tax needs to be applied to the transaction total.

need_to_ship

“yes” or “no”

Indicates if a shipping amount needs to be applied to the transaction total. 

A full listing of reserved fields and expected data format for each reserved parameter is included in the Reserved Fields section of this guide.

Including User Input

Sometimes our form is mostly static but we need some additional input from the user. This could be the amount to pay, the account/location to make the payment to, or the quantity. Thankfully, HTML forms make this task easy.

To allow the user to specify the quantity of an item we could simply update our previous example and change the “quantity” input element from type “hidden” to “text” and add a label element so the user knows what to put in the field*:

<label>Widget Cleaning Service - $100</label>
  <form method="POST" action="https://www.payjunction.com/trinity/quickshop/add_to_cart_snap.action">
  <input type="hidden" name="store" value="myShopName">
  <input type="hidden" name="description" value="Widget Cleaning Service">
  <input type="hidden" name="price" value="100.00">
  <label>
    <span>Quantity:</span>
    <input type="text" name="quantity" value="1">
  </label>
  <input type="hidden" name="need_to_tax" value="no">
  <input type="hidden" name="need_to_ship" value="no">
  <input type="submit" name="submit" value="Purchase Now">
</form>

Our example now looks like the following:

Perhaps we have more than one location and we want the user to specify. By using multiple Hosted Payment Shops we can give the user a drop-down selection to choose from:

<div style="padding:10px; border:1px solid; border-radius:5px; width: 220px;">
  <label>Widget Cleaning Service - $100</label>
  <br></br>
  <div style="display: block; width: 200px; margin: 5px;">
    <form method="POST" action="https://www.payjunction.com/trinity/quickshop/add_to_cart_snap.action">
      <label>
        <span>Select Your Service Location:</span>
        <select name="store">
          <option value="mySBShop">Santa Barbara</option>
          <option value="myGoletaShop">Goleta</option>
        </select>
      </label>
      <br></br>
      <input type="hidden" name="description" value="Widget Cleaning Service">
      <input type="hidden" name="price" value="100.00">
      <label>
        <span>Quantity:</span>
        <input type="text" name="quantity" value="1">
      </label>
    <input type="hidden" name="need_to_tax" value="no">
    <input type="hidden" name="need_to_ship" value="no">
    <input type="submit" name="submit" value="Purchase Now">
  </form>
</div>

    </div>

</div>

Our minimally styled form now looks like this:

Reserved Fields

Note: In order for reserved fields to record data in PayJunction, instead of just passing them through to the relay, the fields must be set to either Display or Required in the Hosted Payments Shop Field settings.

NOTE: Instructions for accessing and updating Shop Field settings for Hosted Payments: https://support.payjunction.com/hc/en-us/articles/115000259913-How-to-update-fields-on-checkout-page-for-Hosted-Payment-Shops

The following fields will cause data to be validated and saved in PayJunction. If field validation fails, the data for that field will not be passed through to the third party server. If certain data must get through to the third party server, use a custom field name instead or make sure the field is set to Required in the Shop Field settings to force the value to be corrected at checkout by the card holder.

Name

Validation

Additional Notes

invoice

ASCII

 

billingFirstName

ASCII

 

billingMiddleName

ASCII

 

billingLastName

ASCII

 

billingPhone

ASCII

 

billingFax

ASCII

 

billingEmail

Valid Email Address

RFC 2822

billingCustomerId

ASCII

 

billingCompany

ASCII

 

billingCountry

ASCII

 

billingStreetAddress

ASCII

 

billingCity

ASCII

 

shippingFirstName

ASCII

 

shippingMiddleName

ASCII

 

shippingLastName

ASCII

 

shippingStreetAddress

ASCII

 

shippingCity

ASCII

 

shippingTerritory

ASCII

 

shippingCountry

ASCII

 

shippingZip

ASCII

 

shippingCustomerId

ASCII

 

shippingCompany

ASCII

 

shippingDepartment

ASCII

 

shippingOccupation

ASCII

 

shippingTitle

ASCII

 

shippingEmail

ASCII

 

shippingPhone

ASCII

 

shippingFax

ASCII

 

relay

HTTPS URL

 

echo

None

 

Passing Data to a Third Party Server

The Hosted Payments service can be configured to send data about the transaction, along with arbitrary data, by setting the “relay” field to a valid HTTPS address. This will cause Hosted Payments to redirect the user’s browser to the provided address, using the HTTP method (GET or POST) set in the Shop Settings configuration, after the payment has been collected. 

NOTE: There is currently no way to detect and handle declined transactions on Hosted Payments without logging into the PayJunction Virtual Terminal (VT) web interface to view the declined transaction. The redirect will only occur when the transaction is approved by the card issuing bank and PayJunction.

NOTE: The HTTP method must be set to POST in the Shop Settings if multiple items will be added to the cart.

Custom Fields - Passing Arbitrary Data 

The “echo” field can be used to create your own keywords and values to be passed to the third party server. To do so, simply provide a URL encoded string with the keywords and values, separated by an ampersand. 

Example:

Original Data

{
  "myCustomField1": "Some arbitrary data.",
  "myCustomField2": "Data! With~Lots+of&Symbols"
}

Formatted and URL Encoded Values

myCustomerField1=Some%20arbitrary%20data.&myCustomField2=Data%21%20With~Lots%2Bof%26Symbols

Web Form

<input type=”hidden” name=”echo” value=”myCustomerField1=Some%20arbitrary%20data.&myCustomField2=Data%21%20With~Lots%2Bof%26Symbols”>

The browser should take care of the encoding before sending to the server. For a payment link however...

Payment Link 

https://www.payjunctionlabs.com/trinity/quickshop/add_to_cart_snap.action?store=YourShopName&price=1.00&description=Payment+on+Invoice&need_to_ship=no&need_to_tax=no&relay=https%3A%2F%2Fyour.secure.site%2Fhostedpayments&echo=myCustomerField1%3DSome%2520arbitrary%2520data.%26myCustomField2%3DData%2521%2520With~Lots%252Bof%2526Symbols

Note that in order to include it directly in the link, we had to URL encode the entire string before assigning it to the echo parameter. 

Code Examples

PHP

$custom_data = http_build_query(
    array(
        "myCustomField1" => "Some arbitrary data.",
        "myCustomField2" => "Data! With~Lots+of&Symbols"
    )
);
echo '<input type="hidden" name="echo" value="$custom_data">';

Javascript

let raw_data = {myCustomField1: "Some arbitrary data.", myCustomField2: "Data! With~Lots+of&Symbols"},
    custom_data = Object.keys(raw_data)
        .map(fieldName => `${fieldName}=${encodeURIComponent(raw_data[fieldName])}`)
        .join('&')
;

Receiving the Data Passed to a Third-Party Server

Data Response Format

When the end-user’s browser performs the post back to the relay URL it will set the Content-Type header to application/x-www-form-urlencoded

Whether or not this will automatically be converted into an object or associative array for consumption in your code will depend on the HTTP library used. 

Data Response Keys and Value Descriptions

Other than the custom field names supplied by you, the following table shows the standard fields sent to the server:

transaction_code

“00” & “85” are Approved values

tracking_code

PayJunction generated tracking_code for this order. In the REST API, this is referenced as transactionId

fingerprint

The fingerprint code that was generated for payment button. This is only useful for payment buttons/forms that are completely static and do not use arbitrary values of any kind (such as a variable amount).  

store

The store id for the payment button

qs_total

The total dollar amount charged to the customer's card.

qs_total_shipping

The total shipping amount for the order

qs_total_tax

The total tax amount for the order

qs_number_last_four_digits

The last four digits of the credit card the customer used to make a purchase.

qs_cc_name

The name on the credit card.

qs_cc_city

The credit card billing statement city.

qs_cc_state

The credit card billing statement state.

qs_cc_street

The credit card billing statement street.

qs_cc_zip

The credit card billing zip code.

qs_cc_country

The credit card billing statement country.

qs_cc_email

The email address as set by billingEmail

qs_o_name

The name of the person to ship this order to.

qs_o_street

The street of the shipping address.

qs_o_city

The city of the shipping address.

qs_o_state

The state of the shipping address.

qs_o_zip

The zip code of the shipping address.

qs_o_e_mail

The e-mail address as set by shippingEmail.

qs_o_day_phone

A daytime phone number extension

qs_o_day_phone_extension

The daytime phone number extension.

qs_o_night_phone

A nighttime phone number for the customer.

qs_o_night_phone_extension

A nighttime phone number extension.

invoice

The invoice number that was entered for the transaction.

qs_o_notes

Any special notes relevant to the order.

In addition, for each product the customer has in his shopping cart, the following fields will be populated, with x representing the product index:

qs_identifier_x

The short product description.

qs_description_x

A brief description of the product.

qs_quantity_x

The quantity to add to the cart.

qs_price_x

Cost for each item.

qs_need_to_ship_x

A value of “Yes” means that this item needs to be shipped.

qs_s_h_amount_x

The shipping & handling cost for each item.

qs_need_to_tax_x

A value of “Yes” means that this item was taxed.

qs_tax_amount_x

The amount to tax for each item.

Error: For the above breakout of individual cart items, the Shop Settings must have POST selected for the Method. Instructions for accessing Hosted Payments Shop Settings: https://support.payjunction.com/hc/en-us/articles/115000089613-How-Do-I-Manage-My-Hosted-Payment-Shops-

Each product/line item added to the cart will be given an index number, starting from 1. There is no limit to the number of products/line items you can add to the cart.

Hosted Payments will not combine line items added to the cart, even if they share the same price and identifier. Each request sent to either add_to_cart.action or add_to_cart_snap.action will create a new line item in the cart, even if the same line item already exists in the cart. 

Example Raw HTTP Post-Back sent to the URL relay

The following example is with the HTTP Method in Shop Settings set to POST which is the recommended setting. 

POST /test HTTP/1.1
Host: pjtest.requestcatcher.com
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Cache-Control: max-age=0
Connection: keep-alive
Content-Type: application/x-www-form-urlencoded
Cookie: _ga=GA1.2.640822999.1580432561; _gid=GA1.2.1102145283.1580520970
Origin: https://d1.www.payjunctionlabs.com
Referer: https://d1.www.payjunctionlabs.com/trinity/quick-shop/receipt
Sec-Fetch-Mode: nested-navigate
Sec-Fetch-Site: cross-site
Sec-Fetch-User: ?1
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36

relay=https%3A%2F%2Fpjtest.requestcatcher.com%2Ftest&store=REDACTED&billingLastName=Doe&billingEmail=no-email%40payjunction.com&billingFirstName=John&invoice=1&myCustomField2=Data%21+With%7ELots%2Bof%26Symbols&myCustomerField1=Some+arbitrary+data.&qs_tracking_code=8571&response_code=00&transaction_code=00&tracking_code=8571&qs_number_last_four_digits=4444&number_last_four_digits=4444&qs_total=200.00&qs_total_shipping=&qs_total_tax=&qs_cc_name=John+Doe&qs_cc_street=1903&qs_cc_city=&qs_cc_state=&qs_cc_zip=93101&qs_cc_country=&qs_cc_email=no-email%40payjunction.com&qs_cc_day_phone=&qs_cc_day_phone_extension=&qs_cc_night_phone=&qs_cc_night_phone_extension=&qs_o_name=&qs_o_street=&qs_o_city=&qs_o_state=&qs_o_zip=&qs_o_country=&qs_o_e_mail=&e_mail=&qs_o_day_phone=&qs_o_day_phone_extension=&qs_o_night_phone=&qs_o_night_phone_extension=&qs_o_notes=&qs_identifier_1=&qs_description_1=Widget+Cleaning+Service&qs_quantity_1=2&qs_price_1=100.00&qs_need_to_ship_1=no&qs_s_h_amount_1=&qs_need_to_tax_1=no&qs_tax_amount_1=

Validating and Updating Transaction Details

As mentioned above, if a field is not set to either Display or Required in the Shop Fields configuration, that data will not be saved in the transaction details. So how do we handle the situation where we want to hide one or more fields, but still have the data saved for subsequent use? Or what if the field was displayed, but the end user changed it at checkout?

While the relay webhook will echo back what was originally sent to the checkout form, so that integrations receive the data expected, this is not true when fetching the transaction details at a later date with the REST API or by logging into the Virtual Terminal web portal. If we want to make sure the information is accurate, or update local records based on changes made by the user during checkout, we need to use the REST API. Such corrections could include the name, address, or other billing information for the customer. 

It is also strongly encouraged to validate transaction details with the REST API. Due to the asynchronous nature of using a secure checkout with webhooks, it is theoretically possible for a malicious user to try and trick a platform into thinking that a transaction has been paid. To protect against this type of fraud and hacking, an integrated platform should always leverage the REST API to verify the transaction exists and for the correct amount in the PayJunction account. 

Hosted_Payments_Integration_Workflow_Diagram__1_.png