NAV Navbar
java php ruby python
  • Introduction
  • Work Flow
  • Header Specification
  • Transaction Status Change Notification
  • Transactions Search API
  • Test Environment
  • Errors
  • Introduction

    We put together this integration manual to provide you all of the information about the technical aspects of transactions notifications and searches.


    Work Flow

    Transaction Status Notification Change API

    Status Change Flow

    How it Works

    1. UOL BoaCompra notifies Merchant that a transaction status has changed

    2. Merchant requests the transaction information provided in the notification to UOL BoaCompra

    3. UOL BoaCompra responds back with the transaction information

    Transaction Search API

    Transaction Search Flow

    1. Merchant requests transaction information

    2. UOL BoaCompra responds back with a list or a single transaction

    Header Specification

    For all API requests it is mandatory to format the header as described below:

    Parameter Description
    Accept This parameter informs the API version, data format (JSON) and encoding. Default value is: application/vnd.boacompra.com.v1+json; charset=UTF-8
    Accept-Language Input language. Default value is en-US.
    Authorization To create a request the following information is required: store-id¹, secret-key¹, HTTP-Verb (url path + query string) and Content-MD5. : The string-authorization is done using hmac-sha256-algorithm. The secret-key is the key parameter. The message parameter is formed by the HTTP-Verb and base64_encode(Content-MD5) concatenated.
    Content-MD5 MD5 of the json request body. Can be empty in case of GET operations.
    Content-Type application/json

    Headers Example

    Accept: application/vnd.boacompra.com.v1+json; charset=UTF-8
    Content-Type: application/json
    Content-MD5:
    Accept-Language: en-US
    Authorization: 10:05eddbf68e09cb3d339b08a8e478c020d50d7c3604ad3da67def785e9399daaa
    


    Generating the Headers

    public class Header {
      private String secretKey = "YOURSECRETKEY";
      private String storeId = "10";
      private String contentMD5;
      private String httpVerb;
    
      public Header(String url, String content) throws NoSuchAlgorithmException, MalformedURLException, UnsupportedEncodingException {
        this.setContentMd5(content);
        this.setHttpVerb(new URL(url));
      }
    
      private void setHttpVerb(URL url) {
        this.httpVerb = url.getPath() + (url.getQuery() != null ? url.getQuery() : "");
      }
    
      private void setContentMd5(String content) throws NoSuchAlgorithmException, UnsupportedEncodingException {
        if (content == "") {
          this.contentMD5 = "";
        }else {
          MessageDigest md = MessageDigest.getInstance("MD5");
          byte messageDigest[] = md.digest(content.getBytes("UTF-8"));
          this.contentMD5 = Base64.encodeBase64String(new BigInteger(1,messageDigest).toString(16).getBytes());
        }
      }
    
      private String generateAuthorization() throws NoSuchAlgorithmException, InvalidKeyException, UnsupportedEncodingException {
        final String data = this.httpVerb+this.contentMD5;
        Mac mac = Mac.getInstance("HmacSHA256");
        mac.init(new SecretKeySpec(this.secretKey.getBytes("UTF8"), "HmacSHA256"));
        return Hex.encodeHexString(mac.doFinal(data.getBytes("UTF-8")));
      }
    
      public HashMap<String,String> generateHeader() throws InvalidKeyException, NoSuchAlgorithmException, UnsupportedEncodingException {
        HashMap<String, String> headers = new HashMap<>();
    
        headers.put("Accept", "application/vnd.boacompra.com.v1+json; charset=UTF-8");
        headers.put("Content-Type", "application/json");
        headers.put("Content-MD5", this.contentMD5);
        headers.put("Authorization", this.storeId+':'+this.generateAuthorization());
        headers.put("Accept-Language", "en-US");
    
        return headers;
      }
    }
    
    Header header = new Header("https://api.boacompra.com/transactions/87585840", "");
    HashMap<String, String> headerMap = header.generateHeader();
    System.out.println(Arrays.asList(headerMap));
    
    <?php
    
    class header {
    
        private $_secretKey = 'YOURSECRETKEY';
        private $_storeId = '10';
    
        function __construct($url, $content = '') {
            $this->_setContentMd5($content);
            $this->_setHttpVerb($url);
        }
    
        private function _setContentMd5($content) {
            if ($content == '') $this->_contentMd5 = '';
            else $this->_contentMd5 = base64_encode(md5($content));
        }
    
        private function _getQueryString($url){
            $queryString = parse_url($url, PHP_URL_QUERY);
            return empty($queryString) ? '' : '?' . $queryString;
        }
    
            private function _setHttpVerb($url) {
            $this->_httpVerb = parse_url($url, PHP_URL_PATH) . $this->_getQueryString($url);
        }
    
        private function _generateAuthorization() {
            return hash_hmac('sha256', $this->_httpVerb . $this->_contentMd5, $this->_secretKey);
        }
    
        public function generateHeader() {
            $headers = array(
            'Accept' => 'application/vnd.boacompra.com.v1+json; charset=UTF-8',
            'Content-Type' => 'application/json',
            'Content-MD5' => $this->_contentMd5,
            'Authorization' => $this->_storeId.':'.$this->_generateAuthorization(),
            'Accept-Language' => 'en-US'
            );
            return $headers;
        }
    }
    
    echo '<pre>'. 'GET EXAMPLE <br />';
    $headerGet = new header('https://api.boacompra.com/transactions/87585840', '');
    
    print_r($headerGet->generateHeader());
    
    require 'uri'
    require 'base64'
    require 'openssl'
    require 'digest/md5'
    
    class Header
    
       SECRET_KEY = 'YOURSECRETKEY'
       STORE_ID = 10
    
       attr_reader :contentMD5, :httpVerb
    
       def initialize(url, content = '')
        setContentMD(content)
        setHttpVerb(url)
       end
    
       private
       def setContentMD(content)
          if content.to_s.empty?
              @contentMD5 = ''
          else
              @contentMD5 = Base64.encode64(Digest::MD5.hexdigest(content)).delete!("\n")
          end
       end
    
       private
       def getQueryString(url)
        uri = URI(url)
        url.to_s.empty? || uri.query.nil? ? '' : '?' + uri.query
       end
    
       private
       def setHttpVerb(url)
        uri = URI::parse(url)
        @httpVerb = uri.path + getQueryString(url)
       end
    
       private
       def generateAuthorization()
        OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha256'), SECRET_KEY, @httpVerb + @contentMD5)
       end
    
       public
       def generateHeader()
        headers = {
         "Accept"           => 'application/vnd.boacompra.com.v1+json; charset=UTF-8',
         "Content-Type"     => 'application/json',
         "Content-MD5"      => @contentMD5,
         "Authorization"    => STORE_ID.to_s + ":" + generateAuthorization(),
         "Accept-Language"  => 'en-US'
        }
        headers
       end
    end
    
    puts '<pre>GET EXAMPLE <br />'
    headerGet = Header.new('https://api.boacompra.com/transactions/87585840', '')
    puts headerGet.generateHeader()
    
    """Boacompra python 2.7"""
    import base64
    import hashlib
    import hmac
    
    from urlparse import urlparse
    
    class Header:
      secretKey = "YOURSECRETKEY"
      storeId = "10"
    
      def __init__(self, url, content):
        self.setContentMd5(content)
        self.setHttpVerb(url)
    
      def setContentMd5(self, content):
        self.contentMd5 = '' if content == '' else base64.b64encode(hashlib.md5(content).hexdigest())
    
      def setHttpVerb(self, url):
        self.httpVerb = '{}''{}'.format(urlparse(url).path, self.getQueryStrint(url))
    
      def getQueryStrint(self, url):
        return '' if urlparse(url).query == '' else '?{}'.format(urlparse(url).query)
    
      def generateAuthorization(self):
        return hmac.new(self.secretKey, self.httpVerb + self.contentMd5, hashlib.sha256).hexdigest()
    
      def generateHeader(self):
        return dict({'Accept':'application/vnd.boacompra.com.v1+json; charset=UTF-8', 'Content-Type':'application/json', 'Content-MD5': self.contentMd5, 'Authorization': '{}'':{}'.format(self.storeId, self.generateAuthorization()), 'Accept-Language':'en-US'})
    
    
    """Boacompra python 3.x"""
    import base64
    import hashlib
    import hmac
    
    from urllib.parse import urlparse
    
    class Header3(object):
      secretKey = "YOURSECRETKEY"
      storeId = "10"
    
      def __init__(self, url, content):
        self.setContentMd5(content)
        self.setHttpVerb(url)
        self.generateAuthorization()
    
      def setContentMd5(self, content):
        self.contentMd5 = ''
        if content == ''
        else base64.b64encode(hashlib.md5(content.encode()).hexdigest().encode('ascii')).decode('ascii')
    
      def setHttpVerb(self, url):
        self.httpVerb = '{}''{}'.format(urlparse(url).path, self.getQueryStrint(url))
    
      def getQueryStrint(self, url):
        return '' if urlparse(url).query == '' else '?{}'.format(urlparse(url).query)
    
      def generateAuthorization(self):
        message = bytes('{}''{}'.format(self.httpVerb, self.contentMd5), 'utf-8')
        secret = bytes(self.secretKey, 3 'utf-8')
    
        return hmac.new(secret, message, hashlib.sha256).hexdigest()
    
      def generateHeader(self):
        return dict({'Accept':'application/vnd.boacompra.com.v1+json; charset=UTF-8', 'Content-Type':'application/json', 'Content-MD5':
    self.contentMd5, 'Authorization': '{}'':{}'.format(self.storeId, self.generateAuthorization()), 'Accept-Language':'en-US'})
    

    Transaction Status Change Notification

    Whenever a transaction has its status changed, UOL BoaCompra will send a POST notification to the notify-url informed by the Merchant when a transaction was started. The notification expects a HTTP Status 200 as response. In case such status is not returned, a new notification will be triggered after 10 minutes. Until a successful response is achieved. Besides HTTP Status 200 as response, notifications of COMPLETE status expect that the Transaction Search API is accessed for the notified transaction. If a request is not made for such API, notifications will be triggered every 10 minutes as well. Parameters are described below.

    Parameter Type Description
    transaction-code Required String Transaction code. It is the same as “transaction_id”
    notification-type Required String Value: transaction

    Example

    POST http://your-virtual-store.com/transaction-notification/ HTTP/1.1
    Host: boacompra.com
    Content-Length:86
    Content-Type: application/x-www-form-urlencoded
    transaction-code=1234567890
    notification-type=transaction
    

    Transactions Search API

    Retrieve information about transactions. The API can return information about one specific transaction or a list of transactions, based on the search criteria requested via API.

    Host: https://api.boacompra.com/transactions/{transactionCode}

    Method: GET

    Input Parameters

    Parameter Type Description
    initial-order-date Optional Timestamp Initial date, based when the order was created, to be searched. Only transactions created after the date sent in this parameter will be returned. If a transactionCode is not sent, a date range search is mandatory. Format: YYYY-MM-DDThh:mm:ss.sTZD Example: 2015-06-09T14:00:00.000-03:00
    final-order-date Optional Timestamp Final date, based when the order was created, to be searched. Only transactions created before this date will be returned. If an initial-order-date is sent and the final-order-date is left in blank, the current date will be considered unless it is greater than 30 days. In this case, will be considered a 30-day search. If a final-order-date is sent, the parameter initial-order-date is required. Format: YYYY-MM-DDThh:mm:ss.sTZD Example: 2015-06-10T14:00:00.000-03:00
    initial-payment-date Optional Timestamp Initial date, based when the order was payed, to be searched. Only transactions payed after the date sent in this parameter will be returned. If a transactionCode is not sent, a date range search is mandatory. Format: YYYY-MM-DDThh:mm:ss.sTZD Example: 2015-06-09T14:00:00.000-03:00
    final-payment-date Optional Timestamp Final date, based when the order was created, to be searched. Only transactions payed before this dates will be returned. If an initial-payment-date is sent and the final-payment-date is left in blank, the current date will be considered unless it is greater than 30 days. In this case, will be considered a 30-day search. If a final-payment-date is sent, the parameter initial-payment-date becomes required. Format: YYYY-MM-DDThh:mm:ss.sTZD **Example: 2015-06-10T14:00:00.000-03:00
    initial-last-status-change-date Optional Timestamp Initial date, based on the last status change, to be searched. Only transactions with changes on their status after the date sent in this parameter will be returned. If a transactionCode is not sent, a date range search is mandatory. Format: YYYY-MM-DDThh:mm:ss.sTZD
    final-last-status-change-date Optional Timestamp Final date, based on the last status change, to be searched. Only transactions with changes on their status before this dates will be returned. If the initial-last-status-change-date is sent and the final-last-status-change-date is left in blank, the current date will be considered unless it is greater than 30 days. In this case, will be considered a 30-day search. If final-last-status-change-date is sent, the parameter initial-last-status-change-date becomes required. Format: YYYY-MM-DDThh:mm:ss.sTZD Example: 2015-06-10T14:00:00.000-03:00
    status Optional String Transactions status to be filtered. Values: CANCELLED, COMPLETE, CHARGEBACK, EXPIRED, NOT-PAID, PENDING, REFUNDED, UNDER-REVIEW
    page Optional Int If the search result is presented in more than one page, it’s possible to use this parameter to navigate among the pages.
    max-page-results Optional Int Number of results per page. Default value and maximum accepted is 10.


    In the sequence, a few examples of requests are available:

    1. https://api.boacompra.com/transactions/{transactionCode} - Returns the information of a specific transaction

    2. https://api.boacompra.com/transactions?initial-order-date=2015-06-10T14:00:00.000-03:00&final-order-date=2015-06-20T14:00:00.000-03:00 - Returns the first ten transactions created on the informed period

    Success Response

    The response contains metadata information with the number of transactions returned for the request and an array of transaction’s object with the information of each transaction.

    HTTP Status Code: 200

    Status Description

    Name Description
    CANCELLED Transaction was cancelled by UOL BoaCompra
    COMPLETE Transaction was paid and approved. Products should be deliver to the End User
    CHARGEBACK An approved transaction was cancelled by the End User. Please consult your Account Manager for costs.
    EXPIRED Payment date of transaction expired
    NOT-PAID Payment confirmation of transaction was not receive.
    PENDING Transaction was created
    REFUNDED A partial or full refund was requested and accepted for the transaction
    UNDER-REVIEW Transaction is under review by UOL BoaCompra Analysis team. It will be approved or cancelled based on the analysis.


    JSON Response example:

    {
        "transaction-result": {
            "store-id": "10",
            "transactions": [
                {
                    "transaction-code": "87990145",
                    "order-id": " 1500397602",
                    "order-description": "Purchase Test",
                    "status": "REFUNDED",
                    "currency": "BRL",
                    "amount": "10.00",
                    "customer-email": "test@boacompra.com",
                    "customer-country": "BR",
                    "notify-url": "https://loja_teste.boacompra.com/consume_notifications.php",
                    "payment-country": "BR",
                    "payment-id": "3",
                    "payment-name": "mastercard",
                    "order-date": "2017-07-18T14:18:44-03:00",
                    "payment-date": "2017-07-18T14:21:02-03:00",
                    "last-status-change-date": "2017-07-18T14:30:10-03:00",
                    "chargeback-date": null,
                    "refundable": false,
                    "refunds": [
                        {
                            "refund-id": "32926",
                            "refund-status": "PROCESSED",
                            "refund-amount": "10.00",
                            "refund-date": "2017-07-18T14:21:47-03:00",
                            "refund-processing-date": "2017-07-18T00:00:00-03:00",
                            "refund-reference": "BC-34134"
                        }
                    ]
                }
            ]
        },
        "metadata": {
            "found": "1",
            "page-results": 1,
            "current-page": 1,
            "total-pages": 1
        }
    }
    


    Parameter Description
    transactions-result Object
    transaction-code BoaCompra unique identifier for the transaction
    order-id Merchant unique identifier for the transaction
    order-description Description provided by the Merchant when the checkout was created
    status Transaction status
    currency Currency related to the amount of the transaction
    amount Amount of the transaction
    customer-mail Customer e-mail used in BoaCompra checkout
    customer-country Country in which the customer IP was tracked
    notify-url URL that BoaCompra notified the Merchant
    payment-country Country where the payment was made
    payment-id BoaCompra payment identifier (for more information, check the Integration Guide)
    order-date Date that the checkout was created
    payment-date Date that the customer paid the order
    last-status-change-date Date that the last status change occurred
    chargeback-date Date that BoaCompra were notified that a chargeback occurred for that transaction
    refunds Object
    refund-id BoaCompra unique identifier for a refund
    refund-status Status of the refund
    refund-amount Amount to be refunded
    refund-date Date that the refund was requested
    refund-processing-date Date that the refund was paid
    refund-reference Merchant refund identifier

    Error response

    In case of errors in the request, expect a HTTP Status Code different from 200. The body response also contains an error object with the description and an error code, like the following example. Error Code list here.

    Response Body Example:

    {
        "errors": [
            {
                "code": "17078",
                "description": "currency_not_accepted"
            }
        ]
    }
    

    Test Environment

    BoaCompra provides a sandbox(test-mode) environment for testing purposes, to create a testing transaction simply send the request to the following endpoint api.sandbox.boacompra.com

    For proper simulation of all status and integration flow, UOL BoaCompra offers a panel. Please access the following URL with credentials provided by your Account Manager.

    Host: https://billing-partner.boacompra.com

    Search for your test transaction in the “Transactions test” menu:

    Menu

    Once you find it, please click on the “detail” icon:

    Search Result

    You can select the status you want to simulate and send a notification by clicking in “Notify”:

    Example

    POST http://your-virtual-store.com/transaction-notification/ HTTP/1.1
    Host: boacompra.com
    Content-Length:86
    Content-Type: application/x-www-form-urlencoded
    transaction-code=1234567890
    notification-type=transaction
    test-mode=true
    

    Status Notification

    A notification will be sent to the URL defined in the notify_url integration field along with the test-mode parameter.

    Errors

    1XXXX - Header Errors

    100XX - Authorization Header

    Code Key Description
    10001 header_authorization_missing Missing header Authorization in request
    10002 header_authorization_bad_format Authorization header bad formation
    10003 header_authorization_invalid Authorization header error

    101XX - Content-MD5 Header

    Code Key Description
    10101 header_contentmd5_missing Missing header Content-MD5
    10102 header_contentmd5_failed Content-MD5 doesn't match with the request MD5

    102XX - Accept Header

    Code Key Description
    10201 header_accept_missing Missing header Accept in request
    10202 header_accept_application_missing Missing Application on header Accept
    10203 header_accept_bad_format Header Accept with bad format
    10204 header_accept_format_missing Missing Format on header Accept
    10205 header_accept_charset_missing Missing Charset on header Accept
    10206 header_accept_application_invalid Invalid Application on Accept Header
    10207 header_accept_format_invalid Invalid Format on Accept Header
    10208 header_accept_charset_invalid Invalid Charset on Accept Header
    10209 header_accept_version_invalid Invalid Version on Accept Header

    103XX - Content-Type Header

    Code Key Description
    10301 header_contenttype_missing Missing header Content-Type in request
    10302 header_contenttype_not_accepted Content-Type is not accepted

    104XX - Accept Language

    Code Key Description
    10401 header_language_not_accepted Language not accepted

    2XXXX - Body Errors

    221XX – Transaction Search API

    Code Key Description
    22100 initial_order_date_invalid Initial order date has an invalid format
    22101 final_order_date_invalid Final order date has an invalid format
    22102 initial_payment_date_invalid Initial payment date has an invalid format
    22103 final_payment_date_invalid Final payment date has an invalid format
    22104 initial_last_status_change_date_invalid Initial last status change date has an invalid format
    22105 final_last_status_change_date_invalid Final last status change date has an invalid format
    22106 initial_order_date_is_mandatory_to_filter_by_final_order_date Initial order date is mandatory to filter by final order date
    22107 final_order_date_must_be_greater_than_initial_order_date Initial order date must be greater than final order date
    22108 initial_payment_date_is_mandatory_to_filter_by_final_payment_date Initial payment date is mandatory to filter by final payment date
    22109 final_payment_date_must_be_greater_than_initial_payment_date Initial payment date must be greater than final payment date
    22110 initial_last_status_change_date_is_mandatory_to_filter_by_final_last_status_change_date Initial last status change date is mandatory to filter by final last status change date
    22111 final_last_status_change_date_must_be_greater_than_initial_last_status_change_date Initial last status change date must be greater than final last status change date
    22112 final_order_date_range_exceeded Order date range date exceeded
    22113 final_payment_date_range_exceeded Order payment range date exceeded
    22114 final_last_status_change_date_range_exceeded Order last status change range date exceeded
    22115 page_invalid Page has an invalid format
    22116 max_page_results_invalid Max page results has an invalid format
    22117 any_initial_date_is_mandatory_for_multiple_records TransactionCode or any initial-date is mandatory
    22118 status_invalid Transaction status provided is invalid
    22119 status_not_exists Transaction status provided does not exists
    22120 id_invalid Transaction ID provided has an invalid format

    3XXXX - Search Errors

    301XX - Search Transaction and Notification

    Code Key Description
    30101 internal_server_error Error on Boa Compra servers