# EXCLUDE URI's from caching
<If "%{THE_REQUEST} =~ m#/page_name#">
<IfModule mod_headers.c>
Header set Cache-Control "private"
</IfModule>
</If>
wp_get_current_user()
Purpose
- Retrieves the current user object.
Implementation
- Include in
- Plugin
- functions.php of active theme
<?php
$current_user = wp_get_current_user();
Example of output of Object $current_user
WP_User Object
(
[data] => stdClass Object
(
[ID] => 8
[user_login] => subscriber
[user_pass] => {Users Password}
[user_nicename] => subscriber
[user_email] => subscriber@sblik.com
[user_url] =>
[user_registered] => 2023-05-02 19:41:27
[user_activation_key] =>
[user_status] => 0
[display_name] => Subscriber Sblik
)
[ID] => 8
[caps] => Array
(
[subscriber] => 1
)
[cap_key] => wp_capabilities
[roles] => Array
(
[0] => subscriber
)
[allcaps] => Array
(
[read] => 1
[level_0] => 1
[subscriber] => 1
)
[filter] =>
[site_id:WP_User:private] => 1
)
WordPress Get Logged In User Info for Front End
Objective
Get logged in user information to use in javascript.
- In order to use user information on the front end with Javascript or jQuery, you can use wp_localize_script
- wp_localize_script creates a Javascript object that can be accessed by javascript.
- function: wp_localize_script($handle, $nameOfObject, $dataStoredInObject)
- $handle: script handle the data will be attached to
- $nameOfObject: Name of Javascript Object
- $dataStoredInObject: single or multi-dimensional array
- Reference
Step 1: How to include wp_localize_script in a plugin
<?php
/**
* Plugin Name: Bliksem Sandbox Plugin
* Version: 1.0.0
* Description: Sandbox development for
* Author: Andre Nell
* Author URI: http://www.simplifysmallbiz.com/
*
*
* @package Bliksem
* @author Andre Nell
* @since 1.0.0
*/
if (!function_exists('get_option')) {
header('HTTP/1.0 403 Forbidden');
die; // Silence is golden, direct call is prohibited
}
// DEFINE CONSTANTS
define('BS_NAME_VERSION', '1.0.1');
define('BS_NAME_PLUGIN_URL', plugin_dir_url(__FILE__));
// IMPLEMENTATION
function bs_enqueue_bs_frontend_scripts()
{
global $current_user;
$current_user = wp_get_current_user();
wp_register_script('bs-sandbox-js', BS_NAME_PLUGIN_URL . 'js/sandbox.js', array('jquery'), '1.0.0', true);
wp_enqueue_script('bs-sandbox-js');
wp_localize_script('bs-sandbox-js', 'theUser', array(
'roles' => $current_user->roles,
));
}
add_action('wp_enqueue_scripts', 'bs_enqueue_bs_frontend_scripts');
Step2: How to access the data stored in the Javascript Object created in Step 1
jQuery(window).load(function ($) {
var user_roles = theUser.roles;
console.log(user_roles);
if (jQuery.inArray("Subscriber", user_roles)) {
console.log("is in array");
} else {
console.log("is NOT in array");
}
});
LawPay Pament Integration
https://developers.affinipay.com/quickstart/quickstart.html
- You can integrate your website or application with AffiniPay, ClientPay, CPACharge, or LawPay to take payments securely using the AffiniPay Payment Platform.
- AffiniPay’s integration tasks are written for developers;
- for a successful integration, you should be familiar with writing code that interacts with REST endpoints using the HTTP protocol.
1 Connect to the AffiniPay Payment Platform
- To take payments for yourself, connect using API keys
- When you run transactions through the AffiniPay Payment Gateway, you need your:
- Public key that identifies you to AffiniPay.
- Secret keys that authenticate API requests made on your behalf.
- Account IDs that specify the credit account or eCheck account associated with each transaction.
2 Create payment forms using hosted fields
https://developers.affinipay.com/collect/create-payment-form-hosted-fields.html
- AffiniPay hosted fields protect your payment page by tokenizing payment information. They provide SAQ-A PCI compliance, the highest level of PCI compliance. Hosted fields are <iframe> elements sourced from AffiniPay’s servers that contain a single corresponding <input> element. These iframes replace the input elements on your form that contain payment information.
- Hosted fields should be integrated into your site by a developer. This integration requires web developer skills as well as the ability to pass information to a backend server and then to AffiniPay. If you have questions, contact AffiniPay Support.
Hosted Fields Versioning
- With version 1.4.0, hosted fields now supports enabling surcharge, disabling and enabling fields, focusing on a field, and clearing a field.
- The AffiniPay hosted fields JavaScript library (
fieldGen.js
) is versioned. The versioning URL is: - https://cdn.affinipay.com/hostedfields/
/fieldGen_ .js - For example, the URL for version 1.4.0 is:
- https://cdn.affinipay.com/hostedfields/1.4.0/fieldGen_1.4.0.js
- For SRI and
integrity
attribute purposes, here are the SHA384 digests: - 1.4.0 Release
integrity="sha384-2LuR5n01lipNZjmgOGn8snFZbtajEtxHUI057u3NHA/Q7rJkVeP0qmLknnZ2YsZ4
To create a payment page with hosted fields:
1: Add a reference to the AffiniPay hosted fields JavaScript library
On your payment page, add a reference to the AffiniPay hosted fields library.
<script src="https://cdn.affinipay.com/hostedfields/1.4.0/fieldGen_1.4.0.js"></script>
The AffiniPay hosted fields library binds the following functions to the window.AffiniPay.HostedFields
namespace:
window.AffiniPay.HostedFields.initializeFields(config, callback)
to instantiate hosted fields. This is the only function you are required to call to use AffiniPay hosted fields.window.AffiniPay.HostedFields.parseException(hostedFieldException)
to parse exception objects thrown by the hosted fields library.window.AffiniPay.HostedFields.exceptionMap(errorCode)
to look up an exception type of an error code thrown by the hosted fields library.
2: Create a Payment Form
Create an HTML form and replace the <input> elements that contain payment information with <div> elements. On each <div>, set an id
that will be used when configuring the hosted field. Your payment page must additionally include all required fields and other payment page requirements.
- For credit card payments, card number and CVV <input> elements must be replaced with hosted fields <div> elements.
- For eCheck payments, account number and routing number <input> elements must be replaced with hosted fields <div> elements.
Here’s an example:
<div>
<label for="my_credit_card_field_id">Credit Card</label>
<div id="my_credit_card_field_id"></div>
</div>
<div>
<label for="exp_month">Exp Month</label>
<input id="exp_month" type="text" name="exp_month">
</div>
<div>
<label for="exp_year">Exp Year</label>
<input id="exp_year" type="text" name="exp_year">
</div>
<div>
<label for="my_cvv_field_id">CVV</label>
<div id="my_cvv_field_id"></div>
</div>
<div>
<label for="postal_code">Zip Code</label>
<input id="postal_code" type="text" name="postal_code">
</div>
<input type="submit" value="Submit" />
3: Create a hosted fields configuration object
The initializeFields
function must be called with a valid config object and a user-defined callback function (in the Create a user-defined callback step). The config
object is the only way to configure hosted fields. The config
object contains keys that apply to all hosted field as well as individual fieldConfig
objects that apply to individual hosted fields.
A valid config
object includes:
- The merchant’s public key, which is required to tokenize payment details on behalf of the merchant. The merchant’s public key is safe to expose in web pages (as opposed to secret keys, which must be safeguarded).
- An optional
input
key that contains styling that applies to all hosted fields. - Two
fieldConfig
objects that contain individual hosted field configurations. ThefieldConfig
objects are passed to theconfig
object as an array under thefields
key.- A credit card payment page must have one
fieldConfig
of typecredit_card_number
and one of typecvv
. - An eCheck payment page must have one
fieldConfig
of typebank_account_number
one of typerouting_number
.
fieldConfig
object, set theselector
key to theid
of the corresponding <div> in the payment form. - A credit card payment page must have one
The window.AffiniPay.HostedFields.initializeFields
function returns an object with the following methods. Be sure to save this object.
- The
getState()
method returns the current tokenization state of hosted fields. - The
getPaymentToken(formData)
method gets a payment token by passing your hosted field tokens and form data to your AffiniPay backend services. This is required for completing a charge. - The
updateSavedPaymentMethod(formData)
uses the the ID of a previously saved payment method from setSavedPaymentMethod (either Card or Bank) and a form data JSON object of fields to be updated and returns a one-time token to be used for updating a saved payment method. - The
updateSavedPaymentMethod(formData, paymentMethodId)
takes the ID of a saved payment method (either Card or Bank) and a form data JSON object of fields to be updated and returns a one-time token to be used for updating a saved payment method. This call doesn’t require a previous call to setSavedPaymentMethod. - The
setSavedPaymentMethod(paymentMethod)
sets a saved payment method. This function will disable hosted fields and attempt to populate your payment form with data from the saved payment method. It can be used with updateSavedPaymentMethod to avoid passing in a paymentMethodId to updateSavedPaymentMethod. - The
clearSavedPaymentMethod()
clears a currently saved payment method. This will enable hosted fields and clear input elements.
Here’s an example:
const creditCardFieldConfig = {
selector: "#my_credit_card_field_id",
input: {
type: "credit_card_number"
}
}
const cvvFieldConfig = {
selector: "#my_cvv_field_id",
input: {
type: "cvv"
}
}
const hostedFieldsConfiguration = {
publicKey: 'm_1234567890',
fields: [
creditCardFieldConfig,
cvvFieldConfig,
]
}
const hostedFieldsCallback = function (state) {
console.log(JSON.stringify(state, null, 2))
}
const hostedFields = window.AffiniPay.HostedFields.initializeFields(hostedFieldsConfiguration, hostedFieldsCallback)
// Save the return value of initializeFields for later use
// hostedFields.getState()
// hostedFields.getPaymentToken(formData)
4: Style the hosted fields
Although it is not required, styling is recommended.
- To style your page and the <iframe> elements (including their size), use your stylesheet.
- For the content inside the hosted fields—the <input> element contained within the <iframe>, provide styling information within the
config
andfieldConfig
objects. Styling within the hosted fields is defined (from highest to lowest precedence) by:fieldConfig
styling,config
styling, hosted fields library defaults, and browser defaults.
Within the css
key for a config
or fieldConfig
object, you can:
- Pass any valid CSS as a JSON object.
- Style input states (such as :focus, :valid, and :invalid) by passing in a nested style object.
- Style placeholder (::placeholder) text by passing in a nested style object.
Here’s an example of hosted field styling:
const hostedFieldsConfiguration = {
publicKey: "m_1234567890",
input: {
css: {
'font-family': 'serif',
'font-size': '22px',
'color': '#0BEEF0', // fieldConfig css will overwrite this value
':focus': { color: 'orange' },
':invalid': { background: 'antiquewhite' },
':valid': { color: 'blanchedalmond' }
}
},
fields: [
{
selector: "#my_credit_card_field_id",
input: {
type: "credit_card_number",
css: {
"border": "1px solid rgb(204, 204, 204)",
"color": "#000",
"font-size": "30px",
"font-weight": "200",
"width": "100%",
"::placeholder": { color: 'green' }
}
}
},
{
selector: "#my_cvv_field_id",
input: {
type: "cvv",
css: {
"border": "1px solid rgb(204, 204, 204)",
"border-style": 'inset',
"color": "blue",
"font-size": "11px",
"font-weight": "400",
"padding": "8px",
':invalid': { color: 'purple' },
"width": "100%"
}
}
}
]
}
5: Create a user-defined callback
The second parameter to window.AffiniPay.HostedFields.initializeFields
is a user-defined callback function. The callback function is called with a single argument state
, which is a JavaScript object containing the tokenization state for all hosted fields. The bulk of your JavaScript logic that interacts with hosted fields is likely to be contained within this callback function.
Here’s an example:
const hostedFieldsCallBack = function(state) {
console.log(state)
}
COPY
The callback function will be called when the following input events occur:
- valid keydown
- paste
- focus
- blur
The callback will also be called in intervals and when trying to recover from network failure.
- interval
- retry
The state argument passed to your callback function has three keys.
isReady
is a flag that will betrue
if all hosted fields have tokenized successfully. After all fields are tokenized, you can callgetPaymentToken(formData)
.target
is the the state of the hosted field that generated the most recent event. This is useful for CSS changes. The target is the only way the parent page knows a user has navigated into and out of a hosted field.fields
is an array of all hosted fields states.
Here’s an example of the state
argument passed to the callback function:
{
"isReady": false,
"target": {
"selector": "#my_credit_card_field_id",
"token": "TZiDwi9kJdhQRBVuL41F7LSspCDP1j7h",
"type": "credit_card_number",
"card": "visa",
"luhn": true,
"error": "",
"focus": true
},
"fields": [
{
"selector": "#my_credit_card_field_id",
"token": "TZiDwi9kJdhQRBVuL41F7LSspCDP1j7h",
"type": "credit_card_number",
"card": "visa",
"luhn": true,
"error": "",
"focus": true
},
{
"selector": "#my_cvv_field_id",
"token": "M9Wte44S2p5smwqmsjFTJNuOTQ4OgSoH",
"type": "cvv",
"error": "",
"focus": false
}
]
}
6: Initialize hosted fields
To initialize hosted fields, call window.AffiniPay.HostedFields.initializeFields(config, callback)
.
const hostedFields = window.AffiniPay.HostedFields.initializeFields(config, callback)
COPY
Tokenization happens automatically and is triggered by events. The token will be visible in the state object passed to your callback function. Do not use or interact with these tokens directly; they appear on the state object in your callback function for visual feedback only.
Tokenization occurs on keydown and paste events if the input passes validation. Additionally tokenization occurs at intervals to ensure tokens have not expired. In the event of a network failure, a tokenization retry will be done with an exponential backoff.
7: Get a payment token
When the state object passed to your callback function has isReady
set to true
, all fields have tokenized successfully and you can call getPaymentToken(formData)
. You must include the required fields in your formData
argument when calling getPaymentToken
. The getPaymentToken(formData)
function trades the hosted field tokens and other required parameters for a payment token from AffiniPay backend services.
When you create a charge, you will pass this payment token to your own backend services, which will make the charge.
Here’s an example:
form.onsubmit = function(event) {
event.preventDefault()
console.log(hostedFields.getState())
if(!hostedFields.getState()) {
//send error
return
}
hostedFields.getPaymentToken({ "postal_code": postal_code, "exp_year": exp_year, "exp_month": exp_month })
.then(function(result) {
console.log(result.id)
// If getPaymentToken returns successfully you may pass your payment token to your backend service.
}).catch(function(err) {
console.log(err)
})
}
Example Credit Card
Example page: credit card
Here’s an example of a payment form that includes hosted fields for credit card payments and the information required to support them.
Use this example as a guideline as you develop your own payment form. It is not intended to be a turnkey solution.
<html>
<head>
<title>Hosted Fields Payment Page</title>
<script src="https://cdn.affinipay.com/hostedfields/1.4.0/fieldGen_1.4.0.js"></script>
<style type="text/css">
form {
width: 500px;
margin: 0 auto;
}
form input, form iframe {
width: 100%;
margin: 5px;
}
form iframe {
border: none;
height: 20px;
}
</style>
</head>
<body>
<form id="form">
<div>
<label for="my_credit_card_field_id">Credit Card</label>
<div id="my_credit_card_field_id"></div>
</div>
<div>
<label for="exp_month">Exp Month</label>
<input id="exp_month" type="text" name="exp_month">
</div>
<div>
<label for="exp_year">Exp Year</label>
<input id="exp_year" type="text" name="exp_year">
</div>
<div>
<label for="my_cvv_field_id">CVV</label>
<div id="my_cvv_field_id"></div>
</div>
<div>
<label for="postal_code">Zip Code</label>
<input id="postal_code" type="text" name="postal_code">
</div>
<input type="submit" value="Submit" />
</form>
<script type="text/javascript">
const style = {
border: "1px solid rgb(204, 204, 204)",
'border-style': 'inset',
color: "#000",
"font-size": "11px",
"font-weight": "400",
padding: "8px",
width: "100%"
};
const hostedFieldsConfiguration = {
publicKey: "m_1234567890",
fields: [
{
selector: "#my_credit_card_field_id",
input: {
type: "credit_card_number",
css: style
}
},
{
selector: "#my_cvv_field_id",
input: {
type: "cvv",
css: style
}
}
]
};
const hostedFieldsCallBack = function(state) {
console.log(state);
};
const hostedFields = window.AffiniPay.HostedFields.initializeFields(
hostedFieldsConfiguration,
hostedFieldsCallBack
);
form.onsubmit = function(event) {
event.preventDefault();
console.log(hostedFields.getState())
const postal_code = document.getElementById('postal_code').value
const exp_year = document.getElementById('exp_year').value
const exp_month = document.getElementById('exp_month').value
if(!hostedFields.getState()){
//send error
return;
}
hostedFields.getPaymentToken({ "postal_code": postal_code, "exp_year": exp_year, "exp_month": exp_month })
.then(function(result){
console.log(result.id)
// If getPaymentToken returns successfully you may pass your payment token to your backend service.
}).catch(function(err){
console.log(err);
});
};
</script>
</body>
</html>
Example Credit Card & Check
Example page: credit card and eCheck payments
Note: If your payment page allows both credit card and eCheck payments, it must have separate config objects, initializeFields calls, and getPaymentToken calls for each.
Here’s an example of a payment form that includes hosted fields for credit card and eCheck payments and the information required to support them.
Use this example as a guideline as you develop your own payment form. It is not intended to be a turnkey solution.
<html>
<head>
<title>Hosted Fields Payment Page</title>
<script src="https://cdn.affinipay.com/hostedfields/1.4.0/fieldGen_1.4.0.js"></script>
<style type="text/css">
form {
margin: 0 auto;
}
form input, form iframe {
width: 100%;
margin: 5px;
}
form iframe {
border: none;
height: 20px;
}
</style>
</head>
<body>
<form id="form" name="form">
<table>
<tr>
<td>
<table width="100%">
<tr>
<td>
<input type="radio" id="card_radio" name="payment_type_radio" value="card">
</td>
<td>
<label for="card_radio">Credit Card</label>
</td>
<td width="20px"></td>
<td>
<input type="radio" id="bank_radio" name="payment_type_radio" value="bank" >
</td>
<td>
<label for="bank_radio">eCheck</label>
</td>
</tr>
</table>
</td>
</tr>
<tr>
<td>
<div>
<label for="my_credit_card_field_id">Credit Card</label>
<div id="my_credit_card_field_id"></div>
</div>
<div>
<label for="exp_month">Exp Month</label>
<input id="exp_month" type="text" name="exp_month">
</div>
<div>
<label for="exp_year">Exp Year</label>
<input id="exp_year" type="text" name="exp_year">
</div>
<div>
<label for="my_cvv_field_id">CVV</label>
<div id="my_cvv_field_id"></div>
</div>
<div>
<label for="postal_code">Zip Code</label>
<input id="postal_code" type="text" name="postal_code">
</div>
</td>
<td width="20px">
</td>
<td>
<table width="100%">
<tr>
<td>
<input type="radio" id="business_radio" name="account_holder_type_radio" value="business">
</td>
<td>
<label for="business_radio">Business</label>
</td>
<td>
<input type="radio" id="personal_radio" name="account_holder_type_radio" value="personal">
</td>
<td>
<label for="personal_radio">Personal</label>
</td>
</tr>
</table>
<div>
<label for="my_routing_number_id">Routing Number</label>
<div id="my_routing_number_id"></div>
</div>
<div>
<label for="my_bank_account_number_id">Account Number</label>
<div id="my_bank_account_number_id"></div>
</div>
<table width="100%">
<tr>
<td>
<input type="radio" name='account_type_radio' id="checking_radio" value="checking">
</td>
<td>
<label for="checking_radio">Checking</label>
</td>
<td>
<input type="radio" name='account_type_radio' id="savings_radio" value="savings">
</td>
<td>
<label for="savings_radio">Savings</label>
</td>
</tr>
</table>
<div>
<label for="given_name">First Name</label>
<input id="given_name" type="text" name="given_name">
</div>
<div>
<label for="surname">Last Name</label>
<input id="surname" type="text" name="surname">
</div>
<div>
<label for="business_name">Business Name</label>
<input id="business_name" type="text" name="business_name">
</div>
</td>
</tr>
</table>
<table>
<tr>
<td>
<input type="submit" value="Submit"/>
</td>
</tr>
</table>
</form>
<script type="text/javascript">
const style = {
border: "1px solid rgb(204, 204, 204)",
'border-style': 'inset',
color: "#000",
"font-size": "11px",
"font-weight": "400",
padding: "8px",
width: "100%"
};
const creditCardHostedFieldsConfig = {
publicKey: "m_1234567890",
fields: [
{
selector: "#my_credit_card_field_id",
input: {
type: "credit_card_number",
css: style
}
},
{
selector: "#my_cvv_field_id",
input: {
type: "cvv",
css: style
}
}
]
};
const eCheckHostedFieldsConfig = {
publicKey: 'm_1234567890',
css: style,
fields: [
{
selector: '#my_bank_account_number_id',
placeholder: 'Bank Account Number',
input: {
type: 'bank_account_number',
css: style
}
},
{
selector: '#my_routing_number_id',
input: {
type: 'routing_number',
css: style
}
}
]
};
const hostedFieldsCallBack = function (state) {
console.log(state);
};
const creditCardHostedFields = window.AffiniPay.HostedFields.initializeFields(
creditCardHostedFieldsConfig,
hostedFieldsCallBack
);
const eCheckHostedFields = window.AffiniPay.HostedFields.initializeFields(
eCheckHostedFieldsConfig,
hostedFieldsCallBack
);
const form = document.getElementById('form');
form.onsubmit = function (event) {
event.preventDefault();
console.log(creditCardHostedFields.getState());
console.log(eCheckHostedFields.getState());
if (form['card_radio'].checked && creditCardHostedFields.getState()) {
const postal_code = document.getElementById('postal_code').value
const exp_year = document.getElementById('exp_year').value
const exp_month = document.getElementById('exp_month').value
creditCardHostedFields.getPaymentToken({"postal_code": postal_code, "exp_year": exp_year, "exp_month": exp_month})
.then(function (result) {
console.log(result.id);
// If getPaymentToken returns successfully you may pass your payment token to your backend service.
}).catch(function (err) {
console.log(err);
});
} else if (form['bank_radio'].checked && eCheckHostedFields.getState()) {
const given_name = document.getElementById('given_name').value
const surname = document.getElementById('surname').value
const business_name = document.getElementById('business_name').value
const isBusiness = document.getElementById('business_radio').checked
const isSavings = document.getElementById('savings_radio').checked
const extra_fields = {}
extra_fields.account_holder_type = isBusiness ? 'business' : 'individual'
extra_fields.account_type = isSavings ? 'savings' : 'checking'
if (business_radio.checked) {
extra_fields.name = business_name
} else {
extra_fields.given_name = given_name
extra_fields.surname = surname
}
console.log(JSON.stringify(extra_fields))
eCheckHostedFields.getPaymentToken(extra_fields).then(function (result) {
console.log(result.id);
// If getPaymentToken returns successfully you may pass your payment token to your backend service.
}).catch(function (err) {
console.log(err);
});
} else {
console.log('error');
}
};
</script>
</body>
</html>
3 Create a Charge
Connect to Affinipay Gateway
Collect & Secure Payment Details
Create a Charge
To authenticate, you’ll need the merchant secret key. Using the test-mode secret key and a test account, you can start using the API immediately without actually submitting charges to the payment processing networks. When you’re ready to start processing payments, just switch to your live-mode secret key and a live account.
When you POST to the charges endpoint, you’ll include:
- amount. The total payment amount in cents. For example: $500.00 = 50000.
- method. The ID of the payment method to use to run the payment. In this case, this payment method is the id property received on the one-time token JSON object collected in your payment form.
- account_id. The ID of the AffiniPay merchant account that should receive payment. Because a merchant can have more than one account, you should set this value for each transaction.
Example request
curl -X POST -H "Content-Type:application/json" --user <secret_key>: https://api.affinipay.com/v1/charges -d '
{
"amount":"100",
"method":" . $payment_token_id . ",
"account_id":" ' $lawpay_account_id ' "
}
Oauth2.0 Flow
Visual description

Step by Step using WordPress plugin
- Send cURL request for access token
LawPay Payment Processing 2
Authentication API
https://developers.affinipay.com/reference/api.html#AuthenticationAPI
1 Request token
- You can access merchant account details after you receive an access token. You must use your partner OAuth application client ID and secret to make this call.
- This endpoint returns an access_token when you POST a valid grant_type parameter.
- Note: Before you can call the AffiniPay Payment Gateway API and manage transactions on a merchant’s behalf, your partner OAuth application must use the access token to request gateway credentials.
Parameter | Description |
---|---|
client_id | A unique 64-character, alphanumeric string used to identify your partner OAuth application in OAuth 2.0 web flows. |
client_secret | A unique 64-character, alphanumeric string used to authenticate your partner OAuth application in OAuth 2.0 web flows. |
grant_type | Specifies which grant type to use in the OAuth 2.0 web flow. Set this to authorization_code. |
scope | Determines the level of access your partner OAuth application has to the merchant’s account. Set this to payments. |
redirect_uri | Per the OAuth 2.0 specification, this is the URI to which the AffiniPay web application will redirect after successful authorization. Your web server must handle redirects to this URI according to the OAuth 2.0 specification. |
code | The authorization_code that the Authentication API sends to the redirect URI you specified in your partner OAuth application after a user logs in and authorizes your application. |
curl -X POST -H "Content-Type:application/json" https://api.affinipay.com/oauth/token -d '
{
"client_id":"Y4QLWPO6wZag2ia8Abw7nbeLUAOgebDlfZGF1KyzgBaqAllzMtYFfP58jRxg5rp5",
"client_secret":"4EG357enIs4m2SWKi9yfC3fQzIeOZmBTWr96ay47tqN4GUtRPYrWwxwCxwlZJbiC",
"grant_type":"authorization_code",
"scope":"payments",
"redirect_uri":"http://localhost:9292/callback",
"code":"EiKvFkJu6rcFwOMWSqW8bWIng6EMFVD93duwn1QhgQKDvmpbA97zWFN2AfC5052R"
}'
Or for PHP script
// Generated by curl-to-PHP: http://incarnate.github.io/curl-to-php/
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://api.affinipay.com/oauth/token');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, "\n{\n \"client_id\":\"Y4QLWPO6wZag2ia8Abw7nbeLUAOgebDlfZGF1KyzgBaqAllzMtYFfP58jRxg5rp5\",\n \"client_secret\":\"4EG357enIs4m2SWKi9yfC3fQzIeOZmBTWr96ay47tqN4GUtRPYrWwxwCxwlZJbiC\",\n \"grant_type\":\"authorization_code\",\n \"scope\":\"payments\",\n \"redirect_uri\":\"http://localhost:9292/callback\",\n \"code\":\"EiKvFkJu6rcFwOMWSqW8bWIng6EMFVD93duwn1QhgQKDvmpbA97zWFN2AfC5052R\"\n}");
$headers = array();
$headers[] = 'Content-Type: application/json';
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
$result = curl_exec($ch);
if (curl_errno($ch)) {
echo 'Error:' . curl_error($ch);
}
curl_close($ch);
This endpoint returns an access_token when you POST a valid grant_type parameter.
Example Response
{
"access_token":"Msp2VL7SEGbLxT8UBWww7WUy33hLsg5Yhf5fFu8znSpPh2BbBMvXPyQkZx5TtWHd",
"token_type":"bearer",
"scope":"payments",
"created_at":1464986958
}
You can access merchant account details after you receive an access token. You must use your partner OAuth application client ID and secret to make this call.
Request Gateway Credentials
curl -X GET -H "Authorization: Bearer <access_token>" https://api.affinipay.com/gateway-credentials
This endpoint returns a list of the test and live accounts associated with the authenticated user’s merchant account. Included in this information are the necessary keys for making calls to the AffiniPay Payment Gateway API. Save these credentials securely so your partner OAuth application can manage transactions on behalf of merchant users.
Payment Gateway API – Merchant Management
https://developers.affinipay.com/reference/api.html#PaymentGatewayAPI
Overview
- The AffiniPay Payment Gateway provides a REST API to facilitate payment processing for Merchants.
- API supports both credit card payments and electronic check (eCheck) payments, which move funds electronically between banks using routing and account numbers.
It uses simple URLs and proven HTTP constructs, simplifying integration with third-party applications and existing web sites. - All interactions with the Gateway are carried out over a secure connection using TLS 1.2 to safeguard data contents, and all requests are authenticated using HTTP.
- All request and response content is formatted using JSON, including error information.
Security
- All merchants are provided with a public key and test- and live-mode secret keys to use when authenticating with the Gateway.
- All requests to the Gateway are authenticated using HTTP Basic Authentication.
- To authenticate, you provide either your test- or live-mode secret key in the HTTP Authorization header.
- basic access authentication is a method for an HTTP user agent (e.g. a web browser) to provide a user name and password when making a request.
In basic HTTP authentication, a request contains a header field in the form ofAuthorization: Basic <credentials>
, where credentials is the Base64 encoding of ID and password joined by a single colon:
- In each request, be sure to always base64-encode the public or secret key plus a trailing colon.
For example, if your public key is: m_cSiyNUh9RBWHfdbFRFGrkA, you’ll base64-encode m_cSiyNUh9RBWHfdbFRFGrkA:. The result is bV9jU2l5TlVoOVJCV0hmZGJGUkZHcmtCOg==, which you’ll use in your request header.
- In each request, be sure to always base64-encode the public or secret key plus a trailing colon.
curl --user secret_key: https://https://api.affinipay.com/...
- Using the curl command line tool used in the API examples, you set this header using the –user flag, followed by the secret key, and then a trailing colon (:).
- Your secret keys provide access to sensitive operations affecting payments, and therefore must be closely guarded.
- These keys should never be exposed in any publicly-accessible web pages, JavaScript, etc.
- If you suspect your test- or live-mode secret keys have been compromised, contact your Gateway account provider immediately to reset your secret keys.
- In order to protect sensitive information, including your credentials and the contents of API requests and responses, the Gateway only accepts encrypted communications using HTTPS.
Test vs Live Mode
- The secret key you specify when making an API request affects how the operation is processed.
- The test-mode secret key only allows you to create new charges and other transactions against TEST merchant bank accounts, while the live-mode secret key only works in conjunction with merchant bank accounts associated with live payment processing networks.
Attempts to mix secret keys and merchant bank accounts will fail.
- The test-mode secret key only allows you to create new charges and other transactions against TEST merchant bank accounts, while the live-mode secret key only works in conjunction with merchant bank accounts associated with live payment processing networks.
- Similarly, the secret key you provide filters the transactions you see when searching or retrieving specific transactions.
- The test-mode secret key only returns transactions created against TEST merchant bank accounts, and the live-mode secret key only returns transactions submitted to the payment processing networks.
Restricting Client Access
- A Merchant that accesses the Gateway via an intermediate application (for example, a hosted web-based application) can set their configuration to restrict the API from accepting requests from any other sources.
- The IP address restrictions are configured by setting the api_allowed_ip_address_ranges property on the Merchant.
- The countries from which transaction operations (Authorize, Void, Capture, Refund, and Credit) are allowed may also be restricted to specific countries. Countries are determined by performing a geographic lookup by IP address.
- Country restrictions are enforced on a per-Account basis via the transaction_allowed_countries property.
Test Card Numbers
Test Card Numbers
Successful charges can be created using the following card numbers in conjunction with the test-mode secret key and a card expiration in the future:
Card Number | Card Type |
---|---|
378282246310005 | American Express |
371449635398431 | American Express |
5105105105105100 | MasterCard |
5499740000000057 | MasterCard |
30569309025904 | Diners Club |
38520000023237 | Diners Club |
6011000990139424 | Discover |
3530111333300000 | JCB |
3566002020360505 | JCB |
4242424242424242 | Visa |
4012888888881881 | Visa |
4400000000000008 | Visa Debit |
Failure scenarios can be tested using the following card numbers and the test-mode secret key:
Card Number | Error Code |
---|---|
4000000000000002 | card_declined |
4000000000000044 | card_declined_insufficient_funds |
4000000000000051 | card_declined_limit_exceeded |
4000000000000069 | card_expired |
4000000000000119 | card_declined_processing_error |
4000000000000127 | card_declined_hold |
4242424242424241 | card_number_invalid |
4000000000000135 | card_type_not_accepted |
6011111111111117 | 503 PROCESSOR NOT AVAILABLE |
5555555555554444 | 500 SERVER ERROR |
CVV and AVS checks can be tested against various account policies using the following card numbers and the test-mode secret key. Note that depending on the policy in effect, the CVV and AVS results may or may not result in an error code being returned. For example, if the CVV policy is set to DISABLED, a CVV Not Matched response will not cause a failure, whereas it would if the CVV policy were set to REQUIRE_MATCH_LENIENT.
Card Number | CVV/AVS Response |
---|---|
4000000000000077 | CVV Unavailable |
4000000000000101 | CVV Not Matched |
4000000000000010 | AVS Not Matched |
4000000000000085 | AVS Unavailable |
4000000000000093 | AVS Error |
4000000000000028 | If card postal code is null or empty, AVS returns Not Matched. Otherwise, an AVS Postal Code Match is returned. |
4000000000000036 | If card address is null or empty, AVS returns Not Matched. Otherwise an AVS Address Match is returned. |
Test Bank Account Numbers
Using a TEST bank account, you can capture eCheck transfers using the routing numbers 000000000 or 000000013 with any account number. The following exceptions return eCheck errors useful for testing purposes:
Routing Number | Account Number | Error Code |
---|---|---|
000000013 | 1000000001 | ach_declined |
000000013 | 1000000002 | ach_declined_hold |
000000013 | 1000000003 | ach_declined_duplicate |
000000013 | 1000000004 | ach_invalid_account_number |
000000013 | 1000000005 | ach_insufficient_funds |
000000013 | 1000000006 | ach_account_not_found |
000000013 | 1000000007 | ach_account_closed |
000000013 | 1000000008 | ach_account_frozen |
000000013 | 1000000009 | ach_limit_exceeded |
000000001 | Any | ach_invalid_routing_number |
000000013 | 1000000004 | 422 INVALID ACCOUNT NUMBER |
000000013 | 1000000011 | 503 ACH PROCESSOR NOT AVAILABLE |
000000013 | 1000000012 | 500 SERVER ERROR |
System Status
System Status
GET /status
Integrating systems can retrieve the current status of the Gateway by issuing a GET request to /status. The operation returns an enumeration indicating the basic status, as detailed in the table below. This operation, which requires no authentication, can be used to check connectivity to the Gateway as well as to identify potential problems that may impact payment processing.
Status | Description |
---|---|
NORMAL | The gateway is functioning normally. |
EXCESSIVE_LATENCY | API request durations are exceeding expected thresholds. |
SERVICE_UNRELIABLE | Recent intermittent failures are impacting payment processing. |
SERVICE_UNAVAILABLE | The system us experiencing problems that prevent payment processing. |
Example Request
curl https://https://api.affinipay.com/status
Example Response
{
"status":"NORMAL"
}
Get Current Merchant
Get Current Merchant
GET /v1/merchant
Returns the currently-authenticated merchant. This operation can be used to test authenticating to the Gateway using a Merchant’s credentials. Note that the merchant and eCheck accounts returned are filtered based on whether a live or test-mode secret key was provided. Only TEST accounts are returned if a test-mode secret key is used, while a live-mode secret key only returns live accounts.
curl -X GET --user secret_key: https://https://api.affinipay.com/v1/merchant
Purge Test Data
Purge Test Data
POST /v1/merchant/purge-test-data
Testing your integration via our API can result in a lot of data being generated associated with your account: payment methods, transactions, recurring charges, etc. This data can sometimes make it more difficult to verify that your integration is working as expected. Using the /v1/merchant/purge-test-data endpoint, you can discard all of your test data and return to a clean slate.
curl -X POST -H "Content-Type:application/json" --user secret_key: https://https://api.affinipay.com/v1/merchant/purge-test-data
Payment Gateway API – Transactions
https://developers.affinipay.com/reference/api.html#PaymentGatewayAPI
- The Gateway’s streamlined transaction API simplifies the process of submitting payments and applying refunds to those payments.
- The API also includes methods for retrieving individual transactions by ID, as well as a search operation that returns paginated results based on criteria specified by the caller.
- Note: To avoid exposing credentials, always make API calls from the server, not from the browser.
Charges
Charges
POST /v1/charges
- The /v1/charges API submits a payment request from a customer using the payment method included in the request.
- The payment method can be a card or bank or the ID of a PaymentMethod, saved card, saved bank, or one-time token.
The operation performs an authorize for the funds specified and returns the Charge in the response. - To meet PCI requirements, create a payment form with hosted fields to tokenize payment details.
See Creating payment forms using hosted fields.
- The payment method can be a card or bank or the ID of a PaymentMethod, saved card, saved bank, or one-time token.
- If no account ID is specified in the request, the Gateway automatically selects the primary merchant or eCheck account, depending on the type of payment method specified; for example, providing a bank method results in the primary eCheck account being selected. If no matching account is found, or if an account ID is provided but does not match the payment method, the charge is rejected.
- By default, all successful authorizations are captured automatically daily for all the Merchant’s accounts at a time configured by the Merchant’s Tenant. For credit card payments, separate authorization and capture can be performed by specifying auto_capture: false in the JSON request, resulting in a hold being placed on the customer’s funds without automatic capture. Transactions must be captured or voided using the corresponding APIs; otherwise they are automatically voided by the Gateway after 7 days.
Creating a charge with automatic capture
curl -X POST -H "Content-Type:application/json" --user secret_key: https://api.affinipay.com/v1/charges -d '
{
"amount": "100",
"account_id": "wKgFeDz5HF-BPPl08dcADQ",
"method": {
"type": "card",
"number": "4242424242424242",
"exp_month": 10,
"exp_year": 2022,
"cvv": "123",
"name": "Some Customer"
}
}'
Creating a charge debiting an individuals bank account
curl -X POST -H "Content-Type:application/json" --user secret_key: https://api.affinipay.com/v1/charges -d '
{
"amount": "46531",
"account_id": "7eyWpvRpEeKcOfUBJK8FBw",
"method": {
"type": "bank",
"routing_number": "000000013",
"account_number": "1100000005",
"account_type": "CHECKING",
"given_name": "Amy",
"surname": "Customer"
}
}'
Create payment. Form
AffiniPay hosted fields protect your payment page by tokenizing payment information. They provide SAQ-A PCI compliance, the highest level of PCI compliance. Hosted fields are <iframe> elements sourced from AffiniPay’s servers that contain a single corresponding <input> element. These iframes replace the input elements on your form that contain payment information.
Hosted fields versioning
With version 1.4.0, hosted fields now supports enabling surcharge, disabling and enabling fields, focusing on a field, and clearing a field.
The AffiniPay hosted fields JavaScript library (fieldGen.js
) is versioned. The versioning URL is:
https://cdn.affinipay.com/hostedfields/1.4.0/fieldGen_1.4.0.js
For SRI and integrity
attribute purposes, here are the SHA384 digests:
1.4.0 Release
integrity="sha384-2LuR5n01lipNZjmgOGn8snFZbtajEtxHUI057u3NHA/Q7rJkVeP0qmLknnZ2YsZ4" crossorigin="anonymous"
1 Add a reference to the AffiniPay hosted fields JavaScript library
On your payment page, add a reference to the AffiniPay hosted fields library.
<script src="https://cdn.affinipay.com/hostedfields/1.4.0/fieldGen_1.4.0.js"></script><script src="https://cdn.affinipay.com/hostedfields/1.4.0/fieldGen_1.4.0.js"></script>
The AffiniPay hosted fields library binds the following functions to the window.AffiniPay.HostedFields
namespace:
window.AffiniPay.HostedFields.initializeFields(config, callback)
to instantiate hosted fields. This is the only function you are required to call to use AffiniPay hosted fields.window.AffiniPay.HostedFields.parseException(hostedFieldException)
to parse exception objects thrown by the hosted fields library.window.AffiniPay.HostedFields.exceptionMap(errorCode)
to look up an exception type of an error code thrown by the hosted fields library.
2 Create a payment form
Create an HTML form and replace the <input> elements that contain payment information with <div> elements. On each <div>, set an id
that will be used when configuring the hosted field. Your payment page must additionally include all required fields and other payment page requirements.
- For credit card payments, card number and CVV <input> elements must be replaced with hosted fields <div> elements.
- For eCheck payments, account number and routing number <input> elements must be replaced with hosted fields <div> elements.
Here’s an example:
<div>
<label for="my_credit_card_field_id">Credit Card</label>
<div id="my_credit_card_field_id"></div>
</div>
<div>
<label for="exp_month">Exp Month</label>
<input id="exp_month" type="text" name="exp_month">
</div>
<div>
<label for="exp_year">Exp Year</label>
<input id="exp_year" type="text" name="exp_year">
</div>
<div>
<label for="my_cvv_field_id">CVV</label>
<div id="my_cvv_field_id"></div>
</div>
<div>
<label for="postal_code">Zip Code</label>
<input id="postal_code" type="text" name="postal_code">
</div>
<input type="submit" value="Submit" />
3 Create a hosted fields configuration object
The initializeFields
function must be called with a valid config object and a user-defined callback function (in the Create a user-defined callback step). The config
object is the only way to configure hosted fields. The config
object contains keys that apply to all hosted field as well as individual fieldConfig
objects that apply to individual hosted fields.
A valid config
object includes:
- The merchant’s public key, which is required to tokenize payment details on behalf of the merchant. The merchant’s public key is safe to expose in web pages (as opposed to secret keys, which must be safeguarded).
- An optional
input
key that contains styling that applies to all hosted fields. - Two
fieldConfig
objects that contain individual hosted field configurations. ThefieldConfig
objects are passed to theconfig
object as an array under thefields
key.- A credit card payment page must have one
fieldConfig
of typecredit_card_number
and one of typecvv
. - An eCheck payment page must have one
fieldConfig
of typebank_account_number
one of typerouting_number
.
fieldConfig
object, set theselector
key to theid
of the corresponding <div> in the payment form. - A credit card payment page must have one
The window.AffiniPay.HostedFields.initializeFields
function returns an object with the following methods. Be sure to save this object.
- The
getState()
method returns the current tokenization state of hosted fields. - The
getPaymentToken(formData)
method gets a payment token by passing your hosted field tokens and form data to your AffiniPay backend services. This is required for completing a charge. - The
updateSavedPaymentMethod(formData)
uses the the ID of a previously saved payment method from setSavedPaymentMethod (either Card or Bank) and a form data JSON object of fields to be updated and returns a one-time token to be used for updating a saved payment method. - The
updateSavedPaymentMethod(formData, paymentMethodId)
takes the ID of a saved payment method (either Card or Bank) and a form data JSON object of fields to be updated and returns a one-time token to be used for updating a saved payment method. This call doesn’t require a previous call to setSavedPaymentMethod. - The
setSavedPaymentMethod(paymentMethod)
sets a saved payment method. This function will disable hosted fields and attempt to populate your payment form with data from the saved payment method. It can be used with updateSavedPaymentMethod to avoid passing in a paymentMethodId to updateSavedPaymentMethod. - The
clearSavedPaymentMethod()
clears a currently saved payment method. This will enable hosted fields and clear input elements.
Here’s an example:
const creditCardFieldConfig = {
selector: "#my_credit_card_field_id",
input: {
type: "credit_card_number"
}
}
const cvvFieldConfig = {
selector: "#my_cvv_field_id",
input: {
type: "cvv"
}
}
const hostedFieldsConfiguration = {
publicKey: 'm_1234567890',
fields: [
creditCardFieldConfig,
cvvFieldConfig,
]
}
const hostedFieldsCallback = function (state) {
console.log(JSON.stringify(state, null, 2))
}
const hostedFields = window.AffiniPay.HostedFields.initializeFields(hostedFieldsConfiguration, hostedFieldsCallback)
// Save the return value of initializeFields for later use
// hostedFields.getState()
// hostedFields.getPaymentToken(formData)
4 Style the hosted fields
Although it is not required, styling is recommended.
- To style your page and the <iframe> elements (including their size), use your stylesheet.
- For the content inside the hosted fields—the <input> element contained within the <iframe>, provide styling information within the
config
andfieldConfig
objects. Styling within the hosted fields is defined (from highest to lowest precedence) by:fieldConfig
styling,config
styling, hosted fields library defaults, and browser defaults.
Within the css
key for a config
or fieldConfig
object, you can:
- Pass any valid CSS as a JSON object.
- Style input states (such as :focus, :valid, and :invalid) by passing in a nested style object.
- Style placeholder (::placeholder) text by passing in a nested style object.
Here’s an example of hosted field styling:
const hostedFieldsConfiguration = {
publicKey: "m_1234567890",
input: {
css: {
'font-family': 'serif',
'font-size': '22px',
'color': '#0BEEF0', // fieldConfig css will overwrite this value
':focus': { color: 'orange' },
':invalid': { background: 'antiquewhite' },
':valid': { color: 'blanchedalmond' }
}
},
fields: [
{
selector: "#my_credit_card_field_id",
input: {
type: "credit_card_number",
css: {
"border": "1px solid rgb(204, 204, 204)",
"color": "#000",
"font-size": "30px",
"font-weight": "200",
"width": "100%",
"::placeholder": { color: 'green' }
}
}
},
{
selector: "#my_cvv_field_id",
input: {
type: "cvv",
css: {
"border": "1px solid rgb(204, 204, 204)",
"border-style": 'inset',
"color": "blue",
"font-size": "11px",
"font-weight": "400",
"padding": "8px",
':invalid': { color: 'purple' },
"width": "100%"
}
}
}
]
}
Disable or enable fields
To disable and enable inputs use the following methods, passing the value from the field selector property in your hostedFieldsConfiguration
object.
const hostedFields = window.AffiniPay.HostedFields.initializeFields(hostedFieldsConfiguration, hostedFieldsCallback)
hostedFields.disableIframeInput("#my_credit_card_field_id")
hostedFields.enableIframeInput("#my_credit_card_field_id")
Focus a field
To focus an input use the following method, passing the value from the field selector property in your hostedFieldsConfiguration
object.
const hostedFields = window.AffiniPay.HostedFields.initializeFields(hostedFieldsConfiguration, hostedFieldsCallback)
hostedFields.focusIframeInput("#my_credit_card_field_id")
Clear a field
To clear an input use the following method, passing the value from the field selector property in your hostedFieldsConfiguration
object.
const hostedFields = window.AffiniPay.HostedFields.initializeFields(hostedFieldsConfiguration, hostedFieldsCallback)
hostedFields.clearIframeInput("#my_credit_card_field_id")
To clear all iframes, call hostedFields.clearIframeInput()
without any arguments.
5 Create a user-defined callback
The second parameter to window.AffiniPay.HostedFields.initializeFields
is a user-defined callback function. The callback function is called with a single argument state
, which is a JavaScript object containing the tokenization state for all hosted fields. The bulk of your JavaScript logic that interacts with hosted fields is likely to be contained within this callback function.
Here’s an example:
const hostedFieldsCallBack = function(state) {
console.log(state)
}
The callback function will be called when the following input events occur:
- valid keydown
- paste
- focus
- blur
The callback will also be called in intervals and when trying to recover from network failure.
- interval
- retry
The state argument passed to your callback function has three keys.
isReady
is a flag that will betrue
if all hosted fields have tokenized successfully. After all fields are tokenized, you can callgetPaymentToken(formData)
.target
is the the state of the hosted field that generated the most recent event. This is useful for CSS changes. The target is the only way the parent page knows a user has navigated into and out of a hosted field.fields
is an array of all hosted fields states.
Here’s an example of the state
argument passed to the callback function:
{
"isReady": false,
"target": {
"selector": "#my_credit_card_field_id",
"token": "TZiDwi9kJdhQRBVuL41F7LSspCDP1j7h",
"type": "credit_card_number",
"card": "visa",
"luhn": true,
"error": "",
"focus": true
},
"fields": [
{
"selector": "#my_credit_card_field_id",
"token": "TZiDwi9kJdhQRBVuL41F7LSspCDP1j7h",
"type": "credit_card_number",
"card": "visa",
"luhn": true,
"error": "",
"focus": true
},
{
"selector": "#my_cvv_field_id",
"token": "M9Wte44S2p5smwqmsjFTJNuOTQ4OgSoH",
"type": "cvv",
"error": "",
"focus": false
}
]
}
6 Initialize hosted fields
To initialize hosted fields, call window.AffiniPay.HostedFields.initializeFields(config, callback)
.
const hostedFields = window.AffiniPay.HostedFields.initializeFields(config, callback)
Tokenization happens automatically and is triggered by events. The token will be visible in the state object passed to your callback function. Do not use or interact with these tokens directly; they appear on the state object in your callback function for visual feedback only.
Tokenization occurs on keydown and paste events if the input passes validation. Additionally tokenization occurs at intervals to ensure tokens have not expired. In the event of a network failure, a tokenization retry will be done with an exponential backoff.
7 Get a payment token
When the state object passed to your callback function has isReady
set to true
, all fields have tokenized successfully and you can call getPaymentToken(formData)
. You must include the required fields in your formData
argument when calling getPaymentToken
. The getPaymentToken(formData)
function trades the hosted field tokens and other required parameters for a payment token from AffiniPay backend services.
When you create a charge, you will pass this payment token to your own backend services, which will make the charge.
Here’s an example:
form.onsubmit = function(event) {
event.preventDefault()
console.log(hostedFields.getState())
if(!hostedFields.getState()) {
//send error
return
}
hostedFields.getPaymentToken({ "postal_code": postal_code, "exp_year": exp_year, "exp_month": exp_month })
.then(function(result) {
console.log(result.id)
// If getPaymentToken returns successfully you may pass your payment token to your backend service.
}).catch(function(err) {
console.log(err)
})
}
COPY
Your payment page must also handle the payment response returned from your web server, displaying any errors or updating the page with a receipt.
Example Page – Credit Card
Example page: credit card
Here’s an example of a payment form that includes hosted fields for credit card payments and the information required to support them.
Use this example as a guideline as you develop your own payment form. It is not intended to be a turnkey solution.
<html>
<head>
<title>Hosted Fields Payment Page</title>
<script src="https://cdn.affinipay.com/hostedfields/1.4.0/fieldGen_1.4.0.js"></script>
<style type="text/css">
form {
width: 500px;
margin: 0 auto;
}
form input, form iframe {
width: 100%;
margin: 5px;
}
form iframe {
border: none;
height: 20px;
}
</style>
</head>
<body>
<form id="form">
<div>
<label for="my_credit_card_field_id">Credit Card</label>
<div id="my_credit_card_field_id"></div>
</div>
<div>
<label for="exp_month">Exp Month</label>
<input id="exp_month" type="text" name="exp_month">
</div>
<div>
<label for="exp_year">Exp Year</label>
<input id="exp_year" type="text" name="exp_year">
</div>
<div>
<label for="my_cvv_field_id">CVV</label>
<div id="my_cvv_field_id"></div>
</div>
<div>
<label for="postal_code">Zip Code</label>
<input id="postal_code" type="text" name="postal_code">
</div>
<input type="submit" value="Submit" />
</form>
<script type="text/javascript">
const style = {
border: "1px solid rgb(204, 204, 204)",
'border-style': 'inset',
color: "#000",
"font-size": "11px",
"font-weight": "400",
padding: "8px",
width: "100%"
};
const hostedFieldsConfiguration = {
publicKey: "m_1234567890",
fields: [
{
selector: "#my_credit_card_field_id",
input: {
type: "credit_card_number",
css: style
}
},
{
selector: "#my_cvv_field_id",
input: {
type: "cvv",
css: style
}
}
]
};
const hostedFieldsCallBack = function(state) {
console.log(state);
};
const hostedFields = window.AffiniPay.HostedFields.initializeFields(
hostedFieldsConfiguration,
hostedFieldsCallBack
);
form.onsubmit = function(event) {
event.preventDefault();
console.log(hostedFields.getState())
const postal_code = document.getElementById('postal_code').value
const exp_year = document.getElementById('exp_year').value
const exp_month = document.getElementById('exp_month').value
if(!hostedFields.getState()){
//send error
return;
}
hostedFields.getPaymentToken({ "postal_code": postal_code, "exp_year": exp_year, "exp_month": exp_month })
.then(function(result){
console.log(result.id)
// If getPaymentToken returns successfully you may pass your payment token to your backend service.
}).catch(function(err){
console.log(err);
});
};
</script>
</body>
</html>
Example Page – Credit Card & eCheck
Example page: credit card and eCheck payments
Note: If your payment page allows both credit card and eCheck payments, it must have separate config objects, initializeFields calls, and getPaymentToken calls for each.
Here’s an example of a payment form that includes hosted fields for credit card and eCheck payments and the information required to support them.
Use this example as a guideline as you develop your own payment form. It is not intended to be a turnkey solution.
<html>
<head>
<title>Hosted Fields Payment Page</title>
<script src="https://cdn.affinipay.com/hostedfields/1.4.0/fieldGen_1.4.0.js"></script>
<style type="text/css">
form {
margin: 0 auto;
}
form input, form iframe {
width: 100%;
margin: 5px;
}
form iframe {
border: none;
height: 20px;
}
</style>
</head>
<body>
<form id="form" name="form">
<table>
<tr>
<td>
<table width="100%">
<tr>
<td>
<input type="radio" id="card_radio" name="payment_type_radio" value="card">
</td>
<td>
<label for="card_radio">Credit Card</label>
</td>
<td width="20px"></td>
<td>
<input type="radio" id="bank_radio" name="payment_type_radio" value="bank" >
</td>
<td>
<label for="bank_radio">eCheck</label>
</td>
</tr>
</table>
</td>
</tr>
<tr>
<td>
<div>
<label for="my_credit_card_field_id">Credit Card</label>
<div id="my_credit_card_field_id"></div>
</div>
<div>
<label for="exp_month">Exp Month</label>
<input id="exp_month" type="text" name="exp_month">
</div>
<div>
<label for="exp_year">Exp Year</label>
<input id="exp_year" type="text" name="exp_year">
</div>
<div>
<label for="my_cvv_field_id">CVV</label>
<div id="my_cvv_field_id"></div>
</div>
<div>
<label for="postal_code">Zip Code</label>
<input id="postal_code" type="text" name="postal_code">
</div>
</td>
<td width="20px">
</td>
<td>
<table width="100%">
<tr>
<td>
<input type="radio" id="business_radio" name="account_holder_type_radio" value="business">
</td>
<td>
<label for="business_radio">Business</label>
</td>
<td>
<input type="radio" id="personal_radio" name="account_holder_type_radio" value="personal">
</td>
<td>
<label for="personal_radio">Personal</label>
</td>
</tr>
</table>
<div>
<label for="my_routing_number_id">Routing Number</label>
<div id="my_routing_number_id"></div>
</div>
<div>
<label for="my_bank_account_number_id">Account Number</label>
<div id="my_bank_account_number_id"></div>
</div>
<table width="100%">
<tr>
<td>
<input type="radio" name='account_type_radio' id="checking_radio" value="checking">
</td>
<td>
<label for="checking_radio">Checking</label>
</td>
<td>
<input type="radio" name='account_type_radio' id="savings_radio" value="savings">
</td>
<td>
<label for="savings_radio">Savings</label>
</td>
</tr>
</table>
<div>
<label for="given_name">First Name</label>
<input id="given_name" type="text" name="given_name">
</div>
<div>
<label for="surname">Last Name</label>
<input id="surname" type="text" name="surname">
</div>
<div>
<label for="business_name">Business Name</label>
<input id="business_name" type="text" name="business_name">
</div>
</td>
</tr>
</table>
<table>
<tr>
<td>
<input type="submit" value="Submit"/>
</td>
</tr>
</table>
</form>
<script type="text/javascript">
const style = {
border: "1px solid rgb(204, 204, 204)",
'border-style': 'inset',
color: "#000",
"font-size": "11px",
"font-weight": "400",
padding: "8px",
width: "100%"
};
const creditCardHostedFieldsConfig = {
publicKey: "m_1234567890",
fields: [
{
selector: "#my_credit_card_field_id",
input: {
type: "credit_card_number",
css: style
}
},
{
selector: "#my_cvv_field_id",
input: {
type: "cvv",
css: style
}
}
]
};
const eCheckHostedFieldsConfig = {
publicKey: 'm_1234567890',
css: style,
fields: [
{
selector: '#my_bank_account_number_id',
placeholder: 'Bank Account Number',
input: {
type: 'bank_account_number',
css: style
}
},
{
selector: '#my_routing_number_id',
input: {
type: 'routing_number',
css: style
}
}
]
};
const hostedFieldsCallBack = function (state) {
console.log(state);
};
const creditCardHostedFields = window.AffiniPay.HostedFields.initializeFields(
creditCardHostedFieldsConfig,
hostedFieldsCallBack
);
const eCheckHostedFields = window.AffiniPay.HostedFields.initializeFields(
eCheckHostedFieldsConfig,
hostedFieldsCallBack
);
const form = document.getElementById('form');
form.onsubmit = function (event) {
event.preventDefault();
console.log(creditCardHostedFields.getState());
console.log(eCheckHostedFields.getState());
if (form['card_radio'].checked && creditCardHostedFields.getState()) {
const postal_code = document.getElementById('postal_code').value
const exp_year = document.getElementById('exp_year').value
const exp_month = document.getElementById('exp_month').value
creditCardHostedFields.getPaymentToken({"postal_code": postal_code, "exp_year": exp_year, "exp_month": exp_month})
.then(function (result) {
console.log(result.id);
// If getPaymentToken returns successfully you may pass your payment token to your backend service.
}).catch(function (err) {
console.log(err);
});
} else if (form['bank_radio'].checked && eCheckHostedFields.getState()) {
const given_name = document.getElementById('given_name').value
const surname = document.getElementById('surname').value
const business_name = document.getElementById('business_name').value
const isBusiness = document.getElementById('business_radio').checked
const isSavings = document.getElementById('savings_radio').checked
const extra_fields = {}
extra_fields.account_holder_type = isBusiness ? 'business' : 'individual'
extra_fields.account_type = isSavings ? 'savings' : 'checking'
if (business_radio.checked) {
extra_fields.name = business_name
} else {
extra_fields.given_name = given_name
extra_fields.surname = surname
}
console.log(JSON.stringify(extra_fields))
eCheckHostedFields.getPaymentToken(extra_fields).then(function (result) {
console.log(result.id);
// If getPaymentToken returns successfully you may pass your payment token to your backend service.
}).catch(function (err) {
console.log(err);
});
} else {
console.log('error');
}
};
</script>
</body>
</html>