3.17. /api/v2/void

Introduction

Void can only be processed for Sale and Capture transactions in the final successful status (See Statuses). To make a void request send an HTTPS POST request to the URLs and the parameters. Use SHA-1 for authentication.

API URLs

IntegrationProduction
https://sandbox.billblend.com/checkout/api/v2/void/ENDPOINTIDhttps://pay.billblend.com/checkout/api/v2/void/ENDPOINTID
https://sandbox.billblend.com/checkout/api/v2/void/group/ENDPOINTGROUPIDhttps://pay.billblend.com/checkout/api/v2/void/void/ENDPOINTGROUPID

Request Parameters

Note

Request must have content-type=application/x-www-form-urlencoded.

Warning

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

Parameter NameDescriptionValue
loginConnecting Party login name.Necessity: MandatoryType: StringLength: 20
orderidUnique order identifier assigned by Billblend system.Necessity: MandatoryType: StringLength: 20
client_orderidUnique Connecting Party identifier.Necessity: MandatoryType: NumericLength: 10
amountThis optional parameter specifies amount to be reversed.Necessity: MandatoryType: StringLength: 10
currencyCurrency the transaction is charged in (See: Currency codes). Sample values are: USD for US Dollar EUR for European Euro.Necessity: ConditionalType: StringLength: 3
controlChecksum generated by SHA-1. Control string is represented as concatenation of the following parameters:1. Request parameter: login2. Request parameter: client_orderid3. Request parameter: orderid4. merchant_control (Control key assigned to Connecting Party account in the Billblend gateway system).Necessity: ConditionalType: StringLength: 128
commentA brief description of reason.Necessity: MandatoryType: StringLength: 50

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-responsevalidation-errorerror. 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.
end-point-idEntry point used for processing this transaction.
error-messageIf status is error this parameter contains the reason for decline or error details.
error-codeThe error code is case of error status.

Request Example

POST /checkout/api/v2/void/39914 HTTP/1.1
Host: sandbox.billblend.com
User-Agent: curl/7.83.0
Accept: */*
Content-Length: 123
Content-Type: application/x-www-form-urlencoded
Connection: close

login=Test
&client_orderid=55
&orderid=6862995
&comment=Service not provided
&control=246e0a2074f9e4b84cff59b2567ed48ec3aab87d

Success Response Example

HTTP/1.1 200 OK
Server: server
Date: Tue, 16 Aug 2022 06:57:40 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: 138

type=async-response
&serial-number=00000000-0000-0000-0000-000002ddae76
&merchant-order-id=55
&paynet-order-id=6862995
&end-point-id=39914

Fail Response Example

HTTP/1.1 200 OK
Server: server
Date: Tue, 16 Aug 2022 07:21:37 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: 148

type=validation-error
&serial-number=00000000-0000-0000-0000-000002ddae78
&merchant-order-id=Test
&error-message=INVALID_CONTROL_CODE
&error-code=2

Postman Collection

Postman Collection is available at this link – https://doc.billblend.com/integration/API_commands/api_v2_void.html#postman-collection

Request Builder

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

Endpointid or groupidinput ENDPOINTID or ENDPOINTGROUPID
login
client_orderidinput Invoice Number
orderid
amount
currency
merchant_controlinput Control Key
comment
curl --data "login=logic&client_orderid=902B4FF5&orderid=159884&amount=10.42&currency=EUR&comment=Service not provided&control=7f5e4878d1cc6788c0dc613930e663f93e54f763" https://sandbox.billblend.com/checkout/api/v2/void/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(
    'login' => 'logic', 
    'client_orderid' => '902B4FF5', 
    'orderid' => '159884', 
    'amount' => '10.42', 
    'currency' => 'EUR', 
    'comment' => 'Service not provided', 

);

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

$responseFields = sendRequest('https://sandbox.billblend.com/checkout/api/v2/void/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 = {
    'login' => 'logic', 
    'client_orderid' => '902B4FF5', 
    'orderid' => '159884', 
    'amount' => '10.42', 
    'currency' => 'EUR', 
    'comment' => 'Service not provided', 

    'control' => '7f5e4878d1cc6788c0dc613930e663f93e54f763'
};

response_fields = send_request('https://sandbox.billblend.com/checkout/api/v2/void/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/void/1";
    //Request parameters
    private static String urlParameters = "login=logic&client_orderid=902B4FF5&orderid=159884&amount=10.42&currency=EUR&comment=Service not provided&";
    //String for calculating control code parameter
    private static String controlParameters = "1logic902B4FF51598841042EURB17F59B4-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