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
| Integration | Production |
|---|---|
| https://sandbox.billblend.com/checkout/api/v2/void/ENDPOINTID | https://pay.billblend.com/checkout/api/v2/void/ENDPOINTID |
| https://sandbox.billblend.com/checkout/api/v2/void/group/ENDPOINTGROUPID | https://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 Name | Description | Value |
|---|---|---|
| login | Connecting Party login name. | Necessity: MandatoryType: StringLength: 20 |
| orderid | Unique order identifier assigned by Billblend system. | Necessity: MandatoryType: StringLength: 20 |
| client_orderid | Unique Connecting Party identifier. | Necessity: MandatoryType: NumericLength: 10 |
| amount | This optional parameter specifies amount to be reversed. | Necessity: MandatoryType: StringLength: 10 |
| currency | Currency the transaction is charged in (See: Currency codes). Sample values are: USD for US Dollar EUR for European Euro. | Necessity: ConditionalType: StringLength: 3 |
| control | Checksum 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 |
| comment | A 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 Name | 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. |
| end-point-id | Entry point used for processing this transaction. |
| 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. |
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 groupid | input ENDPOINTID or ENDPOINTGROUPID |
|---|---|
| login | |
| client_orderid | input Invoice Number |
| orderid | |
| amount | |
| currency | |
| merchant_control | input Control Key |
| comment |
curl --data "login=logic&client_orderid=902B4FF5&orderid=159884&amount=10.42¤cy=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¤cy=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();
}
}
}
}