3.12. /api/v2/preauth-form
Introduction
Preauth-form is initiated throughΒ HTTPS POSTΒ request by usingΒ URLsΒ and theΒ parametersΒ specified below. UseΒ SHA-1Β for authentication. SeeΒ Statuses.
API URLs
| Integration | Production |
|---|---|
| https://sandbox.billblend.com/checkout/api/v2/preauth-form/ENDPOINTID | https://pay.billblend.com/checkout/api/v2/preauth-form/ENDPOINTID |
| https://sandbox.billblend.com/checkout/api/v2/preauth-form/group/ENDPOINTGROUPID | https://pay.billblend.com/checkout/api/v2/preauth-form/group/ENDPOINTGROUPID |
Request Parameters
Note
Request must have content-type=application/x-www-form-urlencoded.
Acquirer can redefine the necessity of some fields so they become required instead of optional.
Leading and trailing whitespace in input parameters will be omitted.
| Parameter Name | Description | Value |
|---|---|---|
| client_orderid | Unique order identifier assigned by Connecting Party. | Necessity: RequiredType: StringLength: 128 |
| order_desc | Brief order description. | Necessity: RequiredType: StringLength: 64k |
| amount | Amount to be charged. The amount has to be specified in the highest units with . delimiter. For instance, 10.5 for USD means 10 US Dollars and 50 Cents. | Necessity: RequiredType: NumericLength: 10 |
| currency | Currency the transaction is charged in (See:Β Currency codes). Sample values are:Β USDΒ for US DollarΒ EURΒ for European Euro. | Necessity: RequiredType: StringLength: 3 |
| address1 | Payerβs address line 1. | Necessity: RequiredType: StringLength: 50 |
| city | Payerβs city. | Necessity: RequiredType: StringLength: 50 |
| zip_code | Payerβs ZIP code. | Necessity: RequiredType: StringLength: 10 |
| country | Payerβs country. Please seeΒ Country codesΒ for a list of valid country codes. | Necessity: RequiredType: StringLength: 2 |
| phone | Payerβs full international phone number, including country code. | Necessity: RequiredType: StringLength: 15 |
| Payerβs e-mail address. | Necessity: RequiredType: StringLength: 50 | |
| ipaddress | Payerβs IP address, included for fraud screening purposes. | Necessity: RequiredType: StringLength: 45 |
| control | Checksum generated byΒ SHA-1. Control string is represented as concatenation of the following parameters:1.Β <ENDPOINTID | ENDPOINTGROUPID>Β (See:Β Request URL).2. Request parameter:Β client_orderid.4. Request parameter:Β amountΒ in minor units (if sent).4. Request parameter:Β email.5.Β merchant_controlΒ (Control key assigned to Connecting Party account in the Billblend gateway system). | Necessity: RequiredType: StringLength: 40 |
| first_name | Payerβs first name. | Necessity: RequiredType: StringLength: 50 |
| last_name | Payerβs last name. | Necessity: RequiredType: StringLength: 50 |
| state | Payerβs state. (two-letter state code). Please seeΒ Mandatory State codesΒ for a list of valid state codes. Required for USA, Canada and Australia. | Necessity: ConditionalType: StringLength: 2 |
| redirect_url | URL, where the Payer is redirected to upon completion of the transaction. Please note that redirection is performed in any case, no matter whether transaction isΒ approved,Β declinedΒ in any other finalΒ status.Connecting Party must not use the parameters come along with the redirect HTTP Request to treat the status of the transaction. Instead Connecting Party can utilizeΒ server_callback_urlΒ orΒ status API command. PassΒ http://https://doc.billblend.com/Β if you have no need to return payer anywhere. Use eitherΒ redirect_urlΒ or combination ofΒ redirect_success_urlΒ andΒ redirect_fail_url, not both. | Necessity: OptionalType: StringLength: 1024 |
| redirect_success_url | URL, where the Payer is redirected to when transaction status isΒ approvedΒ (SeeΒ status list).Connecting Party must not use the parameters come along with the redirect HTTP Request to treat the status of the transaction. Instead Connecting Party can utilizeΒ server_callback_urlΒ orΒ status API command. Otherwise putΒ http://https://doc.billblend.com/Β if there is no need to redirect Payer anywhere. Use either combination ofΒ redirect_success_urlΒ andΒ redirect_fail_urlΒ orΒ redirect_url, not both. | Necessity: OptionalType: StringLength: 1024 |
| redirect_fail_url | URL, where the Payer is redirected to when transaction status is notΒ approvedΒ (SeeΒ status list).Connecting Party must not use the parameters come along with the redirect HTTP Request to treat the status of the transaction. Instead Connecting Party can utilizeΒ server_callback_urlΒ orΒ status API command. PassΒ http://https://doc.billblend.com/Β if there is no need to redirect Payer anywhere. Use either combination ofΒ redirect_fail_urlΒ andΒ redirect_success_urlΒ orΒ redirect_url, not both. | Necessity: OptionalType: StringLength: 1024 |
| ssn | Last four digits of the Payerβs social security number. | Necessity: OptionalType: NumericLength: 32 |
| birthday | Payerβs date of birth, in the format YYYYMMDD. | Necessity: OptionalType: NumericLength: 8 |
| cell_phone | Payerβs full international cell phone number, including country code. | Necessity: OptionalType: StringLength: 15 |
| site_url | The URL of the E-commerce entity, where the payment is originated from. | Necessity: OptionalType: StringLength: 128 |
| server_callback_url | URL, where the transaction status is sent to.Connecting Party may use server callback URL for custom processing of the transaction completion, e.g. to collect payment data in the Connecting Partyβs information system. For the list of parameters which come along with server callback toΒ server_callback_urlΒ refer toΒ Connecting Party callback parameters. This parameter can be sent instead ofΒ notify_url. IfΒ server_callback_urlΒ is sent, Payment Gateway sends callback notification only when original transaction receives final status. IfΒ notify_urlΒ is sent, Payment Gateway sends callback notification once the original transaction receives final status, and about every future update for this original transaction (reversal, chargeback, etc). | Necessity: OptionalType: StringLength: 1024 |
| notify_url | URL, where the transaction status is sent to.Connecting Party may use notify URL for custom processing of the transaction completion, e.g. to collect payment data in the Connecting Partyβs information system. For the list of parameters which come along with server callback toΒ notify_urlΒ refer toΒ Connecting Party callback parameters. This parameter can be sent instead ofΒ server_callback_url. IfΒ notify_urlΒ is sent, Payment Gateway sends callback notification once the original transaction receives final status, and about every future update for this original transaction (reversal, chargeback, etc). IfΒ server_callback_urlΒ is sent, Payment Gateway sends callback notification only when original transaction receives final status. | Necessity: OptionalType: StringLength: 1024 |
| preferred_language | Payerβs two-letter language code for multi-language payment-forms. | Necessity: OptionalType: StringLength: 2 |
| merchant_form_data | Parameters sent in MERCHANT_FORM_DATA API parameter are parsed into macros with the same name, the parameter is url-encoded, example: testparam%3Dtest1%26mynewparam%3Dtest2 and is parsed into $MFD_testparam = test1 and $MFD_mynewparam = test2 macros in the form. Parameter name characters[a-zA-Z0-9], parameter value characters[a-zA-Z0-9], control characters [=&], 2MB max size. For example, this parameter can be used to display payment form in light/dark mode depending on the value passed by Connecting Party (e.g. pass merchant_form_data=theme%3Ddark in request and $MFD_theme macro placeholder on payment form will be changed to dark. | Necessity: OptionalType: StringLength: 128 |
| minimum_transaction_amount | This parameter can be used to limit the minimum transaction amount, if transaction amount is submitted by Payer on the form. Contact support manager to enable this feature. Value format is the same as in the amount parameter. | Necessity: OptionalType: NumericLength: 10 |
| maximum_transaction_amount | This parameter can be used to limit the maximum transaction amount, if transaction amount is submitted by Payer on the form. Contact support manager to enable this feature. Value format is the same as in the amount parameter. | Necessity: OptionalType: NumericLength: 10 |
| customer_level | Customer level in CMS system | Necessity: OptionalType: VarcharLength: 32 |
| customer_id | Customer ID in CMS system. Required if transaction goes via CMS (Payment Gateway mode) | Necessity: OptionalType: IntLength: 10 |
| merchant_customer_identifier | Merchant Customer ID in CMS system. Required if transaction goes via CMS (CRM mode) | Necessity: OptionalType: VarcharLength: 64 |
| preferred_language | Payerβs two-letter language code for multi-language payment forms. | Necessity: OptionalType: StringLength: 2 |
| card_recurring_payment_id | Payerβs tokenized cardholderβs data ID, referred as Recurring Payment ID (RPI). Recurring Payment ID can be created withΒ v4 tokenization request. | Necessity: ConditionalType: Long |
| cardrefid | Card reference ID used in subsequent recurring payments. Card reference ID can be created withΒ v4 tokenization requestΒ orΒ v2 tokenization request. | Necessity: ConditionalType: Long |
Response Parameters
Note
Response has Content-Type: text/html;charset=utf-8 header. All fields are x-www-form-urlencoded, with (0xA) character at the end of each parameterβs value.
| Response Parameters | Description |
|---|---|
| type | The type of response. May be async-response, validation-error, error. If type equals validation-error or error, error-message and error-code parameters contain error details. |
| paynet-order-id | Order id assigned to the order by Billblend. |
| merchant-order-id | Connecting Party order id. |
| serial-number | Unique number assigned by Billblend server to particular request from the Connecting Party. |
| error-message | If status is error this parameter contains the reason for decline or error details. |
| error-code | The error code is case of error status. |
| redirect-url | The URL to the page where the Connecting Party should redirect the clientβs browser. Connecting Party should sendΒ HTTP 302Β redirect, seeΒ General Payment-form Process Flow. |
Request Example
POST /checkout/api/v2/preauth-form/39539 HTTP/1.1 User-Agent: curl/7.83.0 Accept: */* Content-Length: 314 Content-Type: application/x-www-form-urlencoded Connection: close client_orderid=902B4FF5 &order_desc=Test Order Description &first_name=John &last_name=Smith &ssn=1267&birthday=19820115 &address1=100 Main st &city=Seattle &state=WA &zip_code=98102 &country=US &phone=+12063582043 &cell_phone=+19023384543 &amount=69 &email=john.smith@gmail.com ¤cy=USD &ipaddress=65.153.12.232 &site_url=https://doc.billblend.com/ &credit_card_number=4538977399606732 &card_printed_name=CARD HOLDER &expire_month=12 &expire_year=2099 &cvv2=123 &purpose=user_account1 &redirect_url=http://sandbox.billblend.com/doc/dummy.htm &server_callback_url=https://httpstat.us/200 &merchant_data=VIP customer &merchant_form_data=testparam%3Dtest1%26mynewparam%3Dtest2 &control=b7ba0b0ce36fda192c3772e045520c7a9cb5e442 &preferred_language=en
Success Response Example
HTTP/1.1 200 OK Server: server Date: Thu, 13 Oct 2022 09:54:53 GMT Content-Type: text/html;charset=utf-8 Connection: close Vary: Accept-Encoding X-XSS-Protection: 1 X-Content-Type-Options: nosniff Strict-Transport-Security: max-age=31536000 Content-Language: en-US Strict-Transport-Security: max-age=31536000 Content-Length: 280 type=async-form-response &serial-number=00000000-0000-0000-0000-000002ddb0d3 &merchant-order-id=Test &paynet-order-id=6863103 &redirect-url=https%3A%2F%2Fsandbox.billblend.com%2Fpaynet%2Fform%2Finit%2FBB587546567A31587163597A68633370432F78675258396E6F78367975715973596936522B594B4F646168553D
Fail Response Example
HTTP/1.1 200 OK Server: server Date: Thu, 13 Oct 2022 09:58:28 GMT Content-Type: text/html;charset=utf-8 Connection: close Vary: Accept-Encoding X-XSS-Protection: 1 X-Content-Type-Options: nosniff Strict-Transport-Security: max-age=31536000 Content-Language: en-US Strict-Transport-Security: max-age=31536000 Content-Length: 170 type=validation-error &serial-number=00000000-0000-0000-0000-000002ddb0d4 &error-message=Project+with+currency+RUB+does+not+apply+request+with+currency+USD &error-code=16
Postman Collection
Postman Collection is available at this link – https://doc.billblend.com/integration/API_commands/api_v2_preauth-form.html#postman-collection
Request Builder
Request Builder is available at this link –Β https://doc.billblend.com/integration/API_commands/api_v2_preauth-form.html#request-builder
| endpointid or groupid | input ENDPOINTID or ENDPOINTGROUPID |
|---|---|
| client_orderid | make it or use internal invoice ID |
| order_desc | |
| first_name | |
| last_name | |
| ssn | |
| birthday | |
| address1 | |
| city | |
| state | |
| zip_code | |
| country | |
| phone | |
| cell_phone | |
| amount | |
| currency | |
| ipaddress | |
| site_url | |
| purpose | |
| merchant_control | input Control Key |
| redirect_url | |
| redirect_success_url | |
| redirect_fail_url | |
| server_callback_url | |
| merchant_data | |
| cardrefid | |
| maximum-transaction-amount | |
| minimum-transaction-amount | |
| merchant_form_data | |
| preferred_language |
curl --data "client_orderid=902B4FF5&order_desc=Test Order Description&first_name=John&last_name=Smith&ssn=1267&birthday=19820115&address1=100 Main st&city=Seattle&state=WA&zip_code=98102&country=US&phone=+12063582043&cell_phone=+19023384543&amount=10.42&email=john.smith@gmail.com¤cy=USD&ipaddress=65.153.12.232&site_url=https://doc.billblend.com/&purpose=user_account1&redirect_url=https://doc.billblend.com//doc/dummy.htm&server_callback_url=https://httpstat.us/200&merchant_data=VIP customer&merchant_form_data=testparam%3Dtest1%26mynewparam%3Dtest2&preferred_language=en&control=768eb8162fc361a3e14150ec46e9a6dd8fbfa483" https://sandbox.billblend.com/checkout/api/v2/preauth-form/1<?php
/**
* Executes request
*
* @param string $url Url for payment method
* @param array $requestFields Request data fields
*
* @return array Host response fields
*
* @throws RuntimeException Error while executing request
*/
function sendRequest($url, array $requestFields)
{
$curl = curl_init($url);
curl_setopt_array($curl, array
(
CURLOPT_HEADER => 0,
CURLOPT_USERAGENT => 'Billblend-Client/1.0',
CURLOPT_SSL_VERIFYHOST => 0,
CURLOPT_SSL_VERIFYPEER => 0,
CURLOPT_POST => 1,
CURLOPT_RETURNTRANSFER => 1
));
curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($requestFields));
$response = curl_exec($curl);
if(curl_errno($curl))
{
$error_message = 'Error occurred: ' . curl_error($curl);
$error_code = curl_errno($curl);
}
elseif(curl_getinfo($curl, CURLINFO_HTTP_CODE) != 200)
{
$error_code = curl_getinfo($curl, CURLINFO_HTTP_CODE);
$error_message = "Error occurred. HTTP code: '{$error_code}'";
}
curl_close($curl);
if (!empty($error_message))
{
throw new RuntimeException($error_message, $error_code);
}
if(empty($response))
{
throw new RuntimeException('Host response is empty');
}
$responseFields = array();
parse_str($response, $responseFields);
return $responseFields;
}
function signString($s, $merchantControl)
{
return sha1($s . $merchantControl);
}
/**
* Signs payment (sale/auth/transfer) request
*
* @param array $requestFields request array
* @param string $endpointOrGroupId endpoint or endpoint group ID
* @param string $merchantControl merchant control key
*/
function signPaymentRequest($requestFields, $endpointOrGroupId, $merchantControl)
{
$base = '';
$base .= $endpointOrGroupId;
$base .= $requestFields['client_orderid'];
$base .= $requestFields['amount'] * 100;
$base .= $requestFields['email'];
return signString($base, $merchantControl);
}
/**
* Signs status request
*
* @param array $requestFields request array
* @param string $login merchant login
* @param string $merchantControl merchant control key
*/
function signStatusRequest($requestFields, $login, $merchantControl)
{
$base = '';
$base .= $login;
$base .= $requestFields['client_orderid'];
$base .= $requestFields['orderid'];
return signString($base, $merchantControl);
}
function signAccountVerificationRequest($requestFields, $endpointOrGroupId, $merchantControl)
{
$base = '';
$base .= $endpointOrGroupId;
$base .= $requestFields['client_orderid'];
$base .= $requestFields['email'];
return signString($base, $merchantControl);
}
$endpointId = 1;
$merchantControl = 'B17F59B4-A7DC-41B4-8FF9-37D986B43D20';
$requestFields = array(
'client_orderid' => '902B4FF5',
'order_desc' => 'Test Order Description',
'first_name' => 'John',
'last_name' => 'Smith',
'ssn' => '1267',
'birthday' => '19820115',
'address1' => '100 Main st',
'city' => 'Seattle',
'state' => 'WA',
'zip_code' => '98102',
'country' => 'US',
'phone' => '+12063582043',
'cell_phone' => '+19023384543',
'amount' => '10.42',
'email' => 'john.smith@gmail.com',
'currency' => 'USD',
'ipaddress' => '65.153.12.232',
'site_url' => 'https://doc.billblend.com/',
'purpose' => 'user_account1',
'redirect_url' => 'https://doc.billblend.com//doc/dummy.htm',
'server_callback_url' => 'https://httpstat.us/200',
'merchant_data' => 'VIP customer',
'merchant_form_data' => 'testparam%3Dtest1%26mynewparam%3Dtest2',
'preferred_language' => 'en',
);
$requestFields['control'] = signPaymentRequest($requestFields, $endpointId, $merchantControl);
$responseFields = sendRequest('https://sandbox.billblend.com/checkout/api/v2/preauth-form/1', $requestFields);
print_r($responseFields);
?>require 'net/http'
require 'uri'
require 'cgi'
require 'digest/sha1'
##
# Executes request
#
# @param url [String] Url for payment method
# @param request_fields [Hash] Request data fields
#
# @return [Hash] Host response fields
def send_request(url, request_fields)
begin
uri = URI url
response = Net::HTTP.start uri.hostname, uri.port, :use_ssl => uri.scheme == 'https' do |http|
post = Net::HTTP::Post.new uri.request_uri
post.set_form_data request_fields
http.request post
end
rescue Exception => e
raise RuntimeError, "Error occurred. #{e.message}"
end
unless Net::HTTPOK === response
raise RuntimeError, "Error occurred. HTTP code: '#{response.code}'. Server message: '#{response.message}'"
end
unless response.body
raise RuntimeError, 'Host response is empty'
end
# Change hash format from {'key' => ['value']} to {'key' => 'value'} in map block
Hash[CGI.parse(response.body).map {|key, value| [key, value.first]}]
end
def sign_string(str, merchant_control)
Digest::SHA1.hexdigest(str + merchant_control)
end
def sign_payment_request(request_fields, endpoint_or_group_id, merchant_control)
base = ''
base += endpoint_or_group_id
base += request_fields['client_orderid']
base += (request_fields['amount'].to_f * 100).to_i
base += request_fields['email']
sign_string(base, merchant_control)
end
def sign_status_request(request_fields, login, merchant_control)
base = ''
base += login
base += request_fields['client_orderid']
base += request_fields['orderid'].nil? ? '' : request_fields['orderid']
sign_string(base, merchant_control)
end
request_fields = {
'client_orderid' => '902B4FF5',
'order_desc' => 'Test Order Description',
'first_name' => 'John',
'last_name' => 'Smith',
'ssn' => '1267',
'birthday' => '19820115',
'address1' => '100 Main st',
'city' => 'Seattle',
'state' => 'WA',
'zip_code' => '98102',
'country' => 'US',
'phone' => '+12063582043',
'cell_phone' => '+19023384543',
'amount' => '10.42',
'email' => 'john.smith@gmail.com',
'currency' => 'USD',
'ipaddress' => '65.153.12.232',
'site_url' => 'https://doc.billblend.com/',
'purpose' => 'user_account1',
'redirect_url' => 'https://doc.billblend.com//doc/dummy.htm',
'server_callback_url' => 'https://httpstat.us/200',
'merchant_data' => 'VIP customer',
'merchant_form_data' => 'testparam%3Dtest1%26mynewparam%3Dtest2',
'preferred_language' => 'en',
'control' => '768eb8162fc361a3e14150ec46e9a6dd8fbfa483'
};
response_fields = send_request('https://sandbox.billblend.com/checkout/api/v2/preauth-form/1', request_fields);
require 'pp'
pp response_fields
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class Main {
//Transactions are initiated by using URL in the following format: /checkout/api/v2/TRANSACTION_TYPE/ENDPOINTID or /checkout/api/v2/TRANSACTION_TYPE/ENDPOINTGROUPID (if group is supported)
//Use "gate" for production purposes or "sandbox" for integration needs
private static String targetURL = "https://sandbox.billblend.com/checkout/api/v2/preauth-form/1";
//Request parameters
private static String urlParameters = "client_orderid=902B4FF5&order_desc=Test Order Description&first_name=John&last_name=Smith&ssn=1267&birthday=19820115&address1=100 Main st&city=Seattle&state=WA&zip_code=98102&country=US&phone=+12063582043&cell_phone=+19023384543&amount=10.42&email=john.smith@gmail.com¤cy=USD&ipaddress=65.153.12.232&site_url=https://doc.billblend.com/&purpose=user_account1&redirect_url=https://doc.billblend.com//doc/dummy.htm&server_callback_url=https://httpstat.us/200&merchant_data=VIP customer&merchant_form_data=testparam%3Dtest1%26mynewparam%3Dtest2&preferred_language=en&";
//String for calculating control code parameter
private static String controlParameters = "1902B4FF51042john.smith@gmail.comB17F59B4-A7DC-41B4-8FF9-37D986B43D20";
public static void main(String[] args) throws NoSuchAlgorithmException, UnsupportedEncodingException {
//Sending POST request to the specified URL with request parameters and SHA1-encrypted control parameter
System.out.println(executePost(targetURL, urlParameters + "control= " + sha1(controlParameters)));
}
static String sha1(String input) throws NoSuchAlgorithmException, UnsupportedEncodingException {
MessageDigest mDigest = MessageDigest.getInstance("SHA1");
byte[] result = mDigest.digest(input.getBytes("utf-8"));
StringBuffer sb = new StringBuffer();
for (int i = 0; i < result.length; i++) {
sb.append(Integer.toString((result[i] & 0xff) + 0x100, 16).substring(1));
}
return sb.toString();
}
public static String executePost(String targetURL, String urlParameters)
{
URL url;
HttpURLConnection connection = null;
try {
//Create connection
url = new URL(targetURL);
connection = (HttpURLConnection)url.openConnection();
connection.setDoOutput(true);
//Send request
DataOutputStream wr = new DataOutputStream (
connection.getOutputStream ());
wr.writeBytes (urlParameters);
wr.flush ();
wr.close ();
//Get Response
InputStream is = connection.getInputStream();
BufferedReader rd = new BufferedReader(new InputStreamReader(is));
String line;
StringBuffer response = new StringBuffer();
while((line = rd.readLine()) != null) {
response.append(line);
response.append('\n');
}
rd.close();
return response.toString();
} catch (Exception e) {
e.printStackTrace();
return null;
} finally {
if(connection != null) {
connection.disconnect();
}
}
}
}