3.15. /api/v2/sale-form

Introduction

Sale-form is initiated through HTTPS POST request by using URLs and the parameters specified below. Use SHA-1 for authentication. See Statuses.

API URLs

IntegrationProduction
https://sandbox.billblend.com/checkout/api/v2/sale-form/ENDPOINTIDhttps://pay.billblend.com/checkout/api/v2/sale-form/ENDPOINTID
https://sandbox.billblend.com/checkout/api/v2/sale-form/group/ENDPOINTGROUPIDhttps://pay.billblend.com/checkout/api/v2/sale-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.

Warning

The following characters must be escaped in the parameter values: & + “.

Parameter NameDescriptionValue
client_orderidUnique order identifier assigned by Connecting Party.Necessity: RequiredType: StringLength: 128
order_descBrief order description.Necessity: RequiredType: StringLength: 64k
first_namePayer’s first name. Parameter necessity depends on the Acquiring channel and necessity of it must be clarified with Tech Support.Necessity: RequiredType: StringLength: 50
last_namePayer’s last name. Parameter necessity depends on the Acquiring channel and necessity of it must be clarified with Tech Support.Necessity: RequiredType: StringLength: 50
ssnLast four digits of the payer’s social security number.Necessity: OptionalType: NumericLength: 32
birthdayPayer’s date of birth, in the format YYYYMMDD.Necessity: OptionalType: NumericLength: 8
address1Payer’s address line 1.Necessity: RequiredType: StringLength: 50
cityPayer’s city.Necessity: RequiredType: StringLength: 50
statePayer’s state. Please see Mandatory State codes for a list of valid state codes. Required for USA, Canada and Australia.Necessity: ConditionalType: StringLength: 2
zip_codePayer’s ZIP code.Necessity: RequiredType: StringLength: 10
countryPayer’s country. Please see Country codes for a list of valid country codes.Necessity: RequiredType: StringLength: 2
phonePayer’s full international phone number, including country code.Necessity: RequiredType: StringLength: 15
cell_phonePayer’s full international cell phone number, including country code.Necessity: OptionalType: StringLength: 15
emailPayer’s e-mail address.Necessity: RequiredType: StringLength: 50
purposeDestination to where the payment goes. It is useful for the Connecting Party’s who let their payers to top up their accounts with bank card (Mobile phone accounts, game accounts etc.). Sample values are: +7123456789gamer0001@ereality.com etc. This value can be used by the fraud monitoring system.Necessity: OptionalType: StringLength: 128
amountAmount 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
currencyCurrency the transaction is charged in (See: Currency codes). Sample values are: USD for US Dollar EUR for European Euro.Necessity: RequiredType: StringLength: 3
ipaddressPayer’s IP address, included for fraud screening purposes.Necessity: RequiredType: StringLength: 20
site_urlThe URL of the E-commerce entity, where the payment is originated from.Necessity: OptionalType: StringLength: 128
controlChecksum generated by SHA-1. Control string is represented as concatenation of the following parameters:1. <ENDPOINTID | ENDPOINTGROUPID> (See: Request URL)2. Request parameter: client_orderid3. Request parameter: amount in minor units (if sent).4. Request parameter: email5. merchant_control (Control key assigned to Connecting Party account in the Billblend gateway system).Necessity: RequiredType: StringLength: 40
redirect_urlURL, 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 approveddeclined 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_urlURL, 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_urlURL, 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
server_callback_urlURL, 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_urlURL, 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_languagePayer’s two-letter language code for multi-language payment-forms.Necessity: OptionalType: StringLength: 2
merchant_dataCustom Connecting Party details, which can be attached to the transaction and passed back in the status response, Connecting Party callback parameters or server_callback_url. Additional information of transaction which may be useful in Connecting Party’s external system, e.g. VIP customerTV promo campaign lead.Information returns in Status response and Connecting Party Callback.Necessity: OptionalType: StringLength: 64k
merchant_form_dataParameters 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_amountThis 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_amountThis 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_levelCustomer level in CMS systemNecessity: OptionalType: VarcharLength: 32
customer_idCustomer ID in CMS system. Required if transaction goes via CMS (Payment Gateway mode)Necessity: OptionalType: IntLength: 10
merchant_customer_identifierMerchant Customer ID in CMS system. Required if transaction goes via CMS (CRM mode)Necessity: OptionalType: VarcharLength: 64
card_recurring_payment_idPayer’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
cardrefidCard 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.

Parameter nameDescription
typeThe type of response. May be async-form-responsevalidation-errorerror etc..If type equals validation-error or errorerror-message and error-code parameters contain error details.
paynet-order-idOrder id assigned to the order by Billblend.
merchant-order-idConnecting Party order id.
serial-numberUnique number assigned by Billblend server to particular request from the Connecting Party.
error-messageIf status is declined or error this parameter contains the reason for decline or error details.
error-codeThe error code in case of declined or error status.
redirect-urlThe 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/sale-form/39519 HTTP/1.1
User-Agent: curl/7.83.0
Accept: */*
Content-Length: 314
Content-Type: application/x-www-form-urlencoded
Connection: close

client_orderid=inv1409911
&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=156
&email=john.smith@gmail.com
&currency=USD
&ipaddress=65.153.12.232
&site_url=https://doc.billblend.com/
&purpose=user_account1
&redirect_url=http://connectingparty.com/result
&server_callback_url=https://httpstat.us/200
&merchant_data=VIP customer
&merchant_form_data=testparam%3Dtest1%26mynewparam%3Dtest2
&control=185aea68b751221b78fa9138e9d44a6aa4c2c446

Success Response Example

HTTP/1.1 200 OK
Server: server
Date: Tue, 11 Oct 2022 14:25:25 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-000002ddb0b9
&merchant-order-id=Test
&paynet-order-id=6863099
&redirect-url=https%3A%2F%2Fsandbox.billblend.com%2Fpaynet%2Fform%2Finit%2FBB587546567A31587163597A68633370432F786752582F6154674965594A696F4D41306C50596E334F5453553D

Fail Response Example

HTTP/1.1 200 OK
Server: server
Date: Tue, 11 Oct 2022 14:16:06 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-000002ddb0b7
&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_sale-form.html#postman-collection

Request Builder

Request Builder is available at this link – https://doc.billblend.com/integration/API_commands/api_v2_sale-form.html#request-builder

endpointid or groupidinput ENDPOINTID or ENDPOINTGROUPID
client_orderidmake it  or use internal invoice ID
order_desc
first_name
last_name
ssn
birthday
address1
city
state
zip_code
country
phone
cell_phone
amount
email
currency
ipaddress
site_url
purpose
merchant_controlinput 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
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&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&control=768eb8162fc361a3e14150ec46e9a6dd8fbfa483" https://sandbox.billblend.com/checkout/api/v2/sale-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', 

);

$requestFields['control'] = signPaymentRequest($requestFields, $endpointId, $merchantControl);

$responseFields = sendRequest('https://sandbox.billblend.com/checkout/api/v2/sale-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', 

    'control' => '768eb8162fc361a3e14150ec46e9a6dd8fbfa483'
};

response_fields = send_request('https://sandbox.billblend.com/checkout/api/v2/sale-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/sale-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&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&";
    //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();
            }
        }
    }
}

Contact us

By clicking on the button, you agree to the data protection policy

Complete the quiz

By clicking on the button, you agree to the data protection policy