There are multiple ways to incorporate the payment gateway within a website or mobile device. These options vary based upon ease of integration, required resources, features, and additional security.
Step One:
Submit all transaction details to the Payment Gateway except the customer’s sensitive payment information. The Payment Gateway will return a variable form-url.
Step Two:
Create an HTML form that collects the customer’s sensitive payment information and use the form-url that the Payment Gateway returns as the submit action in that form.
Step Three:
Once the customer has been redirected, obtain the token-id and complete the transaction through an HTTPS POST including the token-id which abstracts the sensitive payment information that was collected directly by the Payment Gateway.
To start step one, your payment application will submit a behind-the-scenes HTTPS direct POST that includes transaction variables, including an additional variable redirect-url, which is a URL that must exist on your web server that handles a future browser redirect. Sensitive payment information such as cc-number, cc-exp, and cvv cannot be submitted during step one. The Payment Gateway will generate and return the form-url variable containing a unique URL to be used in Step 2.
Next, during step two, you must develop an HTML form that collects at least the customer’s sensitive payment information such as cc-number, cc-exp, and cvv. You must use the form-url obtained in step one as the action in the HTML of your payment form. When the customer submits the form, the customer’s browser will transparently POST the contents of the payment form directly to the Payment Gateway. This methodology keeps your web server and payment application from seeing or transmitting any credit card data or other sensitive data. Once the Payment Gateway has collected the customer’s sensitive payment details, the customer’s browser will be instructed to return to the redirect-url on your web server. Furthermore, the Payment Gateway will generate and append a unique variable named token-id to the redirect-url in the GET query string. This token-id is an abstraction of the customer’s sensitive payment information that the Payment Gateway collected. Your redirect-url script must parse the token-id for use in step three.
To complete the transaction, you will submit another behind-the-scenes HTTPS direct POST including only the token-id and api-key. This token-id is used to “tie” together the initial customer information with the sensitive payment information that the payment gateway collected directly.
XML Element | Description |
---|---|
<sale|auth|credit|validate|offline> | Type of transaction to perform. |
api-key* | api-key is obtained in the security keys section of the control panel settings. |
redirect-url* | A URL on your web server that the gateway will redirect your customer to after sensitive data collection. |
amount* | Total amount to be charged (For “validate” actions, amount must be 0.00 or omitted). |
surcharge-amount | Surcharge amount. Format: x.xx |
authorization-code** | Specify authorization code. For use with “offline” action only. |
ip-address | Cardholder’s IP address. Format: xxx.xxx.xxx.xxx |
industry | Specify industry classification of transaction. Values: ‘ecommerce’, ‘moto’, or ‘retail’ |
billing-method | Set additional billing indicators. Values: ‘recurring’ or ‘installment’ |
billing-number | Specify installment billing number, on supported processors. For use when “billing-method” is set to installment. Values: 0-99 |
billing-total | Specify installment billing total on supported processors. For use when “billing-method” is set to installment. |
processor-id | If using multiple processors, route to specified processor. Obtained under Settings->Transaction Routing in the merchant control panel. |
sec-code | ACH standard entry class codes. Values: ‘PPD’, ‘WEB’, ‘TEL’, ‘CCD’, ‘POP’, or ‘ARC’ |
descriptor | Set payment descriptor on supported processors. |
descriptor-phone | Set payment descriptor phone on supported processors. |
descriptor-address | Set payment descriptor address on supported processors. |
descriptor-city | Set payment descriptor city on supported processors. |
descriptor-state | Set payment descriptor state on supported processors. |
descriptor-postal | Set payment descriptor postal code on supported processors. |
descriptor-country | Set payment descriptor country on supported processors. |
descriptor-mcc | Set payment descriptor mcc on supported processors. |
descriptor-merchant-id | Set payment descriptor merchant id on supported processors. |
descriptor-url | Set payment descriptor url on supported processors. |
currency | Set transaction currency. Format: ISO 4217 |
order-description | Order description. |
customer-id | Customer identification. |
customer-vault-id | Load customer details from an existing customer vault record. If set, no payment information is required during step two. |
merchant-receipt-email | Send merchant receipt to email |
customer-receipt | Send receipt if billing email included. Values: ‘true’ or ‘false’ |
merchant-defined-field-# | Merchant specified custom fields. Format: <merchant-defined-field-1>Value</merchant-defined-field-1> |
tracking-number | Shipping tracking number. |
shipping-carrier | Shipping carrier. Values: ‘ups’, ‘fedex’, ‘dhl’, or ‘usps’ |
order-id*** | Order id. |
signature-image | Cardholder signature image. For use with “sale” and “auth” actions only. Format: base64 encoded raw PNG image. (16kiB maximum) |
po-number*** | Cardholder’s purchase order number. |
tax-amount*** | The sales tax included in the transaction amount associated with the purchase. Setting tax equal to ‘-1’ indicates an order that is exempt from sales tax. Default: ‘0.00’ Format: x.xx |
shipping-amount*** | Total shipping amount. |
ship-from-postal**** | Postal/ZIP code of the address from where purchased goods are being shipped. Defaults to merchant profile postal code. |
summary-commodity-code**** | A code representing the type of commodity being purchased. The acquirer or processor will provide a list of current codes. |
duty-amount | Amount included in the transaction amount associated with the import of the purchased goods. Default: ‘0.00’ |
discount-amount | Amount included in the transaction amount of any discount applied to the complete order by the merchant. Default: ‘0.00’ |
national-tax-amount | The national tax amount included in the transaction amount. Default: ‘0.00’ |
alternate-tax-amount | Second tax amount included in the transaction amount in countries where more than one type of tax can be applied to the purchases. Default: ‘0.00’ |
alternate-tax-id | Tax identification number of the merchant that reported the alternate tax amount. |
vat-tax-amount | Contains the amount of any value added taxes which can be associated with the purchased item. Default: ‘0.00’ |
vat-tax-rate | Contains the tax rate used to calculate the sales tax amount appearing. Can contain up to 2 decimal places, ie 1% = 1.00. Default: ‘0.00’ |
vat-invoice-reference-number | Invoice number that is associated with the VAT invoice. |
customer-vat-registration | Value added tax registration number supplied by the cardholder. |
merchant-vat-registration | Government assigned tax identification number of the merchant from whom the goods or services were purchased. |
order-date | Purchase order date. Defaults to the date of the transaction. Format: YYMMDD |
skip-3ds | Skip over 3DS authentication process for this specific transaction. Values: “true” or “false” |
cardholder-auth† | Set 3D Secure condition. Values: ‘verified’ or ‘attempted’ |
eci† | E-commerce indicator. Values: ‘0’, ‘1’, ‘2’, ‘5’, ‘6’, or ‘7’ |
cavv† | Cardholder authentication verification value. Format: base64 encoded |
xid† | Cardholder authentication transaction id. Format: base64 encoded |
three-ds-version† | 3DSecure version. Examples: “1.0.2” or “2.0” |
directory-server-id | Directory Server Transaction ID. May be provided as part of 3DSecure 2.0 authentication. Format: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx |
initiated-by | Who initiated the transaction. Values: ‘customer’ or ‘merchant’ |
initial-transaction-id | Original payment gateway transaction id. |
stored-credential-indicator | The indicator of the stored credential. Values: ‘stored’ or ‘used’ Use ‘stored’ when processing the initial transaction in which you are storing a customer’s payment details (customer credentials) in the Customer Vault or other third-party payment storage system. Use ‘used’ when processing a subsequent or follow-up transaction using the customer payment details (customer credentials) you have already stored to the Customer Vault or third-party payment storage method. |
dup-seconds‡ | Override duplicate transaction detection time in seconds. |
avs-reject‡ | The transaction is rejected if the address verification result is a code in this list. Values are letters obtained under Settings->Address Verification in the control panel. Format: x|x|x|x… |
cvv-reject‡ | The transaction is rejected if the card ID verification result is a code in this list. Values are letters obtained under Settings->Card ID Verification in the control panel. Format: x|x|x|x… |
<billing> | The customer’s billing information |
billing-id | Specify billing id. Recommended when using customer vault hybrid action. Will be ignored if no hybrid add/update-customer is done. |
first-name | Cardholder’s first name. |
last-name | Cardholder’s last name. |
address1 | Cardholder’s billing address. |
city | Card billing city. |
state | Card billing state/province. Format: CC |
postal | Card billing postal code. |
country | Card billing country code. Format: CC/ISO 3166 |
phone | Billing phone number. |
Billing email address. | |
company | Cardholder’s company. |
address2 | Card billing address, line 2. |
fax | Billing fax number. |
account-type§ | The customer’s ACH account type. Values: ‘checking’ or ‘savings’ |
entity-type§ | The customer’s ACH account entity. Values: ‘personal’ or ‘business’ |
</billing> | |
<shipping> | The customer’s shipping information. |
shipping-id | Specify shipping id. Recommended when using customer vault hybrid action. Will be ignored if no hybrid add/update-customer is done. |
first-name | Shipping first name. |
last-name | Shipping last name. |
address1 | Shipping billing address. |
city | Shipping city. |
state | Shipping state/province. Format: CC |
postal**** | Shipping postal code. |
country**** | Shipping country code. Format: CC/ISO 3166 |
phone | Shipping phone number. |
Shipping email address. | |
company | Shipping company. |
address2 | Shipping address, line 2. |
fax | Shipping fax number. |
</shipping> | |
<product> | Product line item detail. Multiple product elements are allowed. |
product-code****¶ | Merchant defined description code of the item being purchased. |
description**** | Description of the item(s) being supplied. |
commodity-code**** | International description code of the individual good or service being supplied. The acquirer or processor will provide a list of current codes. |
unit-of-measure**** | Code for units of measurement as used in international trade. Default: ‘EACH’ |
unit-cost**** | Unit cost of item purchased. May contain up to 4 decimal places. |
quantity**** | Quantity of the item(s) being purchased. Default: ‘1’ |
total-amount**** | Purchase amount associated with the item. Default to ‘unit-cost’ x ‘quantity’ rounded to the nearest penny. |
tax-amount**** | Amount of tax on specific item. Amount should not be included in item-total-amount. Default: ‘0.00’ |
tax-rate**** | Percentage representing the value-added tax applied. 1% = 1.00. Default: ‘0.00’ |
discount-amount | Discount amount which can have been applied by the merchant on the sale of the specific item. Amount should not be included in ‘item-total-amount’. |
discount-rate | Discount rate for the line item. 1% = 1.00. Default: ‘0.00’ |
tax-type | Type of value-added taxes that are being used. |
alternate-tax-id | Tax identification number of the merchant that reported the alternate tax amount. |
</product> | |
<add-subscription> | Perform a simultaneous ‘hybrid’ recurring action while processing a transaction. |
start-date | The first day that the customer will be charged. Format: YYYYMMDD |
<plan> | |
plan-id | The unique plan ID that references only this recurring plan. |
payments | The number of payments before the recurring plan is complete. Note: Use ‘0’ for ‘until canceled’ |
amount | The plan amount to be charged each billing cycle. Format: x.xx |
day-frequency | How often, in days, to charge the customer. Cannot be set with ‘month-frequency’ or ‘day-of-month’. |
month-frequency | How often, in months, to charge the customer. Cannot be set with ‘day-frequency’. Must be set with ‘day-of-month’. Values: 1 through 24 |
day-of-month | The day that the customer will be charged. Cannot be set with ‘day-frequency’. Must be set with ‘month-frequency’. Values: 1 through 31 – for months without 29, 30, or 31 days, the charge will be on the last day |
</plan> | |
</add-subscription> | |
<add-customer|update-customer> | Perform a simultaneous ‘hybrid’ customer vault action while processing a transaction. This tag can be blank if submitting an ‘add-customer’ without specifying a ‘customer-vault-id’. |
customer-vault-id | Specify customer vault id. If omitted, will be auto-generated and returned in response. Required for ‘update-customer’. |
</add-customer|update-customer> | |
partial-payments†† | Specify whether a partial amount or full amount of the transaction should be settled. Format: ‘settle_partial’ or ‘payment_in_full’ |
partial-payment-id†† | Specify a partial payment ID. Required to collect an additional amount associated with an existing Partial Payment Transaction. Do not use on initial transaction. |
</sale|auth|credit|validate|offline> |
* | Always required |
** | Required for offline transactions |
*** | Required for Level 2 and Level 3 transactions |
**** | Required for Level 3 transactions |
† | Required for 3D-Secure transactions |
‡ | Required for Override transactions |
†† | Required for Partial Payment Transactions |
§ | Required for ACH transactions |
¶ | Required for Line Item Reporting |
XML Element | Description |
---|---|
<response> | |
result |
1=Approved 2=Declined 3=Error in transaction data or system error |
result-text | Textual response. |
transaction-id | Payment Gateway transaction id. |
result-code | Numeric mapping of processor responses (See Appendix 3). |
form-url | URL used as the action of the HTML form in step two. |
</response> |
HTML Form Fields | Description |
---|---|
billing-cc-number* | Credit card number. |
billing-cc-exp* | Credit card expiration. Format: MMYY |
billing-cvv | Card security code. |
billing-account-name** | The name on the customer’s ACH Account. |
billing-account-number** | The customer’s bank account number. |
billing-routing-number** | The customer’s bank routing number. |
billing-account-type | The customer’s ACH account type. Values: ‘checking’ or ‘savings’ |
billing-entity-type | The customer’s ACH account entity. Values: ‘personal’ or ‘business’ |
billing-micr† | Physical check’s Magnetic ink strip, on supported check processors. For use with ‘POP’ or ‘ARC’ sec-code. |
billing-track-1*** | Raw magnetic stripe data, track 1. |
billing-track-2*** | Raw magnetic stripe data, track 2. |
billing-track-3*** | Raw magnetic stripe data, track 3. |
billing-magnesafe-track-1*** | Raw MagTek Magensa encrypted reader data. |
billing-magnesafe-track-2*** | Raw MagTek Magensa encrypted reader data. |
billing-magnesafe-track-3*** | Raw MagTek Magensa encrypted reader data. |
billing-magnesafe-ksn*** | Raw MagTek Magensa encrypted reader data. |
billing-magnesafe-magneprint*** | Raw MagTek Magensa encrypted reader data. |
billing-magnesafe-magneprint-status*** | Raw MagTek Magensa encrypted reader data. |
billing-social-security-number**** | Customer’s social security number, checked against bad check writers database if check verification is enabled. |
billing-drivers-license-number**** | Driver’s license number, checked against bad check writers’ database if check verification is enabled. |
billing-drivers-license-dob**** | Driver’s license date of birth. |
billing-drivers-license-state**** | Customer’s driver’s license state. Format: CC |
billing-first-name | Cardholder’s first name. Overwrites value if passed during step one. |
billing-last-name | Cardholder’s last name. Overwrites value if passed during step one.. |
billing-address1 | Cardholder’s billing address. Overwrites value if passed during step one. |
billing-city | Card billing city. Overwrites value if passed during step one. |
billing-state | Card billing state/province. Overwrites value if passed during step one. Format: CC |
billing-postal | Card billing postal code. Overwrites value if passed during step one. |
billing-country | Card billing country code. Overwrites value if passed during step one. Format: CC/ISO 3166 |
billing-phone | Billing phone number. Overwrites value if passed during step one. |
billing-email | Billing email address. Overwrites value if passed during step one. |
billing-company | Cardholder’s company. Overwrites value if passed during step one. |
billing-address2 | Card billing address, line 2. Overwrites value if passed during step one. |
billing-fax | Billing fax number. Overwrites value if passed during step one. |
shipping-first-name | Shipping first name. Overwrites value if passed during step one. |
shipping-last-name | Shipping last name. Overwrites value if passed during step one. |
shipping-address1 | Shipping billing address. Overwrites value if passed during step one. |
shipping-city | Shipping city. Overwrites value if passed during step one. |
shipping-state | Shipping state/province. Overwrites value if passed during step one. |
shipping-postal | Shipping postal code. Overwrites value if passed during step one. |
shipping-country | Shipping country code. Overwrites value if passed during step one. |
shipping-phone | Shipping phone number. Overwrites value if passed during step one. |
shipping-email | Shipping email address. Overwrites value if passed during step one. |
shipping-company | Shipping company. Overwrites value if passed during step one. |
shipping-address2 | Shipping address, line 2. Overwrites value if passed during step one. |
shipping-fax | Shipping fax number. Overwrites value if passed during step one. |
* | Required for keyed credit card transactions. |
** | Required for ACH transactions. |
*** | Used for retail transactions. Variables used dependent on swipe device. |
**** | Required for check verification. |
† | Required for check scanning. |
Once the Payment Gateway has collected the customer’s sensitive payment details, the customer’s browser will immediately be redirected back to the redirect-url on your web server. A variable named token-id will be appended to the redirect-url in the GET query string as described below:
https://redirect-url/?token-id=[token]
XML Element | Description |
---|---|
<complete-action> | |
api-key* | api-key is obtained in the security keys section of the control panel settings. |
token-id* | Customer payment token returned during step two. |
</complete-action> |
* | Required |
XML Element | Description |
---|---|
<response> | |
result |
1=Transaction Approved 2=Transaction Declined 3=Error in transaction data or system error |
result-text | Textual response. |
transaction-id | Payment Gateway transaction ID |
result-code | Numeric mapping of processor responses. (See Appendix 3) |
authorization-code | Transaction authorization code. |
avs-result | AVS response code. (See Appendix 1) |
cvv-result | CVV response code. (See Appendix 2) |
action-type | Action type that was initially specified. Values: ‘sale’, ‘auth’, ‘credit’, ‘validate’, or ‘offline’ |
amount | Total amount charged. Format: x.xx |
amount-authorized | Returns the amount authorized. Format: x.xx |
ip-address | Cardholder’s IP address. Format: xxx.xxx.xxx.xxx |
industry | Industry classification of transaction. Values: ‘ecommerce’, ‘moto’, or ‘retail’ |
billing-method | Billing indicators used. Values: ‘recurring’ or ‘installment’ |
processor-id | Processor transaction was made through. |
sec-code | ACH standard entry class codes. Values: ‘PPD’, ‘WEB’, ‘TEL’, ‘CCD’, ‘POP’, or \ARC’ |
descriptor | Payment descriptor. |
descriptor-phone | Payment descriptor phone. |
descriptor-address | Set payment descriptor address on supported processors. |
descriptor-city | Set payment descriptor city on supported processors. |
descriptor-state | Set payment descriptor state on supported processors. |
descriptor-postal | Set payment descriptor postal code on supported processors. |
descriptor-country | Set payment descriptor country on supported processors. |
descriptor-mcc | Set payment descriptor mcc on supported processors. |
descriptor-merchant-id | Set payment descriptor merchant id on supported processors. |
descriptor-url | Set payment descriptor url on supported processors. |
currency | Transaction currency used. (Table 1.b) |
order-description | Order description. |
customer-id | Customer identification. |
customer-vault-id | Customer vault id used or created during action. |
merchant-receipt-email | Merchant receipt email. |
customer-receipt | Customer email receipt sent. Values: ‘true’ or ‘false’ |
partial-payment-balance | Returns the payment’s remaining balance. |
partial-payment-id | Numeric identifier used to submit subsequent partial payment transactions. |
merchant-defined-field-# | Merchant specified custom fields. Format: <merchant-defined-field-1>Value</merchant-defined-field-1> |
tracking-number | Shipping tracking number. |
shipping-carrier | Shipping carrier. Values: ‘ups’, ‘fedex’, ‘dhl’, or ‘usps’ |
order-id | Order id. |
po-number | Cardholder’s purchase order number. |
tax-amount | The sales tax included in the transaction amount associated with the purchase. Format: x.xx |
shipping-amount | Total shipping amount. Format: x.xx |
ship-from-postal | Postal/ZIP code of the address from where purchased goods are being shipped. |
summary-commodity-code | A code representing the type of commodity being purchased. The acquirer or processor will provide a list of current codes. |
duty-amount | Amount included in the transaction amount associated with the import of the purchased goods. Format: x.xx |
discount-amount | Amount included in the transaction amount of any discount applied to the complete order by the merchant. Format: x.xx |
national-tax-amount | The national tax amount included in the transaction amount. Format: x.xx |
alternate-tax-amount | Second tax amount included in the transaction amount in countries where more than one type of tax can be applied to the purchases. Default: ‘0.00’ Format: x.xx |
alternate-tax-id | Tax identification number of the merchant that reported the alternate tax amount. |
vat-tax-amount | Contains the amount of any value added taxes which can be associated with the purchased item. Format: x.xx |
vat-tax-rate | Contains the tax rate used to calculate the sales tax amount appearing. Can contain up to 2 decimal places, ie 1% = 1.00. Format: x.xx |
vat-invoice-reference-number | Invoice number that is associated with the VAT invoice. |
customer-vat-registration | Value added tax registration number supplied by the cardholder. |
merchant-vat-registration | Government assigned tax identification number of the merchant from whom the goods or services were purchased. |
order-date | Purchase order date. Format: YYMMDD |
cardholder-auth | 3D Secure condition. Values: ‘verified’ or ‘attempted’ |
eci | E-commerce indicator. Values: ‘0’, ‘1’, ‘2’, ‘5’, ‘6’, or ‘7’ |
cavv | Cardholder authentication verification value. Format: base64 encoded |
xid | Cardholder authentication transaction id. Format: base64 encoded |
three-ds-version | 3DSecure version. Examples: “1.0.2” or “2.0” |
directory-server-id | Directory Server Transaction ID. May be provided as part of 3DSecure 2.0 authentication. Format: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx |
dup-seconds | Override duplicate transaction detection checking in seconds. |
avs-reject | Values are letters obtained under Settings->Address Verification in the control panel. |
cvv-reject | Values are letters obtained under Settings->Card ID Verification in the control panel. |
<billing> | The customer’s billing information |
billing-id | Billing id used or created for this action. |
first-name | Cardholder’s first name. |
last-name | Cardholder’s last name. |
address1 | Cardholder’s billing address. |
city | Card billing city. |
state | Card billing state/province. Format: CC |
postal | Card billing postal code. |
country | Card billing country code. Format: CC/ISO 3166 |
phone | Billing phone number. |
Billing email address. | |
company | Cardholder’s company. |
address2 | Card billing address, line 2. |
fax | Billing fax number. |
social-security-number | Customer’s social security number |
drivers-license-number | Driver’s license number. |
drivers-license-dob | Driver’s license date of birth. |
drivers-license-state | Customer’s driver’s license state. Format: CC |
cc-number | Masked credit card number. Format: XXXXXX********XXXX |
cc-exp | Credit card expiration Format: MMYY |
account-name | The name on the customer’s bank account. |
account-number | Masked bank account number. Format: X****XXXX |
routing-number | Masked bank routing number. Format: X****XXXX |
account-type | The customer’s ACH account type. Values: ‘checking’ or ‘savings’ |
entity-type | The customer’s ACH account entity. Values: ‘personal’ or ‘business’ |
priority | Billing id priority. Format: Numeric, 1-255 |
</billing> | |
<shipping> | The customer’s shipping information. |
shipping-id | Shipping id used or created for this action. Recommended when using customer vault hybrid action; will be ignored if no hybrid add/update-customer is done. |
first-name | Shipping first name. |
last-name | Shipping last name. |
address1 | Shipping billing address. |
city | Shipping city. |
state | Shipping state/province. Format: CC |
postal | Shipping postal code. |
country | Shipping country code. Format: CC/ISO 3166 |
phone | Shipping phone number. |
Shipping email address. | |
company | Shipping company. |
address2 | Shipping address, line 2. |
fax | Shipping fax number. |
priority | Shipping id priority. Format: Numeric, 1-255 |
</shipping> | |
<product> | Product line item detail. Multiple product elements are allowed. |
product-code | Merchant defined description code of the item being purchased. |
description | Description of the item(s) being supplied. |
commodity-code | International description code of the individual good or service being supplied. The acquirer or processor will provide a list of current codes. |
unit-of-measure | Code for unites of measurement as used in international trade. |
unit-cost | Unit cost of item purchased. May contain up to 4 decimal places. |
quantity | Quantity of the item(s) being purchased. |
total-amount | Purchase amount associated with the item. Format: x.xx |
tax-amount | Amount of tax on specific item. Amount should not be included in item-total-amount. Format: x.xx |
tax-rate | Percentage representing the value-added tax applied. 1% = 1.00. Format: x.xx |
discount-amount | Discount amount which can have been applied by the merchant on the sale of the specific item. Format: x.xx |
discount-rate | Discount rate for the line item. 1% = 1.00 Format: x.xx |
tax-type | Type of value-added taxes that are being used. |
alternate-tax-id | Tax identification number of the merchant that reported the alternate tax amount. |
</product> | |
</response> |
Element | Description |
---|---|
<capture> | |
api-key* | api-key is obtained in the security keys section of the control panel settings. |
transaction-id* | Original Payment Gateway transaction id. |
amount | Total amount to be settled, this amount may be equal to or less than the authorized amount. |
merchant-defined-field-# | Merchant specified custom fields. Format: <merchant-defined-field-1>Value</merchant-defined-field-1> |
tracking-number | Shipping tracking number. |
shipping-carrier | Shipping carrier used. Values: ‘ups’, ‘fedex’, ‘dhl’, or ‘usps’ |
order-id | Order ID. |
signature-image | Cardholder signature image. Format: base64 encoded raw PNG image. (16kiB maximum) |
</capture> |
* | Required |
Element | Description |
---|---|
<void> | |
api-key* | api-key is obtained in the security keys section of the control panel settings. |
transaction-id* | Original Payment Gateway transaction id. |
merchant-defined-field-# | Merchant specified custom fields. Format: <merchant-defined-field-1>Value</merchant-defined-field-1> |
</void> |
* | Required |
Element | Description |
---|---|
<refund> | |
api-key* | api-key is obtained in the security keys section of the control panel settings. |
transaction-id* | Original Payment Gateway transaction id. |
amount | Total amount to be refunded. This amount may be equal to or less than the settled amount. Setting the amount to 0.00 will refund the entire amount. |
merchant-defined-field-# | Merchant specified custom fields. Format: <merchant-defined-field-1>Value</merchant-defined-field-1> |
</refund> |
* | Required |
Element | Description |
---|---|
<update> | |
api-key* | api-key is obtained in the security keys section of the control panel settings. |
transaction-id* | Original Payment Gateway transaction id. |
merchant-defined-field-# | Merchant specified custom fields. Format: <merchant-defined-field-1>Value</merchant-defined-field-1> |
tracking-number | Shipping tracking number. |
shipping-carrier | Shipping carrier used. Values: ‘ups’, ‘fedex’, ‘dhl’, or ‘usps’ |
order-id | Order ID. |
signature-image | Cardholder signature image. Format: base64 encoded raw PNG image. (16kiB maximum) |
</update> |
* | Required |
Element | Description |
---|---|
<complete-partial-payment> | |
api-key* | api-key is obtained in the security keys section of the control panel settings. |
partial-payment-id* | Specify a partial payment ID. Required to collect an additional amount associated with an existing Partial Payment Transaction. Do not use on initial transaction. |
</complete-partial-payment> |
* | Required |
Element | Description |
---|---|
<add-subscription> | Associate payment information with a recurring plan. |
api-key* | api-key is obtained in the Security Keys section of the Control Panel Settings. |
redirect-url* | A URL on your web server that the gateway will redirect your customer to after sensitive data collection. Value is not required when sensitive data is not presented. Example: Adding a Subscription using a Customer Vault ID. |
customer-vault-id | Load customer details from an existing customer vault record. If set, no payment information is required during step two. |
start-date | The first day that the customer will be charged. Format: YYYYMMDD |
order-id | Order id. |
po-number | Cardholder’s purchase order number. |
order-description | Order description. |
currency | Set transaction currency. Format: ISO 4217 |
tax-amount | The sales tax included in the transaction amount associated with the purchase. Setting tax equal to ‘-1’ indicates an order that is exampt from sales tax. Default: 0.00′ Format: x.xx |
shipping-amount | Total shipping amount. |
merchant-defined-field-# | Merchant specified custom fields. Format: <merchant-defined-field-1>Value</merchant-defined-field-1> |
source-transaction-id | Specifies a payment gateway transaction id in order to associate payment information with a Subscription record. |
<plan> | |
plan-id* | The unique plan ID that references only this recurring plan. |
</plan> | |
<billing> | The customer’s billing information |
billing-id | Specify billing id. Recommended when using customer vault hybrid action. Will be ignored if no hybrid add/update-customer is done. |
first-name | Cardholder’s first name. |
last-name | Cardholder’s last name. |
address1 | Cardholder’s billing address. |
city | Card billing city. |
state | Card billing state/province. Format: CC |
postal | Card billing postal code. |
country | Card billing country code. Format: CC/ISO 3166 |
phone | Billing phone number. |
Billing email address. | |
company | Cardholder’s company. |
address2 | Card billing address, line 2. |
fax | Billing fax number. |
account-type** | The customer’s ACH account type. Values: ‘checking’ or ‘savings’ |
entity-type** | The customer’s ACH account entity. Values: ‘personal’ or ‘business’ |
</billing> | |
<shipping> | The customer’s shipping information. |
shipping-id | Specify shipping id. Recommended when using customer vault hybrid action. Will be ignored if no hybrid add/update-customer is done. |
first-name | Shipping first name. |
last-name | Shipping last name. |
address1 | Shipping address. |
city | Shipping city. |
state | Shipping state/province. Format: CC |
postal | Shipping postal code. |
country | Shipping country code. Format: CC/ISO 3166 |
phone | Shipping phone number. |
Shipping email address. | |
company | Shipping company. |
address2 | Shipping address, line 2. |
fax | Shipping fax number. |
</shipping> | |
</add-subscription> |
* | Always required |
** | Required for ACH transactions |
Element | Description |
---|---|
<add-subscription> | Associate payment information with a recurring plan. |
api-key* | api-key is obtained in the Security Keys section of the Control Panel Settings. |
redirect-url* | A URL on your web server that the gateway will redirect your customer to after sensitive data collection. Value is not required when sensitive data is not presented. Example: Adding a Subscription using a Customer Vault ID. |
customer-vault-id | Load customer details from an existing customer vault record. If set, no payment information is required during step two. |
start-date | The first day that the customer will be charged. Format: YYYYMMDD |
order-id | Order id. |
po-number | Cardholder’s purchase order number. |
order-description | Order description. |
currency | Set transaction currency. Format: ISO 4217 |
tax-amount | The sales tax included in the transaction amount associated with the purchase. Setting tax equal to ‘-1’ indicates an order that is exampt from sales tax. Default: ‘0.00’ Format: x.xx |
shipping-amount | Total shipping amount. |
merchant-defined-field-# | Merchant specified custom fields. Format: <merchant-defined-field-1>Value</merchant-defined-field-1> |
source-transaction-id | Specifies a payment gateway transaction id in order to associate payment information with a Subscription record. |
<plan> | |
payments* | The number of payments before the recurring plan is complete. Notes: ‘0’ for until canceled |
amount* | The plan amount to be charged each billing cycle. Format: x.xx |
day-frequency*** | How often, in days, to charge the customer. Cannot be set with ‘month-frequency’ or ‘day-of-month’. |
month-frequency**** | How often, in months, to charge the customer. Cannot be set with ‘day-frequency’. Must be set with ‘day-of-month’. Values: 1 through 24 |
day-of-month**** | The day that the customer will be charged. Cannot be set with ‘day-frequency’. Must be set with ‘month-frequency’. Values: 1 through 31 – for months without 29, 30, or 31 days, the charge will be on the last day |
</plan> | |
<billing> | The customer’s biling information |
billing-id | Specify billing id. Recommended when using customer vault hybrid action. Will be ignored if no hybrid add/update-customer is done. |
first-name | Cardholder’s first name. |
last-name | Cardholder’s last name. |
address1 | Cardholder’s billing address. |
city | Card billing city. |
state | Card billing state/province. Format: CC |
postal | Card billing postal code. |
country | Card billing country code. Format: CC/ISO 3166 |
phone | Billing phone number. |
Billing email address. | |
company | Cardholder’s company. |
address2 | Card billing address, line 2. |
fax | Billing fax number. |
account-type** | The customer’s ACH account type. Values: ‘checking’ or ‘savings’ |
entity-type** | The customer’s ACH account entity. Values: ‘personal’ or ‘business’ |
</billing> | |
<shipping> | The customer’s shipping information. |
shipping-id | Specify shipping id. Recommended when using customer vault hybrid action. Will be ignored if no hybrid add/update-customer is done. |
first-name | Shipping first name. |
last-name | Shipping last name. |
address1 | Shipping address. |
city | Shipping city. |
state | Shipping state/province. Format: CC |
postal | Shipping postal code. |
country | Shipping country code. Format: CC/ISO 3166 |
phone | Shipping phone number. |
Shipping email address. | |
company | Shipping company. |
address2 | Shipping address, line 2. |
fax | Shipping fax number. |
</shipping> | |
</add-subscription> |
* | Always required |
** | Required for ACH transactions |
*** | Required unless ‘month-frequency’ and ‘day-of-month’ is set. |
**** | Required unless ‘day-frequency’ is set. |
Element | Description |
---|---|
<update-subscription> | Update Customer’s information for a subscription. |
api-key* | api-key is obtained in the Security Keys section of the Control Panel Settings. |
redirect-url* | A URL on your web server that the gateway will redirect your customer to after sensitive data collection. Value is not required when sensitive data is not presented. Example: Updating a Subscription using a Customer Vault ID. |
subscription-id* | The subscription that will be updated. |
order-id | Order id. |
po-number | Cardholder’s purchase order number. |
order-description | Order description. |
currency | Set transaction currency. Format: ISO 4217 |
merchant-defined-field-# | Merchant specified custom fields. Format: <merchant-defined-field-1>Value</merchant-defined-field-1> |
<billing> | The customer’s billing information |
first-name | Cardholder’s first name. |
last-name | Cardholder’s last name. |
address1 | Cardholder’s billing address. |
city | Card billing city. |
state | Card billing state/province. Format: CC |
postal | Card billing postal code. |
country | Card billing country code. Format: CC/ISO 3166 |
phone | Billing phone number. |
Billing email address. | |
company | Cardholder’s company. |
address2 | Card billing address, line 2. |
fax | Billing fax number. |
account-type** | The customer’s ACH account type. Values: ‘checking’ or ‘savings’ |
entity-type** | The customer’s ACH account entity. Values: ‘personal’ or ‘business’ |
</billing> | |
<shipping> | The customer’s shipping information. |
first-name | Shipping first name. |
last-name | Shipping last name. |
address1 | Shipping address. |
city | Shipping city. |
state | Shipping state/province. Format: CC |
postal | Shipping postal code. |
country | Shipping country code. Format: CC/ISO 3166 |
phone | Shipping phone number. |
Shipping email address. | |
company | Shipping company. |
address2 | Shipping address, line 2. |
fax | Shipping fax number. |
</shipping> | |
</update-subscription> |
* | Always Required. |
** | Required for ACH subscriptions. |
HTML Form Fields | Description |
---|---|
billing-cc-number* | Credit card number. |
billing-cc-exp* | Credit card expiration. Format: MMYY |
billing-cvv | Card security code. |
billing-account-name** | The name on the customer’s ACH Account. |
billing-account-number** | The customer’s bank account number. |
billing-routing-number** | The customer’s bank routing number. |
billing-account-type | The customer’s ACH account type. Values: ‘checking’ or ‘savings’ |
billing-entity-type | The customer’s ACH account entity. Values: ‘personal’ or ‘business’ |
billing-micr† | Physical check’s Magnetic ink strip, on supported check processors. For use with ‘POP’ or ‘ARC’ sec-code. |
billing-track-1*** | Raw magnetic stripe data, track 1. |
billing-track-2*** | Raw magnetic stripe data, track 2. |
billing-track-3*** | Raw magnetic stripe data, track 3. |
billing-magnesafe-track-1*** | Raw MagTek Magensa encrypted reader data. |
billing-magnesafe-track-2*** | Raw MagTek Magensa encrypted reader data. |
billing-magnesafe-track-3*** | Raw MagTek Magensa encrypted reader data. |
billing-magnesafe-ksn*** | Raw MagTek Magensa encrypted reader data. |
billing-magnesafe-magneprint-status*** | Raw MagTek Magensa encrypted reader data. |
billing-social-security-number**** | Customer’s social security number, checked against bad check writers database if check verification is enabled. |
billing-drivers-license-number**** | Drivers license number, checked against bad check writers database if check verification is enabled. |
billing-drivers-license-dob**** | Drivers license date of birth. |
billing-drivers-license-state**** | Customer’s drivers license state. Format: CC |
billing-first-name | Cardholder’s first name. Overwrites value if passed during step one. |
billing-last-name | Cardholder’s last name. Overwrites value if passed during step one. |
billing-address1 | Cardholder’s billing address. Overwrites value if passed during step one. |
billing-city | Card billing city. Overwrites value if passed during step one. |
billing-state | Card billing state/province. Overwrites value if passed during step one. Format: CC |
billing-postal | Card billing postal code. Overwrites value if passed during step one. |
billing-country | Card billing country code. Overwrites value if passed during step one. Format: CC/ISO 3166 |
billing-phone | Billing phone number. Overwrites value if passed during step one. |
billing-email | Billing email address. Overwrites value if passed during step one. |
billing-company | Cardholder’s company. Overwrites value if passed during step one. |
billing-address2 | Card billing address, line 2. Overwrites value if passed during step one. |
billing-fax | Billing fax number. Overwrites value if passed during step one. |
shipping-first-name | Shipping first name. Overwrites value if passed during step one. |
shipping-last-name | Shipping last name. Overwrites value if passed during step one. |
shipping-address1 | Shipping address. Overwrites value if passed during step one. |
shipping-city | Shipping city. Overwrites value if passed during step one. |
shipping-state | Shipping state/province. Overwrites value if passed during step one. |
shipping-postal | Shipping postal code. Overwrites value if passed during step one. |
shipping-country | Shipping country code. Overwrites value if passed during step one. |
shipping-phone | Shipping phone number. Overwrites value if passed during step one. |
shipping-email | Shipping email address. Overwrites value if passed during step one. |
shipping-company | Shipping company. Overwrites value if passed during step one. |
shipping-address2 | Shipping address, line 2. Overwrites value if passed during step one. |
shipping-fax | Shipping fax number. Overwrites value if passed during step one. |
* | Required for keyed credit card transactions. |
** | Required for ACH transactions. |
*** | Used for retail transactions. Variables used dependant on swipe device. |
**** | Required for check verification. |
† | Required for check scanning. |
Once the Payment Gateway has collected the customer’s sensitive payment details, the customer’s browser will immediately be redirected back to the redirect-url on your web server. A variable named token-id will be appended to the redirect-url in the GET query string as described below:
https://redirect-url/?token-id=[token]
XML Element | Description |
---|---|
<complete-action> | |
api-key* | api-key is obtained in the security keys section of the control panel settings. |
token-id* | Customer payment token returned during step two. |
</complete-action> |
* | Required |
XML Element | Description |
---|---|
response | |
result |
1=Transaction Approved 2=Transction Declined 3=Error in transaction data or system error |
result-text | Textual response. |
result-code | Numeric mapping of processor responses. (See Appendix 3) |
action-type | Action type that was initially specified. Values: ‘sale’, ‘auth’, ‘credit’, ‘validate’, or ‘offline’ |
subscription-id | Subscription ID used or created during action. |
merchant-defined-field-# | Merchant specified custom fields. Format: <merchant-defined-field-1>Value</merchant-defined-field-1> |
<plan> | |
payments | The number of payments before the recurring plan is complete. Notes: ‘0’ for until canceled |
amount | The plan amount to be charged each billing cycle. Format: x.xx |
name | The display name of the plan. |
plan-id | The plan ID that is associated with this subscription. |
day-frequency | How often, in days, to charge the customer. Cannot be set with ‘month-frequency’ or ‘day-of-month’. |
month-frequency | How often, in months, to charge the customer. Cannot be set with ‘day-frequency’. Must be set with ‘day-of-month’. Values: 1 through 24 |
day-of-month | The day that the customer will be charged. Cannot be set with ‘day-frequency’. Must be set with ‘month-frequency’. Values: 1 through 31 – for months without 29, 30, or 31 days, the charge will be on the last day |
</plan> | |
<billing> | The customer’s billing information. |
billing-id | Billing id used or created for this action. |
first-name | Cardholder’s first name. |
last-name | Cardholder’s last name. |
address1 | Cardholder’s billing address. |
city | Card billing city. |
state | Card billing state/province. Format: CC |
postal | Card billing postal code. |
country | Card billing country code. Format: CC/ISO 3166 |
phone | Billing phone number. |
Billing email address. | |
company | Cardholder’s company. |
address2 | Card billing address, line 2. |
fax | Billing fax number. |
social-security-number | Customer’s social security number |
drivers-license-number | Drivers license number. |
drivers-license-dob | Drivers license date of birth. |
drivers-license-state | Customer’s drivers license state. Format: CC |
cc-number | Masked credit card number. Format: XXXXXX********XXXX |
cc-exp | Credit card expiration. Format: MMYY |
account-name | The name on the customer’s bank account. |
account-number | Masked bank account number. Format: X****XXXX |
routing-number | Masked bank routing number. Format: X****XXXX |
account-type | The customer’s ACH account type. Values: ‘checking’ or ‘savings’ |
entity-type | The customer’s ACH account entity. Values: ‘personal’ or ‘business’ |
priority | Billing id priority. Format: Numeric, 1-255 |
</billing> | |
<shipping> | The customer’s shipping information. |
shipping-id | Shipping id used or created during action. |
first-name | Shipping first name. |
last-name | Shipping last name. |
address1 | Shipping address. |
city | Shipping city. |
state | Shipping state/province. Format: CC |
postal | Shipping postal code. |
country | Shipping country code. Format: CC/ISO 3166 |
phone | Shipping phone number. |
Shipping email address. | |
company | Shipping company. |
address2 | Shipping address, line 2. |
fax | Shipping fax number. |
priority | Shipping id priority. Format: Numeric, 1-255 |
</shipping> | |
</response> |
Element | Description |
---|---|
<add-plan> | Add a recurring plan that subscriptions can be added to in the future. |
api-key* | api-key is obtained in the Security Keys section of the Control Panel Settings. |
<plan> | |
payments* | The number of payments before the recurring plan is complete. Notes: ‘0’ for until canceled |
amount* | The plan amount to be charged each billing cycle. Format: x.xx |
name* | The display name of the plan. |
plan-id* | The unique plan ID that references only this recurring plan. |
day-frequency** | How often, in days, to charge the customer. Cannot be set with ‘month-frequency’ or ‘day-of-month’. |
month-frequency*** | How often, in months, to charge the customer. Cannot be set with ‘day-frequency’. Must be set with ‘day-of-month’. Values: 1 through 24 |
day-of-month*** | The day that the customer will be charged. Cannot be set with ‘day-frequency’. Must be set with ‘month-frequency’. Values: 1 through 31 – for months without 29, 30, or 31 days, the charge will be on the last day |
</plan> | |
</add-plan> |
* | Always required |
** | Required unless ‘month-frequency’ and ‘day-of-month’ is set. |
*** | Required unless ‘day-frequency’ is set. |
Element | Description |
---|---|
<delete-subscription> | Delete the subscription. Customer will no longer be charged. |
api-key* | api-key is obtained in the Security Keys section of the Control Panel Settings. |
subscription-id* | The subscription ID that will be deleted. |
</delete-subscription> |
* | Always required |
XML Element | Description |
---|---|
<add-customer|update-customer> | Type of transaction to perform. |
api-key* | api-key is obtained in the security keys section of the control panel settings. |
redirect-url* |
A URL on your web server that the gateway will redirect your customer to after sensitive data collection. Value is not required for ‘update-customer’ requests when sensitive data is not being presented. Example: Updating an address or zip code only. |
customer-vault-id | Load customer details from an existing customer vault record. If set, no payment information is required during step two. |
merchant-defined-field-# | Merchant specified custom fields. Format: <merchant-defined-field-1>Value</merchant-defined-field-1> |
source-transaction-id | Specifies a payment gateway transaction id in order to associate payment information with a Customer Vault record. |
<billing> | The customer’s billing information |
billing-id | Specify billing id. Required for ‘update-customer’ if multiple billing-ids exist, optional for ‘add-billing’. |
first-name | Cardholder’s first name. |
last-name | Cardholder’s last name. |
address1 | Cardholder’s billing address. |
city | Card billing city. |
state | Card billing state/province. Format: CC |
postal | Card billing postal code. |
country | Card billing country code. Format: CC/ISO 3166 |
phone | Billing phone number. |
Billing email address. | |
company | Cardholder’s company. |
address2 | Card billing address, line 2. |
fax | Billing fax number. |
account-type | The customer’s ACH account type. Values: ‘checking’ or ‘savings’ |
entity-type | The customer’s ACH account entity. Values: ‘personal’ or ‘business’ |
priority | Specify priority (If omitted, will be auto-generated and returned in response). Format: Numeric, 1-255 |
</billing> | |
<shipping> | The customer’s shipping information. |
shipping-id | Specify shipping id (Required for update-customer if multiple shipping-ids exist. Optional for add-billing). |
first-name | Shipping first name. |
last-name | Shipping last name. |
address1 | Shipping billing address. |
city | Shipping city. |
state | Shipping state/province. Format: CC |
postal | Shipping postal code. |
country | Shipping country code. Format: CC/ISO 3166 |
phone | Shipping phone number. |
Shipping email address. | |
company | Shipping company. |
address2 | Shipping address, line 2. |
fax | Shipping fax number. |
priority | Specify priority, if omitted, will be auto-generated and returned in response. Format: Numeric, 1-255 |
</shipping> | |
</add-customer|update-customer> |
* | Required |
XML Element | Description |
---|---|
<response> | |
result |
1=Approved 2=Declined 3=Error in transaction data or system error |
result-text | Textual response. |
result-code | Numeric mapping of processor responses. (See Appendix 3) |
form-url | URL used as the action of the HTML form in step two. |
</response> |
HTML Form Fields | Description |
---|---|
billing-cc-number* | Credit card number. |
billing-cc-exp* | Credit card expiration. Format: MMYY |
billing-cvv | Card security code. |
billing-account-name** | The name on the customer’s ACH Account. |
billing-account-number** | The customer’s bank account number. |
billing-routing-number** | The customer’s bank routing number. |
billing-account-type | The customer’s ACH account type. Values: ‘checking’ or ‘savings’ |
billing-entity-type | The customer’s ACH account entity. Values: ‘personal’ or ‘business’ |
billing-micr† | Physical check’s Magnetic ink strip, on supported check processors. For use with ‘POP’ or ‘ARC’ sec-code. |
billing-track-1*** | Raw magnetic stripe data, track 1. |
billing-track-2*** | Raw magnetic stripe data, track 2. |
billing-track-3*** | Raw magnetic stripe data, track 3. |
billing-magnesafe-track-1*** | Raw MagTek Magensa encrypted reader data. |
billing-magnesafe-track-2*** | Raw MagTek Magensa encrypted reader data. |
billing-magnesafe-track-3*** | Raw MagTek Magensa encrypted reader data. |
billing-magnesafe-ksn*** | Raw MagTek Magensa encrypted reader data. |
billing-magnesafe-magneprint-status*** | Raw MagTek Magensa encrypted reader data. |
billing-social-security-number**** | Customer’s social security number (Checked against bad check writers database if check verification is enabled). |
billing-drivers-license-number**** | Driver’s license number (Checked against bad check writers database if check verification is enabled). |
billing-drivers-license-dob**** | Driver’s license date of birth. |
billing-drivers-license-state**** | Customer’s driver’s license state. Format: CC |
billing-first-name | Cardholder’s first name, overwrites value if passed during step one. |
billing-last-name | Cardholder’s last name, overwrites value if passed during step one. |
billing-address1 | Cardholder’s billing address, overwrites value if passed during step one. |
billing-city | Card billing city, overwrites value if passed during step one. |
billing-state | Card billing state/province, overwrites value if passed during step one. Format: CC |
billing-postal | Card billing postal code, overwrites value if passed during step one. |
billing-country | Card billing country code, overwrites value if passed during step one. Format: CC/ISO 3166 |
billing-phone | Billing phone number, overwrites value if passed during step one. |
billing-email | Billing email address, overwrites value if passed during step one. |
billing-company | Cardholder’s company, overwrites value if passed during step one. |
billing-address2 | Card billing address, line 2, overwrites value if passed during step one. |
billing-fax | Billing fax number, overwrites value if passed during step one. |
shipping-first-name | Shipping first name, overwrites value if passed during step one. |
shipping-last-name | Shipping last name, overwrites value if passed during step one. |
shipping-address1 | Shipping billing address, overwrites value if passed during step one. |
shipping-city | Shipping city, overwrites value if passed during step one. |
shipping-state | Shipping state/province, overwrites value if passed during step one. Format: CC |
shipping-postal | Shipping postal code, overwrites value if passed during step one. |
shipping-country | Shipping country code, overwrites value if passed during step one. Format: CC/ISO 3166 |
shipping-phone | Shipping phone number, overwrites value if passed during step one. |
shipping-email | Shipping email address, overwrites value if passed during step one. |
shipping-company | Shipping company, overwrites value if passed during step one. |
shipping-address2 | Shipping address, line 2, overwrites value if passed during step one. |
shipping-fax | Shipping fax number, overwrites value if passed during step one. |
* | Required for keyed credit card transactions. |
** | Required for ACH transactions. |
*** | Used for retail transactions. Variables used dependent on swipe device. |
**** | Required for check verification. |
† | Required for check scanning. |
Once the Payment Gateway has collected the customer’s sensitive payment details, the customer’s browser will immediately be redirected back to the redirect-url on your web server. A variable named token-id will be appended to the redirect-url in the GET query string as described below:
https://redirect-url/?token-id=[token]
XML Element | Description |
---|---|
<complete-action> | |
api-key* | api-key is obtained in the security keys section of the control panel settings. |
token-id* | Customer payment token returned during step two. |
</complete-action> |
* | Required |
XML Element | Description |
---|---|
<response> | |
result |
1=Transaction Approved 2=Transaction Declined 3=Error in transaction data or system error |
result-text | Textual response. |
result-code | Numeric mapping of processor responses. (See Appendix 3) |
action-type | Action type that was initially specified. Values: ‘sale’, ‘auth’, ‘credit’, ‘validate’, or ‘offline’ |
customer-vault-id | Customer vault id used or created during action. |
merchant-defined-field-# | Merchant specified custom fields. Format: <merchant-defined-field-1>Value</merchant-defined-field-1> |
<billing> | The customer’s billing information. |
billing-id | Billing id used or created for this action. |
first-name | Cardholder’s first name. |
last-name | Cardholder’s last name. |
address1 | Cardholder’s billing address. |
city | Card billing city. |
state | Card billing state/province. Format: CC |
postal | Card billing postal code. |
country | Card billing country code. Format: CC/ISO 3166 |
phone | Billing phone number. |
Billing email address. | |
company | Cardholder’s company. |
address2 | Card billing address, line 2. |
fax | Billing fax number. |
social-security-number | Customer’s social security number |
drivers-license-number | Driver’s license number. |
drivers-license-dob | Driver’s license date of birth. |
drivers-license-state | Customer’s driver’s license state. Format: CC |
cc-number | Masked credit card number. Format: XXXXXX********XXXX |
cc-exp | Credit card expiration. Format: MMYY |
account-name | The name on the customer’s bank account. |
account-number | Masked bank account number. Format: X****XXXX |
routing-number | Masked bank routing number. Format: X****XXXX |
account-type | The customer’s ACH account type. Values: ‘checking’ or ‘savings’ |
entity-type | The customer’s ACH account entity. Values: ‘personal’ or ‘business’ |
priority | Billing id priority. Format: Numeric, 1-255 |
</billing> | |
<shipping> | The customer’s shipping information. |
shipping-id | Shipping id used or created during action. |
first-name | Shipping first name. |
last-name | Shipping last name. |
address1 | Shipping billing address. |
city | Shipping city. |
state | Shipping state/province. Format: CC |
postal | Shipping postal code. |
country | Shipping country code. Format: CC/ISO 3166 |
phone | Shipping phone number. |
Shipping email address. | |
company | Shipping company. |
address2 | Shipping address, line 2. |
fax | Shipping fax number. |
priority | Shipping id priority. Format: Numeric, 1-255 |
</shipping> | |
</response> |
XML Element | Description |
---|---|
<add-billing|update-billing> | Type of transaction to perform. |
api-key* | api-key is obtained in the security keys section of the control panel settings. |
redirect-url* |
A URL on your web server that the gateway will redirect your customer to after sensitive data collection. Value is not required for ‘update-billing’ requests when sensitive data is not presented. Example: Updating an address or zip code only. |
customer-vault-id* | Load customer details from an existing customer vault record. If set, no payment information is required during step two. |
<billing> | The customer’s billing information |
billing-id | Specify billing id. Required for update-customer if multiple billing ids exist, optional for add-billing. |
first-name | Cardholder’s first name. |
last-name | Cardholder’s last name. |
address1 | Cardholder’s billing address. |
city | Card billing city. |
state | Card billing state/province. Format: CC |
postal | Card billing postal code. |
country | Card billing country code. Format: CC/ISO 3166 |
phone | Billing phone number. |
Billing email address. | |
company | Cardholder’s company. |
address2 | Card billing address, line 2. |
fax | Billing fax number. |
account-type | The customer’s ACH account type. Values: ‘checking’ or ‘savings’ |
entity-type | The customer’s ACH account entity. Values: ‘personal’ or ‘business’ |
priority | Specify priority (If omitted, will be auto-generated and returned in response.) Format: Numeric, 1-255 |
</billing> | |
</add-billing|update-billing> |
* | Required |
Element | Description |
---|---|
<sale|auth|credit|validate|offline> | Any and all optional fields described here can be appended to this request. |
api-key* | api-key is obtained in the security keys section of the control panel settings. |
amount* | Total amount to be charged (For “validate” actions, amount must be 0.00 or omitted). Format: x.xx |
surcharge-amount | Surcharge amount. Format: x.xx |
authorization-code | Specify authorization code. For use with “offline” action only. |
processor-id | If using multiple MIDs, route to this processor. The values for ‘processor-id’ are obtained under ‘Settings’->’Transaction Routing’ in the Control Panel. |
customer-vault-id* | Load Customer details from an existing Customer Vault record. |
signature-image | Cardholder signature image. For use with “sale” and “auth” actions only. Format: base64 encoded raw PNG image. (16kiB maximum) |
<billing> | The customer’s billing information. |
billing-id | Load Billing ID details from an existing Billing record. If not set, the billing-id with the highest priority will be used by default. |
</billing> | |
<shipping> | The customer’s shipping information. |
shipping-id | Load shipping id details from an existing shipping record. If unset, the shipping-id with the highest priority will be used by default. |
</shipping> | |
</sale|auth|credit|validate|offline> |
* | Required |
Element | Description |
---|---|
<delete-customer> | |
api-key* | api-key is obtained in the security keys section of the control panel settings. |
customer-vault-id* | Specify customer to be deleted. |
</delete-customer> |
* | Required |
Element | Description |
---|---|
<delete-billing> | |
api-key* | api-key is obtained in the security keys section of the control panel settings. |
customer-vault-id* | Load customer details from an existing customer vault record. If set, no payment information is required during step two. |
<billing> | |
billing-id* | Specify billing id to delete. |
</billing> | |
</delete-billing> |
* | Required |
These requests can be made the by replacing the billing section with shipping
Transactions can be tested using one of two methods. First, transactions can be submitted to any merchant account that is in test mode. Keep in mind that if an account is in test mode, all valid credit cards will be approved but no charges will actually be processed.
The Payment Gateway demo account can also be used for testing at any time. Please use the following api-key for testing with this account:
api-key: | 2F822Rw39fx762MaV7Yy86jXGTC7sCDy |
In step one and step three, transaction details should be POST’ed using XML to the following URL:
POST URL | https://secure.apsmerchantgateway.com/api/v2/three-step |
Transactions can be submitted using the following information:
Visa: | 4111111111111111 |
MasterCard: | 5431111111111111 |
Discover: | 6011601160116611 |
American Express: | 341111111111111 |
Diner’s Club: | 30205252489926 |
JCB: | 3541963594572595 |
Maestro: | 6799990100000000019 |
Credit Card Expiration: | 10/25 |
account (ACH): | 123123123 |
routing (ACH): | 123123123 |
amount | 1.00 (Amounts under 1.00 generate failure). |
X | Exact match, 9-character numeric ZIP |
Y | Exact match, 5-character numeric ZIP |
D | Exact match, 5-character numeric ZIP |
M | Exact match, 5-character numeric ZIP |
2 | Exact match, 5-character numeric ZIP, customer name |
6 | Exact match, 5-character numeric ZIP, customer name |
A | Address match only |
B | Address match only |
3 | Address, customer name match only |
7 | Address, customer name match only |
W | 9-character numeric ZIP match only |
Z | 5-character ZIP match only |
P | 5-character ZIP match only |
L | 5-character ZIP match only |
1 | 5-character ZIP, customer name match only |
5 | 5-character ZIP, customer name match only |
N | No address or ZIP match only |
C | No address or ZIP match only |
4 | No address or ZIP or customer name match only |
8 | No address or ZIP or customer name match only |
U | Address unavailable |
G | Non-U.S. issuer does not participate |
I | Non-U.S. issuer does not participate |
R | Issuer system unavailable |
E | Not a mail/phone order |
S | Service not supported |
0 | AVS not available |
O | AVS not available |
B | AVS not available |
M | CVV2/CVC2 match |
N | CVV2/CVC2 no match |
P | Not processed |
S | Merchant has indicated that CVV2/CVC2 is not present on card |
U | Issuer is not certified and/or has not provided Visa encryption keys |
100 | Transaction was approved. |
200 | Transaction was declined by processor. |
201 | Do not honor. |
202 | Insufficient funds. |
203 | Over limit. |
204 | Transaction not allowed. |
220 | Incorrect payment information. |
221 | No such card issuer. |
222 | No card number on file with issuer. |
223 | Expired card. |
224 | Invalid expiration date. |
225 | Invalid card security code. |
226 | Invalid PIN. |
240 | Call issuer for further information. |
250 | Pick up card. |
251 | Lost card. |
252 | Stolen card. |
253 | Fraudulent card. |
260 | Declined with further instructions available. (See response text) |
261 | Declined-Stop all recurring payments. |
262 | Declined-Stop this recurring program. |
263 | Declined-Update cardholder data available. |
264 | Declined-Retry in a few days. |
300 | Transaction was rejected by gateway. |
400 | Transaction error returned by processor. |
410 | Invalid merchant configuration. |
411 | Merchant account is inactive. |
420 | Communication error. |
421 | Communication error with issuer. |
430 | Duplicate transaction at processor. |
440 | Processor format error. |
441 | Invalid transaction information. |
460 | Processor feature not available. |
461 | Unsupported card type. |
Download example as a ZIP file
Example Files:
[ Back to Top ]
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="step1.aspx.cs" Inherits="ThreeStepExample._Default" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Collect non-sensitive Customer Info</title>
<style type="text/css">
.style1
{
margin-left: 150px;
}
</style>
</head>
<body>
<form id="form1" runat="server" action="step1.aspx" >
<h2>Step One: Collect non-sensitive payment information.<br /></h2>
<h3> Customer Information</h3>
<h4> Billing Details</h4>
<table>
<tr><td>Customer Vault Id </td><td><asp:TextBox ID="CustomerVaultId" runat="server"></asp:TextBox></td></tr>
<tr><td>Company</td><td><asp:TextBox ID="billingAddressCompany" runat="server">Acme, Inc.</asp:TextBox> </td></tr>
<tr><td>First Name </td><td><asp:TextBox ID="billingAddressFirstName" runat="server"> John</asp:TextBox></td></tr>
<tr><td>Last Name </td><td><asp:TextBox ID="billingAddressLastName" runat="server" value="Smith"/></td></tr>
<tr><td>Address </td><td><asp:TextBox ID="billingAddressAddress1" runat="server" value="1234 Main St."/></td></tr>
<tr><td>City </td><td><asp:TextBox ID="billingAddressCity" runat="server" value="Beverly Hills"/></td></tr>
<tr><td>State/Province </td><td><asp:TextBox ID="billingAddressState" runat="server" value="CA"/></td></tr>
<tr><td>Zip/Postal </td><td><asp:TextBox ID="billingAddressZip" runat="server" value="90210"/></td></tr>
<tr><td>Country </td><td><asp:TextBox ID="billingAddressCountry" runat="server" value="US"/></td></tr>
<tr><td>Phone Number </td><td><asp:TextBox ID="billingAddressPhone" runat="server" value="555-555-5555"/></td></tr>
<tr><td>Email Address </td><td><asp:TextBox ID="billingAddressEmail" runat="server" value="test@example.com"/></td></tr>
<tr><td><h4><br /> Shipping Details</h4> </td></tr>
<tr><td>First Name </td><td><asp:TextBox ID="shippingAddressFirstName" runat="server" value="Mary"/></td></tr>
<tr><td>Last Name </td><td><asp:TextBox ID="shippingAddressLastName" runat="server" value="Smith"/></td></tr>
<tr><td>Address </td><td><asp:TextBox ID="shippingAddressAddress1" runat="server" value="1234 Main St."/></td></tr>
<tr><td>Suite</td><td><asp:TextBox ID="shippingAddressAddress2" runat="server" value="Unit #2"/></td></tr>
<tr><td>City </td><td><asp:TextBox ID="shippingAddressCity" runat ="server" value="Beverly Hills"/></td></tr>
<tr><td>State/Province </td><td><asp:TextBox ID="shippingAddressState" runat="server" value="CA"/></td></tr>
<tr><td>Zip/Postal </td><td><asp:TextBox ID="shippingAddressZip" runat="server" value="90210"/></td></tr>
<tr><td>Country</td><td><asp:TextBox ID="shippingAddressCountry" runat="server" value="US"/></td></tr>
<tr><td>Phone Number </td><td><asp:TextBox ID="shippingAddressPhone" runat="server" value="555-555-5555"/></td></tr>
<tr><td colspan="2"> </td></tr>
<tr><td colspan="2" align="center">Total Amount $12.00 </td></tr>
<tr><td colspan="2" align="center"><asp:Button runat="server" Text="Submit Step One"
ID="submitStepOne" onclick="stepOneSubmit_Click" ></asp:Button> </td></tr>
</table>
</form>
</body>
</html>
[ Back to Top ]
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Windows.Forms;
using System.Web.UI;
using System.Xml;
using System.Web.UI.WebControls;
using System.IO;
using System.Net;
using System.Text;
using System.Security.Cryptography.X509Certificates;
namespace ThreeStepExample
{
public class Program :ICertificatePolicy {
public bool CheckValidationResult (ServicePoint sp,
X509Certificate certificate, WebRequest request, int error)
{
return true;
}
}
public partial class _Default :System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (Request["token-id"] != null)
{
//MessageBox.Show(Request["token-id"]);
XmlDocument xmlRequest = new XmlDocument();
XmlDeclaration xmlDecl = xmlRequest.CreateXmlDeclaration("1.0", "UTF-8", "yes");
XmlElement root = xmlRequest.DocumentElement;
xmlRequest.InsertBefore(xmlDecl, root);
XmlElement xmlCompleteTransaction = xmlRequest.CreateElement("complete-action");
XmlElement xmlApiKey = xmlRequest.CreateElement("api-key");
xmlApiKey.InnerText = "2F822Rw39fx762MaV7Yy86jXGTC7sCDy";
xmlCompleteTransaction.AppendChild(xmlApiKey);
XmlElement xmlTokenId = xmlRequest.CreateElement("token-id");
xmlTokenId.InnerText = Request["token-id"];
xmlCompleteTransaction.AppendChild(xmlTokenId);
xmlRequest.AppendChild(xmlCompleteTransaction);
string responseFromServer = this.sendXMLRequest(xmlRequest);
XmlReader responseReader = XmlReader.Create(new StringReader(responseFromServer));
XmlDocument xDoc = new XmlDocument();
xDoc.Load(responseReader);
XmlNodeList response = xDoc.GetElementsByTagName("result");
XmlNodeList responseText = xDoc.GetElementsByTagName("result-text");
Session["data"] = responseFromServer;
Session["result"] = response[0].InnerText;
Session["result-text"] = responseText[0].InnerText;
responseReader.Close();
Server.Transfer("step3.aspx");
}
}
protected void stepOneSubmit_Click(object sender, EventArgs e)
{
XmlDocument xmlRequest = new XmlDocument();
XmlDeclaration xmlDecl = xmlRequest.CreateXmlDeclaration("1.0","UTF-8","yes");
XmlElement root = xmlRequest.DocumentElement;
xmlRequest.InsertBefore(xmlDecl, root);
XmlElement xmlSale = xmlRequest.CreateElement("sale");
XmlElement xmlApiKey = xmlRequest.CreateElement("api-key");
xmlApiKey.InnerText = "2F822Rw39fx762MaV7Yy86jXGTC7sCDy";
xmlSale.AppendChild(xmlApiKey);
XmlElement xmlRedirectUrl = xmlRequest.CreateElement("redirect-url");
xmlRedirectUrl.InnerText = Request.ServerVariables["HTTP_REFERER"];
xmlSale.AppendChild(xmlRedirectUrl);
XmlElement xmlAmount = xmlRequest.CreateElement("amount");
xmlAmount.InnerText = "12.00";
xmlSale.AppendChild(xmlAmount);
XmlElement xmlRemoteAddr = xmlRequest.CreateElement("ip-address");
xmlRemoteAddr.InnerText = Request.ServerVariables["REMOTE_ADDR"];
xmlSale.AppendChild(xmlRemoteAddr);
XmlElement xmlCurrency = xmlRequest.CreateElement("currency");
xmlCurrency.InnerText = "USD";
xmlSale.AppendChild(xmlCurrency);
XmlElement xmlOrderId = xmlRequest.CreateElement("order-id");
xmlOrderId.InnerText = "1234";
xmlSale.AppendChild(xmlOrderId);
XmlElement xmlOrderDescription = xmlRequest.CreateElement("order-description");
xmlOrderDescription.InnerText = "Small Order";
xmlSale.AppendChild(xmlOrderDescription);
XmlElement xmlMDF1 = xmlRequest.CreateElement("merchant-defined-field-1");
xmlMDF1.InnerText = "Red";
xmlSale.AppendChild(xmlMDF1);
XmlElement xmlMDF2 = xmlRequest.CreateElement("merchant-defined-field-2");
xmlMDF2.InnerText = "Medium";
xmlSale.AppendChild(xmlMDF2);
XmlElement xmlTax = xmlRequest.CreateElement("tax-amount");
xmlTax.InnerText = "0.00";
xmlSale.AppendChild(xmlTax);
XmlElement xmlShipping = xmlRequest.CreateElement("shipping-amount");
xmlShipping.InnerText = "0.00";
xmlSale.AppendChild(xmlShipping);
if (!(CustomerVaultId.Text.Equals("") || CustomerVaultId.Text.Equals('0')))
{
XmlElement xmlCustomerVaultId = xmlRequest.CreateElement("customer-vault-id");
xmlCustomerVaultId.InnerText = CustomerVaultId.Text;
xmlSale.AppendChild(xmlCustomerVaultId);
}
//To Add a customer
/* else
{
XmlElement xmlAddCustomer = xmlRequest.CreateElement("add-customer");
XmlElement xmlCustomerVaultId = xmlRequest.CreateElement("customer-vault-id");
xmlCustomerVaultId.InnerText = "411";
xmlAddCustomer.AppendChild(xmlCustomerVaultId);
xmlSale.AppendChild(xmlAddCustomer);
}
*/
XmlElement xmlBillingAddress = xmlRequest.CreateElement("billing");
XmlElement xmlFirstName = xmlRequest.CreateElement("first-name");
xmlFirstName.InnerText = billingAddressFirstName.Text;
xmlBillingAddress.AppendChild(xmlFirstName);
XmlElement xmlLastName = xmlRequest.CreateElement("last-name");
xmlLastName.InnerText = billingAddressLastName.Text;
xmlBillingAddress.AppendChild(xmlLastName);
XmlElement xmlAddress1 = xmlRequest.CreateElement("address1");
xmlAddress1.InnerText = billingAddressAddress1.Text;
xmlBillingAddress.AppendChild(xmlAddress1);
XmlElement xmlCity = xmlRequest.CreateElement("city");
xmlCity.InnerText = billingAddressCity.Text;
xmlBillingAddress.AppendChild(xmlCity);
XmlElement xmlState = xmlRequest.CreateElement("state");
xmlState.InnerText = billingAddressState.Text;
xmlBillingAddress.AppendChild(xmlState);
XmlElement xmlZip = xmlRequest.CreateElement("postal");
xmlZip.InnerText = billingAddressZip.Text;
xmlBillingAddress.AppendChild(xmlZip);
XmlElement xmlCountry = xmlRequest.CreateElement("country");
xmlCountry.InnerText = billingAddressCountry.Text;
xmlBillingAddress.AppendChild(xmlCountry);
XmlElement xmlPhone = xmlRequest.CreateElement("phone");
xmlPhone.InnerText = billingAddressPhone.Text;
xmlBillingAddress.AppendChild(xmlPhone);
XmlElement xmlCompany = xmlRequest.CreateElement("company");
xmlCompany.InnerText = billingAddressCompany.Text;
xmlBillingAddress.AppendChild(xmlCompany);
XmlElement xmlAddress2 = xmlRequest.CreateElement("address2");
xmlAddress2.InnerText = billingAddressAddress1.Text;
xmlBillingAddress.AppendChild(xmlAddress2);
XmlElement xmlFax = xmlRequest.CreateElement("fax");
xmlFax.InnerText = "";
xmlBillingAddress.AppendChild(xmlFax);
xmlSale.AppendChild(xmlBillingAddress);
//////////
XmlElement xmlShippingAddress = xmlRequest.CreateElement("shipping");
XmlElement xmlSFirstName = xmlRequest.CreateElement("first-name");
xmlSFirstName.InnerText = shippingAddressFirstName.Text;
xmlShippingAddress.AppendChild(xmlSFirstName);
XmlElement xmlSLastName = xmlRequest.CreateElement("last-name");
xmlSLastName.InnerText = shippingAddressLastName.Text;
xmlShippingAddress.AppendChild(xmlSLastName);
XmlElement xmlSAddress1 = xmlRequest.CreateElement("address1");
xmlSAddress1.InnerText = shippingAddressAddress1.Text;
xmlShippingAddress.AppendChild(xmlSAddress1);
XmlElement xmlSCity = xmlRequest.CreateElement("city");
xmlSCity.InnerText = shippingAddressCity.Text;
xmlShippingAddress.AppendChild(xmlSCity);
XmlElement xmlSState = xmlRequest.CreateElement("state");
xmlSState.InnerText = shippingAddressState.Text;
xmlShippingAddress.AppendChild(xmlSState);
XmlElement xmlSZip = xmlRequest.CreateElement("postal");
xmlSZip.InnerText = shippingAddressZip.Text;
xmlShippingAddress.AppendChild(xmlSZip);
XmlElement xmlSCountry = xmlRequest.CreateElement("country");
xmlSCountry.InnerText = shippingAddressCountry.Text;
xmlShippingAddress.AppendChild(xmlSCountry);
XmlElement xmlSPhone = xmlRequest.CreateElement("phone");
xmlSPhone.InnerText = shippingAddressPhone.Text;
xmlShippingAddress.AppendChild(xmlSPhone);
XmlElement xmlSCompany = xmlRequest.CreateElement("company");
xmlSCompany.InnerText = "";
xmlShippingAddress.AppendChild(xmlSCompany);
XmlElement xmlSAddress2 = xmlRequest.CreateElement("address2");
xmlSAddress2.InnerText = shippingAddressAddress1.Text;
xmlShippingAddress.AppendChild(xmlSAddress2);
XmlElement xmlSFax = xmlRequest.CreateElement("fax");
xmlFax.InnerText = "";
xmlShippingAddress.AppendChild(xmlSFax);
xmlSale.AppendChild(xmlShippingAddress);
////////////////
XmlElement xmlProduct = xmlRequest.CreateElement("product");
XmlElement xmlSku = xmlRequest.CreateElement("product-code");
xmlSku.InnerText = "SKU-123456";
xmlProduct.AppendChild(xmlSku);
XmlElement xmlDescription = xmlRequest.CreateElement("description");
xmlDescription.InnerText = "Books";
xmlProduct.AppendChild(xmlDescription);
XmlElement xmlQuantity = xmlRequest.CreateElement("quantity");
xmlQuantity.InnerText = "1";
xmlProduct.AppendChild(xmlQuantity);
XmlElement xmlUnit = xmlRequest.CreateElement("unit-of-measure");
xmlUnit.InnerText = "1";
xmlProduct.AppendChild(xmlUnit);
XmlElement xmlUnitAmount = xmlRequest.CreateElement("total-amount");
xmlUnitAmount.InnerText = "1";
xmlProduct.AppendChild(xmlUnitAmount);
XmlElement xmlUnitDiscount = xmlRequest.CreateElement("discount-amount");
xmlUnitDiscount.InnerText = "0.00";
xmlProduct.AppendChild(xmlUnitDiscount);
XmlElement xmlUnitTax = xmlRequest.CreateElement("tax-amount");
xmlUnitTax.InnerText = "0.00";
xmlProduct.AppendChild(xmlUnitTax);
XmlElement xmlTaxRate = xmlRequest.CreateElement("tax-rate");
xmlTaxRate.InnerText = "0.01";
xmlProduct.AppendChild(xmlTaxRate);
xmlSale.AppendChild(xmlProduct);
///////////////
XmlElement xmlProduct2 = xmlRequest.CreateElement("product");
XmlElement xmlSku2 = xmlRequest.CreateElement("product-code");
xmlSku2.InnerText = "SKU-654321";
xmlProduct2.AppendChild(xmlSku2);
XmlElement xmlDescription2 = xmlRequest.CreateElement("description");
xmlDescription2.InnerText = "Videos";
xmlProduct2.AppendChild(xmlDescription2);
XmlElement xmlQuantity2 = xmlRequest.CreateElement("quantity");
xmlQuantity2.InnerText = "1";
xmlProduct2.AppendChild(xmlQuantity2);
XmlElement xmlUnit2 = xmlRequest.CreateElement("unit-of-measure");
xmlUnit2.InnerText = "";
xmlProduct2.AppendChild(xmlUnit2);
XmlElement xmlUnitAmount2 = xmlRequest.CreateElement("total-amount");
xmlUnitAmount2.InnerText = "2";
xmlProduct2.AppendChild(xmlUnitAmount2);
XmlElement xmlUnitDiscount2 = xmlRequest.CreateElement("discount-amount");
xmlUnitDiscount2.InnerText = "0.00";
xmlProduct2.AppendChild(xmlUnitDiscount2);
XmlElement xmlUnitTax2 = xmlRequest.CreateElement("tax-amount");
xmlUnitTax2.InnerText = "0.00";
xmlProduct2.AppendChild(xmlUnitTax2);
XmlElement xmlTaxRate2 = xmlRequest.CreateElement("tax-rate");
xmlTaxRate2.InnerText = "0.01";
xmlProduct2.AppendChild(xmlTaxRate2);
xmlSale.AppendChild(xmlProduct2);
xmlRequest.AppendChild(xmlSale);
string responseFromServer = this.sendXMLRequest(xmlRequest);
XmlReader responseReader = XmlReader.Create(new StringReader(responseFromServer));
XmlDocument xDoc = new XmlDocument();
xDoc.Load(responseReader);
XmlNodeList response = xDoc.GetElementsByTagName("result");
if (response[0].InnerText.Equals("1"))
{
XmlNodeList formUrl = xDoc.GetElementsByTagName("form-url");
Session["formURL"] = "";
Session["formURL"] = formUrl[0].InnerText;
responseReader.Close();
Server.Transfer("step2.aspx");
}
}
protected string sendXMLRequest(XmlDocument xmlRequest)
{
ServicePointManager.CertificatePolicy = new Program ();
string uri = "https://secure.apsmerchantgateway.com/api/v2/three-step";
WebRequest req = WebRequest.Create(uri);
//req.Proxy = WebProxy.GetDefaultProxy(); // Enable if using proxy
req.Method = "POST"; // Post method
req.ContentType = "text/xml"; // content type
// Wrap the request stream with a text-based writer
StreamWriter writer = new StreamWriter(req.GetRequestStream());
// Write the XML text into the stream
xmlRequest.Save(writer);
writer.Close();
// Send the data to the webserver
WebResponse rsp = req.GetResponse();
Stream dataStream = rsp.GetResponseStream();
// Open the stream using a StreamReader
StreamReader reader = new StreamReader(dataStream);
// Read the content.
string responseFromServer = reader.ReadToEnd();
// int index = responseFromServer.IndexOf("<?");
//string substr = responseFromServer.Substring(index);
// Display the content.
//MessageBox.Show(responseFromServer);
// Clean up the streams.
reader.Close();
dataStream.Close();
rsp.Close();
return responseFromServer;
}
}
}
[ Back to Top ]
// ------------------------------------------------------------------------------
// <autogenerated>
// This code was generated by a tool.
// Mono Runtime Version: 4.0.30319.1
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </autogenerated>
// ------------------------------------------------------------------------------
namespace ThreeStepExample {
public partial class _Default {
protected System.Web.UI.HtmlControls.HtmlForm form1;
protected System.Web.UI.WebControls.TextBox CustomerVaultId;
protected System.Web.UI.WebControls.TextBox billingAddressCompany;
protected System.Web.UI.WebControls.TextBox billingAddressFirstName;
protected System.Web.UI.WebControls.TextBox billingAddressLastName;
protected System.Web.UI.WebControls.TextBox billingAddressAddress1;
protected System.Web.UI.WebControls.TextBox billingAddressCity;
protected System.Web.UI.WebControls.TextBox billingAddressState;
protected System.Web.UI.WebControls.TextBox billingAddressZip;
protected System.Web.UI.WebControls.TextBox billingAddressCountry;
protected System.Web.UI.WebControls.TextBox billingAddressPhone;
protected System.Web.UI.WebControls.TextBox billingAddressEmail;
protected System.Web.UI.WebControls.TextBox shippingAddressFirstName;
protected System.Web.UI.WebControls.TextBox shippingAddressLastName;
protected System.Web.UI.WebControls.TextBox shippingAddressAddress1;
protected System.Web.UI.WebControls.TextBox shippingAddressAddress2;
protected System.Web.UI.WebControls.TextBox shippingAddressCity;
protected System.Web.UI.WebControls.TextBox shippingAddressState;
protected System.Web.UI.WebControls.TextBox shippingAddressZip;
protected System.Web.UI.WebControls.TextBox shippingAddressCountry;
protected System.Web.UI.WebControls.TextBox shippingAddressPhone;
protected System.Web.UI.WebControls.Button submitStepOne;
}
}
[ Back to Top ]
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="step2.aspx.cs" Inherits="ThreeStepExample.WebForm1" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server" action="step2.aspx" >
<h2>Step Two: Collect sensitive payment information and POST directly to payment gateway<br /></h2>
<h3> Payment Information</h3>
<table>
<tr><td>Credit Card Number </td><td><asp:TextBox ID="cc_number" name="cc_number" runat="server" >4111111111111111</asp:TextBox></td></tr>
<tr><td>Expiration Date</td><td><asp:TextBox ID="cc_exp" name="cc_exp" runat="server">1012</asp:TextBox> </td></tr>
<tr><td>CVV </td><td><asp:TextBox ID="cvv" name="cvv" runat="server"> </asp:TextBox></td></tr>
<tr><td colspan="2"> </td></tr>
<tr><td colspan="2" align="center">Total Amount $12.00 </td></tr>
<tr><td colspan="2" align="center"><asp:Button runat="server" Text="Submit Step Two"
ID="submitStepTwo"></asp:Button> </td></tr>
</table>
</form>
</body>
</html>
[ Back to Top ]
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Windows.Forms;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace ThreeStepExample
{
public partial class WebForm1 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
form1.Action = (string)Session["formUrl"];
}
}
}
[ Back to Top ]
// ------------------------------------------------------------------------------
// <autogenerated>
// This code was generated by a tool.
// Mono Runtime Version: 4.0.30319.1
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </autogenerated>
// ------------------------------------------------------------------------------
namespace ThreeStepExample {
public partial class WebForm1 {
protected System.Web.UI.HtmlControls.HtmlForm form1;
protected System.Web.UI.WebControls.TextBox cc_number;
protected System.Web.UI.WebControls.TextBox cc_exp;
protected System.Web.UI.WebControls.TextBox cvv;
protected System.Web.UI.WebControls.Button submitStepTwo;
}
}
[ Back to Top ]
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="step3.aspx.cs" Inherits="ThreeStepExample.step3" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Step Three - Complete Transaciton</title>
</head>
<body>
<form id="form1" runat="server">
<pre>
<p><h2>Step Three: Script automatically completes the transaction </h2></p>
<% if(Session["result"].Equals("1"))
{ %>
<p><h3> Transaction was Approved.</h3></p>
<% }
else if (Session["result"].Equals("2"))
{ %>
<p><h3> Transaction was Declined.</h3>Decline Description: </p>
<% }
else
{ %>
<p><h3> Transaction caused an Error.</h3></p>
Error Description:
<%} %>
<asp:Label ID="LabelResponseText" runat="server" Height="20px" Text="Label" Width="20px"></asp:Label>
<p><h3>XML response was:</h3></p>
<asp:Label ID="LabelResponse" runat="server" Height="150px" Text="Label" Width="350px"></asp:Label>
</pre>
</form>
</body>
</html>
[ Back to Top ]
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace ThreeStepExample
{
public partial class step3 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
LabelResponse.Text = Server.HtmlEncode(Session["data"].ToString());
if (!Session["result"].Equals("1"))
{
LabelResponseText.Text = (string)Session["result-text"];
}
else
{
LabelResponseText.Text = "";
}
}
}
}
[ Back to Top ]
// ------------------------------------------------------------------------------
// <autogenerated>
// This code was generated by a tool.
// Mono Runtime Version: 4.0.30319.1
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </autogenerated>
// ------------------------------------------------------------------------------
namespace ThreeStepExample {
public partial class step3 {
protected System.Web.UI.HtmlControls.HtmlForm form1;
protected System.Web.UI.WebControls.Label LabelResponseText;
protected System.Web.UI.WebControls.Label LabelResponse;
}
}
// API Setup parameters
$gatewayURL = 'https://secure.apsmerchantgateway.com/api/v2/three-step';
$APIKey = '2F822Rw39fx762MaV7Yy86jXGTC7sCDy';
// If there is no POST data or a token-id, print the initial shopping cart form to get ready for Step One.
if (empty($_POST['DO_STEP_1']) && empty($_GET['token-id'])) {
print ' <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">';
print '
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Collect non-sensitive Customer Info </title>
</head>
<body>
<p><h2>Step One: Collect non-sensitive payment information.<br /></h2></p>
<h3> Customer Information</h3>
<h4> Billing Details</h4>
<form action="" method="post">
<table>
<tr><td>Customer Vault Id </td><td><input type="text" name="customer-vault-id" value=""></td></tr>
<tr><td>Company</td><td><input type="text" name="billing-address-company" value="Acme, Inc."></td></tr>
<tr><td>First Name </td><td><input type="text" name="billing-address-first-name" value="John"></td></tr>
<tr><td>Last Name </td><td><input type="text" name="billing-address-last-name" value="Smith"></td></tr>
<tr><td>Address </td><td><input type="text" name="billing-address-address1" value="1234 Main St."></td></tr>
<tr><td>Address 2 </td><td><input type="text" name="billing-address-address2" value="Suite 205"></td></tr>
<tr><td>City </td><td><input type="text" name="billing-address-city" value="Beverly Hills"></td></tr>
<tr><td>State/Province </td><td><input type="text" name="billing-address-state" value="CA"></td></tr>
<tr><td>Zip/Postal </td><td><input type="text" name="billing-address-zip" value="90210"></td></tr>
<tr><td>Country </td><td><input type="text" name="billing-address-country" value="US"></td></tr>
<tr><td>Phone Number </td><td><input type="text" name="billing-address-phone" value="555-555-5555"></td></tr>
<tr><td>Fax Number </td><td><input type="text" name="billing-address-fax" value="555-555-5555"></td></tr>
<tr><td>Email Address </td><td><input type="text" name="billing-address-email" value="test@example.com"></td></tr>
<tr><td><h4><br /> Shipping Details</h4>
<tr><td>Company</td><td><input type="text" name="shipping-address-company" value="Acme, Inc."></td></tr>
<tr><td>First Name </td><td><input type="text" name="shipping-address-first-name" value="Mary"></td></tr>
<tr><td>Last Name </td><td><input type="text" name="shipping-address-last-name" value="Smith"></td></tr>
<tr><td>Address </td><td><input type="text" name="shipping-address-address1" value="1234 Main St."></td></tr>
<tr><td>Address 2</td><td><input type="text" name="shipping-address-address2" value="Suite 205"></td></tr>
<tr><td>City </td><td><input type="text" name="shipping-address-city" value="Beverly Hills"></td></tr>
<tr><td>State/Province </td><td><input type="text" name="shipping-address-state" value="CA"></td></tr>
<tr><td>Zip/Postal </td><td><input type="text" name="shipping-address-zip" value="90210"></td></tr>
<tr><td>Country</td><td><input type="text" name="shipping-address-country" value="US"></td></tr>
<tr><td>Phone Number </td><td><input type="text" name="shipping-address-phone" value="555-555-5555"></td></tr>
<tr><td colspan="2"> </td>
<tr><td colspan="2" align=center>Total Amount $12.00 </td></tr>
<tr><td colspan="2" align=center><input type="submit" value="Submit Step One"><input type="hidden" name ="DO_STEP_1" value="true"></td></tr>
</table>
</form>
</body>
</html>
';
}else if (!empty($_POST['DO_STEP_1'])) {
// Initiate Step One: Now that we've collected the non-sensitive payment information, we can combine other order information and build the XML format.
$xmlRequest = new DOMDocument('1.0','UTF-8');
$xmlRequest->formatOutput = true;
$xmlSale = $xmlRequest->createElement('sale');
// Amount, authentication, and Redirect-URL are typically the bare minimum.
appendXmlNode($xmlRequest, $xmlSale,'api-key',$APIKey);
appendXmlNode($xmlRequest, $xmlSale,'redirect-url',$_SERVER['HTTP_REFERER']);
appendXmlNode($xmlRequest, $xmlSale, 'amount', '12.00');
appendXmlNode($xmlRequest, $xmlSale, 'ip-address', $_SERVER["REMOTE_ADDR"]);
//appendXmlNode($xmlRequest, $xmlSale, 'processor-id' , 'processor-a');
appendXmlNode($xmlRequest, $xmlSale, 'currency', 'USD');
// Some additonal fields may have been previously decided by user
appendXmlNode($xmlRequest, $xmlSale, 'order-id', '1234');
appendXmlNode($xmlRequest, $xmlSale, 'order-description', 'Small Order');
appendXmlNode($xmlRequest, $xmlSale, 'merchant-defined-field-1' , 'Red');
appendXmlNode($xmlRequest, $xmlSale, 'merchant-defined-field-2', 'Medium');
appendXmlNode($xmlRequest, $xmlSale, 'tax-amount' , '0.00');
appendXmlNode($xmlRequest, $xmlSale, 'shipping-amount' , '0.00');
/*if(!empty($_POST['customer-vault-id'])) {
appendXmlNode($xmlRequest, $xmlSale, 'customer-vault-id' , $_POST['customer-vault-id']);
}else {
$xmlAdd = $xmlRequest->createElement('add-customer');
appendXmlNode($xmlRequest, $xmlAdd, 'customer-vault-id' ,411);
$xmlSale->appendChild($xmlAdd);
}*/
// Set the Billing and Shipping from what was collected on initial shopping cart form
$xmlBillingAddress = $xmlRequest->createElement('billing');
appendXmlNode($xmlRequest, $xmlBillingAddress,'first-name', $_POST['billing-address-first-name']);
appendXmlNode($xmlRequest, $xmlBillingAddress,'last-name', $_POST['billing-address-last-name']);
appendXmlNode($xmlRequest, $xmlBillingAddress,'address1', $_POST['billing-address-address1']);
appendXmlNode($xmlRequest, $xmlBillingAddress,'city', $_POST['billing-address-city']);
appendXmlNode($xmlRequest, $xmlBillingAddress,'state', $_POST['billing-address-state']);
appendXmlNode($xmlRequest, $xmlBillingAddress,'postal', $_POST['billing-address-zip']);
//billing-address-email
appendXmlNode($xmlRequest, $xmlBillingAddress,'country', $_POST['billing-address-country']);
appendXmlNode($xmlRequest, $xmlBillingAddress,'email', $_POST['billing-address-email']);
appendXmlNode($xmlRequest, $xmlBillingAddress,'phone', $_POST['billing-address-phone']);
appendXmlNode($xmlRequest, $xmlBillingAddress,'company', $_POST['billing-address-company']);
appendXmlNode($xmlRequest, $xmlBillingAddress,'address2', $_POST['billing-address-address2']);
appendXmlNode($xmlRequest, $xmlBillingAddress,'fax', $_POST['billing-address-fax']);
$xmlSale->appendChild($xmlBillingAddress);
$xmlShippingAddress = $xmlRequest->createElement('shipping');
appendXmlNode($xmlRequest, $xmlShippingAddress,'first-name', $_POST['shipping-address-first-name']);
appendXmlNode($xmlRequest, $xmlShippingAddress,'last-name', $_POST['shipping-address-last-name']);
appendXmlNode($xmlRequest, $xmlShippingAddress,'address1', $_POST['shipping-address-address1']);
appendXmlNode($xmlRequest, $xmlShippingAddress,'city', $_POST['shipping-address-city']);
appendXmlNode($xmlRequest, $xmlShippingAddress,'state', $_POST['shipping-address-state']);
appendXmlNode($xmlRequest, $xmlShippingAddress,'postal', $_POST['shipping-address-zip']);
appendXmlNode($xmlRequest, $xmlShippingAddress,'country', $_POST['shipping-address-country']);
appendXmlNode($xmlRequest, $xmlShippingAddress,'phone', $_POST['shipping-address-phone']);
appendXmlNode($xmlRequest, $xmlShippingAddress,'company', $_POST['shipping-address-company']);
appendXmlNode($xmlRequest, $xmlShippingAddress,'address2', $_POST['shipping-address-address2']);
$xmlSale->appendChild($xmlShippingAddress);
// Products already chosen by user
$xmlProduct = $xmlRequest->createElement('product');
appendXmlNode($xmlRequest, $xmlProduct,'product-code' , 'SKU-123456');
appendXmlNode($xmlRequest, $xmlProduct,'description' , 'test product description');
appendXmlNode($xmlRequest, $xmlProduct,'commodity-code' , 'abc');
appendXmlNode($xmlRequest, $xmlProduct,'unit-of-measure' , 'lbs');
appendXmlNode($xmlRequest, $xmlProduct,'unit-cost' , '5.00');
appendXmlNode($xmlRequest, $xmlProduct,'quantity' , '1');
appendXmlNode($xmlRequest, $xmlProduct,'total-amount' , '7.00');
appendXmlNode($xmlRequest, $xmlProduct,'tax-amount' , '2.00');
appendXmlNode($xmlRequest, $xmlProduct,'tax-rate' , '1.00');
appendXmlNode($xmlRequest, $xmlProduct,'discount-amount', '2.00');
appendXmlNode($xmlRequest, $xmlProduct,'discount-rate' , '1.00');
appendXmlNode($xmlRequest, $xmlProduct,'tax-type' , 'sales');
appendXmlNode($xmlRequest, $xmlProduct,'alternate-tax-id' , '12345');
$xmlSale->appendChild($xmlProduct);
$xmlProduct = $xmlRequest->createElement('product');
appendXmlNode($xmlRequest, $xmlProduct,'product-code' , 'SKU-123456');
appendXmlNode($xmlRequest, $xmlProduct,'description' , 'test 2 product description');
appendXmlNode($xmlRequest, $xmlProduct,'commodity-code' , 'abc');
appendXmlNode($xmlRequest, $xmlProduct,'unit-of-measure' , 'lbs');
appendXmlNode($xmlRequest, $xmlProduct,'unit-cost' , '2.50');
appendXmlNode($xmlRequest, $xmlProduct,'quantity' , '2');
appendXmlNode($xmlRequest, $xmlProduct,'total-amount' , '7.00');
appendXmlNode($xmlRequest, $xmlProduct,'tax-amount' , '2.00');
appendXmlNode($xmlRequest, $xmlProduct,'tax-rate' , '1.00');
appendXmlNode($xmlRequest, $xmlProduct,'discount-amount', '2.00');
appendXmlNode($xmlRequest, $xmlProduct,'discount-rate' , '1.00');
appendXmlNode($xmlRequest, $xmlProduct,'tax-type' , 'sales');
appendXmlNode($xmlRequest, $xmlProduct,'alternate-tax-id' , '12345');
$xmlSale->appendChild($xmlProduct);
$xmlRequest->appendChild($xmlSale);
// Process Step One: Submit all transaction details to the Payment Gateway except the customer's sensitive payment information.
// The Payment Gateway will return a variable form-url.
$data = sendXMLviaCurl($xmlRequest,$gatewayURL);
// Parse Step One's XML response
$gwResponse = @new SimpleXMLElement($data);
if ((string)$gwResponse->result ==1 ) {
// The form url for used in Step Two below
$formURL = $gwResponse->{'form-url'};
} else {
throw New Exception(print " Error, received " . $data);
}
// Initiate Step Two: Create an HTML form that collects the customer's sensitive payment information
// and use the form-url that the Payment Gateway returns as the submit action in that form.
print ' <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">';
print '
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Collect sensitive Customer Info </title>
</head>
<body>';
// Uncomment the line below if you would like to print Step One's response
// print '<pre>' . (htmlentities($data)) . '</pre>';
print '
<p><h2>Step Two: Collect sensitive payment information and POST directly to payment gateway<br /></h2></p>
<form action="'.$formURL. '" method="POST">
<h3> Payment Information</h3>
<table>
<tr><td>Credit Card Number</td><td><INPUT type ="text" name="billing-cc-number" value="4111111111111111"> </td></tr>
<tr><td>Expiration Date</td><td><INPUT type ="text" name="billing-cc-exp" value="1012"> </td></tr>
<tr><td>CVV</td><td><INPUT type ="text" name="cvv" > </td></tr>
<tr><Td colspan="2" align=center><INPUT type ="submit" value="Submit Step Two"></td> </tr>
</table>
</form>
</body>
</html>
';
} elseif (!empty($_GET['token-id'])) {
// Step Three: Once the browser has been redirected, we can obtain the token-id and complete
// the transaction through another XML HTTPS POST including the token-id which abstracts the
// sensitive payment information that was previously collected by the Payment Gateway.
$tokenId = $_GET['token-id'];
$xmlRequest = new DOMDocument('1.0','UTF-8');
$xmlRequest->formatOutput = true;
$xmlCompleteTransaction = $xmlRequest->createElement('complete-action');
appendXmlNode($xmlRequest, $xmlCompleteTransaction,'api-key',$APIKey);
appendXmlNode($xmlRequest, $xmlCompleteTransaction,'token-id',$tokenId);
$xmlRequest->appendChild($xmlCompleteTransaction);
// Process Step Three
$data = sendXMLviaCurl($xmlRequest,$gatewayURL);
$gwResponse = @new SimpleXMLElement((string)$data);
print ' <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">';
print '
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Step Three - Complete Transaction</title>
</head>
<body>';
print "
<p><h2>Step Three: Script automatically completes the transaction <br /></h2></p>";
if ((string)$gwResponse->result == 1 ) {
print " <p><h3> Transaction was Approved, XML response was:</h3></p>\n";
print '<pre>' . (htmlentities($data)) . '</pre>';
} elseif((string)$gwResponse->result == 2) {
print " <p><h3> Transaction was Declined.</h3>\n";
print " Decline Description : " . (string)$gwResponse->{'result-text'} ." </p>";
print " <p><h3>XML response was:</h3></p>\n";
print '<pre>' . (htmlentities($data)) . '</pre>';
} else {
print " <p><h3> Transaction caused an Error.</h3>\n";
print " Error Description: " . (string)$gwResponse->{'result-text'} ." </p>";
print " <p><h3>XML response was:</h3></p>\n";
print '<pre>' . (htmlentities($data)) . '</pre>';
}
print "</body></html>";
} else {
print "ERROR IN SCRIPT<BR>";
}
function sendXMLviaCurl($xmlRequest,$gatewayURL) {
// helper function demonstrating how to send the xml with curl
$ch = curl_init(); // Initialize curl handle
curl_setopt($ch, CURLOPT_URL, $gatewayURL); // Set POST URL
$headers = array();
$headers[] = "Content-type: text/xml";
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); // Add http headers to let it know we're sending XML
$xmlString = $xmlRequest->saveXML();
curl_setopt($ch, CURLOPT_FAILONERROR, 1); // Fail on errors
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); // Allow redirects
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); // Return into a variable
curl_setopt($ch, CURLOPT_PORT, 443); // Set the port number
curl_setopt($ch, CURLOPT_TIMEOUT, 30); // Times out after 30s
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $xmlString); // Add XML directly in POST
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
// This should be unset in production use. With it on, it forces the ssl cert to be valid
// before sending info.
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
if (!($data = curl_exec($ch))) {
print "curl error =>" .curl_error($ch) ."\n";
throw New Exception(" CURL ERROR :" . curl_error($ch));
}
curl_close($ch);
return $data;
}
// Helper function to make building xml dom easier
function appendXmlNode($domDocument, $parentNode, $name, $value) {
$childNode = $domDocument->createElement($name);
$childNodeValue = $domDocument->createTextNode($value);
$childNode->appendChild($childNodeValue);
$parentNode->appendChild($childNode);
}
// API Setup Parameters
$gatewayURL = 'https://secure.apsmerchantgateway.com/api/v2/three-step';
$APIKey = '2F822Rw39fx762MaV7Yy86jXGTC7sCDy';
// If there is no POST data or a token-id, print the initial Customer Information form to get ready for Step One.
if (empty($_POST['DO_STEP_1'])&& empty($_GET['token-id'])) {
print ' <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">';
print '
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Collect non-sensitive Customer Vault Info </title>
</head>
<body>
<p><h2>Step One: Collect non-sensitive Customer Vault information.<br /></h2></p>
<h3> Customer Information</h3>
<h4> Billing Details</h4>
<form action="" method="post">
<table>
<tr><td>Customer Vault Id </td><td><input type="text" name="customer-vault-id" value=""></td></tr>
<tr><td>Company</td><td><input type="text" name="billing-address-company" value="Acme, Inc."></td></tr>
<tr><td>First Name </td><td><input type="text" name="billing-address-first-name" value="John"></td></tr>
<tr><td>Last Name </td><td><input type="text" name="billing-address-last-name" value="Smith"></td></tr>
<tr><td>Address </td><td><input type="text" name="billing-address-address1" value="1234 Main St."></td></tr>
<tr><td>City </td><td><input type="text" name="billing-address-city" value="Beverly Hills"></td></tr>
<tr><td>State/Province </td><td><input type="text" name="billing-address-state" value="CA"></td></tr>
<tr><td>Zip/Postal </td><td><input type="text" name="billing-address-zip" value="90210"></td></tr>
<tr><td>Country </td><td><input type="text" name="billing-address-country" value="US"></td></tr>
<tr><td>Phone Number </td><td><input type="text" name="billing-address-phone" value="555-555-5555"></td></tr>
<tr><td>Email Address </td><td><input type="text" name="billing-address-email" value="test@example.com"></td></tr>
<tr><td><h4><br /> Shipping Details</h4>
<tr><td>First Name </td><td><input type="text" name="shipping-address-first-name" value="Mary"></td></tr>
<tr><td>Last Name </td><td><input type="text" name="shipping-address-last-name" value="Smith"></td></tr>
<tr><td>Address </td><td><input type="text" name="shipping-address-address1" value="1234 Main St."></td></tr>
<tr><td>Suite</td><td><input type="text" name="shipping-address-address2" value="Unit #2"></td></tr>
<tr><td>City </td><td><input type="text" name="shipping-address-city" value="Beverly Hills"></td></tr>
<tr><td>State/Province </td><td><input type="text" name="shipping-address-state" value="CA"></td></tr>
<tr><td>Zip/Postal </td><td><input type="text" name="shipping-address-zip" value="90210"></td></tr>
<tr><td>Country</td><td><input type="text" name="shipping-address-country" value="US"></td></tr>
<tr><td colspan="2"> </td>
<tr><td colspan="2" align=center><input type="submit" value="Submit Step One"><input type="hidden" name ="DO_STEP_1" value="true"></td></tr>
</table>
</form>
</body>
</html>
';
}else if (!empty($_POST['DO_STEP_1'])) {
// Initiate Step One: Now that we've collected the non-sensitive customer information, we can combine other customer information and build the XML format.
$xmlRequest = new DOMDocument('1.0','UTF-8');
$xmlRequest->formatOutput = true;
$xmlSale = $xmlRequest->createElement('add-customer');
// Authentication, Redirect-URL are typically the bare minimum.
appendXmlNode($xmlRequest, $xmlSale,'api-key',$APIKey);
appendXmlNode($xmlRequest, $xmlSale,'redirect-url',$_SERVER['HTTP_REFERER']);
// Some additonal fields may have been previously decided by user
appendXmlNode($xmlRequest, $xmlSale, 'merchant-defined-field-1' , 'Red');
appendXmlNode($xmlRequest, $xmlSale, 'merchant-defined-field-2', 'Medium');
if(!empty($_POST['customer-vault-id'])) {
appendXmlNode($xmlRequest, $xmlSale, 'customer-vault-id' , $_POST['customer-vault-id']);
}
// Set the Billing & Shipping from what was collected on initial shopping cart form
$xmlBillingAddress = $xmlRequest->createElement('billing');
appendXmlNode($xmlRequest, $xmlBillingAddress,'first-name', $_POST['billing-address-first-name']);
appendXmlNode($xmlRequest, $xmlBillingAddress,'last-name', $_POST['billing-address-last-name']);
appendXmlNode($xmlRequest, $xmlBillingAddress,'address1', $_POST['billing-address-address1']);
appendXmlNode($xmlRequest, $xmlBillingAddress,'city', $_POST['billing-address-city']);
appendXmlNode($xmlRequest, $xmlBillingAddress,'state', $_POST['billing-address-state']);
appendXmlNode($xmlRequest, $xmlBillingAddress,'postal', $_POST['billing-address-zip']);
//billing-address-email
appendXmlNode($xmlRequest, $xmlBillingAddress,'country', $_POST['billing-address-country']);
appendXmlNode($xmlRequest, $xmlBillingAddress,'email', $_POST['billing-address-email']);
appendXmlNode($xmlRequest, $xmlBillingAddress,'phone', $_POST['billing-address-phone']);
appendXmlNode($xmlRequest, $xmlBillingAddress,'company', $_POST['billing-address-company']);
$xmlSale->appendChild($xmlBillingAddress);
$xmlShippingAddress = $xmlRequest->createElement('shipping');
appendXmlNode($xmlRequest, $xmlShippingAddress,'first-name', $_POST['shipping-address-first-name']);
appendXmlNode($xmlRequest, $xmlShippingAddress,'last-name', $_POST['shipping-address-last-name']);
appendXmlNode($xmlRequest, $xmlShippingAddress,'address1', $_POST['shipping-address-address1']);
appendXmlNode($xmlRequest, $xmlShippingAddress,'city', $_POST['shipping-address-city']);
appendXmlNode($xmlRequest, $xmlShippingAddress,'state', $_POST['shipping-address-state']);
appendXmlNode($xmlRequest, $xmlShippingAddress,'postal', $_POST['shipping-address-zip']);
appendXmlNode($xmlRequest, $xmlShippingAddress,'country', $_POST['shipping-address-country']);
appendXmlNode($xmlRequest, $xmlShippingAddress,'address2', $_POST['shipping-address-address2']);
$xmlSale->appendChild($xmlShippingAddress);
$xmlRequest->appendChild($xmlSale);
// Process Step One: Submit all customer details to the Payment Gateway except the customer's sensitive payment information.
// The Payment Gateway will return a variable form-url.
$data = sendXMLviaCurl($xmlRequest,$gatewayURL);
// Parse Step One's XML response
$gwResponse = @new SimpleXMLElement($data);
if ((string)$gwResponse->result ==1 ) {
// The form url for used in Step Two below
$formURL = $gwResponse->{'form-url'};
} else {
throw New Exception(print " Error, received " . $data);
}
// Initiate Step Two: Create an HTML form that collects the customer's sensitive payment information
// and use the form-url that the Payment Gateway returns as the submit action in that form.
print ' <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">';
print '
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Collect sensitive Customer Info </title>
</head>
<body>';
// Uncomment the line below if you would like to print Step One's response
// print '<pre>' . (htmlentities($data)) . '</pre>';
print '
<p><h2>Step Two: Collect sensitive payment information and POST directly to payment gateway<br /></h2></p>
<form action="'.$formURL. '" method="POST">
<h3> Payment Information</h3>
<table>
<tr><td>Credit Card Number</td><td><INPUT type ="text" name="billing-cc-number" value="4111111111111111"> </td></tr>
<tr><td>Expiration Date</td><td><INPUT type ="text" name="billing-cc-exp" value="1014"> </td></tr>
<tr><Td colspan="2" align=center><INPUT type ="submit" value="Submit Step Two"></td> </tr>
</table>
</form>
</body>
</html>
';
// NOTE: CVV cannot be stored, per PCI Requirements
} elseif (!empty($_GET['token-id'])) {
// Step Three: Once the browser has been redirected, we can obtain the token-id and complete
// the Customer Vault Add through another XML HTTPS POST including the token-id which abstracts the
// sensitive payment information that was previously collected by the Payment Gateway.
$tokenId = $_GET['token-id'];
$xmlRequest = new DOMDocument('1.0','UTF-8');
$xmlRequest->formatOutput = true;
$xmlCompleteTransaction = $xmlRequest->createElement('complete-action');
appendXmlNode($xmlRequest, $xmlCompleteTransaction,'api-key',$APIKey);
appendXmlNode($xmlRequest, $xmlCompleteTransaction,'token-id',$tokenId);
$xmlRequest->appendChild($xmlCompleteTransaction);
// Process Step Three
$data = sendXMLviaCurl($xmlRequest,$gatewayURL);
$gwResponse = @new SimpleXMLElement((string)$data);
print ' <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">';
print '
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Step Three - Complete Add Customer </title>
</head>
<body>';
print "
<p><h2>Step Three: Script automatically completes the process of adding the Customer Vault record <br /></h2></p>";
if ((string)$gwResponse->result == 1 ) {
print " <p><h3> Customer Vault was Added, XML response was:</h3></p>\n";
print '<pre>' . (htmlentities($data)) . '</pre>';
} elseif((string)$gwResponse->result == 2) {
print " <p><h3> Customer Vault was Not Added</h3>\n";
print " Reason : " . (string)$gwResponse->{'result-text'} ." </p>";
print " <p><h3>XML response was:</h3></p>\n";
print '<pre>' . (htmlentities($data)) . '</pre>';
} else {
print " <p><h3> Customer Vault Add caused an Error.</h3>\n";
print " Error Description: " . (string)$gwResponse->{'result-text'} ." </p>";
print " <p><h3>XML response was:</h3></p>\n";
print '<pre>' . (htmlentities($data)) . '</pre>';
}
print "</body></html>";
} else {
print "ERROR IN SCRIPT<BR>";
}
function sendXMLviaCurl($xmlRequest,$gatewayURL) {
// helper function demonstrating how to send the xml with curl
$ch = curl_init(); // Initialize curl handle
curl_setopt($ch, CURLOPT_URL, $gatewayURL); // Set POST URL
$headers = array();
$headers[] = "Content-type: text/xml";
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); // Add http headers to let it know we're sending XML
$xmlString = $xmlRequest->saveXML();
curl_setopt($ch, CURLOPT_FAILONERROR, 1); // Fail on errors
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); // Allow redirects
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); // Return into a variable
curl_setopt($ch, CURLOPT_PORT, 443); // Set the port number
curl_setopt($ch, CURLOPT_TIMEOUT, 30); // Times out after 30s
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $xmlString); // Add XML directly in POST
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
// This should be unset in production use. With it on, it forces the ssl cert to be valid
// before sending info.
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
if (!($data = curl_exec($ch))) {
print "curl error =>" .curl_error($ch) ."\n";
throw New Exception(" CURL ERROR :" . curl_error($ch));
}
curl_close($ch);
return $data;
}
// Helper function to make building xml dom easier
function appendXmlNode($domDocument, $parentNode, $name, $value) {
$childNode = $domDocument->createElement($name);
$childNodeValue = $domDocument->createTextNode($value);
$childNode->appendChild($childNodeValue);
$parentNode->appendChild($childNode);
}
1. The customer sends their payment information to the merchant’s web site.
2. The merchant web site posts the payment data to the Payment Gateway.
3. The Payment Gateway responds immediately with the results of the transactions.
4. The merchant web site displays the appropriate message to the customer.
The communication method used to send messages to the Payment Gateway’s server is the standard HTTP protocol over an SSL connection.
In the Direct Post method, the communications with the cardholder (Steps 1 and 4) are developed completely by the merchant and therefore are not defined by the Payment Gateway. Step 1 should simply collect the payment data from the cardholder and Step 4 should display the appropriate transaction receipt or declined message.
In Step 2, transaction details should be delivered to the Payment Gateway using the POST method with the appropriate variables defined below posted along with the request.
In Step 3, the transaction responses are returned in the body of the HTTP response in a query string name/value format delimited by ampersands. For example: variable1=value1&variable2=value2&variable3=value3
The Customer Vault was designed specifically for businesses of any size to address concerns about handling customer payment information. Visa and MasterCard have instituted the Payment Card Industry (PCI) Data Security to protect cardholder data, wherever it resides, ensuring that members, merchants, and service providers maintain the highest information security standards.
These associations have also deemed that merchants will be held liable for any breach of cardholder data. This has become a major concern for merchants who handle credit card or electronic check payments. The Customer Vault is designed for these merchants who desire to avoid the tremendous costs and resources involved in becoming PCI compliant under these circumstances.
The Customer Vault does this by allowing merchants to transmit their payment information through a Secure Sockets Layer (SSL) connection for storage in our Level 1 PCI certified data facility. Once the customer record has been securely transmitted to the Customer Vault, the merchant can then initiate transactions remotely without having to access cardholder information directly. This process is accomplished without the merchant storing the customer’s payment information in their local database or payment application.
Transaction sales are submitted and immediately flagged for settlement.
Transaction authorizations are authorized immediately but are not flagged for settlement. These transactions must be flagged for settlement using the capture transaction type.
Transaction captures flag existing authorizations for settlement. Only authorizations can be captured. Captures can be submitted for an amount equal to or less than the original authorization.
Transaction voids will cancel an existing sale or captured authorization. In addition, non-captured authorizations can be voided to prevent any future capture. Voids can only occur if the transaction has not been settled.
Transaction refunds will reverse a previously settled or pending settlement transaction. If the transaction has not been settled, a transaction void can also reverse it.
Transaction credits apply an amount to the cardholder’s card that was not originally processed through the Gateway. In most situations credits are disabled as transaction refunds should be used instead.
This action is used for doing an “Account Verification” on the cardholder’s credit card without actually doing an authorization.
Transaction updates can be used to update previous transactions with specific order information, such as a tracking number and shipping carrier.
Variable Name | Description |
---|---|
type* | The type of transaction to be processed. Values: ‘sale’, ‘auth’, ‘credit’, ‘validate’, or ‘offline’ |
security_key* |
API Security Key assigned to a merchant account. New keys can be generated from the merchant control panel in Settings > Security Keys |
payment_token | The tokenized version of the customer’s card or check information. This will be generated by Collect.js and is usable only once. |
ccnumber** | Credit card number. |
ccexp** | Credit card expiration date. Format: MMYY |
cvv | The card security code. While this is not required, it is strongly recommended. |
checkname*** | The name on the customer’s ACH account. |
checkaba*** | The customer’s bank routing number. |
checkaccount*** | The customer’s bank account number. |
account_holder_type | The type of ACH account the customer has. Values: ‘business’ or ‘personal’ |
account_type | The ACH account entity of the customer. Values: ‘checking’ or ‘savings’ |
sec_code | The Standard Entry Class code of the ACH transaction. Values: ‘PPD’, ‘WEB’, ‘TEL’, or ‘CCD’ |
amount | Total amount to be charged. For validate, the amount must be omitted or set to 0.00. Format: x.xx |
surcharge | Surcharge amount. Format: x.xx |
currency | The transaction currency. Format: ISO 4217 |
payment*** | The type of payment. Default: ‘creditcard’ Values: ‘creditcard’, ‘check’, or ‘cash’ |
processor_id | If using Multiple MIDs, route to this processor (processor_id is obtained under Settings->Transaction Routing in the Control Panel). |
authorization_code‡ | Specify authorization code. For use with “offline” action only. |
dup_seconds | Sets the time in seconds for duplicate transaction checking on supported processors. Set to 0 to disable duplicate checking. This value should not exceed 7862400. |
descriptor | Set payment descriptor on supported processors. |
descriptor_phone | Set payment descriptor phone on supported processors. |
descriptor_address | Set payment descriptor address on supported processors. |
descriptor_city | Set payment descriptor city on supported processors. |
descriptor_state | Set payment descriptor state on supported processors. |
descriptor_postal | Set payment descriptor postal code on supported processors. |
descriptor_country | Set payment descriptor country on supported processors. |
descriptor_mcc | Set payment descriptor mcc on supported processors. |
descriptor_merchant_id | Set payment descriptor merchant id on supported processors. |
descriptor_url | Set payment descriptor url on supported processors. |
billing_method | Should be set to ‘recurring’ to mark payment as a recurring transaction or ‘installment’ to mark payment as an installment transaction. Values: ‘recurring’, ‘installment’ |
billing_number | Specify installment billing number, on supported processors. For use when “billing_method” is set to installment. Values: 0-99 |
billing_total | Specify installment billing total on supported processors. For use when “billing_method” is set to installment. |
order_template | Order template ID. |
order_description | Order description. Legacy variable includes: orderdescription |
orderid | Order Id |
ipaddress | IP address of cardholder, this field is recommended. Format: xxx.xxx.xxx.xxx |
tax**** | Total tax amount. |
shipping**** | Total shipping amount |
ponumber**** | Original purchase order |
first_name | Cardholder’s first name. Legacy variable includes: firstname |
last_name | Cardholder’s last name Legacy variable includes: lastname |
company | Cardholder’s company |
address1 | Card billing address |
address2 | Card billing address, line 2 |
city | Card billing city |
state | Card billing state. Format: CC |
zip | Card billing zip code |
country | Card billing country. Country codes are as shown in ISO 3166. Format: CC |
phone | Billing phone number |
fax | Billing fax number |
Billing email address | |
social_security_number | Customer’s social security number, checked against bad check writers database if check verification is enabled. |
drivers_license_number | Driver’s license number. |
drivers_license_dob | Driver’s license date of birth. |
drivers_license_state | The state that issued the customer’s driver’s license. |
shipping_firstname | Shipping first name |
shipping_lastname | Shipping last name |
shipping_company | Shipping company |
shipping_address1 | Shipping address |
shipping_address2 | Shipping address, line 2 |
shipping_city | Shipping city |
shipping_state | Shipping state Format: CC |
shipping_zip | Shipping zip code |
shipping_country | Shipping country Country codes are as shown in ISO 3166. Format: CC |
shipping_email | Shipping email address |
merchant_defined_field_# | You can pass custom information in up to 20 fields. Format: merchant_defined_field_1=Value |
customer_receipt | If set to true, when the customer is charged, they will be sent a transaction receipt. Values: ‘true’ or ‘false’ |
signature_image | Cardholder signature image. For use with “sale” and “auth” actions only. Format: base64 encoded raw PNG image. (16kiB maximum) |
cardholder_auth‡‡ | Set 3D Secure condition. Values: ‘verified’ or ‘attempted’ |
eci‡‡ | E-commerce indicator. Values: ‘0’, ‘1’, ‘2’, ‘5’, ‘6’, or ‘7’ |
cavv‡‡ | Cardholder authentication verification value. Format: base64 encoded |
xid‡‡ | Cardholder authentication transaction id. Format: base64 encoded |
three_ds_version‡‡ | 3DSecure version. Examples: “1.0.2” or “2.0” |
directory_server_id | Directory Server Transaction ID. May be provided as part of 3DSecure 2.0 authentication. Format: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx |
source_transaction_id | Specifies a payment gateway transaction id in order to associate payment information with a Subscription or Customer Vault record. Must be set with a ‘recurring’ or ‘customer_vault’ action. |
Recurring specific fields | |
recurring | Recurring action to be processed. Values: add_subscription |
plan_id | Create a subscription tied to a Plan ID if the sale/auth transaction is successful. |
plan_payments | The number of payments before the recurring plan is complete. Note: Use ‘0’ for ‘until canceled’ |
plan_amount | The plan amount to be charged each billing cycle. Format: x.xx |
day_frequency | How often, in days, to charge the customer. Cannot be set with ‘month_frequency’ or ‘day_of_month’. |
month_frequency | How often, in months, to charge the customer. Cannot be set with ‘day_frequency’. Must be set with ‘day_of_month’. Values: 1 through 24 |
day_of_month | The day that the customer will be charged. Cannot be set with ‘day_frequency’. Must be set with ‘month_frequency’. Values: 1 through 31 – for months without 29, 30, or 31 days, the charge will be on the last day |
start_date | The first day that the customer will be charged. Format: YYYYMMDD |
Customer Vault specific fields | |
customer_vault | Associate payment information with a Customer Vault record if the transaction is successful. Values: ‘add_customer’ or ‘update_customer’ |
customer_vault_id | Specifies a customer vault id. If not set, the payment gateway will randomly generate a customer vault id. |
Stored Credentials (CIT/MIT) | |
initiated_by | Who initiated the transaction. Values: ‘customer’ or ‘merchant’ |
initial_transaction_id | Original payment gateway transaction id. |
stored_credential_indicator | The indicator of the stored credential. Values: ‘stored’ or ‘used’ Use ‘stored’ when processing the initial transaction in which you are storing a customer’s payment details (customer credentials) in the Customer Vault or other third-party payment storage system. Use ‘used’ when processing a subsequent or follow-up transaction using the customer payment details (customer credentials) you have already stored to the Customer Vault or third-party payment storage method. |
Level III specific order fields | |
shipping | Freight or shipping amount included in the transaction amount Default: ‘0.00’ Format: x.xx |
tax | The sales tax, included in the transaction amount, associated with the purchase. Setting tax equal to ‘-1’ indicates an order that is exempt from sales tax. Default: ‘0.00’ Format: x.xx |
ponumber† | Purchase order number supplied by cardholder |
orderid† | Identifier assigned by the merchant. This defaults to gateway transaction id. |
shipping_country† | Shipping country (e.g. US) Format: CC |
shipping_postal† | Postal/ZIP code of the address where purchased goods will be delivered. This field can be identical to the ‘ship_from_postal’ if the customer is present and takes immediate possession of the goods. |
ship_from_postal† | Postal/ZIP code of the address from where purchased goods are being shipped, defaults to merchant profile postal code. |
summary_commodity_code† | 4 character international description code of the overall goods or services being supplied. The acquirer or processor will provide a list of current codes. |
duty_amount | Amount included in the transaction amount associated with the import of purchased goods. Default: ‘0.00’ Format: x.xx |
discount_amount | Amount included in the transaction amount of any discount applied to complete order by the merchant. Default: ‘0.00’ Format: x.xx |
national_tax_amount | The national tax amount included in the transaction amount. Default: ‘0.00’ Format: x.xx |
alternate_tax_amount | Second tax amount included in the transaction amount in countries where more than one type of tax can be applied to the purchases. Default: ‘0.00’ Format: x.xx |
alternate_tax_id | Tax identification number of the merchant that reported the alternate tax amount. |
vat_tax_amount | Contains the amount of any value added taxes which can be associated with the purchased item. Default: ‘0.00’ Format: x.xx |
vat_tax_rate | Contains the tax rate used to calculate the sales tax amount appearing. Can contain up to 2 decimal places, e.g. 1% = 1.00. Default: ‘0.00’ Format: x.xx |
vat_invoice_reference_number | Invoice number that is associated with the VAT invoice. |
customer_vat_registration | Value added tax registration number supplied by the cardholder. |
merchant_vat_registration | Government assigned tax identification number of the merchant for whom the goods or services were purchased from. |
order_date | Purchase order date, defaults to the date of the transaction. Format: YYMMDD |
Level III specific line item detail fields | |
item_product_code_#† | Merchant defined description code of the item being purchased. |
item_description_#† | Description of the item(s) being supplied. |
item_commodity_code_#† | International description code of the individual good or service being supplied. The acquirer or processor will provide a list of current codes. |
item_unit_of_measure_#† | Code for units of measurement as used in international trade. Default: ‘EACH’ |
item_unit_cost_#† | Unit cost of item purchased, may contain up to 4 decimal places. |
item_quantity_#† | Quantity of the item(s) being purchased. Default: ‘1’ |
item_total_amount_#† | Purchase amount associated with the item. Defaults to: ‘item_unit_cost_#’ x ‘item_quantity_#’ rounded to the nearest penny. |
item_tax_amount_#† | Amount of tax on specific item, amount should not be included in ‘total_amount_#’. Default: ‘0.00’ |
item_tax_rate_#† | Percentage representing the value-added tax applied. Default: ‘0.00’ |
item_discount_amount_# | Discount amount which can have been applied by the merchant on the sale of the specific item. Amount should not be included in ‘total_amount_#’. |
item_discount_rate_# | Discount rate for the line item. 1% = 1.00. Default: ‘0.00’ |
item_tax_type_# | Type of value-added taxes that are being used. |
item_alternate_tax_id_# | Tax identification number of the merchant that reported the alternate tax amount. |
* | Always required |
** | Required for credit card transactions |
*** | Required for ACH transactions |
**** | Required for Level 2 transactions |
† | Required for Level 3 transactions |
‡ | Required for offline transactions |
‡‡ | Required for 3D Secure transactions |
Variable Name | Description |
---|---|
type* | Type of transaction. Values: ‘capture’ |
security_key* |
API Security Key assigned to a merchant account. New keys can be generated from the merchant control panel in Settings > Security Keys |
transactionid* | Original payment gateway transaction id |
amount* | Total amount to be settled. This amount must be equal to or less than the original authorized amount. Format: x.xx |
tracking_number | Shipping tracking number |
shipping_carrier | Shipping carrier. Values: ‘ups’, ‘fedex’, ‘dhl’, or ‘usps’ |
orderid | Order id. |
signature_image | Cardholder signature image. Format: base64 encoded raw PNG image. (16kiB maximum) |
* | Always required |
Variable Name | Description |
---|---|
type* | Type of transaction. Values: ‘void’ |
security_key* |
API Security Key assigned to a merchant account. New keys can be generated from the merchant control panel in Settings > Security Keys |
transactionid* | Original payment gateway transaction id |
void_reason** | Reason the EMV transaction is being voided. Values: ‘fraud’, ‘user_cancel’, ‘icc_rejected’, ‘icc_card_removed’, ‘icc_no_confirmation’, or ‘pos_timeout’ |
payment*** | The type of payment. Default: ‘creditcard’ Values: ‘creditcard’ or ‘check’ |
* | Always required |
** | Conditionally required for EMV transactions |
*** | Required for ACH transactions |
Variable Name | Description |
---|---|
type* | Type of transaction. Values: ‘refund’ |
security_key* |
API Security Key assigned to a merchant account. New keys can be generated from the merchant control panel in Settings > Security Keys |
transactionid* | Original payment gateway transaction id |
amount | Total amount to be refunded. This amount may be equal to or less than the settled amount. Setting the amount to 0.00 will refund the entire amount. Format: x.xx |
payment** | The type of payment. Default: ‘creditcard’ Values: ‘creditcard’ or ‘check’ |
* | Always required |
** | Required for ACH transactions |
Variable Name | Description |
---|---|
type* | Type of transactions. Values: ‘update’ |
security_key* |
API Security Key assigned to a merchant account. New keys can be generated from the merchant control panel in Settings > Security Keys |
transactionid* | Original payment gateway transaction id |
payment** | The type of payment. Default: ‘creditcard’ Values: ‘creditcard’ or ‘check’ |
tracking_number | Shipping tracking number |
shipping | Total shipping amount. Format: x.xx |
shipping_postal | Postal/ZIP code of the address where purchased goods will be delivered. This field can be identical to the ‘ship_from_postal’ if the customer is present and takes immediate possession of the goods. |
ship_from_postal | Postal/ZIP code of the address from where purchased goods are being shipped, defaults to merchant profile postal code. |
shipping_country | Shipping Country Code. |
shipping_carrier | Shipping carrier. Values: ‘ups’, ‘fedex’, ‘dhl’, or ‘usps’ |
shipping_date | Shipping date. Format: YYYYMMDD |
order_description | Order Description. Legacy variable includes: orderdescription |
order_date | Order date. Format: YYYYMMDD |
customer_receipt | If set to true, when the customer is charged, they will be sent a transaction receipt. Values: ‘true’ or ‘false’ |
signature_image | Cardholder signature image. Format: base64 encoded raw PNG image. (16kiB maximum) |
ponumber | Cardholder’s purchase order number. |
summary_commodity_code | 4 character international description code of the overall goods or services being supplied. The acquirer or processor will provide a list of current codes. |
duty_amount | Amount included in the transaction amount associated with the import of purchased goods. Format: x.xx |
discount_amount | Amount included in the transaction amount of any discount applied to complete order by the merchant. Format: x.xx |
tax | Tax amount. Format: x.xx |
national_tax_amount | The national tax amount included in the transaction amount. Format: x.xx |
alternate_tax_amount | Second tax amount included in the transaction amount in countries where more than one type of tax can be applied to the purchases. Format: x.xx |
alternate_tax_id | Tax identification number of the merchant that reported the alternate tax amount. |
vat_tax_amount | Contains the amount of any value added taxes which can be associated with the purchased item. |
vat_tax_rate | Contains the tax rate used to calculate the sales tax amount appearing. Can contain up to 2 decimal places, e.g. 1% = 1.00. |
vat_invoice_reference_number | Invoice number that is associated with the VAT invoice. |
customer_vat_registration | Value added tax registration number supplied by the cardholder. |
merchant_vat_registration | Government assigned tax identification number of the merchant for whom the goods or services were purchased from. |
merchant_defined_field_# | Merchant Defined Fields. Format: merchant_defined_field_1=Value |
* | Always required |
** | Required for ACH transactions |
Variable Name | Description |
---|---|
recurring* | Add a recurring plan that subscriptions can be added to in the future. Value: ‘add_plan’ |
plan_payments* | The number of payments before the recurring plan is complete. Notes: ‘0’ for until canceled |
plan_amount* | The plan amount to be charged each billing cycle. Format: x.xx |
plan_name* | The display name of the plan. |
plan_id* | The unique plan ID that references only this recurring plan. |
day_frequency** | How often, in days, to charge the customer. Cannot be set with ‘month_frequency’ or ‘day_of_month’. |
month_frequency*** | How often, in months, to charge the customer. Cannot be set with ‘day_frequency’. Must be set with ‘day_of_month’. Values: 1 through 24 |
day_of_month*** | The day that the customer will be charged. Cannot be set with ‘day_frequency’. Must be set with ‘month_frequency’. Values: 1 through 31 – for months without 29, 30, or 31 days, the charge will be on the last day |
* | Always required |
** | Required unless ‘month_frequency’ and ‘day_of_month’ is set. |
*** | Required unless ‘day_frequency’ is set. |
Variable Name | Description |
---|---|
recurring* | Associate payment information with a recurring plan. Value: add_subscription |
plan_id* | The plan ID of the plan that the subscription will be associated with. |
start_date | The first day that the customer will be charged. Format: YYYYMMDD |
payment_token | The tokenized version of the customer’s card or check information. This will be generated by Collect.js and is usable only once. |
ccnumber** | Credit card number. |
ccexp** | Credit card expiration. Format: MMYY |
payment*** | The type of payment. Default: ‘creditcard’ Values: ‘creditcard’ or ‘check’ |
checkname*** | The name on the customer’s ACH account. |
checkaccount*** | The customer’s bank account number. |
checkaba*** | The customer’s bank routing number. |
account_type | The customer’s ACH account type. Values: ‘checking’ or ‘savings’ |
currency | Set transaction currency. |
account_holder_type | The customer’s ACH account entity. Values: ‘personal’ or ‘business’ |
sec_code | ACH standard entry class codes. Values: ‘PPD’, ‘WEB’, ‘TEL’, or ‘CCD’ |
first_name | Cardholder’s first name. Legacy variable includes: firstname |
last_name | Cardholder’s last name. Legacy variable includes: lastname |
address1 | Card billing address. |
city | Card billing city |
state | Card billing state. |
zip | Card billing postal code. |
country | Card billing country code. |
phone | Billing phone number. |
Billing email address. | |
company | Cardholder’s company. |
address2 | Card billing address, line 2. |
fax | Billing fax number. |
orderid | Order ID |
order_description | Order Description |
merchant_defined_field_# | Can be set up in merchant control panel under ‘Settings’->’Merchant Defined Fields’. |
ponumber | Cardholder’s purchase order number. |
processor_id | If using Multiple MIDs, route to this processor (processor_id is obtained under Settings->Transaction Routing in the Control Panel). |
customer_receipt | If set to true, when the customer is charged, they will be sent a transaction receipt. Values: ‘true’ or ‘false’ |
source_transaction_id | Specifies a payment gateway transaction id in order to associate payment information with a Subscription record. |
* | Always required |
** | Required for credit card transactions |
*** | Required for ACH transactions |
Variable Name | Description |
---|---|
recurring* | Add a custom recurring subscription that is NOT associated with an existing plan Value: ‘add_subscription’ |
plan_payments* | The number of payments before the recurring plan is complete. Notes: ‘0’ for until canceled |
plan_amount* | The plan amount to be charged each billing cycle. Format: x.xx |
day_frequency** | How often, in days, to charge the customer. Cannot be set with ‘month_frequency’ or ‘day_of_month’. |
month_frequency*** | How often, in months, to charge the customer. Cannot be set with ‘day_frequency’. Must be set with ‘day_of_month’. Values: 1 through 24 |
day_of_month*** | The day that the customer will be charged. Cannot be set with ‘day_frequency’. Must be set with ‘month_frequency’. Values: 1 through 31 – for months without 29, 30, or 31 days, the charge will be on the last day |
start_date | The first day that the customer will be charged. Format: YYYYMMDD |
payment_token | The tokenized version of the customer’s card or check information. This will be generated by Collect.js and is usable only once. |
ccnumber**** | Credit card number. |
ccexp**** | Credit card expiration. Format: MMYY |
payment† | The type of payment. Default: ‘creditcard’ Values: ‘creditcard’ or ‘check’ |
checkname† | The name on the customer’s ACH account. |
checkaccount† | The customer’s bank account number. |
checkaba† | The customer’s bank routing number. |
account_type | The customer’s ACH account type. Values: ‘checking’ or ‘savings’ |
account_holder_type | The customer’s ACH account entity. Values: ‘personal’ or ‘business’ |
sec_code | ACH standard entry class codes. Values: ‘PPD’, ‘WEB’, ‘TEL’, or ‘CCD’ |
first_name | Cardholder’s first name. Legacy variable includes: firstname |
last_name | Cardholder’s last name. Legacy variable includes: lastname |
address1 | Card billing address. |
city | Card billing city |
state | Card billing state. |
zip | Card billing postal code. |
country | Card billing country code. |
phone | Billing phone number. |
Billing email address. | |
company | Cardholder’s company. |
address2 | Card billing address, line 2. |
fax | Billing fax number. |
orderid | Order ID |
order_description | Order Description Legacy variable includes: orderdescription |
merchant_defined_field_# | Can be set up in merchant control panel under ‘Settings’->’Merchant Defined Fields’. |
ponumber | Cardholder’s purchase order number. |
processor_id | If using Multiple MIDs, route to this processor (processor_id is obtained under Settings->Transaction Routing in the Control Panel). |
customer_receipt | If set to true, when the customer is charged, they will be sent a transaction receipt. Values: ‘true’ or ‘false’ |
source_transaction_id | Specifies a payment gateway transaction id in order to associate payment information with a Subscription record. |
* | Always required |
** | Required unless ‘month_frequency’ and ‘day_of_month’ is set. |
*** | Required unless ‘day_frequency’ is set. |
**** | Required for credit card transactions |
† | Required for ACH transactions |
Variable Name | Description |
---|---|
recurring* | Update the subscription’s billing information. Value: ‘update_subscription’ |
subscription_id* | The subscription ID that will be updated. |
* | Always required |
Variable Name | Description |
---|---|
recurring* | Delete the subscription. Customer will no longer be charged. Value: ‘delete_subscription’ |
subscription_id* | The subscription ID that will be deleted. |
* | Always required |
Variable Name | Description |
---|---|
invoicing* | Create a new invoice and email it to the customer. Values: ‘add_invoice’ |
security_key* |
API Security Key assigned to a merchant account. New keys can be generated from the merchant control panel in Settings > Security Keys |
amount* | Total amount to be invoiced. Must be greater than 0.00. Format: x.xx |
email* | Billing email address An invoice will be sent to this address when it is created. |
payment_terms | When the invoice should be paid Default: ‘upon_receipt’ Values: ‘upon_receipt’, or integers from 0-999. |
payment_methods_allowed | What payment methods a customer may use when paying invoice. Defaults to all available payment methods available in your merchant account Values: ‘cc’, ‘ck’, and ‘cs’. Multiple payment types can be selected by comma-separating values. |
currency | The transaction currency. Format: ISO 4217 |
order_description | Order description. Legacy variable includes: orderdescription |
orderid | Order ID. |
customer_id | Customer ID. |
customer_tax_id | Customer Tax ID. |
tax | Total tax amount. |
shipping | Total shipping amount. |
ponumber | Original purchase order. |
first_name | Cardholder’s first name. Legacy variable includes: firstname |
last_name | Cardholder’s last name. Legacy variable includes: lastname |
company | Cardholder’s company. |
address1 | Card billing address. |
address2 | Card billing address, line 2. |
city | Card billing city. |
state | Card billing state. Format: CC |
zip | Card billing zip code. |
country | Card billing country. Country codes are as shown in ISO 3166. Format: CC |
phone | Billing phone number. |
fax | Billing fax number. |
website | Customer website. |
shipping_firstname | Shipping first name. |
shipping_lastname | Shipping last name. |
shipping_company | Shipping company. |
shipping_address1 | Shipping address. |
shipping_address2 | Shipping address, line 2. |
shipping_city | Shipping city. |
shipping_state | Shipping state. Format: CC |
shipping_zip | Shipping zip code. |
shipping_country | Shipping country. Country codes are as shown in ISO 3166. Format: CC |
shipping_email | Shipping email address. |
merchant_defined_field_# | You can pass custom information in up to 20 fields. Format: merchant_defined_field_1=Value |
Product Information | |
item_product_code_# | Merchant defined description code of the item being purchased. |
item_description_# | Description of the item(s) being supplied. |
item_commodity_code_# | International description code of the individual good or service being supplied. The acquirer or processor will provide a list of current codes. |
item_unit_of_measure_# | Code for units of measurement as used in international trade. Default: ‘EACH’ |
item_unit_cost_# | Unit cost of item purchased, may contain up to 4 decimal places. |
item_quantity_# | Quantity of the item(s) being purchased. Default: ‘1’ |
item_total_amount_# | Purchase amount associated with the item. Defaults to: ‘item_unit_cost_#’ x ‘item_quantity_#’ rounded to the nearest penny. |
item_tax_amount_# | Amount of tax on specific item, amount should not be included in ‘total_amount_#’. Default: ‘0.00’ |
item_tax_rate_# | Percentage representing the value-added tax applied. Default: ‘0.00’ |
item_discount_amount_# | Discount amount which can have been applied by the merchant on the sale of the specific item. Amount should not be included in ‘total_amount_#’. |
item_discount_rate_# | Discount rate for the line item. 1% = 1.00. Default: ‘0.00’ |
item_tax_type_# | Type of value-added taxes that are being used. |
item_alternate_tax_id_# | Tax identification number of the merchant that reported the alternate tax amount. |
* | Always required |
Variable Name | Description |
---|---|
invoicing* | Update an existing invoice. Values: ‘update_invoice’ |
security_key* |
API Security Key assigned to a merchant account. New keys can be generated from the merchant control panel in Settings > Security Keys |
invoice_id* | The invoice ID to be updated. |
* | Always required |
All variables (besides currency) on an invoice may be updated. Updating an invoice will not result in a new invoice being sent to the customer. To send the invoice after updating an invoice, use the send_invoice request after making changes.
Variable Name | Description |
---|---|
invoicing* | Send an existing invoice to a customer. Values: ‘send_invoice’ |
security_key* |
API Security Key assigned to a merchant account. New keys can be generated from the merchant control panel in Settings > Security Keys |
invoice_id* | The invoice ID to be emailed. |
* | Always required |
The invoice will be sent to the billing email address assigned to the invoice.
Variable Name | Description |
---|---|
invoicing* | The invoice to be closed. Values: ‘close_invoice’ |
security_key* |
API Security Key assigned to a merchant account. New keys can be generated from the merchant control panel in Settings > Security Keys |
invoice_id* | The invoice ID to be closed. |
* | Always required |
Variables | Description |
---|---|
customer_vault* | Add/Update a secure customer vault record. Values: ‘add_customer’ or ‘update_customer’ |
customer_vault_id | Specifies a customer vault id. If not set, the payment gateway will randomly generate a customer vault id. |
billing_id | Billing id to be assigned or updated. If none is provided, one will be created or the billing id with priority ‘1’ will be updated. |
security_key* |
API Security Key assigned to a merchant account. New keys can be generated from the merchant control panel in Settings > Security Keys |
payment_token | The tokenized version of the customer’s card or check information. This will be generated by Collect.js and is usable only once. |
ccnumber** | Credit card number. |
ccexp** | Credit card expiration. Format: MMYY |
checkname*** | The name on the customer’s ACH account. |
checkaba*** | The customer’s bank routing number. |
checkaccount*** | The customer’s bank account number. |
account_holder_type | The customer’s ACH account entity. Values: ‘personal’ or ‘business’ |
account_type | The customer’s ACH account type. Values: ‘checking’ or ‘savings’ |
sec_code | ACH standard entry class codes. Values: ‘PPD’, ‘WEB’, ‘TEL’, or ‘CCD’ |
currency | Set transaction currency. |
payment | Set payment type to ACH or credit card. Values: ‘creditcard’ or ‘check’ |
orderid | Order id |
order_description | Order Description Legacy variable includes: orderdescription |
merchant_defined_field_# | Can be set up in merchant control panel under ‘Settings’->’Merchant Defined Fields’. Format: merchant_defined_field_1=Value |
first_name | Cardholder’s first name. Legacy variable includes: firstname |
last_name | Cardholder’s last name. Legacy variable includes: lastname |
address1 | Card billing address. |
city | Card billing city |
state | Card billing state. |
zip | Card billing postal code. |
country | Card billing country code. |
phone | Billing phone number. |
Billing email address. | |
company | Cardholder’s company. |
address2 | Card billing address, line 2. |
fax | Billing fax number. |
shipping_id | Shipping entry id. If none is provided, one will be created or the billing id with priority ‘1’ will be updated. |
shipping_firstname | Shipping first name. |
shipping_lastname | Shipping last name. |
shipping_company | Shipping company. |
shipping_address1 | Shipping address. |
shipping_address2 | Shipping address, line 2. |
shipping_city | Shipping city |
shipping_state | Shipping state. |
shipping_zip | Shipping postal code. |
shipping_country | Shipping country code. |
shipping_phone | Shipping phone number. |
shipping_fax | Shipping fax number. |
shipping_email | Shipping email address. |
source_transaction_id | Specifies a payment gateway transaction id in order to associate payment information with a Customer Vault record. |
* | Always required |
** | Required for credit card transactions |
*** | Required for ACH transactions |
Variable | Description |
---|---|
security_key* |
API Security Key assigned to a merchant account. New keys can be generated from the merchant control panel in Settings > Security Keys |
customer_vault_id* | Specifies a customer vault id. |
amount | Total amount to be charged. For validate, the amount must be omitted or set to 0.00. Format: x.xx |
currency | The transaction currency. Format: ISO 4217 |
processor_id | If using Multiple MIDs, route to this processor (processor_id is obtained under Settings->Transaction Routing in the Control Panel). |
descriptor | Set payment descriptor on supported processors. |
descriptor_phone | Set payment descriptor phone on supported processors. |
order_description | Order description. Legacy variable includes: orderdescription |
orderid | Order ID |
Stored Credentials (CIT/MIT) | |
initiated_by | Who initiated the transaction. Values: ‘customer’ or ‘merchant’ |
initial_transaction_id | Original payment gateway transaction id. |
stored_credential_indicator | The indicator of the stored credential. Values: ‘stored’ or ‘used’ Use ‘stored’ when processing the initial transaction in which you are storing a customer’s payment details (customer credentials) in the Customer Vault or other third-party payment storage system. Use ‘used’ when processing a subsequent or follow-up transaction using the customer payment details (customer credentials) you have already stored to the Customer Vault or third-party payment storage method. |
* | Always required |
Variable | Description |
---|---|
customer_vault* | Deletes a secure customer vault record. Values: ‘delete_customer’ |
customer_vault_id* | Specifies a customer vault id. |
security_key* |
API Security Key assigned to a merchant account. New keys can be generated from the merchant control panel in Settings > Security Keys |
* | Always required |
Variable Name | Description |
---|---|
track_1 | Raw Magnetic Stripe Data |
track_2 | Raw Magnetic Stripe Data |
track_3 | Raw Magnetic Stripe Data |
Variable Name | Description |
---|---|
magnesafe_track_1 | Raw MagTek Magensa Data |
magnesafe_track_2 | Raw MagTek Magensa Data |
magnesafe_magneprint | Raw MagTek Magensa Data |
magnesafe_ksn | Raw MagTek Magensa Data |
magnesafe_magneprint_status | Raw MagTek Magensa Data |
Variable Name | Description |
---|---|
encrypted_track_1 | Raw encrypted data |
encrypted_track_2 | Raw encrypted data |
encrypted_track_3 | Raw encrypted data |
encrypted_ksn | Raw encrypted data |
Variable Name | Description |
---|---|
encrypted_data | Raw encrypted data |
Variable Name | Description |
---|---|
entry_mode | The type of transaction data to be processed. Value: ’emv_icc’ |
emv_auth_request_data | EMV Data for the transaction as received from the EMV Chip Card SDK. |
emv_device | The EMV – capable card reader. Value: ‘ingenico_rba’ |
verification_method | Method used to verify the EMV transaction. Values: ‘signature’, ‘offline_pin’, ‘offline_pin_signature’, or ‘none’ |
encrypted_ksn | Raw encrypted data |
encrypted_track_2 | Raw encrypted data |
Variable Name | Description |
---|---|
entry_mode | The type of transaction data to be processed. Values: ‘swiped’ or ‘swiped_emv_fallback’ |
emv_device | The EMV – capable card reader. Value: ‘ingenico_rba’ |
encrypted_ksn | Raw encrypted data |
encrypted_track_1 | Raw encrypted data |
encrypted_track_2 | Raw encrypted data |
Variable Name | Description |
---|---|
entry_mode | The type of transaction data to be processed. Value: ‘nfc_msd’ |
emv_device | The EMV – capable card reader. Value: ‘ingenico_rba’ |
encrypted_ksn | Raw encrypted data |
encrypted_track_2 | Raw encrypted data |
Variable Name | Description |
---|---|
entry_mode | The type of transaction data to be processed. Value: ‘keyed’ |
emv_device | The EMV – capable card reader. Value: ‘ingenico_rba’ |
encrypted_ksn | Raw encrypted data |
encrypted_track_2 | Raw encrypted data |
Currently Apple Pay is supported only on the TSYS – EMV platform.
Creating an Apple Merchant ID
First, you must obtain an Apple Merchant ID before you can generate the Certificate Signing Request that Apple requires. You will need to set up an Apple Merchant ID in your iOS Developer Account. Follow these steps to complete the setup:
Generating the Certificate Signing Request
Next, you will need to associate a Certificate with the Merchant ID in Apple’s Developer Portal. After downloading the Certificate Signing Request from the gateway’s options page, follow these steps.
PassKit provides the payment data in the (PKPayment *)payment that is returned to your app’s paymentAuthorizationViewController:didAuthorizePayment:completion method. The Apple Pay encrypted payment data is found in payment.token.paymentData.
payment.token.paymentData is a binary (NSData) object, so you must encode it as a hexadecimal string before it can be passed to the Gateway.
To submit a payment with Apple Pay, send the encrypted token data into the applepay_payment_data variable. There is no need to decrypt the data in your app. Only the Gateway will have access to the private key that can decrypt the token.
When passing in applepay_payment_data, you should not include the variables ccnumber or ccexp; they are extracted from the token data.
Important Note: The authorization amount must match the amount the customer approves in the app. If you pass in a currency, that must also match the currency approved in the app. If omitted, the currency from the app is used.
For working example code, including how to obtain the PKPayment object and how to pass a simple transaction to the Gateway, download the sample project.
Variable Name | Description |
---|---|
applepay_payment_data | The encrypted Apple Pay payment data (payment.token.paymentData) from PassKit encoded as a hexadecimal string |
If you receive the error “Failed to decrypt Apple Pay data. Ensure that the Apple Pay Merchant ID is correct in the Gateway Settings and that the certificate was generated from a Gateway Certificate Signing Request.”, try these steps:
Variable | Description |
---|---|
partial_payment_id | Unique identifier returned when making the original transaction. This should only be used for secondary transactions. |
partial_payments | This variable allows the following two values to be passed to it: |
settle_partial: Settles any amount of tender collected (captured partial auth’s and approved partial sales) at cut off. | |
payment_in_full: Required that any split tendered transaction is collected in-full before settlement gets initiated. | |
type | This variable can be passed the value ‘complete_partial_payment’ which will complete a payment_in_full transaction that has not been collected in full. This allows industries that require payment_in_full but subsequently decide to still settle the transaction even though it has not been collected in full. |
Variable | Description |
---|---|
partial_payment_id | A numeric identifier which is used when submitting subsequent transactions. |
partial_payment_balance | Returns the payment’s remaining balance. |
amount_authorized | Provides the amount that was authorized. |
Example 1: In this request, if nothing more was done, a transaction for 30.00 would settle at the next cut-off.
Request | …type=sale&partial_payments=settle_partial&ccnumber=4111111111111111&ccexp=1016&amount=100.00… |
Response | …response=1&partial_payment_id=123456789&partial_payment_balance=70.00&amount_authorized=30.00… |
Example 2: In this request, payment_in_full was required and two transaction were collected – this transaction would settle at the next cut-off.
Request 1 | …type=sale&partial_payments=payment_in_full&ccnumber=4111111111111111&ccexp=1016&amount=100.00… |
Response 1 | …response=1&partial_payment_id=123456789&partial_payment_balance=70.00&amount_authorized=30.00… |
Request 2 | …type=sale&partial_payment_id=123456789&partial_payments=payment_in_full&ccnumber=4000000000000002&ccexp=1016&amount=70.00… |
Response 2 | …response=1& partial_payment_id=123456789&partial_payment _balance=0.00&amount_authorized=70.00… |
Example 3: In this example, payment_in_full was required and two transactions were attempted, but only one collected. The merchant decided to force it out anyways – this transaction would settle at the next cut-off.
Request 1 | …type=sale&partial_payments=payment_in_full&ccnumber=4111111111111111&ccexp=1016&amount=100.00… |
Response 1 | …response=1&partial_payment_id=123456789&partial_payment_balance=70.00&amount_authorized=30.00… |
Request 2 | …type=sale&partial_payment_id=123456789&partial_payments=payment_in_full&ccnumber=4000000000000002&ccexp=1016&amount=70.00… |
Response 2 | …response=2&partial_payment_id=123456789&partial_payment_balance=70.00&amount_authorized=70.00… |
Request 3 | …type=complete_partial_payment& partial_payment_id=123456789&partial_payments=payment_in_full&amount=70.00… |
Response 3 | …response=1& partial_payment_id=123456789&partial_payment_balance=0.00&amount_authorized=70.00… |
Please note the below is meant to be a guide for how the platform supports CIT and MIT use cases. This is not meant to be an exhaustive list of items needed in order to be compliant. For more information on CIT/MIT compliance, please consult your processor.
Credential on File regulations apply any time data is stored to process future purchases for a cardholder.
Customer vs Merchant Initiated
When a customer is actively engaged in checkout – either physical present in a store, or checking out online in their browser, that is a Customer Initiated Transaction (CIT).
When the customer isn’t actively engaged, but has given permission for their card to be charged, that is a Merchant Initiated Transaction (MIT). In order for a merchant to submit a Merchant Initiated Transaction, a Customer Initiated transaction is required first.
Overview
A cardholder’s consent is required for the initial storage of credentials. When a card is stored, an initial transaction should be submitted (Validate, Sale, or Auth) with the correct credential-on-file type. The transaction must be approved (not declined or encounter an error.) Then, store the transaction ID of the initial customer initiated transaction. The transaction ID must then be submitted with any follow up transactions (MIT or CIT.)
Credential on File types include Recurring, Installment, and Unscheduled types.
For simplicity – we are using the Direct Post API variables. These match the names of the Batch Upload, Collect.js, or the Browser Redirect APIs. The Three-Step API follows the same pattern, and the variables should be submitted on Step 1.
Variable | Description |
---|---|
initiated_by | Who initiated the transaction. Values: ‘customer’ or ‘merchant’ |
initial_transaction_id | Original payment gateway transaction id. |
stored_credential_indicator | The indicator of the stored credential. Values: ‘stored’ or ‘used’ Use ‘stored’ when processing the initial transaction in which you are storing a customer’s payment details (customer credentials) in the Customer Vault or other third-party payment storage system. Use ‘used’ when processing a subsequent or follow-up transaction using the customer payment details (customer credentials) you have already stored to the Customer Vault or third-party payment storage method. |
Variable | Description |
---|---|
cof_supported | Credential on File support indicator specific to the transaction. Values: ‘stored’ or ‘used’ Value will be ‘stored’ if CIT/MIT transaction was sent to a processor that supports the feature. Value will be ‘used’ if CIT/MIT transaction was sent to a processor that does not support the feature or if a merchant-initiated transaction cannot occur due to Cross-Processor limitations. |
Please Note: For Three-Step Redirect transactions, the request details must be sent in Step 1 and the ‘cof-supported’ element will be returned in the response of Step 3.
Recurring:
A transaction in a series of transactions that uses a stored credential and are processed at fixed, regular intervals (not to exceed one year between transactions), and represents cardholder agreement for the merchant to initiate future transactions for the purchase of goods or services provided at regular intervals.
If a customer is signing up for a recurring subscription, the merchant is expected to send “an initial recurring transaction” every time the customer signs up for a new recurring subscription.
For an initial transaction:
Either transaction MUST INCLUDE three items:
Example 1: In this request, an initial recurring sale is sent and an approved transaction is returned in the response. Store this transaction for the follow up request.
Request | …type=sale&billing_method=recurring&initiated_by=customer&stored_credential_indicator=stored… |
Response | …response=1&responsetext=Approved&transactionid=1234567890… |
The transaction ID would be stored and submitted on follow up transactions. The follow up transaction(s) would include:
Example 2: In this request, the subsequent merchant initiated sale is processed using the stored transaction from Example 1.
Request | …type=sale&billing_method=recurring&initiated_by=merchant&stored_credential_indicator=used&initial_transaction_id=1234567890… |
Response | …response=1&responsetext=Approved&transactionid=1234567891… |
Please Note: This transaction ID cannot be used for “unscheduled” or “installment” credential-on-file transactions.
Installment:
An “installment” transaction is a series of transactions that uses a stored credential and represents cardholder agreement with the merchant to initiate one or more future transactions over a period of time for a single purchase of goods or services.
Installment transactions work just like Recurring in that you need a customer initiated transaction for a subsequent installment transaction. The difference is the billing_method will be “installment”.
The customer initiated transaction MUST INCLUDE at least three items (* recommended to send, if available):
Example 3: In this request, an initial installment sale is sent and an approved transaction is returned in the response. Store this transaction for the follow up request.
Request | …type=sale&billing_method=installment&initiated_by=customer&stored_credential_indicator=stored&billing_total=100.00&billing_number=1&amount=25.00… |
Response | …response=1&responsetext=Approved&transactionid=1234567890… |
The transaction ID would be stored and submitted on follow up transactions. The follow up transaction(s) would include (* recommended to send, if available):
Example 4: In this request, the subsequent merchant initiated sale is processed using the stored transaction from Example 3.
Request | …type=sale&billing_method=installment&initiated_by=merchant&stored_credential_indicator=used&initial_transaction_id=1234567890&billing_total=100.00&billing_number=1&amount=25.00… |
Response | …response=1&responsetext=Approved&transactionid=1234567891… |
Please Note: This transaction ID cannot be used for “unscheduled” or “recurring” card on file transactions.
Unscheduled Credential On File:
For payments that aren’t recurring or installment – there are unscheduled options as well.
The first customer initiated transaction will include these two items (no billing method):
Example 5: In this request, an initial unscheduled sale is sent and an approved transaction is returned in the response. Store this transaction for the follow up request.
Request | …type=sale&initiated_by=customer&stored_credential_indicator=stored… |
Response | …response=1&responsetext=Approved&transactionid=1234567890… |
The transaction ID can be used, without a billing method, for a customer initiated or merchant initiated transaction.
Please Note: The transaction ID cannot be used for a “recurring” or “installment” transaction.
Unscheduled, Customer Initiated: A card-absent transaction initiated by the cardholder where the cardholder does not need to enter their card details as the merchant uses the payment credential previously stored by the cardholder to perform the transaction. Examples include a transaction using customer’s merchant profile or digital wallet.
This is your typical shopping cart scenario where the customer checks out without having to re-enter their card details.
The follow up transaction(s) would include:
Example 6: In this request, a subsequent unscheduled sale is sent and an approved transaction is returned in the response.
Request | …type=sale&initiated_by=customer&stored_credential_indicator=used… |
Response | …response=1&responsetext=Approved&transactionid=1234567891… |
Unscheduled, Merchant Initiated: A transaction using a stored credential for a fixed or variable amount that does not occur on a scheduled or regularly occurring transaction date, where the cardholder has provided consent for the merchant to initiate one or more future transactions. An example of this transaction is an account auto-top up transaction.
An example of an account auto-top up would be a customer with an account with a balance. When that balance gets low, the customer’s card is charged automatically, without the customer’s involvement.
The follow up transaction(s) would include:
Example 7: In this request, a subsequent unscheduled sale is sent and an approved transaction is returned in the response.
Request | …type=sale&initiated_by=merchant&stored_credential_indicator=used&initial_transaction_id=1234567890… |
Response | …response=1&responsetext=Approved&transactionid=1234567892… |
Appendix 1: Recommend Further Reading:
If there is any question where a transaction type falls, we recommend reviewing the official card brand documentation. Visa’s guidelines are the most stringent, and generally if you follow those guidelines, you’ll also be compliant for MasterCard, American Express and Discover.
MasterCard:
https://www.mastercard.us/en-us/consumers/offers-promotions/credential-on-file-payments.html
Variable Name | Description |
---|---|
response |
1 = Transaction Approved 2 = Transaction Declined 3 = Error in transaction data or system error |
responsetext | Textual response |
authcode | Transaction authorization code. |
transactionid | Payment gateway transaction id. |
avsresponse | AVS response code (See Appendix 1). |
cvvresponse | CVV response code (See Appendix 2). |
orderid | The original order id passed in the transaction request. |
response_code | Numeric mapping of processor responses (See Appendix 3). |
emv_auth_response_data | This will optionally come back when any chip card data is provided on the authorization. This data needs to be sent back to the SDK after an authorization. |
Transactions can be tested using one of two methods. First, transactions can be submitted to any merchant account that is in test mode. Keep in mind that if an account is in test mode, all valid credit cards will be approved but no charges will actually be processed.
The Payment Gateway demo account can also be used for testing at any time. Please use the following security key for testing with this account:
security_key: | 6457Thfj624V5r7WUwc5v6a68Zsd6YEm |
Transaction details should be POST’ed to the following URL:
POST URL: | https://secure.apsmerchantgateway.com/api/transact.php |
Transactions can be submitted using the following information:
Visa: | 4111111111111111 |
MasterCard: | 5431111111111111 |
Discover: | 6011601160116611 |
American Express: | 341111111111111 |
Diner’s Club: | 30205252489926 |
JCB: | 3541963594572595 |
Maestro: | 6799990100000000019 |
Credit Card Expiration: | 10/25 |
account (ACH): | 123123123 |
routing (ACH): | 123123123 |
X | Exact match, 9-character numeric ZIP |
Y | Exact match, 5-character numeric ZIP |
D | Exact match, 5-character numeric ZIP |
M | Exact match, 5-character numeric ZIP |
2 | Exact match, 5-character numeric ZIP, customer name |
6 | Exact match, 5-character numeric ZIP, customer name |
A | Address match only |
B | Address match only |
3 | Address, customer name match only |
7 | Address, customer name match only |
W | 9-character numeric ZIP match only |
Z | 5-character ZIP match only |
P | 5-character ZIP match only |
L | 5-character ZIP match only |
1 | 5-character ZIP, customer name match only |
5 | 5-character ZIP, customer name match only |
N | No address or ZIP match only |
C | No address or ZIP match only |
4 | No address or ZIP or customer name match only |
8 | No address or ZIP or customer name match only |
U | Address unavailable |
G | Non-U.S. issuer does not participate |
I | Non-U.S. issuer does not participate |
R | Issuer system unavailable |
E | Not a mail/phone order |
S | Service not supported |
0 | AVS not available |
O | AVS not available |
B | AVS not available |
M | CVV2/CVC2 match |
N | CVV2/CVC2 no match |
P | Not processed |
S | Merchant has indicated that CVV2/CVC2 is not present on card |
U | Issuer is not certified and/or has not provided Visa encryption keys |
100 | Transaction was approved. |
200 | Transaction was declined by processor. |
201 | Do not honor. |
202 | Insufficient funds. |
203 | Over limit. |
204 | Transaction not allowed. |
220 | Incorrect payment information. |
221 | No such card issuer. |
222 | No card number on file with issuer. |
223 | Expired card. |
224 | Invalid expiration date. |
225 | Invalid card security code. |
226 | Invalid PIN. |
240 | Call issuer for further information. |
250 | Pick up card. |
251 | Lost card. |
252 | Stolen card. |
253 | Fraudulent card. |
260 | Declined with further instructions available. (See response text) |
261 | Declined-Stop all recurring payments. |
262 | Declined-Stop this recurring program. |
263 | Declined-Update cardholder data available. |
264 | Declined-Retry in a few days. |
300 | Transaction was rejected by gateway. |
400 | Transaction error returned by processor. |
410 | Invalid merchant configuration. |
411 | Merchant account is inactive. |
420 | Communication error. |
421 | Communication error with issuer. |
430 | Duplicate transaction at processor. |
440 | Processor format error. |
441 | Invalid transaction information. |
460 | Processor feature not available. |
461 | Unsupported card type. |
' ***** DISCLAIMER *****
' This code is to be used as an example and not in production.
' It lacks thorough testing and debugging. The Results below will be
' returned when posting against a gateway Test Account or an Active Account with Test Mode Enabled
GatewaySecurityKey = "[[Gateway Security Key Here]]"
' Returns True on Success, False on Failure
Function GatewaySale(amount, ccnumber, ccexp, cvv, name, address, zip)
Set OGateway = Server.CreateObject("MSXML2.ServerXMLHTTP")
OGateway.Open "POST", "https://secure.apsmerchantgateway.com/api/transact.php", false
OGateway.setRequestHeader "Content-Type", "application/x-www-form-urlencoded"
DataToSend = "security_key=" & Server.URLEncode(GatewaySecurityKey) &_
"&ccnumber=" & Server.URLEncode(ccnumber) &_
"&ccexp=" & Server.URLEncode(ccexp) &_
"&cvv=" & Server.URLEncode(cvv) &_
"&amount=" & Server.URLEncode(amount) &_
"&firstname=" & Server.URLEncode(name) &_
"&address1=" & Server.URLEncode(address) &_
"&zip=" & Server.URLEncode(zip)
OGateway.Send DataToSend
ResponseString = OGateway.responseText
Results = Split(ResponseString, "&")
GatewaySale = False
For Each i in Results
Result = Split(i,"=")
If UBound(Result)>0 Then
If LCase(Result(0))="response" Then
If Result(1) = "1" Then
GatewaySale = True
End If
End If
End If
Next
End Function
Results = GatewaySale("10.00","4111111111111111","0112","","John Smith","123 Main St", "60123")
Response.Write("This should be true: " & Results & "
")
Results = GatewaySale("0.99","4111111111111111","0112","","John Smith","123 Main St", "60123")
Response.Write("This should be false: " & Results & "
")
///###########################################################
///# #
///# D I S C L A I M E R #
///# #
///# WARNING: ANY USE BY YOU OF THE SAMPLE CODE PROVIDED #
///# IS AT YOUR OWN RISK. #
///# #
///# This code is provided "as is" without #
///# warranty of any kind, either express or implied, #
///# including but not limited to the implied warranties #
///# of merchantability and/or fitness for a particular #
///# purpose. #
///# #
///# #
///###########################################################
///###########################################################
///# #
///# Direct Post Transaction Submission Methodology #
///# #
///###########################################################
///# #
///# 1. You gather all the required transaction data on #
///# your secure web site. #
///# #
///# 2. The transaction data gets submitted (via HTTPS #
///# POST) to the gateway as one long string, consisting #
///# of specific name/value pairs. #
///# #
///# 3. When performing the HTTPS POST operation, you #
///# remain on the same web page from which you've #
///# performed the operation. #
///# #
///# 4. The Gateway immediately returns a transaction #
///# response string to the same web page from which you #
///# have performed the HTTPS POST operation. #
///# #
///# 5. You may then parse the response string and act #
///# upon certain response criteria, according to your #
///# business needs. #
///# #
///# #
///###########################################################
<%@ Import Namespace="System.Net" %>
<%@ Import Namespace="System.IO" %>
<script language="C#" runat="server">
void Page_Load(Object Src, EventArgs E) {
// Process readHtmlPage function
myPage.Text = readHtmlPage("https://secure.apsmerchantgateway.com/api/transact.php");
}
private String readHtmlPage(string url)
{
//setup some variables
String security_key = "6457Thfj624V5r7WUwc5v6a68Zsd6YEm";
String firstname = "John";
String lastname = "Smith";
String address1 = "1234 Main St.";
String city = "Chicago";
String state = "IL";
String zip = "60193";
//setup some variables end
String result = "";
String strPost = "security_key=" + security_key
+ "&firstname=" + firstname + "&lastname=" + lastname
+ "&address1=" + address1 + "&city=" + city + "&state=" + state
+ "&zip=" + zip + "&payment=creditcard&type=sale"
+ "&amount=1.00&ccnumber=4111111111111111&ccexp=1015&cvv=123";
StreamWriter myWriter = null;
HttpWebRequest objRequest = (HttpWebRequest)WebRequest.Create(url);
objRequest.Method = "POST";
objRequest.ContentLength = strPost.Length;
objRequest.ContentType = "application/x-www-form-urlencoded";
try
{
myWriter = new StreamWriter(objRequest.GetRequestStream());
myWriter.Write(strPost);
}
catch (Exception e)
{
return e.Message;
}
finally {
myWriter.Close();
}
HttpWebResponse objResponse = (HttpWebResponse)objRequest.GetResponse();
using (StreamReader sr =
new StreamReader(objResponse.GetResponseStream()) )
{
result = sr.ReadToEnd();
// Close and clean up the StreamReader
sr.Close();
}
return result;
}
</script>
<html>
<body>
<b>The content on this web page is the result of an HTTP POST operation to the Gateway, using the Direct Post method.<br>
<br/>
</b><hr/>
<asp:literal id="myPage" runat="server"/>
</body>
</html>
<CFLOCK Name="#session.sessionID#" timeout="10" Type ="Exclusive">
<CFPARAM NAME="session.status" Default="none">
<CFPARAM NAME="emsg" Default="A connection with the financial gateway failed.">
<CFSET oid = ''>
<CFSET em = 0>
<CFIF not IsDefined('URL.ccinterim')>
<CFSET em = 100>
<CFELSEIF not IsDefined('session.store')>
<CFSET em = 101>
<CFELSEIF not session.active>
<CFSET em = 102>
<CFELSEIF not session.store>
<CFSET em = 103>
<CFELSEIF #session.retry# gt 2>
<CFSET em = 400>
</CFIF>
<CFIF em gt 0>
<CFLOCATION URL="../Templates/process_error.cfm?#session.URLtoken#&em=#em#">
</CFIF>
<CFSET start = GetTickCount()>
<CFPARAM NAME="result" DEFAULT="false">
<CFPARAM NAME="com_error" DEFAULT="none">
<CFPARAM NAME="session.redirect" Default="x">
<CFPARAM NAME="session.status" Default="none">
<CFPARAM NAME="theactioncode" Default="">
<CFSET oid = session.ponumber>
<!--- fix date for 4 digits only now 09/09--->
<CFSET ccmonth = SpanExcluding(session.exprdate, '/')>
<CFSET ccyear = Mid(session.exprdate, 4, 2)>
<CFSET session.exprdate = '#ccmonth##ccyear#'>
<!--- the session.cvv value is set to a form default in ccinterim --->
<!--- the session order values come from paydirect and the cc values from ccinterim --->
<!--- Tax(default=0), shipping(default=0), and PO Number provide Level II processing --->
<CFHTTP url="https://secure.apsmerchantgateway.com/api/transact.php"
method="POST" resolveurl="yes" throwonerror="yes"
PATH="d:\html\users\cfxa2\zanaducom\html\Test\CardTech\" FILE="tempfile.txt">
<CFHTTPPARAM type="FORMFIELD" name="security_key" value="#session.TRNSKEY#">
<CFHTTPPARAM type="FORMFIELD" name="type" value="#session.TRNSTYPE#">
<CFHTTPPARAM type="FORMFIELD" name="amount" value="#session.ustotal#">
<CFHTTPPARAM type="FORMFIELD" name="ccnumber" value="#session.ccnumber#">
<CFHTTPPARAM type="FORMFIELD" name="ccexp" value="#session.exprdate#">
<CFHTTPPARAM type="FORMFIELD" name="address1" value="#session.ccaddress#">
<CFHTTPPARAM type="FORMFIELD" name="zip" value="#session.cczip#">
<CFHTTPPARAM type="FORMFIELD" name="orderid" value="#session.ponumber#">
<CFHTTPPARAM type="FORMFIELD" name="cvv" value="#session.cvv#">
<CFHTTPPARAM type="FORMFIELD" name="tax" value="#session.ustax#">
<CFHTTPPARAM type="FORMFIELD" name="shipping" value="#session.usshipping#">
<!---CFHTTPPARAM type="FORMFIELD" name="transactionid" value="#form.transid#"--->
</CFHTTP>
<!---CFSET result = cfhttp.filecontent would be the usual method of getting the
stored reply; however, when working in a shared server environment with ColdFusion,
the user may not have authorization to access this storage area and instead will
have to specify the full path within their domain for the file storage location
and again specify the path for a file read action. With multiple domains in a
sandbox environment, any of the domains can be used for saving the reply file. On
each transaction this file gets over written.--->
<CFFILE ACTION="read"
FILE="d:\html\users\cfxa2\zanaducom\html\Test\CardTech\tempfile.txt"
VARIABLE="result">
<CFIF IsDefined('result')>
<!--- create array of names and then loop to populate a query structure
called "crdck". Map mynames to Island names for standardization. If
this is a first time gateway setup, the mapping will not be necessary. Simply
parse the names and values.--->
<CFSET mystring = result>
<!--- CFSET mynames = "response,responsetext,authcode,transactionid,avsresponse,cvvresponse,orderid,type" --->
<!--- create arrays from the strings --->
<CFSET myarray = ListToArray(mystring, "&")>
<CFSET islandnames = "ActionCode,Status,AuthNumber,MerchantTransaction,AVSCode,CVVcode,OrderID,Referencecode">
<CFSET islandnamearray = ListToArray(islandnames, ",")>
<!--- create a new array called crdck and then populate it in a loop with the Island
names and the values. This is done to remain compatible with previous
instances of other gateways without having to change all of the downstream syntax. --->
<CFSET crdck = QueryNew(islandnames)>
<CFSET temp = QueryAddRow(crdck)>
<!--- loop to populate array with desired names (island names) and values --->
<CFLOOP INDEX="k" FROM="1" TO="#ArrayLen(myarray)#">
<CFSET sz = Len(myarray[k])>
<CFSET m = FindNoCase("=", myarray[k], 1)>
<CFIF m is 0><!--- create dummy value in case the = sign not found --->
<CFSET temp = QuerySetCell(crdck, islandnamearray[k], "xxx")>
<CFELSE>
<CFSET n = Find("=", myarray[k], m+sz)>
<CFSET avalue = Mid(myarray[k], m+1, sz)>
<CFSET temp = QuerySetCell(crdck, islandnamearray[k], avalue)>
</CFIF>
<CFIF #k# gt 20><CFBREAK></CFIF><!--- prevent an endless loop for any reason --->
</CFLOOP>
</CFIF>
<CFIF IsDefined('crdck.Actioncode')>
<CFSET theactioncode = crdck.Actioncode>
<!--- this call will timeout based on server configuration --->
<CFSET thedate = DateFormat(now(), 'mm/dd/yy')>
<!--- some mapping is required because CardTech gateway uses their Responsetext
field, our STATUS field, for both status and error messages. --->
<!--- In our database STATUS is a short advisory to the merchant on the order
summary page. Their 'response' is our actioncode--->
<CFSET thestatus = crdck.Actioncode>
<CFIF thestatus eq 1>
<CFSET thestatus = 'auth-settle::1'>
<CFELSEIF thestatus eq 2>
<CFSET thestatus = 'retry-auth(credit)::2'>
<CFELSEIF thestatus eq 3>
<CFSET thestatus = 'retry-auth(data)::3'>
<CFELSEIF thestatus eq "">
<CFSET thestatus = 'retry-auth(comm)::'>
</CFIF>
<!--- A short statement for the 'trnsmsg' on the order detail page. CardTech
returns 'success' in their responsetext field when actioncode=1 --->
<CFSET msg = crdck.status>
<CFIF crdck.Actioncode is not 1>
<CFSET msg = 'declined'>
</CFIF>
<!--- CardTech Responsetext(our status) is a message which is mapped to our
error message when 'success' (CardTech actioncode is not equal to 1)is not
returned. The emsg(error message) is for the customer and order detail page. --->
<CFSET emsg = crdck.status>
<CFIF crdck.Actioncode is 1>
<CFSET emsg = 'no-error'>
</CFIF>
<!--- zero lenth not allowed in database table entry --->
<CFSET oid = crdck.OrderID>
<CFIF #Len(oid)# is 0>
<CFSET oid = #session.ponumber#>
</CFIF>
<CFSET avs = crdck.AVSCode>
<CFIF Len(avs) is 0>
<CFSET avs = 'no return'>
</CFIF>
<CFSET cvv = crdck.CVVCode>
<CFIF Len(cvv) is 0>
<CFSET cvv = 'no return'>
</CFIF>
<CFSET authnum = crdck.AuthNumber>
<CFIF Len(authnum) is 0>
<CFSET authnum = 'xxx'>
</CFIF>
<CFSET trnsmsg = '#authnum#::#msg#::#crdck.ActionCode#'>
<CFSET trnsid = '#crdck.MerchantTransaction#::#crdck.ReferenceCode#'>
<CFQUERY NAME="logpayment" DATASOURCE="#application.ordersDSN#">
UPDATE #session.table#
SET TRNSMSG = '#trnsmsg#',<!--- this is RESULT entry on order detail page --->
STATUS = '#thestatus#',
AVS = '#avs#',
TRNSRSV = '#cvv#',
ERRORMSG = '#emsg#',
TRANSID = '#trnsid#' <!--- this is Authorize ID on order detail page --->
WHERE
PONUMBER = '#oid#'
</CFQUERY>
<CFSET session.retry = session.retry +1>
<CFSET end = GetTickCount()>
<CFSET session.duration = evaluate((end - session.start)/1000)>
<CFIF crdck.Actioncode is 1>
<CFLOCATION URL = "../Templates/cc_good.cfm?#session.URLToken#&ccon=1">
<CFELSEIF crdck.Actioncode is 2>
<CFSET em = 401>
<CFLOCATION URL="../Templates/process_error.cfm?#session.URLToken#&em=#em#&emsg=#emsg#">
<CFELSEIF crdck.ActionCode is 3 AND FindNoCase('expiration', emsg,1) gt 0>
<CFSET em = 402>
<CFLOCATION URL="../Templates/process_error.cfm?#session.URLToken#&em=#em#&emsg=#emsg#">
<CFELSEIF crdck.ActionCode is 3 AND FindNoCase('invalid', emsg,1) gt 0>
<CFSET em = 405>
<CFLOCATION URL="../Templates/process_error.cfm?#session.URLToken#&em=#em#&emsg=#emsg#">
<CFELSEIF crdck.ActionCode is 3>
<CFSET em = 404>
<CFLOCATION URL="../Templates/process_error.cfm?#session.URLToken#&em=#em#&emsg=#emsg#">
</CFIF>
</CFIF><!--- end of crdck.actioncode defined --->
<CFIF theactioncode is ""><!--- from the default value modified by crdck.actioncode --->
<CFSET em = 406>
<CFLOCATION URL="../Templates/process_error.cfm?#session.URLToken#&em=#em#&emsg=""">
</CFIF>
</CFLOCK>
<DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html><head><title>ColdFusion test</title>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<meta http-equiv="Expires" content="Mon,23 Sept 1998 00:00:00 GMT">
<meta name='description' content=''>
<meta name='keywords' content=''>
<meta name='author' content='ImagineNation'>
<meta name='url' content='http://www.ImagineNation.com'>
<!--- COPYRIGHT:===============================================
Any commercial use or duplication, in part or in whole, of this
copyright material without prior licensing is forbidden by
federal law. Violators may be subject to civil and/or criminal
penalties, (Title 17, Sections 501 and 506).
========================================================== --->
<!-- script language="JavaScript1.1" src="whatever.js" type="text/javascript" -->
<script language="JavaScript1.1" type="text/javascript">
//<!-- ==========================Hide SCRIPT=============================
//onError = null
//===============================The End============================= -->
</script>
<style>
body{background-color:#cadaca; margin: 5px 0px 0px 5px;
font-family:verdana; font-size:12pt; font-weight:bold; color:#000000;
}
.toptable{background-color:#daeaca; font-family:Verdana; font-size:10pt;
font-weight:bold; color:#000000; padding:10px; width:350px; height:150px;
border-width:2px; border-color:#b07050; border-style:solid; float:left;
display:inline;
}
.cr{color:#000000; font-family:Ariel; font-size:8pt;
font-weight:normal; font-style:italic;
}
</style>
</head>
<body>
<h4>HTML Test File<br>
Submits to the ColdFusion process.cfm File</h4>
<div class="toptable" align="right">
The names in parenthesis are the processing names which are
populated with values in the form fields. The security key allows for
test transactions on the gateway.<br>
<form name="testtrans" action="process.cfm" method="post">
security_key: <input type="text" name="security_key" size=32 value="6457Thfj624V5r7WUwc5v6a68Zsd6YEm"><br>
amount: <input type="text" name="amount" size=20 value="2.00"><br>
transtype: <input type="text" name="transtype" size=20 value="auth"><br>
ccnumber: <input type="text" name="ccnumber" size=20 value="4111111111111111"><br>
ccexp: <input type="text" name="ccexp" size=20 value="0407"><br>
address1: <input type="text" name="ccaddress" size=20 value="20 demo lane"><br>
zip: <input type="text" name="cczip" size=20 value="20123"><br>
cvv: <input type="text" name="cvv" size=20 value="444"><br>
orderid: <input type="text" name="orderid" size=20 value="UM12345678"><br>
tax: <input type="text" name="tax" size=20 value="1.20"><br>
transid: <input type="text" name="transid" size=20 value=""><br>
<input type="submit" value=" SUBMIT ">
</form><br>
Transid is the transaction ID number returned and the number that must be used
to capture an authorization or make a return.
</div>
<center class="cr">
<p> <p><a href="http://ImagineNation.com" target="_blank">ImagineNation</a><br>© 1996 - 2006
</center>
</body></html>
<!--- It is advisable to run this file in a managed application with a lock on
the session to avoid interference from some other operation while waiting for
the return information. --->
<CFLOCK Name="testfiles" timeout="10" Type ="Exclusive">
<CFSET begin =GetTickCount()>
<!--- These default values are provided to prevent errors of omission. --->
<CFPARAM NAME="form.security_key" DEFAULT="xx">
<CFPARAM NAME="form.amount" DEFAULT="xx">
<CFPARAM NAME="form.transtype" DEFAULT="xx">
<CFPARAM NAME="form.ccnumber" DEFAULT="xx">
<CFPARAM NAME="form.ccexp" DEFAULT="xx">
<CFPARAM NAME="form.ccaddress" DEFAULT="xx">
<CFPARAM NAME="form.cczip" DEFAULT="xx">
<CFPARAM NAME="form.orderid" DEFAULT="xx">
<CFPARAM NAME="form.ccv" DEFAULT="">
<CFPARAM NAME="form.tax" DEFAULT="0.75">
<CFPARAM NAME="form.transid" DEFAULT="">
<CFPARAM NAME="result" DEFAULT="xx">
<!--- CFSET result = cfhttp.filecontent would be the usual method of getting the
stored reply from a post action without specifying a path; however, when working
in a shared server environment with ColdFusion, the user may not have authorization
to access this storage area and instead will have to specify the full path within
their own domain for the file storage location and again specify the same path for
a file read action. With multiple domains in a sandbox environment, any of the
domains can be used for saving the reply file. On each transaction this file gets
over written. The example below is specific to ImagineNation and must be changed
for your own testing.--->
<!--- This is the post to the gateway server. --->
<cfhttp url="https://secure.apsmerchantgateway.com/api/transact.php"
method="POST" resolveurl="yes" throwonerror="yes"
PATH="d:\html\users\cfxa2\zanaducom\html\Test\CardTech\" FILE="tempfile.txt">
<cfhttpparam type="FORMFIELD" name="security_key" value="#form.security_key#">
<cfhttpparam type="FORMFIELD" name="amount" value="#form.Amount#">
<cfhttpparam type="FORMFIELD" name="type" value="#form.transtype#">
<cfhttpparam type="FORMFIELD" name="ccnumber" value="#form.CCNumber#">
<cfhttpparam type="FORMFIELD" name="ccexp" value="#form.CCExp#">
<cfhttpparam type="FORMFIELD" name="address1" value="#form.ccaddress#">
<cfhttpparam type="FORMFIELD" name="zip" value="#form.cczip#">
<cfhttpparam type="FORMFIELD" name="orderid" value="#form.orderid#">
<cfhttpparam type="FORMFIELD" name="cvv" value="#form.cvv#">
<cfhttpparam type="FORMFIELD" name="tax" value="#form.tax#">
<cfhttpparam type="FORMFIELD" name="transactionid" value="#form.transid#">
</CFHTTP>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html><head><title>ImagineNation: ColdFusion process</title>
<style>
body{background-color:#cadaca; margin: 5px 0px 0px 5px;
font-family:verdana; font-size:12pt; font-weight:bold; color:#000000;
}
.toptable{background-color:#daeaca; font-family:Verdana; font-size:10pt;
font-weight:bold; color:#000000; padding:10px; width:350px; height:150px;
border-width:2px; border-color:#b07050; border-style:solid; float:left;
display:inline;
}
.cr{color:#000000; font-family:Ariel; font-size:8pt;
font-weight:normal; font-style:italic;
}
</style>
</head>
<body>
<h4>Transaction results appear here.</h4>
<CFFILE ACTION="read"
FILE="d:\html\users\cfxa2\zanaducom\html\Test\CardTech\tempfile.txt"
VARIABLE="result">
<CFOUTPUT>
<CFIF IsDefined('result')>
<b>The returned string is:<br>
<font size="-1">#result#</font></b>
<CFELSE>
<b>
No return found</b>
</CFIF>
<div class="toptable">
The string can be converted to an array of name/value pairs by splitting on the "&" sign.<br><br>
<CFSET responsearray = ListToArray(result, "&")>
The array length is #ArrayLen(responsearray)#
<br><br>
The returned array values are:<br><br>
<CFLOOP INDEX="k" FROM="1" TO="#ArrayLen(responsearray)#">
#responsearray[k]#<br>
<CFIF #k# gt 20><CFBREAK></CFIF><!--- prevent an endless loop for any reason --->
</CFLOOP>
</CFOUTPUT><br><br>
If this was a type=auth transaction, you can return to the <a href="mytest.htm">
form page</a> and enter the transaction id and change type to capture to test
the capture mode.
</div>
<CFOUTPUT>
<p><CFSET end =GetTickCount()>
process duration = #Evaluate((end-begin)/1000)# seconds
</CFOUTPUT>
</CFLOCK>
<center class="cr">
<p> <p><a href="http://ImagineNation.com" target="_blank">ImagineNation</a><br>© 1996 - 2006
</center>
</body></html>
import java.util.*;
import java.io.*;
import java.net.*;
import java.security.*;
import java.text.*;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLSession;
class PaymentGateway {
protected String server;
protected String port;
protected String path;
protected String security_key;
public PaymentGateway(String key)
{
server = "secure.apsmerchantgateway.com";
port = "443";
path = "https://secure.apsmerchantgateway.com/api/transact.php";
security_key = key;
}
public HashMap doSale( double amount,
String ccNumber,
String ccExp
) throws Exception
{
HashMap result = new HashMap();
HashMap request = new HashMap();
DecimalFormat form = new DecimalFormat("#.00");
request.put("amount", form.format(amount));
request.put("type", "sale");
request.put("ccnumber", ccNumber);
request.put("ccexp", ccExp);
String data_out = prepareRequest(request);
String error = "";
String data_in = "";
boolean success = true;
try {
HashMap retval = postForm(data_out);
data_in = (String)retval.get("response");
result.put("transactionid", retval.get("transactionid"));
} catch (IOException e) {
success = false;
error = "Connect error, " + e.getMessage();
} catch (Exception e) {
success = false;
error = e.getMessage();
}
if (!success) {
throw new Exception(error);
}
return result;
}
// Utility Functions
public String prepareRequest(HashMap request) {
if (request.size() == 0) {
return "";
}
request.put("security_key", security_key);
Set s = request.keySet();
Iterator i = s.iterator();
Object key = i.next();
StringBuffer buffer = new StringBuffer();
buffer.append(key).append("=")
.append(URLEncoder.encode((String) request.get(key)));
while (i.hasNext()) {
key = i.next();
buffer.append("&").append(key).append("=")
.append(URLEncoder.encode((String) request.get(key)));
}
return buffer.toString();
}
protected HashMap postForm(String data) throws Exception {
HashMap result = new HashMap();
HttpURLConnection postConn;
HostnameVerifier hv = new HostnameVerifier() {
public boolean verify(String urlHostName, SSLSession session) {
return true;
}
};
HttpsURLConnection.setDefaultHostnameVerifier(hv);
URL post = new URL("https", server, Integer.parseInt(port), path);
postConn = (HttpURLConnection)post.openConnection();
postConn.setRequestMethod("POST");
postConn.setDoOutput(true);
PrintWriter out = new PrintWriter(postConn.getOutputStream());
out.print(data);
out.close();
BufferedReader in =
new BufferedReader(new InputStreamReader(postConn.getInputStream()));
String inputLine;
StringBuffer buffer = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
buffer.append(inputLine);
}
in.close();
String response = buffer.toString();
result.put("response", response);
// Parse Result
StringTokenizer st = new StringTokenizer(response, "&");
while (st.hasMoreTokens()) {
String varString = st.nextToken();
StringTokenizer varSt = new StringTokenizer(varString, "=");
if (varSt.countTokens() > 2 || varSt.countTokens()<1) {
throw new Exception("Bad variable from processor center: " + varString);
}
if (varSt.countTokens()==1) {
result.put(varSt.nextToken(), "");
} else {
result.put(varSt.nextToken(), varSt.nextToken());
}
}
if (result.get("response")=="") {
throw new Exception("Bad response from processor center" + response);
}
if (!result.get("response").toString().equals("1")) {
throw new Exception(result.get("responsetext").toString());
}
return result;
}
}
public class TestPaymentGateway
{
public static void main(String arg[])
{
HashMap retval = new HashMap();
PaymentGateway gw = new PaymentGateway("6457Thfj624V5r7WUwc5v6a68Zsd6YEm");
try {
retval = gw.doSale(10.05, "4111111111111111", "0909");
System.out.println("Success\nTransId: " + retval.get("transactionid") + "\n");
} catch (Exception e) {
System.out.println("Error: " + e.getMessage());
}
}
}
const https = require('https');
const querystring = require('querystring');
class DirectPost {
constructor(security_key) {
this.security_key = security_key;
}
setBilling(billingInformation) {
// Validate that passed in information contains valid keys
const validBillingKeys = ['first_name', 'last_name', 'company', 'address1',
'address2', 'city', 'state', 'zip', 'country', 'phone', 'fax', 'email'];
for (let key in billingInformation) {
if (!validBillingKeys.includes(key)) {
throw new Error(`Invalid key provided in billingInformation. '${key}'
is not a valid billing parameter.`)
}
};
this.billing = billingInformation;
}
setShipping(shippingInformation) {
// Validate that passed in information contains valid keys
const validShippingKeys = [
'shipping_first_name', 'shipping_last_name', 'shipping_company',
'shipping_address1', 'address2', 'shipping_city', 'shipping_state',
'shipping_zip', 'shipping_country', 'shipping_email'
];
for (let key in shippingInformation) {
if (!validShippingKeys.includes(key)) {
throw new Error(`Invalid key provided in shippingInformation. '${key}'
is not a valid shipping parameter.`)
}
};
this.shipping = shippingInformation;
}
doSale(amount, ccNum, ccExp, cvv) {
let requestOptions = {
'type': 'sale',
'amount': amount,
'ccnumber': ccNum,
'ccexp': ccExp,
'cvv': cvv
};
// Merge together all request options into one object
Object.assign(requestOptions, this.billing, this.shipping);
// Make request
this._doRequest(requestOptions);
}
_doRequest(postData) {
const hostName = 'secure.apsmerchantgateway.com';
const path = '/api/transact.php';
postData.security_key = this.security_key;
postData = querystring.stringify(postData);
const options = {
hostname: hostName,
path: path,
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': Buffer.byteLength(postData)
}
};
// Make request to Direct Post API
const req = https.request(options, (response) => {
console.log(`STATUS: ${response.statusCode}`);
console.log(`HEADERS: ${JSON.stringify(response.headers)}`);
response.on('data', (chunk) => {
console.log(`BODY: ${chunk}`);
});
response.on('end', () => {
console.log('No more data in response.');
});
});
req.on('error', (e) => {
console.error(`Problem with request: ${e.message}`);
});
// Write post data to request body
req.write(postData);
req.end();
}
}
const dp = new DirectPost('{security_key}');
const billingInfo = {
'first_name': 'Test',
'last_name': 'User',
'address1': '123 Main St',
'city': 'New York',
'state': 'NY',
'zip' : '12345',
}
const shippingInfo = {
'shipping_first_name': 'User',
'shipping_last_name': 'Test',
'shipping_address1': '987 State St',
'shipping_city': 'Los Angeles',
'shipping_state': 'CA',
'shipping_zip' : '98765',
}
dp.setBilling(billingInfo);
dp.setShipping(shippingInfo);
// Set dummy data for sale
dp.doSale('100.00', '4111111111111111', '1221', '123');
define("APPROVED", 1);
define("DECLINED", 2);
define("ERROR", 3);
class gwapi {
// Initial Setting Functions
function setLogin($security_key) {
$this->login['security_key'] = $security_key;
}
function setOrder($orderid,
$orderdescription,
$tax,
$shipping,
$ponumber,
$ipaddress) {
$this->order['orderid'] = $orderid;
$this->order['orderdescription'] = $orderdescription;
$this->order['tax'] = $tax;
$this->order['shipping'] = $shipping;
$this->order['ponumber'] = $ponumber;
$this->order['ipaddress'] = $ipaddress;
}
function setBilling($firstname,
$lastname,
$company,
$address1,
$address2,
$city,
$state,
$zip,
$country,
$phone,
$fax,
$email,
$website) {
$this->billing['firstname'] = $firstname;
$this->billing['lastname'] = $lastname;
$this->billing['company'] = $company;
$this->billing['address1'] = $address1;
$this->billing['address2'] = $address2;
$this->billing['city'] = $city;
$this->billing['state'] = $state;
$this->billing['zip'] = $zip;
$this->billing['country'] = $country;
$this->billing['phone'] = $phone;
$this->billing['fax'] = $fax;
$this->billing['email'] = $email;
$this->billing['website'] = $website;
}
function setShipping($firstname,
$lastname,
$company,
$address1,
$address2,
$city,
$state,
$zip,
$country,
$email) {
$this->shipping['firstname'] = $firstname;
$this->shipping['lastname'] = $lastname;
$this->shipping['company'] = $company;
$this->shipping['address1'] = $address1;
$this->shipping['address2'] = $address2;
$this->shipping['city'] = $city;
$this->shipping['state'] = $state;
$this->shipping['zip'] = $zip;
$this->shipping['country'] = $country;
$this->shipping['email'] = $email;
}
// Transaction Functions
function doSale($amount, $ccnumber, $ccexp, $cvv="") {
$query = "";
// Login Information
$query .= "security_key=" . urlencode($this->login['security_key']) . "&";
// Sales Information
$query .= "ccnumber=" . urlencode($ccnumber) . "&";
$query .= "ccexp=" . urlencode($ccexp) . "&";
$query .= "amount=" . urlencode(number_format($amount,2,".","")) . "&";
$query .= "cvv=" . urlencode($cvv) . "&";
// Order Information
$query .= "ipaddress=" . urlencode($this->order['ipaddress']) . "&";
$query .= "orderid=" . urlencode($this->order['orderid']) . "&";
$query .= "orderdescription=" . urlencode($this->order['orderdescription']) . "&";
$query .= "tax=" . urlencode(number_format($this->order['tax'],2,".","")) . "&";
$query .= "shipping=" . urlencode(number_format($this->order['shipping'],2,".","")) . "&";
$query .= "ponumber=" . urlencode($this->order['ponumber']) . "&";
// Billing Information
$query .= "firstname=" . urlencode($this->billing['firstname']) . "&";
$query .= "lastname=" . urlencode($this->billing['lastname']) . "&";
$query .= "company=" . urlencode($this->billing['company']) . "&";
$query .= "address1=" . urlencode($this->billing['address1']) . "&";
$query .= "address2=" . urlencode($this->billing['address2']) . "&";
$query .= "city=" . urlencode($this->billing['city']) . "&";
$query .= "state=" . urlencode($this->billing['state']) . "&";
$query .= "zip=" . urlencode($this->billing['zip']) . "&";
$query .= "country=" . urlencode($this->billing['country']) . "&";
$query .= "phone=" . urlencode($this->billing['phone']) . "&";
$query .= "fax=" . urlencode($this->billing['fax']) . "&";
$query .= "email=" . urlencode($this->billing['email']) . "&";
$query .= "website=" . urlencode($this->billing['website']) . "&";
// Shipping Information
$query .= "shipping_firstname=" . urlencode($this->shipping['firstname']) . "&";
$query .= "shipping_lastname=" . urlencode($this->shipping['lastname']) . "&";
$query .= "shipping_company=" . urlencode($this->shipping['company']) . "&";
$query .= "shipping_address1=" . urlencode($this->shipping['address1']) . "&";
$query .= "shipping_address2=" . urlencode($this->shipping['address2']) . "&";
$query .= "shipping_city=" . urlencode($this->shipping['city']) . "&";
$query .= "shipping_state=" . urlencode($this->shipping['state']) . "&";
$query .= "shipping_zip=" . urlencode($this->shipping['zip']) . "&";
$query .= "shipping_country=" . urlencode($this->shipping['country']) . "&";
$query .= "shipping_email=" . urlencode($this->shipping['email']) . "&";
$query .= "type=sale";
return $this->_doPost($query);
}
function doAuth($amount, $ccnumber, $ccexp, $cvv="") {
$query = "";
// Login Information
$query .= "security_key=" . urlencode($this->login['security_key']) . "&";
// Sales Information
$query .= "ccnumber=" . urlencode($ccnumber) . "&";
$query .= "ccexp=" . urlencode($ccexp) . "&";
$query .= "amount=" . urlencode(number_format($amount,2,".","")) . "&";
$query .= "cvv=" . urlencode($cvv) . "&";
// Order Information
$query .= "ipaddress=" . urlencode($this->order['ipaddress']) . "&";
$query .= "orderid=" . urlencode($this->order['orderid']) . "&";
$query .= "orderdescription=" . urlencode($this->order['orderdescription']) . "&";
$query .= "tax=" . urlencode(number_format($this->order['tax'],2,".","")) . "&";
$query .= "shipping=" . urlencode(number_format($this->order['shipping'],2,".","")) . "&";
$query .= "ponumber=" . urlencode($this->order['ponumber']) . "&";
// Billing Information
$query .= "firstname=" . urlencode($this->billing['firstname']) . "&";
$query .= "lastname=" . urlencode($this->billing['lastname']) . "&";
$query .= "company=" . urlencode($this->billing['company']) . "&";
$query .= "address1=" . urlencode($this->billing['address1']) . "&";
$query .= "address2=" . urlencode($this->billing['address2']) . "&";
$query .= "city=" . urlencode($this->billing['city']) . "&";
$query .= "state=" . urlencode($this->billing['state']) . "&";
$query .= "zip=" . urlencode($this->billing['zip']) . "&";
$query .= "country=" . urlencode($this->billing['country']) . "&";
$query .= "phone=" . urlencode($this->billing['phone']) . "&";
$query .= "fax=" . urlencode($this->billing['fax']) . "&";
$query .= "email=" . urlencode($this->billing['email']) . "&";
$query .= "website=" . urlencode($this->billing['website']) . "&";
// Shipping Information
$query .= "shipping_firstname=" . urlencode($this->shipping['firstname']) . "&";
$query .= "shipping_lastname=" . urlencode($this->shipping['lastname']) . "&";
$query .= "shipping_company=" . urlencode($this->shipping['company']) . "&";
$query .= "shipping_address1=" . urlencode($this->shipping['address1']) . "&";
$query .= "shipping_address2=" . urlencode($this->shipping['address2']) . "&";
$query .= "shipping_city=" . urlencode($this->shipping['city']) . "&";
$query .= "shipping_state=" . urlencode($this->shipping['state']) . "&";
$query .= "shipping_zip=" . urlencode($this->shipping['zip']) . "&";
$query .= "shipping_country=" . urlencode($this->shipping['country']) . "&";
$query .= "shipping_email=" . urlencode($this->shipping['email']) . "&";
$query .= "type=auth";
return $this->_doPost($query);
}
function doCredit($amount, $ccnumber, $ccexp) {
$query = "";
// Login Information
$query .= "security_key=" . urlencode($this->login['security_key']) . "&";
// Sales Information
$query .= "ccnumber=" . urlencode($ccnumber) . "&";
$query .= "ccexp=" . urlencode($ccexp) . "&";
$query .= "amount=" . urlencode(number_format($amount,2,".","")) . "&";
// Order Information
$query .= "ipaddress=" . urlencode($this->order['ipaddress']) . "&";
$query .= "orderid=" . urlencode($this->order['orderid']) . "&";
$query .= "orderdescription=" . urlencode($this->order['orderdescription']) . "&";
$query .= "tax=" . urlencode(number_format($this->order['tax'],2,".","")) . "&";
$query .= "shipping=" . urlencode(number_format($this->order['shipping'],2,".","")) . "&";
$query .= "ponumber=" . urlencode($this->order['ponumber']) . "&";
// Billing Information
$query .= "firstname=" . urlencode($this->billing['firstname']) . "&";
$query .= "lastname=" . urlencode($this->billing['lastname']) . "&";
$query .= "company=" . urlencode($this->billing['company']) . "&";
$query .= "address1=" . urlencode($this->billing['address1']) . "&";
$query .= "address2=" . urlencode($this->billing['address2']) . "&";
$query .= "city=" . urlencode($this->billing['city']) . "&";
$query .= "state=" . urlencode($this->billing['state']) . "&";
$query .= "zip=" . urlencode($this->billing['zip']) . "&";
$query .= "country=" . urlencode($this->billing['country']) . "&";
$query .= "phone=" . urlencode($this->billing['phone']) . "&";
$query .= "fax=" . urlencode($this->billing['fax']) . "&";
$query .= "email=" . urlencode($this->billing['email']) . "&";
$query .= "website=" . urlencode($this->billing['website']) . "&";
$query .= "type=credit";
return $this->_doPost($query);
}
function doOffline($authorizationcode, $amount, $ccnumber, $ccexp) {
$query = "";
// Login Information
$query .= "security_key=" . urlencode($this->login['security_key']) . "&";
// Sales Information
$query .= "ccnumber=" . urlencode($ccnumber) . "&";
$query .= "ccexp=" . urlencode($ccexp) . "&";
$query .= "amount=" . urlencode(number_format($amount,2,".","")) . "&";
$query .= "authorizationcode=" . urlencode($authorizationcode) . "&";
// Order Information
$query .= "ipaddress=" . urlencode($this->order['ipaddress']) . "&";
$query .= "orderid=" . urlencode($this->order['orderid']) . "&";
$query .= "orderdescription=" . urlencode($this->order['orderdescription']) . "&";
$query .= "tax=" . urlencode(number_format($this->order['tax'],2,".","")) . "&";
$query .= "shipping=" . urlencode(number_format($this->order['shipping'],2,".","")) . "&";
$query .= "ponumber=" . urlencode($this->order['ponumber']) . "&";
// Billing Information
$query .= "firstname=" . urlencode($this->billing['firstname']) . "&";
$query .= "lastname=" . urlencode($this->billing['lastname']) . "&";
$query .= "company=" . urlencode($this->billing['company']) . "&";
$query .= "address1=" . urlencode($this->billing['address1']) . "&";
$query .= "address2=" . urlencode($this->billing['address2']) . "&";
$query .= "city=" . urlencode($this->billing['city']) . "&";
$query .= "state=" . urlencode($this->billing['state']) . "&";
$query .= "zip=" . urlencode($this->billing['zip']) . "&";
$query .= "country=" . urlencode($this->billing['country']) . "&";
$query .= "phone=" . urlencode($this->billing['phone']) . "&";
$query .= "fax=" . urlencode($this->billing['fax']) . "&";
$query .= "email=" . urlencode($this->billing['email']) . "&";
$query .= "website=" . urlencode($this->billing['website']) . "&";
// Shipping Information
$query .= "shipping_firstname=" . urlencode($this->shipping['firstname']) . "&";
$query .= "shipping_lastname=" . urlencode($this->shipping['lastname']) . "&";
$query .= "shipping_company=" . urlencode($this->shipping['company']) . "&";
$query .= "shipping_address1=" . urlencode($this->shipping['address1']) . "&";
$query .= "shipping_address2=" . urlencode($this->shipping['address2']) . "&";
$query .= "shipping_city=" . urlencode($this->shipping['city']) . "&";
$query .= "shipping_state=" . urlencode($this->shipping['state']) . "&";
$query .= "shipping_zip=" . urlencode($this->shipping['zip']) . "&";
$query .= "shipping_country=" . urlencode($this->shipping['country']) . "&";
$query .= "shipping_email=" . urlencode($this->shipping['email']) . "&";
$query .= "type=offline";
return $this->_doPost($query);
}
function doCapture($transactionid, $amount =0) {
$query = "";
// Login Information
$query .= "security_key=" . urlencode($this->login['security_key']) . "&";
// Transaction Information
$query .= "transactionid=" . urlencode($transactionid) . "&";
if ($amount>0) {
$query .= "amount=" . urlencode(number_format($amount,2,".","")) . "&";
}
$query .= "type=capture";
return $this->_doPost($query);
}
function doVoid($transactionid) {
$query = "";
// Login Information
$query .= "security_key=" . urlencode($this->login['security_key']) . "&";
// Transaction Information
$query .= "transactionid=" . urlencode($transactionid) . "&";
$query .= "type=void";
return $this->_doPost($query);
}
function doRefund($transactionid, $amount = 0) {
$query = "";
// Login Information
$query .= "security_key=" . urlencode($this->login['security_key']) . "&";
// Transaction Information
$query .= "transactionid=" . urlencode($transactionid) . "&";
if ($amount>0) {
$query .= "amount=" . urlencode(number_format($amount,2,".","")) . "&";
}
$query .= "type=refund";
return $this->_doPost($query);
}
function _doPost($query) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://secure.apsmerchantgateway.com/api/transact.php");
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30);
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($ch, CURLOPT_POSTFIELDS, $query);
curl_setopt($ch, CURLOPT_POST, 1);
if (!($data = curl_exec($ch))) {
return ERROR;
}
curl_close($ch);
unset($ch);
print "\n$data\n";
$data = explode("&",$data);
for($i=0;$i<count($data);$i++) {
$rdata = explode("=",$data[$i]);
$this->responses[$rdata[0]] = $rdata[1];
}
return $this->responses['response'];
}
}
$gw = new gwapi;
$gw->setLogin("6457Thfj624V5r7WUwc5v6a68Zsd6YEm");
$gw->setBilling("John","Smith","Acme, Inc.","123 Main St","Suite 200", "Beverly Hills",
"CA","90210","US","555-555-5555","555-555-5556","support@example.com",
"www.example.com");
$gw->setShipping("Mary","Smith","na","124 Shipping Main St","Suite Ship", "Beverly Hills",
"CA","90210","US","support@example.com");
$gw->setOrder("1234","Big Order",1, 2, "PO1234","65.192.14.10");
$r = $gw->doSale("50.00","4111111111111111","1010");
print $gw->responses['responsetext'];
###########################################################
# #
# D I S C L A I M E R #
# #
# WARNING: ANY USE BY YOU OF THE SAMPLE CODE PROVIDED #
# IS AT YOUR OWN RISK. #
# #
# The code is provided "as is" without #
# warranty of any kind, either express or implied, #
# including but not limited to the implied warranties #
# of merchantability and/or fitness for a particular #
# purpose. #
# #
# #
###########################################################
import pycurl
import urllib
import urlparse
import StringIO
class gwapi():
def __init__(self):
self.login= dict()
self.order = dict()
self.billing = dict()
self.shipping = dict()
self.responses = dict()
def setLogin(self,security_key):
self.login['security_key'] = security_key
def setOrder(self, orderid, orderdescription, tax, shipping, ponumber,ipadress):
self.order['orderid'] = orderid;
self.order['orderdescription'] = orderdescription
self.order['shipping'] = '{0:.2f}'.format(float(shipping))
self.order['ipaddress'] = ipadress
self.order['tax'] = '{0:.2f}'.format(float(tax))
self.order['ponumber'] = ponumber
def setBilling(self,
firstname,
lastname,
company,
address1,
address2,
city,
state,
zip,
country,
phone,
fax,
email,
website):
self.billing['firstname'] = firstname
self.billing['lastname'] = lastname
self.billing['company'] = company
self.billing['address1'] = address1
self.billing['address2'] = address2
self.billing['city'] = city
self.billing['state'] = state
self.billing['zip'] = zip
self.billing['country'] = country
self.billing['phone'] = phone
self.billing['fax'] = fax
self.billing['email'] = email
self.billing['website'] = website
def setShipping(self,firstname,
lastname,
company,
address1,
address2,
city,
state,
zipcode,
country,
email):
self.shipping['firstname'] = firstname
self.shipping['lastname'] = lastname
self.shipping['company'] = company
self.shipping['address1'] = address1
self.shipping['address2'] = address2
self.shipping['city'] = city
self.shipping['state'] = state
self.shipping['zip'] = zipcode
self.shipping['country'] = country
self.shipping['email'] = email
def doSale(self,amount, ccnumber, ccexp, cvv=''):
query = ""
# Login Information
query = query + "security_key=" + urllib.quote(self.login['security_key']) + "&"
# Sales Information
query += "ccnumber=" + urllib.quote(ccnumber) + "&"
query += "ccexp=" + urllib.quote(ccexp) + "&"
query += "amount=" + urllib.quote('{0:.2f}'.format(float(amount))) + "&"
if (cvv!=''):
query += "cvv=" + urllib.quote(cvv) + "&"
# Order Information
for key,value in self.order.iteritems():
query += key +"=" + urllib.quote(str(value)) + "&"
# Billing Information
for key,value in self.billing.iteritems():
query += key +"=" + urllib.quote(str(value)) + "&"
# Shipping Information
for key,value in self.shipping.iteritems():
query += key +"=" + urllib.quote(str(value)) + "&"
query += "type=sale"
return self.doPost(query)
def doPost(self,query):
responseIO = StringIO.StringIO()
curlObj = pycurl.Curl()
curlObj.setopt(pycurl.POST,1)
curlObj.setopt(pycurl.CONNECTTIMEOUT,30)
curlObj.setopt(pycurl.TIMEOUT,30)
curlObj.setopt(pycurl.HEADER,0)
curlObj.setopt(pycurl.SSL_VERIFYPEER,0)
curlObj.setopt(pycurl.WRITEFUNCTION,responseIO.write);
curlObj.setopt(pycurl.URL,"https://secure.apsmerchantgateway.com/api/transact.php")
curlObj.setopt(pycurl.POSTFIELDS,query)
curlObj.perform()
data = responseIO.getvalue()
temp = urlparse.parse_qs(data)
for key,value in temp.iteritems():
self.responses[key] = value[0]
return self.responses['response']
# NOTE: your security_key should replace the one below
gw = gwapi()
gw.setLogin("6457Thfj624V5r7WUwc5v6a68Zsd6YEm");
gw.setBilling("John","Smith","Acme, Inc.","123 Main St","Suite 200", "Beverly Hills",
"CA","90210","US","555-555-5555","555-555-5556","support@example.com",
"www.example.com")
gw.setShipping("Mary","Smith","na","124 Shipping Main St","Suite Ship", "Beverly Hills",
"CA","90210","US","support@example.com")
gw.setOrder("1234","Big Order",1, 2, "PO1234","65.192.14.10")
r = gw.doSale("5.00","4111111111111111","1212",'999')
print gw.responses['response']
if (int(gw.responses['response']) == 1) :
print "Approved"
elif (int(gw.responses['response']) == 2) :
print "Declined"
elif (int(gw.responses['response']) == 3) :
print "Error"
###########################################################
# #
# D I S C L A I M E R #
# #
# WARNING: ANY USE BY YOU OF THE SAMPLE CODE PROVIDED #
# IS AT YOUR OWN RISK. #
# #
# The code is provided "as is" without #
# warranty of any kind, either express or implied, #
# including but not limited to the implied warranties #
# of merchantability and/or fitness for a particular #
# purpose. #
# #
# #
###########################################################
require 'rubygems'
require 'curb'
require 'uri'
require 'addressable/uri'
class GwApi
def initialize()
@login = {}
@order = {}
@billing = {}
@shipping = {}
@responses = {}
end
def setLogin(security_key)
@login['security_key'] = security_key
end
def setOrder( orderid, orderdescription, tax, shipping, ponumber,ipadress)
@order['orderid'] = orderid;
@order['orderdescription'] = orderdescription
@order['shipping'] = "%.2f" % shipping
@order['ipaddress'] = ipadress
@order['tax'] = "%.2f" % tax
@order['ponumber'] = ponumber
end
def setBilling(
firstname,
lastname,
company,
address1,
address2,
city,
state,
zip,
country,
phone,
fax,
email,
website)
@billing['firstname'] = firstname
@billing['lastname'] = lastname
@billing['company'] = company
@billing['address1'] = address1
@billing['address2'] = address2
@billing['city'] = city
@billing['state'] = state
@billing['zip'] = zip
@billing['country'] = country
@billing['phone'] = phone
@billing['fax'] = fax
@billing['email'] = email
@billing['website'] = website
end
def setShipping(firstname,
lastname,
company,
address1,
address2,
city,
state,
zipcode,
country,
email)
@shipping['firstname'] = firstname
@shipping['lastname'] = lastname
@shipping['company'] = company
@shipping['address1'] = address1
@shipping['address2'] = address2
@shipping['city'] = city
@shipping['state'] = state
@shipping['zip'] = zipcode
@shipping['country'] = country
@shipping['email'] = email
end
def doSale(amount, ccnumber, ccexp, cvv='')
query = ""
# Login Information
query = query + "security_key=" + URI.escape(@login['security_key']) + "&"
# Sales Information
query += "ccnumber=" + URI.escape(ccnumber) + "&"
query += "ccexp=" + URI.escape(ccexp) + "&"
query += "amount=" + URI.escape("%.2f" %amount) + "&"
if (cvv!='')
query += "cvv=" + URI.escape(cvv) + "&"
end
# Order Information
@order.each do | key,value|
query += key +"=" + URI.escape(value) + "&"
end
# Billing Information
@billing.each do | key,value|
query += key +"=" + URI.escape(value) + "&"
end
# Shipping Information
@shipping.each do | key,value|
query += key +"=" + URI.escape(value) + "&"
end
query += "type=sale"
return doPost(query)
end
def doPost(query)
curlObj = Curl::Easy.new("https://secure.apsmerchantgateway.com/api/transact.php")
curlObj.connect_timeout = 30
curlObj.timeout = 30
curlObj.header_in_body = false
curlObj.ssl_verify_peer=false
curlObj.post_body = query
curlObj.perform()
data = curlObj.body_str
# NOTE: The domain name below is simply used to create a full URI to allow URI.parse to parse out the query values
# for us. It is not used to send any data
data = '"https://secure.apsmerchantgateway.com/api/transact.php?' + data
uri = Addressable::URI.parse(data)
@responses = uri.query_values
return @responses['response']
end
def getResponses()
return @responses
end
end
gw = GwApi.new()
# NOTE: your security_key should replace the one below
gw.setLogin("6457Thfj624V5r7WUwc5v6a68Zsd6YEm");
gw.setBilling("John","Smith","Acme, Inc.","123 Main St","Suite 200", "Beverly Hills",
"CA","90210","US","555-555-5555","555-555-5556","support@example.com",
"www.example.com")
gw.setShipping("Mary","Smith","na","124 Shipping Main St","Suite Ship", "Beverly Hills",
"CA","90210","US","support@example.com")
gw.setOrder("1234","Big Order",1, 2, "PO1234","65.192.14.10")
r = gw.doSale("5.00","4111111111111111","1212",'999')
myResponses = gw.getResponses
print myResponses['response'] + " "
if (myResponses['response'] == '1')
print "Approved \n"
elsif (myResponses['response'] == '2')
print "Declined \n"
elsif (myResponses['response'] == '3')
print "Error \n"
end
Collect.js is a JavaScript framework that allows merchants to collect sensitive payment information from their customers without exposing their website to the sensitive information. This can be done while allowing merchants to retain full control over the look and feel of their checkout experience.
This is a data collection and tokenization system, not a full payments API, so you can use this in conjunction with an existing transaction API (Direct Post) to submit transactions or use other gateway services that utilize payment information.
Collect.js is designed to be flexible, and its implementation can be as simple as pasting a single script tag to your checkout page, or it can be customized to interact with your website however you’d like.
Authentication is done via a “tokenization key” that you can generate in your merchant control panel under the “Security Keys” settings page. Select “Tokenization” for the key type.
This tokenization key can only be used with Collect.js and will not work with any other APIs. Similarly, any API keys already created will not work with Collect.js.
This key will be visible to customers in your website’s source code, so please make sure you only use the tokenization key here.
This is a new variable added to the Direct Post API that should be used in conjunction with this tool. This is what Collect.js will return to your website and it takes the place of the sensitive card or bank account information. It will look something like this:
3455zJms-7qA2K2-VdVrSu-Rv7WpvPuG7s8
This variable can be used in place of the existing ccnumber, ccexp, and cvv variables we have today. For ACH transactions (details below) it can be used in place of checkname, checkaba, and checkaccount.
The payment token can only be used once, and will expire after 24 hours if it is not used at all.
The payment token will also work when adding customers to the Customer Vault or recurring subscriptions. Just use “payment_token” where you were using the credit card and ACH account information before.
For example, if you would previously send this string:
type=sale&amount=3.00&ccnumber=4111111111111111&ccexp=1020&cvv=123
Or:
type=sale&amount=3.00&checkname=Jane Doe&checkaba=123123123&checkaccount=123123123
You could now send this:
type=sale&amount=3.00&payment_token=3455zJms-7qA2K2-VdVrSu-Rv7WpvPuG7s8
If you would like to test using the payment token without using Collect.js to create one, you can use the below tokens to return test credit card and bank account information.
Payment Token Value | Test Data |
00000000-000000-000000-000000000000 | Card: 4111111111111111, Expiration: October 2025, CVV: 999 |
11111111-111111-111111-111111111111 | ABA: 123123123, Account: 123123123, Name: Jane Doe |
Collect.js supports two different ways to integrate with your site. Both offer the same basic functionality and security, so you can choose based on your interface and design requirements,
The “lightbox” integration displays all sensitive payment fields in a single “pop-up” style display. All the entry and validation of payment data occurs within this single box; once valid information is provided, an event is provided for your page to capture the finished Payment Token.
The “inline” integration allows you to seamlessly build Collect.js into your payment form. This solution allows you to create a payment form that looks and feels exactly like your website, but without the need for your service to handle any sensitive payment information.
This works by creating iframes on your website for each credit card or electronic check field you need your customers to fill out. Using our custom “style sniffer” these fields will typically look exactly like the other fields on the page. If you want to just style them however you want, you can do that too by passing in custom CSS.
See the Simple Example for a basic web page using this implementation.
The simplest way to integrate is by pasting in the following script tag to your web page (preferably in the header) where you’ll be collecting payments:
<script src="https://secure.apsmerchantgateway.com/token/Collect.js" data-tokenization-key="your-token-key-here"></script>
With this script, you just need to add a button with the ID of “payButton” to your page inside a form where you ask for the customer’s information (name, address, email, etc.) You should make this button somewhere that indicates to the customer that they will be prompted to enter their card information and check out. Collect.js will find this button and display the below form in a lightbox over your website.
The customer will enter their card information and when they submit this mini-form, the lightbox will disappear, a hidden field will be inserted into your form with the “payment_token” value, and your form will be submitted.
You can then submit the transaction to the gateway with the Direct Post API using the “payment_token” variable.
See the advanced HTML example and advanced JavaScript example files for examples.
If you want to have a little more control over the default behavior, you can pass in additional data elements in the script tag. Here’s an example using all the available variables:
<script
src="https://secure.apsmerchantgateway.com/token/Collect.js"
data-tokenization-key="your-token-key-here"
data-payment-selector=".customPayButton"
data-primary-color="#ff288d"
data-theme="bootstrap"
data-secondary-color="#ffe200"
data-button-text="Submit the Payment"
data-instruction-text="Enter Card Information"
data-payment-type="cc"
data-field-cvv-display=”hide"
></script>
Variable | Format | Behavior |
data-tokenization-key | String | Authenticates the request |
data-payment-selector | String | Tells Collect.js what class or id value will trigger the lightbox Default: “#payButton” |
data-primary-color | String | The HEX value for the color of the submit button in the lightbox Default: “#007BFF” |
data-theme | String (“bootstrap” or “material”) | The version of the payment form customers will see. All available themes will use the primary and secondary colors provided. Default: “bootstrap” |
data-secondary-color | String | The HEX value for the color of the lightbox border Default: “#282828” |
data-button-text | String | The text that will display on the submit button in the lightbox Default: “Submit Payment” |
data-instruction-text | String | The text that will display above the payment fields. Custom text should be short so as not to overlap with other elements in the lightbox. Default: “Please enter payment info” |
data-payment-type | String (“cc” or “ck”) | Whether the lightbox shows credit card or check fields (“cc” for credit cards or “ck” for checks) Default: “cc” |
data-field-cvv-display | String (“show”, “hide”, or “required”) | Whether the CVV field is required (“required”), optional (“show”), or not displayed at all (“hide”). Also supported as data-field-cvv for legacy users. Default: “required” |
Function Name | Parameters | Description |
---|---|---|
configure | Object |
Call this when you’d like to reconfigure Collect.js. Collect.js will try to run this automatically on page load, but you can run it manually to change the configuration at any time.
This method optionally accepts an object with all configuration variables you’re using for Collect.js. |
startPaymentRequest | Event | Call this to bring up the lightbox with the secure payment form for the customer to fill out. If you are using the “payButton” ID or custom payment selector, this will automatically be called when the customer clicks that element on the page.
This method accepts an event object as an optional parameter and will call the provided callback function with a token response and the optional event. |
closePaymentRequest | Call this to dismiss the lightbox. This replicates the behavior of the user clicking the “close” button inside the lightbox. No card or checking information will be saved. |
You may also choose to configure Collect.js directly in your JavaScript, in which case you can do all of the above, and also implement a callback function that will execute when the customer submits the lightbox form. The payment token value will be returned in a “response” variable that you can do whatever you’d like with.
{
card: {
number: "411111******1111",
bin: "411111",
exp: "1028",
hash: "abcdefghijklmnopqrstuv1234567890",
},
check: {
name: null,
account: null,
hash: null,
aba: null,
},
token: "3455zJms-7qA2K2-VdVrSu-Rv7WpvPuG7s8",
initiatedBy: Event,
}
This implementation method allows for additional changes to the look and feel to better match your website’s UI
If you have a webpage where you would like the lightbox to trigger without an element getting clicked, then you can call the following function:
CollectJS.startPaymentRequest(event)
This function will trigger the lightbox to show up and request payment details. If you wish to change any options, this should be done before calling this function since changes after this point wont affect the lightbox.
This function optionally receives an event object. If an event is passed into the startPaymentRequest function, that same event will exist in the callback’s response variable under “response.initiatedBy”. This can be used to track what event started the payment request and the next steps.
{
card: {
number: null,
bin: null,
exp: null,
hash: null,
},
check: {
name: "Jane Doe",
account: "1******23",
hash: "abcdefghijklmnopqrstuv1234567890",
aba: "123123123",
},
token: "3455zJms-7qA2K2-VdVrSu-Rv7WpvPuG7s8",
initiatedBy: Event,
}
If you wish to close the payment request without waiting for the user to click the close button, you can call the function:
CollectJS.closePaymentRequest()
This function will remove the lightbox from the page. No other functions will trigger from this function being called, including the callback.
Note that this implementation also requires you to include the standard script tag on the page as well.
See the Simple Inline Example for a basic web page using this implementation.
While the Inline integration model offers many customizable options, you can also get started quickly with a basic form. First, install the following JavaScript on your payment form page, preferably in the HEAD element:
<script src="https://secure.apsmerchantgateway.com/token/Collect.js" data-tokenization-key="your-token-key-here" data-variant="inline"></script>
This script assumes that you’ve set up a payment form already. The form can be laid out however you’d like, but there should be block-level elements (div
, for example) where the sensitive payment info will be collected. The following IDs are expected to be used in place of standard form inputs:
For Credit Card Payments
ccnumber
(Credit card number)ccexp
(Credit card expiration date)cvv
(CVV)For Electronic Check Payments
checkname
(Checking account name)checkaccount
(Checking account number)checkaba
(Routing number)This is a very basic form that has integrated Inline Collect.js.
<form>
<input type="text" id="first_name">
<input type="text" id="last_name">
<input type="text" id="address">
<div id="ccnumber"></div>
<div id="ccexp"></div>
<div id="cvv"></div>
<input type="submit" id="payButton">
</form>
These elements will have iframes inserted into them, contents of which will be hosted by the gateway. They will be full width text fields and will use the style sniffer to match the rest of your page. The ID values let us know what field is collecting what information from the customer.
In addition to the empty fields, there must be a submit button in the form with an ID of “payButton
.” When the customer clicks this to submit the form, Collect.js will collect the data from all inline iframes and submit the form with a new “payment_token
” value which is an encrypted version of the payment data.
After this form is submitted to your site, you can submit the data to the gateway via the Direct Post API. For example:
security_key: 3456h45k6b4k56h54kj6h34kj6445hj4
type: sale
amount: 4.00
payment_token: 3455zJms-7qA2K2-VdVrSu-Rv7WpvPuG7s8
first_name: Jane
last_name: Doe
address: 123 Main St.
See the advanced HTML example and advanced JavaScript example files for examples.
If the simple implementation does not give you everything you need, then you can use the advanced implementation to customize the experience more to your liking. The options available are extensive, and you may use as many or as few as you want. Below is an example of using every variable possible.
<script
src="https://secure.apsmerchantgateway.com/token/Collect.js"
data-tokenization-key="your-token-key-here"
data-variant="inline"
data-payment-selector="#demoPayButton"
data-style-sniffer="false"
data-google-font="Montserrat:400"
data-validation-callback = "(function (field, valid, message) {console.log(field + ': ' + valid + ' -- ' + message)})"
data-custom-css='{
"background-color": "#a0a0ff",
"color": "#0000ff"
}'
data-invalid-css='{
"background-color":"red",
"color":"white"
}'
data-valid-css='{
"background-color":"#d0ffd0",
"color":"black"
}'
data-placeholder-css='{
"background-color":"#808080",
"color":"green"
}'
data-focus-css='{
"background-color":"#202020",
"color":"yellow"
}'
data-timeout-duration = "2000"
data-timeout-callback = "(function() {console.log('Timeout reached')})
data-fields-available-callback = "(function() {console.log('Collect.js has added fields to the form')})"
data-field-ccnumber-selector = '#demoCcnumber'
data-field-ccnumber-title = 'Card Number'
data-field-ccnumber-placeholder = '0000 0000 0000 0000'
data-field-ccexp-selector = '#demoCcexp'
data-field-ccexp-title = 'Expiration Date'
data-field-ccexp-placeholder = '00 / 00'
data-field-cvv-display = 'required'
data-field-cvv-selector = '#demoCvv'
data-field-cvv-title = 'CVV Code'
data-field-cvv-placeholder = '***'
data-field-checkaccount-selector = '#demoCheckaccount'
data-field-checkaccount-title = 'Account Number'
data-field-checkaccount-placeholder = '000000000000'
data-field-checkaba-selector = '#demoCheckaba'
data-field-checkaba-title = 'Routing Number'
data-field-checkaba-placeholder = '000000000'
data-field-checkname-selector = '#demoCheckname'
data-field-checkname-title = 'Account Name'
data-field-checkname-placeholder = 'Customer Name'
></script>
Variable | Format | Behavior |
data-tokenization-key | String | Authenticates the request |
data-variant | String (“inline” or “lightbox”) | Whether to use “inline” or “lightbox” integration (required for inline integration) Default: “lightbox” |
data-payment-selector | String | Tells Collect.js what class or id value will trigger the form submission Default: “#payButton” |
data-style-sniffer | String (“true” or “false”) | Whether Collect.js should try to calculate the style of form fields in your current form and use that as a baseline style for the Collect.js fields (“true” to calculate style, “false” to start with unstyled text fields) Default: “true” |
data-validation-callback | String | A JavaScript function which will be called each time a Collect.js field attempts to validate. It will recieve three paramaters: a string indicating which field was validated (ccnum or checkname, for example), a boolean for whether or not it validated successfully, and a string which may provide more detailed information about why the validation failed. For broadest compatibility, enclose the function in parentheses like in the example above |
data-custom-css | JSON String | The CSS rules that will be applied to the fields by default. These override anything provided through the style-sniffer, if used. The rules should be packaged as a JSON-formatted object, containing a key-value pair for each property’s name and value. Please see below for a list of the supported CSS properties |
data-invalid-css | JSON String | The CSS rules that will be added to a field when it fails to validate. These override anything provided through the style-sniffer and the custom-css paramater, if used. The rules should be packaged as a JSON-formatted object, containing a key-value pair for each property’s name and value. Please see below for a list of the supported CSS properties |
data-placeholder-css | JSON String | The CSS rules that will be added to a field when it’s displaying a placeholder. The rules should be packaged as a JSON-formatted object, containing a key-value pair for each property’s name and value. Please see below for a list of the supported CSS properties |
data-focus-css | JSON String | The CSS rules that will be added to a field when it has the keyboard focus. The rules should be packaged as a JSON-formatted object, containing a key-value pair for each property’s name and value. Please see below for a list of the supported CSS properties |
data-valid-css | JSON String | The CSS rules that will be added to a field when it successfully validates and saves. These override anything provided through the style-sniffer and the custom-css paramater, if used. The rules should be packaged as a JSON-formatted object, containing a key-value pair for each property’s name and value. Please see below for a list of the supported CSS properties |
data-google-font | String | Directs Collect.js to load font collections available through Google Fonts. This only makes the fonts available in the fields; you must still provide (either directly or through the style sniffer) styles that specify them. List the font name, followed by a colon and the specific weights or variants needed. Example: “Open Sans:400,700i” |
data-timeout-duration | Integer | When form submission is triggered, Collect.js will wait only this long (in milliseconds) for payment data validation and recording to complete. If, by this time, Collect.js is still missing confirmation on vital fields, the data-timeout-callback function will be invokedDefault: “0” which disables the timeout |
data-timeout-callback | String | A JavaScript function which gets called if data-timeout-duration has passed since we tried to submit the form, but we still haven’t confirmed that enough fields are stored with the token to make a viable payment. This allows for the site to retry submission, or ask the customer to try submission again, if an invalid entry or intermittent connection caused the data storage to fail. For broadest compatibility, enclose the function in parentheses like in the example aboveDefault: an internal function that displays a “Please submit the form again.” alert |
data-fields-available-callback | String | A JavaScript function which gets called once Collect.js has installed the fields onto your page. A typical use case is to wire up event handlers to the fields when they are enterred or left. For broadest compatibility, enclose the function in parentheses like in the example above |
data-field-ccnumber-selector | String (CSS Selector) | A CSS selector for the Credit Card Number inline field Default: “#ccnumber” |
data-field-ccnumber-title | String | A title for the Credit Card Number inline field |
data-field-ccnumber-placeholder | String | Placeholder text for the Credit Card Number inline field |
data-field-ccexp-selector | String (CSS Selector) | A CSS selector for the Credit Card Expiration Date inline field Default: “#ccexp” |
data-field-ccexp-title | String | A title for the Credit Card Expiration Date inline field |
data-field-ccexp-placeholder | String | Placeholder text for the Credit Card Expiration Date inline field |
data-field-cvv-display | String (“show”, “hide”, or “required”) | Whether the CVV field is required (“required”), optional (“show”), or not displayed at all (“hide”). If the CVV field is required, a space for it must be provided on the form. Also supported as data-field-cvv for legacy usersDefault: “required” |
data-field-cvv-selector | String (CSS Selector) | A CSS selector for the CVV inline field Default: “#cvv” |
data-field-cvv-title | String | A title for the CVV inline field |
data-field-cvv-placeholder | String | Placeholder text for the CVV inline field |
data-field-checkaccount-selector | String (CSS Selector) | A CSS selector for Checking Account Number inline field Default: “#checkaccount” |
data-field-checkaccount-title | String | A title for the Checking Account Number inline field |
data-field-checkaccount-placeholder | String | Placeholder text for the Checking Account Number inline field |
data-field-checkaba-selector | String (CSS Selector) | A CSS selector for the Checking Routing Number inline field Default: “#checkaba” |
data-field-checkaba-title | String | A title for the Checking Routing Number inline field |
data-field-checkaba-placeholder | String | Placeholder text for the Checking Routing Number inline field |
data-field-checkname-selector | String (CSS Selector) | A CSS selector for the Checking Account Name inline field Default: “#checkname” |
data-field-checkname-title | String | A title for the Checking Account Name inline field |
data-field-checkname-placeholder | String | Placeholder text for the Checking Account Name inline field |
Function Name | Parameters | Description |
---|---|---|
configure | Object |
Call this when you’d like to reconfigure Collect.js. Collect.js will try to run this automatically on page load, but you can run it manually to change the configuration at any time. This will draw or re-draw all iframes onto the page.
This method optionally accepts an object with all configuration variables you’re using for Collect.js. |
startPaymentRequest | Event | Call this when you want to save the data in the iframes and get the token value in the callback.
This method accepts an event object as an optional parameter. It will call the provided callback function with a token response and the optional event. |
clearInputs | Call this when you want to clear whatever the user has entered into any input provided by Collect.js. |
You may also choose to configure Collect.js directly in your JavaScript, For this, you will typically only include the data-tokenization-key
parameter in the script tag, and deploy the other options with a CollectJS.configure()
call. See the Advanced Inline JavaScript Example for a demonstration with the main available options.
The CollectJS.configure
function also lets you specify a callback
function that will execute when the customer submits the payment form and payment info has been successfully stored. The callback takes the place of the default “add the payment token and submit the form” behavior and gets passed a “response” variable with the Payment Token. It is your responsibility to ensure this is posted to your server.
{
card: {
number: "411111******1111",
bin: "411111",
exp: "1028",
hash: "abcdefghijklmnopqrstuv1234567890",
},
check: {
name: null,
account: null,
hash: null,
aba: null,
},
token: "3455zJms-7qA2K2-VdVrSu-Rv7WpvPuG7s8",
initiatedBy: Event,
}
For security and compatibility reasons, the styling system- whether provided via custom-css
, invalid-css
, valid-css
, focus-css
or calculated using the style-sniffer, only supports the following CSS properties:
Placeholder CSS can only use the following attributes
Any other CSS properties will be ignored.
Each field that Collect.js supplies communicates with your Gateway independently. These fields will check the payment information, and if valid, direct the Gateway to save it, as soon as the customer exits a field. This process triggers the validation callbacks you can use to monitor the user’s progress and control their interactions with your form.
When the submit button is pressed (or CollectJS.startPaymentRequest
is manually called), Collect.js directs each field to validate and save one last time. Once it gets back a notice of successful validation and saving from enough fields to make a viable payment request, it proceeds to submit the form or call an alternative callback
as configured.
Once the Payment Token is used in a Direct Post request, it’s automatically destroyed. This prevents its reuse for a later unauthorized charge, but means that if you have to collect the payment information again (for example, after a declined transaction), you’re going to have to start fresh and generate a new token.
You can take control of when the final validate-and-save process is triggered. Rather than binding it explicitly to a payment button, you can call the following JavaScript function when ready.
CollectJS.startPaymentRequest(event)
When triggered, this causes the same behavior as pressing a payment button does by default: all the fields are told to validate and save. Once we confirm all data is stored, the callback you configured is executed.
This function optionally receives an event object. If an event is passed into the startPaymentRequest function, that same event will exist in the callback’s response variable under “response.initiatedBy”. This can be used to track what event started the recording request and the next steps.
{
card: {
number: null,
bin: null,
exp: null,
hash: null,
},
check: {
name: "Jane Doe",
account: "1******23",
hash: "abcdefghijklmnopqrstuv1234567890",
aba: "123123123",
},
token: "3455zJms-7qA2K2-VdVrSu-Rv7WpvPuG7s8",
initiatedBy: Event,
}
Note that this implementation also requires you to include the standard script tag on the page as well.
The expert example shows how the process can be triggered in code.
While Collect.js doesn’t let you directly access the contents of the payment information fields, it does provide several ways to check if they contain valid content. There are two distinct ways you can access this information in your form validation code:
This will listen for all Collect.js validation changes. This function will get a notice about each field change, and you can keep a tally during the form’s life.
<script
src="https://secure.apsmerchantgateway.com/token/Collect.js"
data-tokenization-key="your-token-key-here"
data-validation-callback="(
function(fieldName, valid, message) {
if (valid) {
... store the fact that fieldName is valid ...
} else {
... remove fieldName from the valid list, maybe display message to the user ...
}
}
)">
When you start the validation process, you can see if the elements you loaded Collect.js fields into have either CollectJSValid
or CollectJSInvalid
elements within them. Note that blank fields, or some fields in the process or being edited or saved, will have neither set. You can decide how to handle these depending on when you’re performing the check, what field is blank or unsaved, and how that fits into your site’s flow.
validCardNumber = document.querySelector("#ccnumber .CollectJSValid") !== null;
validExpiration = document.querySelector("#ccexp .CollectJSValid") !== null;
validCvv = document.querySelector("#cvv .CollectJSValid") !== null;
invalidCvv = document.querySelector("#cvv .CollectJSInvalid") !== null;
blankOrUnsavedCvv = !validCvv && !invalidCvv;
Some styling techniques will change the classes of related elements as a user enters and leaves a form field. Google’s Material Design Components for the Web is a typical example– the label moves above the text, and an underline that’s not part of the field changes color. Collect.js exposes focus
and blur
events that can be used to trigger these types of effects with Collect.js fields.
Here’s a tangible example. The data-fields-available-callback
code adds a listener to each Collect.js field’s blur
and focus
events. This listener adds or removes the active
class from the nearest label. When a user enters the field, the label next to it changes from gray to bold and blue, reverting once they leave the field.
<script
src="https://secure.apsmerchantgateway.com/token/Collect.js"
data-tokenization-key="your-token-key-here"
data-variant="inline"
data-fields-available-callback='
(function() {
var frames = document.querySelectorAll(".input-field iframe.CollectJSInlineIframe")
for (var i = 0; i < frames.length; i++) {
frames[i].addEventListener("focus", function (event) {
var panel = event.target.parentNode.parentNode;
panel.querySelector("label").classList.add("active");
});
frames[i].addEventListener("blur", function (event) {
var panel = event.target.parentNode.parentNode;
if(event.detail && event.detail.empty) {
panel.querySelector("label").classList.remove("active");
}
});
}
});'
></script>
<style>
label {
color: gray;
}
label.active {
color: blue;
font-weight: bold;
}
</style>
<div class="input-field">
<label for="ccnumber">Card Number</label>
<div id="ccnumber"></div>
</div>
<div class="input-field">
<label for="ccexp">Expiration Date</label>
<div id="ccexp"></div>
</div>
<div class="input-field">
<label for="cvv">CVV</label>
<div id="cvv"></div>
</div>
When the blur
event is fired, it will include a detail
structure with one element: empty
. This tells you if the field is blank, so you can style it differently, without disclosing its contents.
The Inline Integration system is powerful and flexible, so we’ve compiled some hints to help you make the most of it.
If you specify the Style Sniffer option, Collect.js will first create a temporary INPUT
element in the form at the location you targeted, and measure the styles from that element to model the actual field after. That means you can target individual payment fields via the CSS on your site.
For example, you can add a special green border to just the credit card number field as follows:
<script
src="https://secure.apsmerchantgateway.com/token/Collect.js"
data-tokenization-key="your-token-key-here"
data-style-sniffer="true"
data-field-ccnumber-selector = '#myCcnumber'></script>
<style>
#myCcnumber input {
border-color: green;
border-width: 3px;
border-style: solid;
}
</style>
<div id="myCcnumber"></div>
Styles provided by the Style Sniffer will be overridden by ones provided in the custom-css paramater, which in turn are overridden by the ones in the invalid-css paramater
Collect.js lays out its fields on your form with a “width” property of 100%, and a “height” calculated to fit the field as rendered plus provided margins. If you’d like to control the width of the field, or add horizontal space around it, you can specify width and/or padding on the block-level element that the field resides in, allowing the field itself to fill it in horizontally.
When styling CollectJSValid
and CollectJSInvalid
classes in your stylesheet, remember these represent the outer edge of an iframe
that contains the field. Some CSS rules may not be very visible, or could behave unexpectedly. Body and background colors are unlikely to be visible, but borders and drop shadows are good choices.
Payment fields have to be retrieved from the Gateway and styled, so you may briefly see a blank space in your page during the loading process. This effect can be mitigated by styling the Collect.js fields to have no border or background, and applying those style components to the div
, td
, or other block-level element that contains them instead.
It’s generally good practice to only let your customer enter credit card or check information on your payment form. However, Collect.js will allow you to include both credit card and electronic check fields in your form, so you could have a token that has encrypted data for both payment types. If all required fields are present for both payment types, then submitting a transaction in the Direct Post API with this payment_token
will process a credit card sale by default, discarding the check data. To use the electronic check data instead, pass the payment
variable in your Direct Post request with the value check
.
The data-google-font
option takes a font string in the same format as you get from the Google Font selection tool. That rool provides a stylesheet link like
<link href="https://fonts.googleapis.com/css?family=Montserrat:400,700,700i|Roboto:300,400" rel="stylesheet">
The section you need is the portion after family=
. and before the closing quotation mark
data-google-font="Montserrat:400,700,700i|Roboto:300,400"
If you intend to set up custom handlers for the blur
or focus
events, we suggest preparing a fields-available-callback
function to set them up. That will ensure the events are handled as soon as the Collect.js fields are loaded into the page.
Defining a custom callback is a great way to integrate Collect.js into an AJAX-based purchase process. When the callback is activated, you can retrieve the payment-token and submit it with the rest of the form. confident that the payment info it represents is at least complete and sensibly formatted.
For a smoother user experience, disable form submission until you have confirmed that the payment fields are successfully stored, as well as any other pre-transaction checks you perform. Collect.js won’t let the submission process complete until the payment information is sufficient to run a transaction, which may be surprising if a user tries to submit an incomplete or invalid form.
<html>
<script src="https://secure.apsmerchantgateway.com/token/Collect.js" data-tokenization-key="your-token-key-here"></script>
<body>
<h1>CollectJS Payment Form</h1>
<form action="/your-page.php" method="post">
<table>
<tr>
<td>First Name</td>
<td><input size="30" type="text" name="fname" value="Test" /></td>
</tr>
<tr>
<td>Last Name</td>
<td><input size="30" type="text" name="lname" value="User" /></td>
</tr>
<tr>
<td>Address</td>
<td><input size="30" type="text" name="address" value="123 Main Street"></td>
</tr>
<tr>
<td>City</td>
<td><input size="30" type="text" name="city" value="Beverley Hills"></td>
</tr>
<tr>
<td>State</td>
<td><input size="30" type="text" name="state" value="CA"></td>
</tr>
<tr>
<td>Zip</td>
<td><input size="30" type="text" name="zip" value="90210"></td>
</tr>
<tr>
<td>Country</td>
<td><input size="30" type="text" name="country" value="US"></td>
</tr>
<tr>
<td>Phone</td>
<td><input size="30" type="text" name="phone" value="5555555555"></td>
</tr>
</table>
<br>
<button id="payButton" type="button">Submit Payment</button>
</form>
</body>
</html>
<html>
<head>
<script
src="https://secure.apsmerchantgateway.com/token/Collect.js"
data-tokenization-key="your-token-key-here"
data-payment-selector=".customPayButton"
data-theme="bootstrap"
data-primary-color="#ff288d"
data-secondary-color="#ffe200"
data-button-text="SUBMIT ME!"
data-payment-type="cc"
data-field-cvv-display="hide"
data-instruction-text="Enter Card Information"
></script>
</head>
<body>
<h1>CollectJS Payment Form</h1>
<form action="/your-page.php" method="post">
<table>
<tr>
<td>First Name</td>
<td><input size="30" type="text" name="fname" value="Test" /></td>
</tr>
<tr>
<td>Last Name</td>
<td><input size="30" type="text" name="lname" value="User" /></td>
</tr>
<tr>
<td>Address</td>
<td><input size="30" type="text" name="address" value="123 Main Street"></td>
</tr>
<tr>
<td>City</td>
<td><input size="30" type="text" name="city" value="Beverley Hills"></td>
</tr>
<tr>
<td>State</td>
<td><input size="30" type="text" name="state" value="CA"></td>
</tr>
<tr>
<td>Zip</td>
<td><input size="30" type="text" name="zip" value="90210"></td>
</tr>
<tr>
<td>Country</td>
<td><input size="30" type="text" name="country" value="US"></td>
</tr>
<tr>
<td>Phone</td>
<td><input size="30" type="text" name="phone" value="5555555555"></td>
</tr>
</table>
<br>
<button class="customPayButton" type="button">Pay the money.</button>
</form>
</body>
</html>
<html>
<head>
<script src="https://secure.apsmerchantgateway.com/token/Collect.js" data-tokenization-key="your-token-key-here"></script>
<script>
document.addEventListener('DOMContentLoaded', function () {
CollectJS.configure({
'paymentSelector' : '#customPayButton',
'theme': 'bootstrap',
'primaryColor': '#ff288d',
'secondaryColor': '#ffe200',
'buttonText': 'SUBMIT ME!',
'instructionText': 'Enter Card Info Below',
'paymentType': 'cc',
'fields': {
'cvv': {
"display":'hide'
}
},
'callback' : function(response) {
alert(response.token);
var input = document.createElement("input");
input.type = "hidden";
input.name = "payment_token";
input.value = response.token;
var form = document.getElementsByTagName("form")[0];
form.appendChild(input);
form.submit();
}
});
});
</script>
</head>
<body>
<h1>CollectJS Payment Form</h1>
<form action="/your-page.php" method="post">
<table>
<tr>
<td>First Name</td>
<td><input size="30" type="text" name="fname" value="Test" /></td>
</tr>
<tr>
<td>Last Name</td>
<td><input size="30" type="text" name="lname" value="User" /></td>
</tr>
<tr>
<td>Address</td>
<td><input size="30" type="text" name="address" value="123 Main Street"></td>
</tr>
<tr>
<td>City</td>
<td><input size="30" type="text" name="city" value="Beverley Hills"></td>
</tr>
<tr>
<td>State</td>
<td><input size="30" type="text" name="state" value="CA"></td>
</tr>
<tr>
<td>Zip</td>
<td><input size="30" type="text" name="zip" value="90210"></td>
</tr>
<tr>
<td>Country</td>
<td><input size="30" type="text" name="country" value="US"></td>
</tr>
<tr>
<td>Phone</td>
<td><input size="30" type="text" name="phone" value="5555555555"></td>
</tr>
</table>
<br>
<button id="customPayButton" type="button">Submit Payment</button>
</form>
</body>
</html>
<html>
<head>
<script src="https://secure.apsmerchantgateway.com/token/Collect.js" data-tokenization-key="your-token-key-here"></script>
<script>
document.addEventListener('DOMContentLoaded', function () {
CollectJS.configure({
'paymentSelector' : '#customPayButton',
'theme': 'bootstrap',
'primaryColor': '#ff288d',
'secondaryColor': '#ffe200',
'buttonText': 'SUBMIT ME!',
'paymentType': 'cc',
'fields': {
'cvv': 'hide'
},
'callback' : function(response) {
alert(response.token);
var input = document.createElement("input");
input.type = "hidden";
input.name = "payment_token";
input.value = response.token;
var form = document.getElementsByTagName("form")[0];
form.appendChild(input);
form.submit();
}
});
});
</script>
</head>
<body>
<h1>CollectJS Payment Form</h1>
<form action="/your-page.php" method="post">
<table>
<tr>
<td>First Name</td>
<td><input size="30" type="text" name="fname" value="Test" /></td>
</tr>
<tr>
<td>Last Name</td>
<td><input size="30" type="text" name="lname" value="User" /></td>
</tr>
<tr>
<td>Address</td>
<td><input size="30" type="text" name="address" value="123 Main Street"></td>
</tr>
<tr>
<td>City</td>
<td><input size="30" type="text" name="city" value="Beverley Hills"></td>
</tr>
<tr>
<td>State</td>
<td><input size="30" type="text" name="state" value="CA"></td>
</tr>
<tr>
<td>Zip</td>
<td><input size="30" type="text" name="zip" value="90210"></td>
</tr>
<tr>
<td>Country</td>
<td><input size="30" type="text" name="country" value="US"></td>
</tr>
<tr>
<td>Phone</td>
<td><input size="30" type="text" name="phone" value="5555555555"></td>
</tr>
</table>
<br>
To show the ability to trigger the form without a click, it will appear automatically after 5 seconds and disappear after another 5.
<script>
setTimeout("CollectJS.startPaymentRequest()", 5000);
setTimeout("CollectJS.closePaymentRequest()", 10000);
</script>
</form>
</body>
</html>
<html>
<script src="https://secure.apsmerchantgateway.com/token/Collect.js" data-tokenization-key="your-token-key-here" data-variant="inline"></script>
<body>
<h1>CollectJS Payment Form</h1>
<form action="/your-page.php" method="post">
<table>
<tr>
<td>First Name</td>
<td><input size="30" type="text" name="fname" value="Test" /></td>
</tr>
<tr>
<td>Last Name</td>
<td><input size="30" type="text" name="lname" value="User" /></td>
</tr>
<tr>
<td>Address</td>
<td><input size="30" type="text" name="address" value="123 Main Street"></td>
</tr>
<tr>
<td>City</td>
<td><input size="30" type="text" name="city" value="Beverley Hills"></td>
</tr>
<tr>
<td>State</td>
<td><input size="30" type="text" name="state" value="CA"></td>
</tr>
<tr>
<td>Zip</td>
<td><input size="30" type="text" name="zip" value="90210"></td>
</tr>
<tr>
<td>Country</td>
<td><input size="30" type="text" name="country" value="US"></td>
</tr>
<tr>
<td>Phone</td>
<td><input size="30" type="text" name="phone" value="5555555555"></td>
</tr>
<tr>
<td colspan="2">
Credit Card Information
</td>
</tr>
<tr>
<td>CC Number</td>
<td id="ccnumber"></td>
</tr>
<tr>
<td>CC Exp</td>
<td id="ccexp"></td>
</tr>
<tr>
<td>CVV</td>
<td id="cvv"></td>
</tr>
<tr>
<td colspan="2">
Electronic Check Information
</td>
</tr>
<tr>
<td>Account Number</td>
<td id="checkaccount"></td>
</tr>
<tr>
<td>Routing Number</td>
<td id="checkaba"></td>
</tr>
<tr>
<td>Account Owner's Name</td>
<td id="checkname"></td>
</tr>
</table>
<br>
<button id="payButton" type="button">Submit Payment</button>
</form>
</body>
</html>
<html>
<head>
<script
src="https://secure.apsmerchantgateway.com/token/Collect.js"
data-tokenization-key="your-token-key-here"
data-payment-selector="#demoPayButton"
data-variant="inline"
data-style-sniffer="false"
data-google-font="Montserrat:400"
data-validation-callback = "(function (field, valid, message) {console.log(field + ': ' + valid + ' -- ' + message)})"
data-custom-css='{
"background-color": "#a0a0ff",
"color": "#0000ff"
}'
data-invalid-css='{
"background-color":"red",
"color":"white"
}'
data-valid-css='{
"background-color":"#d0ffd0",
"color":"black"
}'
data-placeholder-css='{
"background-color":"#808080",
"color":"green"
}'
data-focus-css='{
"background-color":"#202020",
"color":"yellow"
}'
data-timeout-duration = "2000"
data-timeout-callback = "(function() {console.log('Timeout reached')})"
data-fields-available-callback = "(function() {console.log('Collect.js has added fields to the form')})"
data-field-cvv-display = 'required'
data-field-ccnumber-selector = '#demoCcnumber'
data-field-ccnumber-title = 'Card Number'
data-field-ccnumber-placeholder = '0000 0000 0000 0000'
data-field-ccexp-selector = '#demoCcexp'
data-field-ccexp-title = 'Expiration Date'
data-field-ccexp-placeholder = '00 / 00'
data-field-cvv-display = 'required'
data-field-cvv-selector = '#demoCvv'
data-field-cvv-title = 'CVV Code'
data-field-cvv-placeholder = '***'
data-field-checkaccount-selector = '#demoCheckaccount'
data-field-checkaccount-title = 'Account Number'
data-field-checkaccount-placeholder = '000000000000'
data-field-checkaba-selector = '#demoCheckaba'
data-field-checkaba-title = 'Routing Number'
data-field-checkaba-placeholder = '000000000'
data-field-checkname-selector = '#demoCheckname'
data-field-checkname-title = 'Account Name'
data-field-checkname-placeholder = 'Customer Name'
></script>
<!-- This style will be inherited by the style-sniffer, with the additions in the configuration -->
<style>
input {
border: 5px inset #808080;
background-color: #c0c0c0;
color: green;
font-size: 25px;
font-family: monospace;
padding: 5px;
}
</style>
</head>
<body>
<h1>CollectJS Payment Form</h1>
<form action="/your-page.php" method="post">
<table>
<tr>
<td>Amount: </td>
<td><input size="50" type="text" name="amount" value="1.00" /></td>
</tr>
<tr>
<td>First Name: </td>
<td><input size="50" type="text" name="first_name" value="Test" /></td>
</tr>
<tr>
<td>Last Name: </td>
<td><input size="50" type="text" name="last_name" value="User" /></td>
</tr>
<tr>
<td>Address1</td>
<td><input size="50" type="text" name="address1" value="123 Main Street"></td>
</tr>
<tr>
<td>City</td>
<td><input size="50" type="text" name="city" value="Beverley Hills"></td>
</tr>
<tr>
<td>State</td>
<td><input size="50" type="text" name="state" value="CA"></td>
</tr>
<tr>
<td>zip</td>
<td><input size="50" type="text" name="zip" value="90210"></td>
</tr>
<tr>
<td>country</td>
<td><input size="50" type="text" name="country" value="US"></td>
</tr>
<tr>
<td>phone</td>
<td><input size="50" type="text" name="phone" value="5555555555"></td>
</tr>
<tr>
<td>CC Number</td>
<td id="demoCcnumber"></td>
</tr>
<tr>
<td>CC Exp</td>
<td id="demoCcexp"></td>
</tr>
<tr>
<td>CVV</td>
<td id="demoCvv"></td>
</tr>
<tr>
<td>Account Number</td>
<td id="demoCheckaccount"></td>
</tr>
<tr>
<td>Routing Number</td>
<td id="demoCheckaba"></td>
</tr>
<tr>
<td>Name on Account</td>
<td id="demoCheckname"></td>
</tr>
</table>
<br>
<button id="demoPayButton" type="button">Pay the money.</button>
</form>
</body>
</html>
<html>
<head>
<script src="https://secure.apsmerchantgateway.com/token/Collect.js" data-tokenization-key="your-token-key-here"></script>
></script>
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1, shrink-to-fit=no">
<style>
input {
border: 5px inset #808080;
background-color: #c0c0c0;
color: green;
font-size: 25px;
font-family: monospace;
padding: 5px;
}
</style>
</head>
<body>
<h1>Inline CollectJS Demo</h1>
<form action="/your-page.php" method="post">
<table>
<tr>
<td>Amount: </td>
<td><input size="50" type="text" name="amount" value="1.00" /></td>
</tr>
<tr>
<td>First Name: </td>
<td><input size="50" type="text" name="first_name" value="Test" /></td>
</tr>
<tr>
<td>Last Name: </td>
<td><input size="50" type="text" name="last_name" value="User" /></td>
</tr>
<tr>
<td>Address1</td>
<td><input size="50" type="text" name="address1" value="123 Main Street"></td>
</tr>
<tr>
<td>City</td>
<td><input size="50" type="text" name="city" value="Beverley Hills"></td>
</tr>
<tr>
<td>State</td>
<td><input size="50" type="text" name="state" value="CA"></td>
</tr>
<tr>
<td>zip</td>
<td><input size="50" type="text" name="zip" value="90210"></td>
</tr>
<tr>
<td>country</td>
<td><input size="50" type="text" name="country" value="US"></td>
</tr>
<tr>
<td>phone</td>
<td><input size="50" type="text" name="phone" value="5555555555"></td>
</tr>
<tr>
<td>CC Number</td>
<td id="demoCcnumber"></td>
</tr>
<tr>
<td>CC Exp</td>
<td id="demoCcexp"></td>
</tr>
<tr>
<td>CVV</td>
<td id="demoCvv"></td>
</tr>
<tr>
<td>Account Number</td>
<td id="demoCheckaccount"></td>
</tr>
<tr>
<td>Routing Number</td>
<td id="demoCheckaba"></td>
</tr>
<tr>
<td>Name on Account</td>
<td id="demoCheckname"></td>
</tr>
</table>
<br>
<button id="demoPayButton" type="button">Pay the money.</button>
</form>
<script>
document.addEventListener('DOMContentLoaded', function () {
CollectJS.configure({
"paymentSelector" : "#demoPayButton",
"variant" : "inline",
"styleSniffer" : "false",
"googleFont": "Montserrat:400",
"customCss" : {
"color": "#0000ff",
"background-color": "#d0d0ff"
},
"invalidCss": {
"color": "white",
"background-color": "red"
},
"validCss": {
"color": "black",
"background-color": "#d0ffd0"
},
"placeholderCss": {
"color": "green",
"background-color": "#808080"
},
"focusCss": {
"color": "yellow",
"background-color": "#202020"
},
"fields": {
"ccnumber": {
"selector": "#demoCcnumber",
"title": "Card Number",
"placeholder": "0000 0000 0000 0000"
},
"ccexp": {
"selector": "#demoCcexp",
"title": "Card Expiration",
"placeholder": "00 / 00"
},
"cvv": {
"display": "show",
"selector": "#demoCvv",
"title": "CVV Code",
"placeholder": "***"
},
"checkaccount": {
"selector": "#demoCheckaccount",
"title": "Account Number",
"placeholder": "0000000000"
},
"checkaba": {
"selector": "#demoCheckaba",
"title": "Routing Number",
"placeholder": "000000000"
},
"checkname": {
"selector": "#demoCheckname",
"title": "Name on Checking Account",
"placeholder": "Customer McCustomerface"
}
},
'validationCallback' : function(field, status, message) {
if (status) {
var message = field + " is now OK: " + message;
} else {
var message = field + " is now Invalid: " + message;
}
console.log(message);
},
"timeoutDuration" : 2000,
"timeoutCallback" : function () {
console.log("The tokenization didn't respond in the expected timeframe. This could be due to an invalid or incomplete field or poor connectivity");
},
"fieldsAvailableCallback" : function () {
console.log("Collect.js loaded the fields onto the form");
},
'callback' : function(response) {
alert(response.token);
var input = document.createElement("input");
input.type = "hidden";
input.name = "payment_token";
input.value = response.token;
var form = document.getElementsByTagName("form")[0];
form.appendChild(input);
form.submit();
}
});
});
</script>
</body>
</html>
<html>
<head>
<script src="https://secure.apsmerchantgateway.com/token/Collect.js" data-tokenization-key="your-token-key-here"></script>
<script>
document.addEventListener('DOMContentLoaded', function () {
CollectJS.configure({
'paymentSelector' : '#customPayButton',
"fields": {
"ccnumber": {
"selector": "#demoCcnumber",
"title": "Card Number",
"placeholder": "0000 0000 0000 0000"
},
"ccexp": {
"selector": "#demoCcexp",
"title": "Card Expiration",
"placeholder": "00 / 00"
},
"cvv": {
"display": "show",
"selector": "#demoCvv",
"title": "CVV Code",
"placeholder": "***"
},
"checkaccount": {
"selector": "#demoCheckaccount",
"title": "Account Number",
"placeholder": "0000000000"
},
"checkaba": {
"selector": "#demoCheckaba",
"title": "Routing Number",
"placeholder": "000000000"
},
"checkname": {
"selector": "#demoCheckname",
"title": "Name on Checking Account",
"placeholder": "Customer McCustomerface"
}
},
"variant": "inline",
"callback" : function(response) {
alert(response.token);
var input = document.createElement("input");
input.type = "hidden";
input.name = "payment_token";
input.value = response.token;
var form = document.getElementsByTagName("form")[0];
form.appendChild(input);
form.submit();
}
});
});
</script>
</head>
<body>
<h1>CollectJS Payment Form</h1>
<form action="/your-page.php" method="post">
<table>
<tr>
<td>First Name</td>
<td><input size="30" type="text" name="fname" value="Test" /></td>
</tr>
<tr>
<td>Last Name</td>
<td><input size="30" type="text" name="lname" value="User" /></td>
</tr>
<tr>
<td>Address</td>
<td><input size="30" type="text" name="address" value="123 Main Street"></td>
</tr>
<tr>
<td>City</td>
<td><input size="30" type="text" name="city" value="Beverley Hills"></td>
</tr>
<tr>
<td>State</td>
<td><input size="30" type="text" name="state" value="CA"></td>
</tr>
<tr>
<td>Zip</td>
<td><input size="30" type="text" name="zip" value="90210"></td>
</tr>
<tr>
<td>Country</td>
<td><input size="30" type="text" name="country" value="US"></td>
</tr>
<tr>
<td>Phone</td>
<td><input size="30" type="text" name="phone" value="5555555555"></td>
</tr>
<tr>
<td>CC Number</td>
<td id="demoCcnumber"></td>
</tr>
<tr>
<td>CC Exp</td>
<td id="demoCcexp"></td>
</tr>
<tr>
<td>CVV</td>
<td id="demoCvv"></td>
</tr>
<tr>
<td>Account Number</td>
<td id="demoCheckaccount"></td>
</tr>
<tr>
<td>Routing Number</td>
<td id="demoCheckaba"></td>
</tr>
<tr>
<td>Name on Account</td>
<td id="demoCheckname"></td>
</tr>
</table>
<br>
This form will be automatically submitted after 30 seconds
<script>
setTimeout("CollectJS.startPaymentRequest()", 30000);
</script>
</form>
</body>
</html>
While our online reporting interface allows merchants to quickly and easily retrieve detailed information about past transactions, a need for additional flexibility may be required. For example, a merchant may have custom accounting software that requires up-to-date information about the settlement status of all credit card transactions every day.
This document describes how developers can query our reporting engine directly to retrieve transaction reports in a machine readable format. Once the data has been retrieved, it can then be parsed and imported into a variety of software applications.
The communication protocol used to send messages to the Payment Gateway is through the HTTP protocol over an SSL connection (HTTPS). The format you must use is name/value pairs delimited by ampersand.
URL: | https://secure.apsmerchantgateway.com/api/query.php |
Example Post Data: | security_key=security_key&transaction_id=123456789 |
You should POST your request to the Query API. The name/value pairs that are accepted by the Payment Gateway can be found in the ‘Variables’ section of this API.
The Query API can be tested with live credentials or a dedicated test account only. Please contact your Merchant Service Provider for more information.
The Query API will respond in Universal Time Coordinated (UTC).
Variable Name | Description(Allowed Values)[Format] |
---|---|
security_key* |
API Security Key assigned to a merchant account. New keys can be generated from the merchant control panel in Settings > Security Keys |
condition |
A combination of values listed below can be passed and should be separated by commas. For example, to retrieve all transactions pending settlement or complete, the following could be used:
Example: condition=pendingsettlement,complete |
pending: ‘Auth Only’ transactions that are awaiting capture. | |
pendingsettlement: This transaction is awaiting settlement. | |
in_progress: This Three-Step Redirect API transaction has not yet been completed. The transaction condition will change to ‘abandoned’ if 24 hours pass with no further action. | |
abandoned: This Three-Step Redirect API transaction has not been completed, and has timed out. | |
failed: This transaction has failed. | |
canceled: This transaction has been voided. | |
complete: This transaction has settled. | |
unknown: An unknown error was encountered while processing this transaction. | |
transaction_type | Retrieves only transactions with the specified transaction type. Use one of the following to specify payment type: |
cc: A credit card transaction. | |
ck: A check transaction. | |
action_type |
Retrieves only transactions with the specified action types. A combination of the values can be used and should be separated by commas. For example, to retrieve all transactions with credit or refund actions, use the following:
Example: action_type=refund,credit |
sale: Sale transactions. | |
refund: Refund transactions. | |
credit: Credit transactions. | |
auth: ‘Auth Only’ transactions. | |
capture: Captured transactions. | |
void: Voided transactions. | |
return: Electronic Check (ACH) transactions that have returned, as well as credit card chargebacks. | |
source |
Retrieves only transactions with a particular ‘transaction source’. A combination of the values can be used and should be separated by commas. For example, to retrieve all transactions with api or recurring actions, use the following: Example: source=api,recurring |
api: API transactions. | |
batch_upload: Batch Upload transactions. | |
mobile: Mobile (iProcess) transactions. | |
quickclick: QuickClick transactions. | |
quickbooks: QuickBooks SyncPay transactions. | |
recurring: Recurring transactions when using Recurring module. | |
swipe: SwIPe Software transactions. | |
virtual_terminal: Virtual Terminal transactions. | |
internal: Internal transactions. Typically indicates settlement | |
transaction_id | Specify a transaction ID or a comma separated list of transaction IDs to retrieve information on. Alternatively, provide a Subscription ID to retrieve processed (approved and declined) transactions associated with it. |
subscription_id | Set a specific subscription record or comma separated list of records. Using this with a transaction search will return all transactions associated with this subscription. This will return this subscription’s payment/plan information when used with report_type=recurring. |
invoice_id | Set a specific Invoice ID. Should only be used when report_type=invoicing. |
partial_payment_id | Retrieves only transactions with the specified partial payment ID. |
order_id | Retrieves only transactions with the specified Order ID. |
first_name | Retrieves only transactions with the specified first name. |
last_name | Retrieves only transactions with the specified last name. |
address1 | Retrieves only transactions with the specified specified address. |
city | Retrieves only transactions with the specified city. |
state | Retrieves only transactions with the specified state. |
zip | Retrieves only transactions with the specified zip/postal code. |
phone | Retrieves only transactions with the specified phone number. |
fax | Retrieves only transactions with the specified fax number. |
order_description | Retrieves only transactions with the specified order description. |
drivers_license_number | Retrieves only transactions with the specified driver’s license number. |
drivers_license_dob | Retrieves only transactions with the specified driver’s license date of birth. |
drivers_license_state | Retrieves only transactions with the specified driver’s license state. |
Retrieves only transactions with the specified billing email address. | |
cc_number | Retrieves only transactions with the specified credit card number. You can use either the full number or the last 4 digits of the credit card number. |
merchant_defined_field_# | Retrieves only transactions with the specified merchant defined field value. Replace the ‘#’ with a field number (1-20) (Example: merchant_defined_field_12=value) |
start_date | Only transactions that have been modified on or after this date will be retrieved. Note that any actions performed on a transaction will cause the modified date to be updated.
Format: YYYYMMDDhhmmss |
end_date | Only transactions that have been modified on or before this date will be retrieved. Note that any actions performed on a transaction will cause the modified date to be updated.
Format: YYYYMMDDhhmmss |
report_type |
Allows customer vault information or a html receipt to be returned. If you would like to query the Customer Vault to view what customer information is stored in the Customer Vault, you must set the customer_vault variable. If you omit the customer_vault_id, the system will return all customers that are stored in the vault. If you include a customer_vault_id, it will return the customer record associated with that ID. Example: report_type=customer_vault&customer_vault_id=123456789 |
receipt: Will return an html receipt for a specified transaction id. | |
customer_vault: Set the Query API to return Customer Vault data. | |
recurring: Set the Query API to return subscription data. | |
recurring_plans: Set the Query API to return plan data. | |
invoicing: Set the Query API to return invoicing data. | |
gateway_processors: Will return Processor details a user has permissions for. Specify a “user” by querying with that security key. | |
account_updater: Will return Customer Vault data that has been updated using the Account Updater service. | |
test_mode_status: Will return whether the account has test mode active or inactive. | |
mobile_device_license |
Retrieves only transactions processed using the specified mobile device. The device IDs for this parameter are available in the License Manager. Use ‘any_mobile’ to retrieve all mobile transactions. A combination of the values can be used and should be separated by commas. Can not be used with ‘mobile_device_nickname’. Example 1: mobile_device_license=D91AC56A-4242-3131-2323-2AE4AA6DB6EB |
mobile_device_nickname |
Retrieves only transactions processed using mobile devices with the specified nickname. The nicknames for this parameter are available in the License Manager. Can not be used with ‘mobile_device_license’. Example (URL encoded): mobile_device_nickname=Jim’s%20iPhone |
customer_vault_id | Set a specific Customer Vault record. Should only be used when report_type=customer_vault. |
date_search |
Allows Customer Vault information to be returned based on the ‘created’ or ‘updated’ date. If you would like to query the Customer Vault to view when customer information was created or updated, you must set the report_type variable with the customer_vault value.
If you omit the report_type variable, the system will ignore the date_search variable. Example: |
created: Will return Customer Vault data created during a specified date range. | |
updated: Will return Customer Vault data updated during a specified date range. | |
result_limit | Determines the maximum number of results that may return for the current query. |
page_number | Determines which “page” of results are returned. For example, “result_limit=100&page_number=0” will return the first 100 results. Using “page_number=1” will return the next 100 results. Default is “0”. |
result_order | Determines order of in which results are returned. Default value is “standard”. |
standard: Returns the results from oldest to newest. | |
reverse: Returns the results from newest to oldest. | |
invoice_status | |
Specify a comma separated list of what invoice statuses will return when using an “invoicing” report type.
Example: invoice_status=open,closed,paid |
|
open: Open Invoices | |
paid: Paid Invoices | |
closed: Closed Invoices | |
past_due: Past Due Invoices |
<nm_response>
<transaction>
<transaction_id>2612675976</transaction_id>
<partial_payment_id></partial_payment_id>
<partial_payment_balance></partial_payment_balance>
<platform_id></platform_id>
<transaction_type>cc</transaction_type>
<condition>complete</condition>
<order_id>1234567890</order_id>
<authorization_code>123456</authorization_code>
<ponumber></ponumber>
<order_description></order_description>
<first_name>John</first_name>
<last_name>Smith</last_name>
<address_1>123 Main St</address_1>
<address_2>Apt B</address_2>
<company></company>
<city>New York City</city>
<state>NY</state>
<postal_code>10001</postal_code>
<country>US</country>
<email>johnsmith@example.com</email>
<phone>1234567890</phone>
<fax></fax>
<cell_phone></cell_phone>
<customertaxid></customertaxid>
<customerid></customerid>
<website></website>
<shipping_first_name></shipping_first_name>
<shipping_last_name></shipping_last_name>
<shipping_address_1></shipping_address_1>
<shipping_address_2></shipping_address_2>
<shipping_company></shipping_company>
<shipping_city></shipping_city>
<shipping_state></shipping_state>
<shipping_postal_code></shipping_postal_code>
<shipping_country></shipping_country>
<shipping_email></shipping_email>
<shipping_carrier></shipping_carrier>
<tracking_number></tracking_number>
<shipping_date></shipping_date>
<shipping>1.00</shipping>
<shipping_phone></shipping_phone>
<cc_number>4xxxxxxxxxxx1111</cc_number>
<cc_hash>f6c609e195d9d4c185dcc8ca662f0180</cc_hash>
<cc_exp>1215</cc_exp>
<cavv></cavv>
<cavv_result></cavv_result>
<xid></xid>
<eci></eci>
<directory_server_id></directory_server_id>
<three_ds_version></three_ds_version>
<avs_response>N</avs_response>
<csc_response>M</csc_response>
<cardholder_auth></cardholder_auth>
<cc_start_date></cc_start_date>
<cc_issue_number></cc_issue_number>
<check_account></check_account>
<check_hash></check_hash>
<check_aba></check_aba>
<check_name></check_name>
<account_holder_type></account_holder_type>
<account_type></account_type>
<sec_code></sec_code>
<drivers_license_number></drivers_license_number>
<drivers_license_state></drivers_license_state>
<drivers_license_dob></drivers_license_dob>
<social_security_number></social_security_number>
<processor_id>processora</processor_id>
<tax>1.00</tax>
<currency>USD</currency>
<surcharge></surcharge>
<tip></tip>
<card_balance></card_balance>
<card_available_balance></card_available_balance>
<entry_mode>Keyed</entry_mode>
<cc_bin>411111</cc_bin>
<cc_type>visa</cc_type>
<signature_image>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAAEnQA
ABJ0Ad5mH3gAAACGSURBVDhPlZGBEoAgCEO1//9nG83mxMrr3dkBG0hVW2vFqLX26CYbPIc7ySAVe8LBq5u4elyV4M0NXIoGXYqA
w4QqMAwJCRu+Az7HSlvgHtexlFKwGrLjG/h/rESmhrhRnLCKwjiNeLYv5QsXOoNSig8IsNYaZ0tXJoGU9hU1k18XlZLOQHTenf7I
cf3BwAAAABJRU5ErkJggg==
</signature_image>
<product>
<sku>RS-100</sku>
<quantity>1.0000</quantity>
<description>Red Shirt</description>
<amount>10.0000</amount>
</product>
<action>
<amount>11.00</amount>
<action_type>sale</action_type>
<date>20150312215205</date>
<success>1</success>
<ip_address>1.1.1.1</ip_address>
<source>virtual_terminal</source>
<api_method></api_method>
<username>demo</username>
<response_text>SUCCESS</response_text>
<batch_id>0</batch_id>
<processor_batch_id></processor_batch_id>
<response_code>100</response_code>
<processor_response_text>NO MATCH</processor_response_text>
<processor_response_code>00</processor_response_code>
<requested_amount>11.00</requested_amount>
<device_license_number></device_license_number>
<device_nickname></device_nickname>
</action>
<action>
<amount>11.00</amount>
<action_type>level3</action_type>
<date>20150312215205</date>
<success>1</success>
<ip_address>1.1.1.1</ip_address>
<source>virtual_terminal</source>
<api_method></api_method>
<username>demo</username>
<response_text></response_text>
<batch_id>0</batch_id>
<processor_batch_id></processor_batch_id>
<response_code>100</response_code>
<processor_response_text></processor_response_text>
<processor_response_code></processor_response_code>
<device_license_number></device_license_number>
<device_nickname></device_nickname>
</action>
<action>
<amount>11.00</amount>
<action_type>settle</action_type>
<date>20150313171503</date>
<success>1</success>
<ip_address></ip_address>
<source>internal</source>
<api_method></api_method>
<username></username>
<response_text>ACCEPTED</response_text>
<batch_id>76158269</batch_id>
<processor_batch_id>782</processor_batch_id>
<response_code>100</response_code>
<processor_response_text></processor_response_text>
<processor_response_code>0000000000021980</processor_response_code>
<device_license_number></device_license_number>
<device_nickname></device_nickname>
</action>
</transaction>
</nm_response>
function testXmlQuery($security_key,$constraints)
{
// transactionFields has all of the fields we want to validate
// in the transaction tag in the XML output
$transactionFields = array(
'transaction_id',
'partial_payment_id',
'partial_payment_balance',
'platform_id',
'transaction_type',
'condition',
'order_id',
'authorization_code',
'ponumber',
'order_description',
'first_name',
'last_name',
'address_1',
'address_2',
'company',
'city',
'state',
'postal_code',
'country',
'email',
'phone',
'fax',
'cell_phone',
'customertaxid',
'customerid',
'website',
'shipping_first_name',
'shipping_last_name',
'shipping_address_1',
'shipping_address_2',
'shipping_company',
'shipping_city',
'shipping_state',
'shipping_postal_code',
'shipping_country',
'shipping_email',
'shipping_carrier',
'tracking_number',
'shipping_date',
'shipping',
'shipping_phone',
'cc_number',
'cc_hash',
'cc_exp',
'cavv',
'cavv_result',
'xid',
'eci',
'avs_response',
'csc_response',
'cardholder_auth',
'cc_start_date',
'cc_issue_number',
'check_account',
'check_hash',
'check_aba',
'check_name',
'account_holder_type',
'account_type',
'sec_code',
'drivers_license_number',
'drivers_license_state',
'drivers_license_dob',
'social_security_number',
'processor_id',
'tax',
'currency',
'surcharge',
'tip',
'card_balance',
'card_available_balance',
'entry_mode',
'cc_bin',
'cc_type'
);
// actionFields is used to validate the XML tags in the
// action element
$actionFields = array(
'amount',
'action_type',
'date',
'success',
'ip_address',
'source',
'api_method',
'username',
'response_text',
'batch_id',
'processor_batch_id',
'response_code',
'processor_response_text',
'processor_response_code',
'device_license_number',
'device_nickname'
);
$mycurl=curl_init();
$postStr='security_key='.$security_key.$constraints;
$url="https://secure.apsmerchantgateway.com/api/query.php?". $postStr;
curl_setopt($mycurl, CURLOPT_URL, $url);
curl_setopt($mycurl, CURLOPT_RETURNTRANSFER, 1);
$responseXML=curl_exec($mycurl);
curl_close($mycurl);
$testXmlSimple= new SimpleXMLElement($responseXML);
if (!isset($testXmlSimple->transaction)) {
throw new Exception('No transactions returned');
}
$transNum = 1;
foreach($testXmlSimple->transaction as $transaction) {
foreach ($transactionFields as $xmlField) {
if (!isset($transaction->{$xmlField}[0])){
throw new Exception('Error in transaction_id:'. $transaction->transaction_id[0] .' id Transaction tag is missing field ' . $xmlField);
}
}
if (!isset ($transaction->action)) {
throw new Exception('Error, Action tag is missing from transaction_id '. $transaction->transaction_id[0]);
}
$actionNum = 1;
foreach ($transaction->action as $action){
foreach ($actionFields as $xmlField){
if (!isset($action->{$xmlField}[0])){
throw new Exception('Error with transaction_id'.$transaction->transaction_id[0].'
Action number '. $actionNum . ' Action tag is missing field ' . $xmlField);
}
}
$actionNum++;
}
$transNum++;
}
return;
}
try {
$constraints = "&action_type=sale&start_date=20060913";
$result = testXmlQuery('6457Thfj624V5r7WUwc5v6a68Zsd6YEm',$constraints);
print "Success.\n";
} catch (Exception $e) {
echo $e->getMessage();
}
const https = require('https');
const querystring = require('querystring');
const security_key = '{security_key}';
const hostName = 'secure.apsmerchantgateway.com';
const path = '/api/query.php';
const actionType = 'sale'; // Can be any valid Query API action.
// Create the post data body to pass into request
const postData = querystring.stringify({
'security_key': security_key,
'action_type': actionType,
});
const options = {
hostname: hostName,
path: path,
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': Buffer.byteLength(postData)
}
};
// Make request to Query API
const req = https.request(options, (response) => {
console.log(`STATUS: ${response.statusCode}`);
console.log(`HEADERS: ${JSON.stringify(response.headers)}`);
response.on('data', (chunk) => {
console.log(`BODY: ${chunk}`);
});
response.on('end', () => {
console.log('No more data in response.');
});
});
req.on('error', (e) => {
console.error(`Problem with request: ${e.message}`);
});
// Write post data to request body
req.write(postData);
req.end();
The ChipDNA Mobile EMV SDK for iOS and Android allows developers to create software that integrates with mobile Bluetooth payment terminals. The SDK abstracts many of the complexities of interacting with terminals so that you can focus on building great apps.
The SDK works with the following payment terminals, all of which need to be purchased through the merchant’s gateway provider.
The SDK is available for iOS and Android and can be downloaded with either of the links below. Full documentation is available in the download.
There are two parts to the Mobile SDK, the end-to-end encryption method and the swipe device library.
The end-to-end encryption library allows credit card data to be encrypted on a mobile device before sending it to the Merchant’s back-end server. During the sale process, the Merchant’s server can send the encrypted card data to the Payment Gateway, where it is decrypted and treated like a normal credit card. This gives the merchant more control of mobile transactions without having to increase compliance costs.
The merchant’s encryption key is an RSA public key that is unique to them. This means that the encrypted credit card data will only be able to be used to make a transaction in that merchant’s payment gateway account. Only the Payment Gateway has access to the private key that corresponds to this public key.
Card data is encrypted using AES encryption with a new randomly generated key for every card. This key is then encrypted with the public key along with the card data. This packet (the encrypted card and AES key) is unreadable to anybody without the private key which is only known to the Payment Gateway.
Note: The public key cannot be used to decrypt an encrypted card. Once encrypted, the card is unusable except by the Gateway when it processes the payment for the merchant. For this reason, there is no need to keep the public key a secret.
This library supports the encrypted card readers supported by the payment gateway. This includes parsing the data and notifying you when a card reader is connected, disconnected, ready to receive a swipe, etc.
The fastest way to get started is to check out the Client Encryption Example project that can be downloaded from the downloads section. Or if you prefer to create your own project, use these steps:
repositories {
flatDir {
dirs 'libs'
}
}
compile '{applicationId}:payment:gateway@aar'
You may notice the library attempting to connect to IDTECH’s website to download a file. Since the audio jack capabilities of different Android devices vary, the IDTECH Shuttle’s library uses different communication settings for each supported device. IDTECH frequently updates a list of the supported devices and the communication settings for each which the library may attempt to download from IDTECH. Internet permission is required.
After logging into the Payment Gateway, navigate to Settings -> Security Keys -> View Mobile SDK Key. You can click on the Java example button to get a version that can easily be copied and pasted into your project.
Use the Query API. In order to get the public key, you will need to use ‘report_type=sdk_key’. The key will be returned in the <sdk_key> tag.
The following is an example of the entire encryption process:
import com.SafeWebServices.PaymentGateway.PGEncrypt;
PGEncrypt pg = new PGEncrypt();
Pg. setKey(
"***999|MIIEEjCCA3ugAwIBAgIBADANBgkqhkiG9w0BAQQFADCBvTELMAkGA1UEBh"
"MCVVMxETAPBgNVBAgTCElsbGlub2lzMRMwEQYDVQQHEwpTY2hhdW1idXJnMRgwFg"
[Several lines omitted]
"cNAQEEBQADgYEAKY8xYc91ESNeXZYTVxEsFA9twZDpRjSKShDCcbutgPlC0XcHUt"
"a2MfFPsdgQoq0I8y1nEn1qJiOuEG1t9Uwux4GAvAPzsWSsKyKQkZhqxrxkJUB39K"
"Pg57pPytfJnlQTgYiSrycCEVHdDvhk92X7K2cab3aVV1+j0rKlR/Sy6b4=***");
PGKeyedCard cardData = new PGKeyedCard(cardNumber, expiration, cvv);
Boolean includeCVV = true;
String encryptedCardData = pg.encrypt(cardData, includeCVV);
In this example, ‘encryptedCardData’ would now contain a string that can be passed to the Payment Gateway in place of credit card information. The parameter name to use when passing this value is ‘encrypted_payment’.
For example, a simple DirectPost API string would look something like this:
(This example assumes your Merchant server is running a PHP script that has received the encrypted card data through a POST parameter called ‘cardData’.)
//Business logic, validation, etc. When ready to process the payment...
$cardData = $_POST['cardData'];
$postString = "security_key=6457Thfj624V5r7WUwc5v6a68Zsd6YEm&type=sale&amount=1.00&encrypted_payment=$cardData";
//Post to Gateway
We suggest using POST instead of GET to reduce the possibility of the data being kept in a log file. For more information on how to communicate with the Payment Gateway, see the API documentation.
You will need to grant the application multiple permissions in order to use a swipe device. This can be done by modifying the manifest file by adding:
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.INTERNET" />
In the class that intends to handle swipe events, add a PGSwipeController property called swipeController, and then in your init function, initialize the object with this line:
//This example is for the iPS Encrypted Mobile Card ReaderswipeController = new PGSwipeController(this, PGSwipeDevice.SwipeDevice.IPS);
If you want to change the default settings, you can change them now. Here are some examples:
swipeController.getDevice().setSwipeTimeout(30);
swipeController.getDevice().setAlwaysAcceptSwipe(false);
swipeController.getDevice().setActivateReaderOnConnect(false);
Your class will have to implement the PGSwipeListener protocol. If you are only interested in knowing when a card is swiped, you can safely leave every other event handler empty, as shown here (or add your own code to, for example, display an image indicating that the swipe reader is ready for a swipe). In this example, when the swipe is received, the card data is saved in a property (swipedCard) for eventual transmission to the Gateway (not shown), and two TextView variables (cardNumberField and expirationField) are set to show the masked card number and expiration date. If a bad swipe occurs, onSwipedCard is still called, but “card” will be null.
@Override
public void onDeviceConnected(final PGSwipeDevice device)
{
}
@Override
Public void onDeviceDisconnected(final PGSwipeDevice device)
{
}
@Override
public void onDeviceActivationFinished(final PGSwipeDevice device)
{
}
@Override
public void onDeviceDeactivated(final PGSwipeDevice device)
{
}
@Override
public void onDeviceReadyForSwipe(final PGSwipeDevice device)
{
}
@Override
public void onDeviceUnreadyForSwipe(final PGSwipeDevice device,
PGSwipeDevice.ReasonUnreadyForSwipe reason)
{
}
@Override
public void onSwipedCard(final PGSwipedCard card, final PGSwipeDevice device)
{
if (card != null) {
this.runOnUiThread(new Runnable() {
public void run() {
TextView cardNumberField = (TextView)findViewById(R.id.cardNumber);
cardNumberField.setText((CharSequence)card.getMaskedCardNumber());
}
}
} else {
//A null card means that there was a swipe but it was unsuccessful. }
}
The PGEncrypt class contains all necessary to encrypt data to be sent to the payment gateway. Merchants wanting to send transaction data to their servers before processing the transaction will want to use this method in order to prevent their server from touching sensitive data.
This method takes in the public key and sets it to be used with the encrypt method.
This method accepts a string to be encrypted. Although any string can be passed, the Payment Gateway will only pull fields related to credit cards from the encrypted text.
This is the preferred way of getting the encrypted card data. It will format and encrypt the card data for you to pass on to the gateway.
This class represents the functionality that is common to the swipe reader devices. A PGSwipeDevice object is passed along with every even generated by the devices in order to identify the device type and access device-specific features by casting it to the specific swipe device.
Used to explain why the device can no longer accept a swipe.
Used to identify the type of device being used.
Returns true if the swipe device is connected.
Returns true if the swipe device is activated.
Returns true if the swipe device is ready.
Returns the current device type.
Sets the event listener.
Sets the timeout interval for the swipe device.
True by default, if this is set to false, a swipe must be requested once the device is ready.
True by default, if this is to false, the device must be activated before it can be used.
Notifies the reader to start waiting for a swipe. The device must be active before this can be called.
Cancels a swipe request.
Cancels the current swipe request, unregisters the swipe device, and frees resources. Will not receive any information from the device until it is resumed.
Registers the swipe device. Should only be called after calling stopSwipeController()
Returns the default message for the current device state.
This class handles communications with the iPS Enterprise Encrypted Mobile Card Reader.
This class is not intended to be instantiated directly. Instantiate a PGSwipeController instead. The PGSwipeController will create a PGSwipeEnterprise instance to interact with the iPS Enterprise device.
This class handles communications with the iPS Encrypted Mobile Card Reader.
This class is not intended to be instantiated directly. Instantiate a PGSwipeController instead. The PGSwipeController will create a PGSwipeIPS instance to interact with the IPS device.
This class handles communication with the IDTECH Unimag device.
This class is not intended to be instantiated directly. Instantiate a PGSwipeController instead. The PGSwipeController will create an instance of PGSwipeUniMag to interact with the Shuttle device.
The UNIMAG device uses an xml compatibility list that consists of specific device settings that are unique to every device. This function should be called to handle new devices.
This is a simple base class for the different types of cards that can be used. There is no reason to ever explicitly declare this.
Sets the CVV for the credit card data.
Returns the CVV for the card.
Returns a query string consisting of the card data that can be passed to the Payment Gateway through the Direct Post API.
This class should be used when accepting credit card information from a keyboard.
The standard constructor for this class. It should be used most of the time.
This constructor accepts two more values that would be used for Maestro cards.
Sets the card number to be used for the current card.
Sets the expiration date to be used for the current card.
Sets the start date for the current card.
Sets the issue number for the current card.
Returns the current card number.
Returns the current expiration date.
Returns the current start date.
Returns the current issue number.
This class should only be used along with an unencrypted swipe device.
The constructor that sets the card data accordingly.
Sets track1 for the current card.
Sets track2 for the current card.
Sets track3 for the current card.
Sets the masked card number for the current card.
Sets the name on the current card.
Sets the expiration date for the current card.
Returns the track1 data.
Returns the track2 data.
Returns the track3 data.
Returns the masked card number. This should be used when trying to display card information to the user.
Returns the name on the card.
Returns the expiration date.
This class should be used for all encrypted swipe devices.
The constructor accepts all class variables.
Sets the KSN that is used to decrypt the card information at the gateway.
Returns the KSN.
The PGSwipeController class is used to maintain the swipe device.
This constructor sets the type of device to be used and initializes it.
This constructor can be used if the activity can not be passed. It also sets the type of device to be used and initializes it.
Returns the device that is currently initialized. Only one should be initialized at a time.
Can be used instead of getDevice, will produce the same result as long as an IPS Enterprise device is being used.
Can be used instead of getDevice, will produce the same result as long as an IPS device is being used.
Can be used instead of getDevice, will produce the same result as long as a UNIMAG device is being used.
This interface must be implemented in order to receive events from the card readers
Method called when a card is swiped. It accepts the card data and the device used.
Called when the device is ready to read a swipe.
Is called when the device can no longer read a card. It is passed the device and the reason it can no longer accept a swipe.
This method is called when the swipe device is connected.
This method is called when the swipe device is unplugged from the android device.
This method is called when a swipe can be requested.
This method is called when the device is stopped. Once this is called, the device has to be restarted to function again.
The fastest way to get started is to check out the PaymentGatewayEncryptionExample and PaymentGatewaySwipeExample projects that can be downloaded from the Payment Gateway’s Integration section. If you prefer to create your own project instead, use these steps (current as of Xcode 6.0):
Note: You may wish to skip step 5 if you do not need to support the iDynamo. Apple requires manufacturers of accessories that use the dock connector to add your app to their product plan before approving your app for the app store. You will need to contact MagTek in order to have your app added to their product plan. Contact MagTek for more details.
Adding the doc set to Xcode allows the most up-to-date, relevant documentation to appear in the IDE as you type. To enable access to the SDK documentation from inside Xcode:
The Apple App Store’s current policy is to require mobile apps to purchase digital goods (e.g. downloadable content, etc.) through the App Store. For that reason, this SDK is intended only for use in apps selling real-world goods and services. Please direct questions about Apple’s App Store policies to Apple. Their policies are subject to change at their discretion.
After logging into the Payment Gateway, navigate to Settings->Security Keys->View Mobile SDK Key. You can click on the Objective-C example link to get a version that can easily be copied and pasted into your project.
Use the Query API. In order to get the public key, you will need to use ‘report_type=sdk_key’. The key will be returned in the <sdk_key> tag.
#import "PGEncrypt.h"
#import "PGCards.h"
PGEncrypt encryption = [[PGEncrypt alloc] init];
[encryption setKey:
@"***999|MIIEEjCCA3ugAwIBAgIBADANBgkqhkiG9w0BAQQFADCBvTELMAkGA1UEBh"
"MCVVMxETAPBgNVBAgTCElsbGlub2lzMRMwEQYDVQQHEwpTY2hhdW1idXJnMRgwFg"
[Several lines omitted]
"cNAQEEBQADgYEAKY8xYc91ESNeXZYTVxEsFA9twZDpRjSKShDCcbutgPlC0XcHUt"
"a2MfFPsdgQoq0I8y1nEn1qJiOuEG1t9Uwux4GAvAPzsWSsKyKQkZhqxrxkJUB39K"
"Pg57pPytfJnlQTgYiSrycCEVHdDvhk92X7K2cab3aVV1+j0rKlR/Sy6b4=***"];
PGCard *cardData = [[PGKeyedCard alloc] initWithCardNumber:cardNumberField.text
expirationDate:expirationField.text
cvv:cvvField.text];
NSString *encryptedCardData = [encryption encrypt:cardData includeCVV:NO];
encryptedCardData will contain a string that can be passed to the Payment Gateway in place of credit card information. The parameter name to use when passing this value through DirectPost is “encrypted_payment”. For example, a simple DirectPost API string would look something like this:
(This example assumes your Merchant server is running a PHP script that has received the encrypted card data through a POST parameter called ‘cardData’.)
//Business logic, validation, etc. When ready to process the payment...
$cardData = $_POST['cardData'];
$postString = "security_key=6457Thfj624V5r7WUwc5v6a68Zsd6YEm&type=sale&amount=1.00&encrypted_payment=$cardData";
//Post to Gateway
For more information on how to communicate with the Payment Gateway, see the API documentation.
In the class that intends to handle swipe events, create a PGSwipeController object in your init method. Initialize the object with one of these lines to support specific readers:
swipeController = [[PGSwipeController alloc] initWithDelegate:self audioReader:AudioJackReaderIpsEnterprise];
swipeController = [[PGSwipeController alloc] initWithDelegate:self audioReader:AudioJackReaderUnimag];
Only a single model of audio jack-connected reader can be enabled at a time. The audioReader parameter allows you to choose which type you want to allow. See the PGSwipeController’s initWithDelegate:audioReader: documentation for more details.
Your class will have to implement the PGSwipeDelegate protocol. If you are only interested in knowing when a card is swiped, you can safely leave every other event handler empty, as shown here (or add your own code to, for example, display an image indicating that the swipe reader is ready for a swipe). In this example, when the swipe is received, the card data is saved in a property (swipedCard) for eventual transmission to the Gateway (not shown), and two UITextField properties (cardNumberField and expirationField) are set to show the masked card number and expiration date.
If a bad swipe occurs, didSwipeCard:device: may still be called, but “card” will be nil. An error message is displayed in this example. Note: Not all card reader models give feedback when a bad swipe is received.
-(void)deviceConnected:(PGSwipeDevice *)sender
{
}
-(void)deviceDisconnected:(PGSwipeDevice *)sender
{
}
-(void)deviceActivationFinished:(PGSwipeDevice *)sender result:(SwipeActivationResult)result
{
}
-(void)deviceDeactivated:(PGSwipeDevice *)sender
{
}
-(void)deviceBecameReadyForSwipe:(PGSwipeDevice *)sender
{
}
-(void)deviceBecameUnreadyForSwipe:(PGSwipeDevice *)sender reason:(SwipeReasonUnreadyForSwipe)reason;
{
}
-(void)didSwipeCard:(PGSwipedCard *)card device:(PGSwipeDevice *)sender
{
if (card != nil) {
swipedCard = [card retain];
cardNumberField.text = card.maskedCardNumber;
expirationField.text = card.expirationDate;
} else {
//A nil card means that there was a swipe but it was unsuccessful.
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Swipe Error"
message:@"The reader was not able to read the card. Please Try Again."
delegate:nil
cancelButtonTitle:@"OK"
otherButtonTitles:nil];
[alert show];
[alert release];
}
}
The PGSwipeController contains a set of swipe reader classes that control individual swipe readers. This is the main Mobile Swipe SDK class required for using swipe devices, intended to be instantiated near the app’s startup. The delegate you set on the PGSwipeController is the object that will receive all of the SDK’s swipe events.
Through this class, you can access the controller classes for individual swipe device types (PGSwipeIpsEnterprise * ipsEnterpriseReader, PGSwipeIDynamo *iDynamoReader, and PGSwipeUniMag *uniMagReader).
You should be sure to call initWithDelegate rather than the parameterless init because during initialization a check is made to see if any devices are already connected and sends a deviceConnected event if they are. If the parameterless init is used, the initial connection message will be missed.
Initializes the PGSwipeController and the individual swipe reader classes. Init checks if any devices are connected and sends a deviceConnected event if they are, so initWithDelegate: should always be used rather than init to ensure that a connection event is received if the device is already connected.
The audioReader: parameter selects which type of audio jack-connected card reader to enable. Only one type of audio jack-connected reader can be used at a time to prevent more than one device library from attempting to access the audio system at the same time. AudioJackReaderIpsEnterprise enables the IPS Enterprise Encrypted Card Reader library, and AudioJackReaderUnimag enables the Shuttle library. You may also select AudioJackReaderNone to disable both libraries, or AudioJackReaderAutodetectOnConnect to allow the SDK to attempt to determine the type on connection. Autodetection has several drawbacks. See PGSwipeController beginAutodetectAudioJackCardReader for more information.
Sets the enabled audioJackReaderType. This can be used to enable support for either the IPS Enterprise Encrypted Card Reader or the UniMag (Shuttle) reader. Since the underlying libraries may not always unload cleanly, you should avoid calling this repeatedly to change the supported device type. Doing so could cause the reader to malfunction or be damaged. Setting this to AudioJackReaderAutodetectOnConnect will disable any currently selected audioJackReaderType and autodetect upon device connection.
messageOptions will be used only when audioJackReaderType is AudioJackReaderUnimag to replace the default message options. For any other AudioJackReaderType, or to use the default message options for AudioJackReaderUnimag, this should be nil.
Asynchronously attempts to detect the card reader type currently attached to the audio jack.
A communication test is first attempted for an IPS Enterprise reader, then an attempt is made to power up a UniMag (Shuttle) card reader. If either test succeeds, the audioJackReaderType is set to the correct value, and the device will be made ready for use. The result of the autodetect is reported to the delegate through deviceAutodetectComplete:.
Note: All tests produce very loud tones through the audio jack. If speakers or headphones are attached, the tones would be unpleasant to the user. It is recommended that the user be warned and allowed to remove headphones before calling this function. This library suppresses user notifications from the UniMag reader during autodetect.
Because the device is powered up in order to test it, you will not receive connection / activation / ready for swipe events during detection. When your delegate receives its deviceAutodetectComplete message, check the isConnected, isActive, and isReadyForSwipe properties for its current state and to complete any initialization.
In order to detect the devices, all of the underlying card reader libraries must be loaded. Under some circumstances, these libraries may not unload cleanly, resulting in unreliable use of the card reader. Autodetect is also a very slow process. For these reasons, you should not rely on autodetection for each use of the app.
Because communication through the audio jack is not always perfect, autodetect does not always return a correct result. The most common failure type is returning CardReaderAutodetectResultFail even though a supported device is connected.
If it is known in advance which card reader type will be used, that type should be specified when initializing the PGSwipeController. If multiple devices must be supported, it is strongly recommended that the result of the autodetect be saved (e.g. in NSUserDefaults) and re-used on app startup.
The PGSwipeDevice class represents the functionality that is common to the swipe reader devices.
A PGSwipeDevice object is passed along with every event generated by the swipe devices to allow you to identify the device type and access device-specific features by casting to the specific swipe type.
True when the reader is physically attached to the device.
True when the reader is powered up / initialized.
True when the reader is able to accept card swipes from the user.
Sets the delegate that will receive the device’s events. You should not set the delegate directly. Setting the delegate on the PGSwipeController sets the delegate for each of its members.
The PGSwipeDelegate protocol must be implemented by the class that intends to receive swipe reader events. The following event handlers will need to be implemented.
This event is sent whenever the user swipes a card. Normally “card” will be either a PGEncryptedSwipedCard or PGMagnesafeSwipedCard (depending on the swipe reader) with track data, masked card number, expiration date, and cardholder name. If the swiped card cannot be read, “card” will be nil.
This event is sent when isReadyForSwipe becomes true. Between this event and the receipt of deviceBecameUnreadyForSwipe, any swipe should produce a didSwipeCard event.
This event is sent when isReadyForSwipe becomes false. There are many reasons the reader could become unready to receive swipe events, e.g. the swipe request times out, the device is disconnected, etc. Check the value of “reason” to determine the cause.
On Shuttle readers, if you have set the device to alwaysAcceptSwipe, the reason may be set to SwipeReasonUnreadyForSwipeRefreshing. In that case, there is no need to request a new swipe. The “unready” state is momentary while the device automatically renews after a timeout, swipe, or other event.
Occurs when the reader is physically connected to the device. With audio-port connected devices, this event can be sent when the user attaches headphones.
Occurs when the reader is physically disconnected from the device. With audio-port connected devices, this event can be sent when the user detaches headphones.
Occurs when the device has finished an attempt to power up/initialize. This may occur at the same time as deviceConnected or later, depending on the device and settings. See the individual device documentation for specifics.
Receiving this event does not mean the initialization succeeded. Be sure to check the value of “result” to verify that it is SwipeActivationResultSuccess.
Occurs when the device has powered down. This may occur when the device is disconnected or, for certain swipe readers, when you make a call to power down the device.
Occurs when an attempt to detect the type of an audio jack-connected card reader has started. This can be triggered by a manual call to PGSwipeController beginAutodetectAudioJackCardReader or automatically when the PGSwipeController is in AudioReaderAutodetectOnConnect mode and an object is attached to the audio jack by the user.
Occurs when an attempt to detect the type of an audio jack-connected card reader has finished. The result may be CardReaderAutodetectResultIpsEnterprise, CardReaderAutodetectResultUniMag, or CardReaderAutodetectResultFail if the type could not be determined.
When this message is received, the PGSwipeController’s audioJackReaderType will have been set to the appropriate value and the card reader will be activated. Since the device is powered up while autodetecting, no events for connection, activation, or readyForSwipe will be received. Check the isConnected, isActivated, and isReadyForSwipe properties to determine the device’s state.
This class is the interface to the IPS Enterprise Encrypted Card Reader. It is not intended to be instantiated directly. Instantiate a PGSwipeController instead. The PGSwipeController will create a PGSwipeIpsEnterprise instance to interact with the IPS Enterprise device.
Gets or sets the delegate that will receive events. You should not set this directly. When the PGSwipeController’s delegate is set, it will pass it through to this delegate.
Closes the card reader’s connections and disables event handling to allow it to be deallocated. You should not call this directly. It is called by the PGSwipeController when necessary.
Asynchronously sends a communication test message to the card reader device and waits for a response. This can be used to detect whether the connected device is an IPS Enterprise Encrypted Card Reader. A message is sent via the audio jack and if no response is received from the device within 5 seconds, the attached object is assumed not to be an IPS Enterprise reader. Note that calling this will produce a short, loud tone through the audio jack if headphones are attached.
The result is returned to the delegate by calling ipsEnterpriseCommunicationTestCompleteWithResult:(BOOL)succes with success set to YES or NO, depending on if a response was sent by the device.
This class is the interface to the iDynamo reader. It is not intended to be instantiated directly. Instantiate a PGSwipeController instead. The PGSwipeController will create a PGSwipeIDynamo instance to interact with the iDynamo device.
The iDynamo has no configurable options. When the device is attached, it is active and ready for swipe. The only property for the PGSwipeIDynamo class is a delegate to receive events, which should not be set directly. When the delegate is set for the PGSwipeController, the same delegate is passed to the PGSwipeIDynamo instance it contains.
This class is the interface to the IDTECH Shuttle reader. It is not intended to be instantiated directly. Instantiate a PGSwipeController instead. The PGSwipeController will create a PGSwipeUniMag instance to interact with the Shuttle device.
There are several flags and methods available for the Shuttle. For an app that does not need much specific control of the swipe device and is mostly interested in the swipe event, the defaults can be kept and the device will power up and become ready for swipe when attached.
Gets or sets the delegate that will receive events. You should not set this directly. When the PGSwipeController’s delegate is set, it will pass it through to this delegate.
Contains a set of options for interactions with the user, e.g. whether to prompt before powering up the Shuttle and the text of error messages. See the PGSwipeUniMagMessageOptions section for specific settings.
If this is true, the SDK will attempt to power-up the reader when attachment is detected. There are 3 things to be aware of:
If this is set to true, the device’s volume will be set to maximum immediately before any attempt to power on the reader. Since the reader requires full volume to activate, this defaults to true and should normally remain true.
The Shuttle does not accept swipes from the user unless a swipe has been requested. If alwaysAcceptSwipe is true, the SDK will immediately request a swipe and renew the request any time the old swipe request times out or ends. You will still receive periodic didBecomeUnreadyForSwipe: messages, but the reason will be SwipeReasonUnreadyForSwipeRefreshing to indicate that you should be receiving a didBecomeReadyForSwipe: message immediately after without any interaction.
The mobile device’s battery may deplete faster if the swipe reader is always awaiting a swipe. If battery life is a concern, consider setting this to false and using requestSwipe when a swipe is expected, or only setting alwaysAcceptSwipe to true when a swipe is expected.
If alwaysAcceptSwipe is true, you should not use requestSwipe or cancelSwipeRequest. By default, alwaysAcceptSwipe is true.
Powers up the reader if powerUp is true or cancels a power up if powerUp is false. If activateReaderOnAttach is true, this is called automatically after connection to power up the device. If you wish to only power up the device after user interaction, you should wait until a deviceConnected: event is received, then call powerUpDevice:YES when they choose to power up. This should only be used if activateReaderOnAttach is false.
Powers down the reader. This may extend mobile device battery life. A deviceConnected event will be received after shut-down, which will trigger a power-up if activateReaderOnAttach is true, so be sure to set activateReaderOnAttach to false before powering down. It is not necessary to power down the reader before disconnecting it from the device.
Starts listening for swipe events. You will never need to call this if you set alwaysAcceptSwipe to true (it is true by default). After receipt of a didBecomeUnreadyForSwipe message, you may request a new swipe (unless the reason is SwipeUnreadyForSwipeReasonRefreshing). The request will timeout after 20 seconds, or the amount of time you set in setSwipeTimeoutDuration:.
Cancels a swipe request to stop listening for swipe events. You should not use this if you did not manually start the swipe request with a call to requestSwipe.
Sets the time between requestSwipe and when swipes will no longer be accepted. Default and maximum are 20 seconds. The minimum is 3 seconds. This still applies even if alwaysAcceptSwipe is true, but the swipe request will be automatically renewed in that case.
This class contains a set of user-interaction options for the Shuttle device.
If this is set to true (false by default), the reader is activated automatically immediately after you receive a deviceConnected: event. If this is false, you will need to call powerUpDevice: during or after the deviceConnected event to power the device or cancel powering up.
If true, an “Initializing Card Reader…” alert is shown while the reader powers up and is dismissed once power-up completes.
Gets or sets the prompt that will be displayed to confirm that the user would like to power up the reader. If you change this prompt, you should also change cardReaderActivationAtMaxVolumePrompt. Note: an activation prompt is only shown before activation if messageOptions.activateReaderWithoutPromptingUser is false. This message is meant to include a warning to indicate that the volume will be set to max. If automaticallySetVolumeToMaxOnActivate is false, cardReaderActivationAtMaxVolumePrompt is shown instead of this.
Gets or sets the prompt that will be displayed to confirm that the user would like to power up the reader. If you change this prompt, you should also change cardReaderActivationPrompt. Note: an activation prompt is only shown before activation if messageOptions.activateReaderWithoutPromptingUser is false. If automaticallySetVolumeToMaxOnActivate is true and the volume is not at maximum, cardReaderActivationPrompt is shown instead of this.
Gets or sets the alert that is shown if the reader times out while attempting to power up. If you prefer to handle this differently, set this message to nil to prevent it from being shown, then handle the activationDidComplete:result: message with a result of SwipeActivationResultTimeout.
IPS Enterprise and IPS Encrypted Card Readers
The IPS devices are audio jack-connected card readers. Unlike the IDTECH Shuttle, these readers are powered by an internal battery. The IPS devices have a fast startup time and do not produce a constant tone through the audio jack.
Because the IPS devices connect through the audio port and there is no way to immediately detect the device type, you will receive a deviceConnected: event even if the user has only plugged in headphones. Since there is no activation with the IPS devices, a deviceActivated: and deviceBecameReadyForSwipe: will also be sent immediately. In order to be sure that the device is an IPS Enterprise or IPS, the PGSwipeIpsEnterprise and PGSwipeIps provide a beginTestCommunication: method you can use to attempt to communicate with the devices. Success is returned when the device has been successfully identified. This is not done by default to eliminate a delay before the device becomes active.
Both Android and iOS SDKs support the iPS Enterprise Encrypted Card Reader and the UniMag Card Reader. The legacy iPS Encrypted Reader is only supported on Android.
iDynamo
The iDynamo connects to the mobile device via Apple’s dock connector and is only compatible with iOS devices that use the older 30-pin (non-Lightning) dock connector.
When physically attached, the iDynamo is almost immediately ready to receive swipe events. When connected, the Swipe Delegate should expect a deviceConnected: message, immediately followed by a deviceActivationFinished: message, then a deviceBecameReadyForSwipe: message.
When the device is physically detached, the delegate receives the events in reverse order, i.e. deviceBecameUnreadyForSwipe:, deviceDeactivated:, deviceDisconnected:.
App Store: To support the iDynamo on an app distributed through the App Store, Apple may require you to contact MagTek for information before they will process your submission. To disable iDynamo support, do not add it to “Supported external accessory protocols” in your info.plist. You will still receive connect and disconnect events, but activation will fail, so be sure to check if the sending device is the iDynamo object and ignore it if so.
Known Issue with the iDynamo: There is an issue with device disconnection with the iDynamo and iOS’s ExternalAccessory framework. Upon disconnection, the stream communicating with the device is closed, during which you may receive the warning: [NSCondition dealloc]: condition (<NSCondition: 0x1d54ce90> ‘(null)’) deallocated while still in use. After reconnecting, a later disconnect may randomly cause the app to crash with an attempt to send a message to the deallocated instance. This does not occur frequently, and is more likely to occur when rapidly opening and closing the application (which sends a disconnect followed by a reconnect when the app re-opens). This issue is with Apple’s accessory-handling framework. Apple is aware of the issue and may fix it in a future iOS release.
IDTECH Shuttle
The Shuttle (referred to in code as a UniMag device) is an audio jack-connected card reader. It is powered by a tone from the iPod / iPad / mobile phone. Before the Shuttle can receive swipes, it must be powered up.
Because the Shuttle connects through the audio port and there is no way to detect the device type until the device is activated, you will receive deviceConnected events whenever any device is attached to that port. For example, if the user attaches headphones, you will receive a connection event from the Mobile SDK.
The Mobile SDK can be configured to automatically attempt to power on the swipe reader immediately (this is the default), or you can disable the automatic activation and only activate the device when desired (e.g. on a payment screen, or when the user clicks a button).
Important: When powering on the device, the audio volume must be at maximum (done automatically by default). The tone generated through the audio port to activate the device can be very painful to a listener if they have connected speakers or headphones. For this reason, swipeController.uniMagReader.messageOptions.activateReaderWithoutPromptingUser is set to NO by default, causing the SDK to prompt the user for confirmation before activating the reader.
The Shuttle saves battery by only allowing swipes when a swipe has been requested, and a timeout occurs if a swipe is not received quickly enough (20 seconds by default). For simplicity, the SDK defaults to automatically requesting a swipe on activation and continuously renewing the swipe request. If you have issues with battery life, you can set swipeController.uniMagReader.alwaysAcceptSwipe to NO and manually call [swipeController.uniMagReader requestSwipe] when ready for a swipe.
The ChipDNA EMV SDK for Windows and Linux allows developers to create software that integrates with numerous payment terminals suppoted by the gateway. The SDK abstracts many of the complexities of interacting with terminals so that you can focus on building great software.
The SDK works with the following payment terminals, all of which need to be purchased through the merchant’s gateway provider.
The SDK is available for Windows and Linux and can be downloaded with either of the links below. Full documentation is available in the download.
QuickClick buttons can be added to your website using an HTML form. This form can be created using our Button Generator or using the values found in the ‘Variables’ section. The form should use the “POST” method and the action should be https://secure.apsmerchantgateway.com/cart/cart.php.
Some websites do not allow for entry of HTML, and can sometimes act finicky. If this is the case with your website, you have the option of using the Link Alternative which can be pasted on your website as a link. The only way to create this link is by using the Button Generator.
Please note that use of this link will nullify any shopping cart product options or text input (amount) fields as these options appear alongside the HTML button.
Please note that QuickClick is NOT supported via iframes as there are documented browser bugs (notably in Safari) that do not allow the user to view QuickClick due to Safari’s documented blocking of third party cookies.
Name | Value: Description |
---|---|
action | show_cart: Displays the customer’s shopping cart. |
process_cart: Adds one or more products to the customer’s cart. | |
process_variable: This processes a variable amount transaction. During the checkout process, the cardholder is given the ability to specify the amount. This is useful for donations. | |
process_fixed: This processes a fixed amount, single item transaction. This is basically a “Buy Now” type transaction. The customer is not able to specify an amount during checkout. | |
username | Specifies a merchant username. Either this or a key_id is required. Using a key_id method is the preferred. |
key_id | Specifies a development key id. Either this or username is required, this method is preferred. |
hash | The hash field is used to pass a verification hash. By using a verification hash, you can ensure that no one will be able to pass an unauthorized price, SKU, shipping price, or tax information. |
product_taxable_# | Controls whether the product will be affected by the tax rates configured in your QuickClick tax options. Set this to ‘0’ or ‘false’ to ensure that a customer doesn’t get charged taxes on a product/service. The default is true.’ |
order_description | Specifies a description for the product. |
currency | Applies to USD and CAD currencies only. The currency is included with the hash, so it will need to be hashed outside of the button generator, or hashing will need to be turned off. |
language | Specifies the language to be used for the cart and checkout webpages. Current valid values are ‘en’ for English and ‘es’ for Spanish. |
url_finish | Specifies a page that the customer should be sent to after finishing their order. This page will receive several pieces of information concerning the completed order. If you have some programming knowledge, you can have your page process and store this information. The information can be useful for order fulfillment, amongst other things. Please ensure URLs are fully qualified (example: http://www.example.com). |
return_link | Used in place of url_finish in order to skip the QuickClick receipt page. Value should be the url to your own receipt/thank you page. |
return_method | Used to skip the QuickClick receipt page. Value should equal “redirect” |
profile | Specify the profile the button should use. |
customer_receipt | Specifies whether to email the customer a receipt after their transaction is complete. If multiple customer email receipts exist, the name of the desired receipt can be passed as the value, otherwise ‘true’ should be passed. |
merchant_receipt_email | Specifies a list of email addresses to send merchant receipts to. Our system will send merchant receipts to all of the specified recipients in addition to any users that are configured to receive transaction receipts in the Merchant Control Panel. If there are multiple recipients, separate them with a comma. You can also set this to ‘false’ if you do not want any merchant receipts to be sent. |
merchant_defined_field_# | A merchant defined field can be used to pass any type of information you’d like. For example, if you wish the user to specify their mother’s maiden name, you could use a merchant defined field. This information shows up in reports and customer/merchant receipts. The # can be any number 1-20. Descriptions for the merchant defined fields can be set within the Merchant Control Panel’s ‘Gateway Options’. |
shipping_same | Indicates whether the shipping information is the same as the billing information. The default setting is 1 (true). Set this to 0 to always ask the customer for separate shipping information. If you plan on passing other shipping_ parameters (i.e. shipping_first_name), ensure that you set this to 0. For additional options regarding the Shipping Address, examine the QuickClick Customer Information Options in your Merchant Control Panel. |
first_name | The customer’s first name. |
last_name | The customer’s last name. |
address_1 | The first part of the customer’s street address. |
address_2 | The second part of the customer’s street address. |
city | The customer’s city. |
company | A company name. |
postal_code | The customer’s postal (zip) code. |
state | If they’re in the US, this should be the customer’s 2 letter state code. Otherwise, this can be used to pass a province or region. |
country | The customer’s 2 letter country code. |
phone | The customer’s phone number. |
fax | The customer’s fax number. |
website | The customer’s website address. |
The customer’s email address. | |
shipping_first_name | The receiver’s first name. |
shipping_last_name | The receiver’s last name. |
shipping_address_1 | The first part of the receiver’s street address. |
shipping_address_2 | The second part of the receiver’s street address. |
shipping_city | The receiver’s city. |
shipping_company | A receiving company name. |
shipping_postal_code | The receiver’s postal (zip) code. |
shipping_state | If they’re in the US, this should be the receiver’s 2 letter state code. Otherwise, this can be used to pass a province or region. |
shipping_country | The receiver’s 2 letter country code. |
shipping_email | The receiver’s email address. |
amount | Specifies the amount, in US dollars. This is used only for fixed and variable price buttons. |
product_description_# | Specifies a description for the given product. | ||||||||
product_sku_# | Specifies a SKU for a given product to uniquely identify it. | ||||||||
product_quantity_# | Specifies the quantity for a given product number. If this parameter isn’t passed, ‘1’ is assumed. | ||||||||
product_amount_# | Specifies the amount, in US dollars, for the given product. | ||||||||
product_option_#_# |
Product options can allow your customers to make some additional choices before adding a product to their cart. For example, if you’re selling a T-Shirt, you may want to allow the customer to define a size (Small, Medium, or Large) before adding the product to their cart. Up to 3 product options can be defined for a single product. The first number field is the product option number, and the last number field is the product number. For product #1, the product option field names would follow this form:
product_option_1_1 (option #1, product #1) Ultimately, any option values passed in are appended to the product description. This can be very useful when fulfilling orders. If your T-Shirt was defined to have a color option and a size option, the resulting description might look like this: T-Shirt (Red) (Large) The value can be anything you want, and you can utilize any form elements to pass it in (i.e. text, a dropdown, or radio buttons). Also note that our Button Creator is able to generate buttons with product options. |
||||||||
product_option_values_#_# |
The product_option_values field can be used for two main purposes:
The product_option_values field’s naming convention is very similar to that of the product_option field. The first number field is the product option number, and the last number field is the product number. For product #1, the product option field names would follow this form: product_option_values_1_1 (option #1, product #1) |
||||||||
product_shipping_# |
Specifies a set of shipping overrides for a particular product. This field allows you override shipping prices on a per-product and per-country basis. The shipping parameter overrides any settings configured in the Merchant Control Panel QuickClick Options.
|
||||||||
url_continue | Specifies a page that the customer should be sent to when they wish to continue shopping. This only applies to shopping cart buttons. Please ensure URLs are fully qualified (example: http://www.example.com). | ||||||||
url_cancel | Specifies a page that the customer should be sent to after they cancel their order. This only applies to shopping cart buttons. Please ensure URLs are fully qualified (example: http://www.example.com). | ||||||||
checkout | When set to true, the shopping cart page is skipped and the customer is sent immediately to the customer information screen or directly to checkout. This is useful if you need to pass SKUs, but still want a ‘Buy Now’ feel to the checkout process. |
Below are some examples of alternative redirect methods available when using QuickClick HTML. This functionality is not available by default through the button generator and must be added after the fact. Enhanced functionality is not available on Link Alternative URLs.
All URLs provided must be fully qualified (Example: http://www.example.com)
If no redirection is wanted after the transaction a receipt is displayed, leave the ‘Finish URL’ field blank in the Button Generator or exclude url_finish variable from button HTML.
This displays a receipt to the customer and asks them to click ‘Continue’ to finalize the order.
When the customer clicks on continue, the non-sensitive transaction response data is returned via GET to the page included. This allows the Merchant’s website to record a SUCCESSFUL transaction in cases where a programmer has built logic to read our response.
In the button generator, enter a fully qualified URL in the ‘Finish URL’ field or include url_finish variable within the button HTML.
Example:
<input type="hidden" name="url_finish" value="http://www.example.com/finish.html" />
This displays a receipt to the customer and asks them to click Continue to finalize the order. When the customer clicks on continue, they are sent to the page included but the transaction data is not posted back to that page.
Useful if a return to the website is needed, but the site is not recording the transaction data. Not available through the button generator or link alternative. Code must be customized.
Example:
<input type="hidden" name="return_link" value="http://www.example.com/finish.html" />
<input type="hidden" name="return_method" value="post" />
This skips our receipt page and automatically redirects the consumer to the return link URL automatically without clicking Continue to finalize the order. The transaction data is posted back to the website as normal.
QuickClick will not display success to the customer, so the page must be built/programmed to tell the customer that the charge went through. To use this method, do not include the ‘url_finish’ variable within your HTML.
Example:
<input type="hidden" name="return_link" value="http://www.example.com/finish.html" />
<input type="hidden" name="return_method" value="redirect" />
You are not required to use these, but they are helpful if the product has variations or special features. These fields appear alongside the button itself, and NOT within the actual cart system.
An example of the use of these fields would be sizes (Small, Medium, Large, etc.) and/or colors (Blue, Red, Yellow, etc.). Some developers even use these to customize monogrammed items. Here is an example of both:
It is strongly recommended that you always select a key and not ‘No Verification’. This protects the button HTML and prohibits malicious users from altering the code.
It is strongly recommended that you always select a key and not ‘No Verification’. This protects the button HTML and prohibits malicious users from altering the code.
Note: This button does not support shipping and/or tax options.
It is strongly recommended that you always select a key and not ‘No Verification’. This protects the button HTML and prohibits malicious users from altering the code.
Note: This button can also be used for Bill Pay. Once the button has been generated, you can change the button text from ‘Donate’ to ‘Pay Now’ or your desired text by altering this line of code:
<input type="submit" name="submit" value="Donate" />
You will need to have the Administrative Options permission set in order to access QuickClick settings. These can be found by clicking on the QuickClick link under Settings(the link, not in Integration).
In order to choose a pre-existing profile, select ‘Make Default’ to the right of the profile name. If there is no ‘Make Default’ link, the profile is already set.
While field names can not be altered, fields that are not required can be hidden if not needed. Here, you will see a list of all available QuickClick fields.
This is where you can decide which payment methods (Credit Card, Electronic Check) will be accepted by QuickClick.
QuickClick ‘Verification’ involves a hashing so that malicious users are unable to alter the button HTML. This can be turned on and off using this interface. If you do not wish to use Verification you must uncheck ‘Require that all values be verified using a security key’. This will associate your Buttons with your GATEWAY USERNAME.
Please advise that buttons can become void if a username is ever deleted from the Gateway. Using Verification eliminates this possibility.
QuickClick also has the option of requiring your customers to enter a CAPTCHA entry in order to process. This makes it more difficult for fraudsters to use your button for fraud using a bot or brute force tool. This can be disabled and enabled using this interface.
In order to set tax, choose the State from the drop-down, and enter the percentage Tax Rate in the field to the right. When you click ‘Save’, QuickClick will automatically calculate Tax based on the State entered into the Billing Address form when checking out. Tax will NOT appear until this occurs. This setting is specific to the Shopping Cart Button and does not apply to Fixed Price or Donation Buttons.
Rather than charging shipping on a ‘per item basis’ most merchants prefer to use the Shipping threshold module. The threshold is based off of dollar amount. For example, the very first threshold should be below the lowest priced item — it’s suggested to use .01 as the first threshold, and then set both the domestic and international rate. It is not possible to exclude the International field from this threshold.
For example: if you want to offer free shipping on purchases over $100.00, enter shipping threshold as such:
Threshold | Domestic | International |
---|---|---|
100.00 | 0.00 | 0.00 |
You can also choose specific shipping types and mark them up by percentages (including 0% if necessary). For example, if ‘Ground’ is checked, and a 15% markup entered, QuickClick will use the Threshold table and add 15% to the total Shipping dependent on the total amount in the cart. As an example:
Shipping Threshold is 50.00 @ 15.00 Domestic. If I, as the customer, buy 53.00 of product and choose Ground Shipping, my total shipping cost will now be $17.25.
The Gateway supports a Convenience Fee/Surcharge feature which can be used with QuickClick. To change these settings, please navigate to ‘Settings’->’Convenience Fee/Surcharging Configuration’ and activate the option, set the fixed and percentages and the Default Type and click ‘Save’.
Once those are saved, the Default Surcharge Type for QuickClick can be set.
QuickClick buttons will return a response to the ‘Finish URL’ using a query string which can be read in using GET. Here are the variables that will be passed back:
Transactions can be tested using one of two methods. First, transactions can be submitted to any merchant account that is in test mode. Keep in mind that if an account is in test mode, all valid credit cards will be approved but no charges will actually be processed.
The Payment Gateway demo account can also be used for testing at any time. Please use the following key id or username for testing with this account:
key_id: | 3785894 |
username: | demo |
Transaction details should be POST’ed to the following URL:
POST URL: | https://secure.apsmerchantgateway.com/cart/cart.php |
Transactions can be submitted using the following information:
Visa: | 4111111111111111 |
MasterCard: | 5431111111111111 |
Discover: | 6011601160116611 |
American Express: | 341111111111111 |
Diner’s Club: | 30205252489926 |
JCB: | 3541963594572595 |
Maestro: | 6799990100000000019 |
Credit Card Expiration: | 10/25 |
account (ACH): | 123123123 |
routing (ACH): | 123123123 |
<?
// Insert your security key ID here
$gw_merchantKeyId = '[[Gateway Key ID Here]]';
// Insert your security key here
$gw_merchantKeyText = '[[Gateway Key Text Here]]';
function gw_printField($name, $value = "") {
global $gw_merchantKeyText;
static $fields;
// Generate the hash
if($name == "hash") {
$stringToHash = implode('|', array_values($fields)) .
"|" . $gw_merchantKeyText;
$value = implode("|", array_keys($fields)) . "|" . md5($stringToHash);
} else {
$fields[$name] = $value;
}
print "<INPUT TYPE=HIDDEN NAME=\"$name\" VALUE=\"$value\">\n";
}
?>
<FORM METHOD=POST
ACTION="https://secure.apsmerchantgateway.com/cart/cart.php">
<INPUT TYPE=HIDDEN NAME="customer_receipt" VALUE="true">
<INPUT TYPE=HIDDEN NAME="key_id" VALUE="<?=$gw_merchantKeyId?>">
<INPUT TYPE=HIDDEN NAME="url_finish" VALUE="http://example.org/finsh_url.html">
<?
// Print the description, SKU, shipping, and amount using the gw_printField
// function. Don't call the gw_printField function for fields that you
// wish to omit (ie. shipping)
?>
<? gw_printField("action", "process_fixed"); ?>
<? gw_printField("order_description", "Product #1"); ?>
<? gw_printField("shipping", "fixed|5.00"); ?>
<? gw_printField("amount", "7.95"); ?>
<?
// Once all product information fields are printed, print the hash field
// There is no need to specify a value when printing the hash field.
?>
<? gw_printField("hash"); ?>
<INPUT TYPE=SUBMIT VALUE="Buy">
</FORM>
<%
' Do not forget obtain md5_lib.asp from our code samples page:'
' https://secure.apsmerchantgateway.com/merchants/resources/examples.php'
%>
<!--#include virtual="md5_lib.asp"-->
<%
' A security key id and key text can be obtained within the Merchant Control'
' Panel, under Options>Security Keys'
Private Const gw_merchantKeyId = "[[Gateway Key ID Here]]"
Private Const gw_merchantKeyText = "[[Gateway Key Text Here]]"
Private gw_hashNames
Private gw_hashValues
Function gw_printField(name, value)
if IsNull(value) Then
gw_hashValues = gw_hashValues & gw_merchantKeyText
hashedResult = MD5(gw_hashValues)
value = gw_hashNames & hashedResult
gw_hashNames = Null
gw_hashValues = Null
Else
gw_hashNames = gw_hashNames & name & "|"
gw_hashValues = gw_hashValues & value & "|"
End If
gw_printField = "<INPUT TYPE=HIDDEN NAME=""" & name & _
""" VALUE=""" & value & """>" & vbCrLf
End Function
%>
<FORM
METHOD=POST
ACTION="https://secure.apsmerchantgateway.com/cart/cart.php">
<INPUT TYPE=HIDDEN NAME="customer_receipt" VALUE="true">
<INPUT TYPE=HIDDEN NAME="key_id" VALUE="<%=gw_merchantKeyId%>">
<%
' Print the description, SKU, shipping, and amount using the gw_printField
' function
%>
<%=gw_printField("action", "process_cart") %>
<%=gw_printField("product_description_1", "Product #1") %>
<%=gw_printField("product_sku_1", "BK001") %>
<%=gw_printField("product_shipping_1", "fixed|3.95|2.00") %>
<%=gw_printField("product_amount_1", "7.95") %>
<%
' Once all product information fields are printed, print the hash field.
' There is no need to specify a value when printing the hash field.'
%>
<%=gw_printField("hash", NULL) %>
How many books do you want?
<INPUT TYPE=TEXT NAME="product_quantity_1" SIZE=3><BR>
<INPUT TYPE=SUBMIT VALUE="Place Order">
</FORM>
We have designed our gateway to be able to handle transaction submissions and responses in the Authorize.Net format. We call this our Gateway Emulator.
To use the Gateway Emulator, your shopping cart or application must support the Authorize.Net AIM or SIM method of integration. If the application supports the AIM or SIM method, you simply need to change the transaction POST URL to our Gateway Emulator URL.
The Gateway does not support the emulation of XML AIM, CIM, ARB, DPM, Card Present or Transaction Details APIs.
Our Gateway Emulator URL is:
AIM: | https://secure.apsmerchantgateway.com/gateway/transact.dll |
SIM: | https://secure.apsmerchantgateway.com/cart/ausi.php |
You will need to change any production and test Authorize.Net URLs to one of the above URLs. The following URLs should be replaced:
https://secure.authorize.net/gateway/transact.dll |
https://test.authorize.net/gateway/transact.dll |
Some applications will not contain the test URL. In that case, you will only be changing one URL. Once you have updated the URLs to point to us, the application will submit transactions without needing changes to the code base.
You will then need to configure the Authorize.Net AIM or SIM payment module with the following credentials:
For testing, you can use the username and password of “demo” and “password”.
CIT/MIT is supported even though the official AIM API does not support it. Please use the variable names and values documented under the Direct Post API on all relevant transactions.
If your application is using Authorize.Net’s current XML API, then you can connect using our newest emulator. Like the above-mentioned
emulators, this will accept requests in the same XML format that Auth.Net would accept, so it’s just a matter of changing
your POST URL to the one below and using your gateway credentials for authentication. This emulator also emulates the
response so that should look the same to your software.
Our Modern XML Emulator URL is:
https://secure.apsmerchantgateway.com/api/transrequest.php |
For authentication, this API looks for “name” and “transactionKey”.
If your application is using SparrowOne’s Services API, you can connect your software to the gateway via this emulator. Simply replace the POST URL in your software to the following address and you can submit transactions, add update, and delete Customer Vault IDs, and create recurring subscriptions.
https://secure.apsmerchantgateway.com/api/spar.php |
Authentication uses your merchant account’s API Security Key in the ‘mkey’ variable.
Fill out the form below to begin your registration process.