NAV Navbar
java php ruby python
  • Introduction
  • Header Specification
  • Refund Request API
  • Transaction Search API
  • Refund in Billing Partner
  • Test Mode
  • Notification
  • Errors
  • Payment Methods Available for Refund
  • Introduction

    UOL BoaCompra API offers an option to Merchant request the refund of a transaction. A transaction needs to be in status Delivered/Complete in UOL BoaCompra in order to be refunded. The payment method/country of the transaction must be one of which UOL BoaCompra accepts refund. Appendix II has a list of payment methods that are eligible for refund.


    Header Specification

    For a new API request it is mandatory to format the header as described below:

    Parameter Type Description
    Accept String Required This parameter informs the API version, data format (JSON) and encoding. The value will depend on which API you are calling. Refund Create: application/vnd.boacompra.com.v2+json; charset=UTF-8
    Authorization String Required SHA256 generated with a secret key to guarantee request authenticity. Format: {store-id}:{hash}
    Content-Type String Required Only application/json is accepted at the moment
    Content-MD5 String Required for POST operations MD5 of the request body

    Header Example

    POST / HTTP 1.1
    Host: api.boacompra.com
    Accept: application/vnd.boacompra.com.v2+json; charset=UTF-8
    Authorization: 10: 52e7178dea75ae0e71e0f8c2379e0278beb7e9d091763ee0a64e6719d2df0fc2
    Content-Type: application/json
    Content-MD5: 75ea8338894232ee5a707125f50869d2
    


    Code Example

    public class Header {
      private String secretKey = "ABCDE0987";
      private String storeId = "10";
      private String contentMD5;
      private String httpVerb;
    
      public Header(String content, String url) 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 {
        MessageDigest md = MessageDigest.getInstance("MD5");
        byte messageDigest[] = md.digest(content.getBytes("UTF-8"));
        this.contentMD5 =  new BigInteger(1,messageDigest).toString(16);
      }
    
      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.v2+json; charset=UTF-8");
        headers.put("Content-Type", "application/json");
        headers.put("Content-MD5", this.contentMD5);
        headers.put("Authorization", this.storeId+':'+this.generateAuthorization());
    
        return headers;
    
      }
    
    }
    
    String content = "{\"transaction-id\":123456789,\"amount\":10.57,\"notify-url\":\"https://virtualstore.com/notifications\",\"test-mode\":0}";
    
    Header header = new Header(content, "https://api.boacompra.com/refunds");
    HashMap<String, String> headerMap = header.generateHeader();
    
    System.out.println(Arrays.asList(headerMap));
    
    <?php
    
    class header
    {
        private $secretKey = 'ABCDE0987';
        private $storeId = 10;
    
        public function __construct($content, $url)
        {
            $this->setContentMd5($content);
            $this->setHttpVerb($url);
        }
    
        private function setContentMd5($content)
        {
            $this->contentMd5 = md5($content);
        }
    
        private function setHttpVerb($url)
        {
            if (parse_url($url, PHP_URL_QUERY)) {
                $this->httpVerb = parse_url($url, PHP_URL_PATH).'?'.parse_url($url, PHP_URL_QUERY);
            } else {
                $this->httpVerb = parse_url($url, PHP_URL_PATH);
            }
        }
    
        private function generateAuthorization()
        {
            return hash_hmac(
                'sha256',
                $this->httpVerb . $this->contentMd5,
                $this->secretKey
            );
        }
    
    
    
    
        public function generateHeader()
        {
    $headers = array(
                'Accept' => 'application/vnd.boacompra.com.v2+json; charset=UTF-8',
                'Content-Type' => 'application/json',
                'Content-MD5' => $this->contentMd5,
                'Authorization' => $this->storeId . ':' . $this->generateAuthorization()
            );
            return $headers;
        }
    }
    
    echo 'POST EXAMPLE <br />';
    $content = '{"transaction-id":123456789,"amount":10.57,"notify-url":"https://virtualstore.com/notifications","test-mode":0}';
    
    $headerPost = new header($content, 'https://api.boacompra.com/refunds');
    print_r($headerPost->generateHeader());
    
    require 'uri'
    require 'openssl'
    require 'digest/md5'
    
    class Header
    
       SECRET_KEY = 'ABCDE0987'
       STORE_ID = 10
    
       attr_reader :contentMD5, :httpVerb
    
       def initialize(content, url)
        setContentMD5(content)
        setHttpVerb(url)
       end
    
       private
       def setContentMD5(content)
          @contentMD5 = Digest::MD5.hexdigest(content).to_s
       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 = getQueryString(url).to_s.empty? ? uri.path : 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.v2+json; charset=UTF-8',
         "Content-Type"     => 'application/json',
         "Content-MD5"      => @contentMD5,
         "Authorization"    => STORE_ID.to_s + ":" + generateAuthorization()
        }
        headers
       end
    end
    
    puts '<pre>POST EXAMPLE <br />'
    content = '{"transaction-id":123456789,"amount":10.57,"notify-url":"https://virtualstore.com/notifications","test-mode":0}';
    headerGet = Header.new(content, 'https://api.boacompra.com/refunds')
    puts headerGet.generateHeader()
    
    """Python 2.7"""
    from urlparse import urlparse
    import hashlib
    import hmac
    import md5
    
    class Header:
    
      __secretKey = '123'
      __storeId = 10
    
      def __init__(self, content, url):
        self.__setHttpVerb(url)
        self.__setContentMd5(content)
    
      def __setHttpVerb(self, url):
        urlParsed = urlparse(url)
        self.__httpVerb = urlParsed.path + urlParsed.query
    
      def __setContentMd5(self, content):
        self.__contentMd5 = md5.new(content).hexdigest()
    
      def __generateAuthorization(self):
        return hmac.new(
          self.__secretKey,
          self.__httpVerb + self.__contentMd5,
          hashlib.sha256
        ).hexdigest()
    
      def generateHeader(self):
        return {
          'Accept': 'application/vnd.boacompra.com.v2+json; charset=UTF-8',
          'Content-Type': 'application/json',
          'Content-MD5': self.__contentMd5,
          'Authorization': str(self.__storeId) + ':' + self.__generateAuthorization()
        }
    
    from Header import Header
    
    content = '{"transaction-id":123456789,"amount":10.57,"notify-url":"https://virtualstore.com/notifications","test-mode":0}'
    url = 'https://api.boacompra.com/refunds'
    
    a = Header(content, url)
    print a.generateHeader()
    
    
    """Python 3.x"""
    from urllib.parse import urlparse
    import hashlib
    import hmac
    
    class Header:
    
      __secretKey = '123'
      __storeId = 10
    
      def __init__(self, content, url):
        self.__setHttpVerb(url)
        self.__setContentMd5(content)
    
      def __setHttpVerb(self, url):
        urlParsed = urlparse(url)
        self.__httpVerb = urlParsed.path + urlParsed.query
    
      def __setContentMd5(self, content):
        self.__contentMd5 = hashlib.md5(content.encode()).hexdigest()
    
      def __generateAuthorization(self):
        authContent = self.__httpVerb + self.__contentMd5
    
        return hmac.new(
          self.__secretKey.encode(),
          authContent.encode(),
          hashlib.sha256
        ).hexdigest()
    
      def generateHeader(self):
        return {
          'Accept': 'application/vnd.boacompra.com.v2+json; charset=UTF-8',
          'Content-Type': 'application/json',
          'Content-MD5': self.__contentMd5,
          'Authorization': str(self.__storeId) + ':' + self.__generateAuthorization()
        }
    
    from Header import Header
    
    content = '{"transaction-id":123456789,"amount":10.57,"notify-url":"https://virtualstore.com/notifications","test-mode":0}'
    url = 'https://api.boacompra.com/refunds'
    
    a = Header(content, url)
    print(a.generateHeader())
    

    Refund Request API

    This request must be made in order to create a refund for a given transaction. This only creates the refund: the processing and finishing of this refund is made by UOL BoaCompra directly through the payment provider.

    Host: https://api.boacompra.com/refunds

    Method: POST

    Input parameters

    Parameter Type Description
    transaction-id Integer Required Transaction identifier in UOL BoaCompra
    notify-url String Required URL used to notify the Merchant. This URL must bind ports 80 or 443. Format: http or https URL format
    amount Float Optional Amount to be refunded. If not sent, the refund will be processed for the entire value of the transaction. For partial refunds, the amount parameter must be sent. Format: 2000.00
    test-mode Integer Optional Parameter used to indicate that a transaction will be processed in test mode. Can be used the value 1 for sandbox or 0 for production environment. If not set assumes value 0. Format: possible entries are 0 or 1
    reference String Optional Merchant refund identifier. Limit of 64 characters.


    JSON Request Body Example

    {
        "transaction-id": 123456789,
        "amount": 10.57,
        "notify-url": "https://virtualstore.com/notifications",
        "test-mode": 0,
        "reference": "BC-380465"
    }
    

    Success Response

    HTTP Status code: 201

    In case of success, the refund process will be started and the transaction will be set to processing refund status. Also, a “Location” parameter will be informed in the header with the transaction URI location.

    Parameter Type Description
    refund-id String Refund identifier code generated by UOL BoaCompra


    Response header example

    HTTP/1.1 201 Created
    Content-type: application/vnd.boacompra.com.v2+json; charset=UTF-8
    Location: /transactions/123456
    


    JSON Response example

    {
        "refund-id":12345
    }
    


    In a few payment methods, an e-mail will be sent to the end user with URL so he can fulfill its refund information. In this case, he can choose if he wants its refund through bank transfer or Gold credits. This process is transparent to the merchant.

    When accessing the URL, a form similar to the following image will be displayed.

    Refund Request

    After the refund is complete, a notification will be sent via notify API to inform the conclusion of the refund. Please refer to the notification section for further details.

    Error response

    In case of errors in the request, expect a HTTP Status Code different from 201. The body response also contains an error object with the description and an error code

    Json Response example

    {
        "errors": [
            {
                "code": "20614",
                "description": "transaction_not_found "
            }
        ]
    }
    


    The full list of errors can be found in Appendix I. It is possible that you encounter one or more errors in an error array, which will have a unique code number. In those cases, there is a problem with the Request Body: the need of a property or a constraint is not met.

    Json Response example

    {
      "errors": [
        {
          "property": "transaction-id",
          "constraint": "required",
          "code": 20698,
          "description": "The property transaction-id is required"
        },
        {
          "property": "amount",
          "constraint": "minimum",
          "minimum": 0.01,
          "code": 20698,
          "description": "Must have a minimum value of 0.01"
        }
      ]
    }
    

    Transaction Search API

    The API can return information about one specific transaction or a list of transactions, based on the search criteria requested via API. There’s a separate guide for the Transaction Search API.

    Refund in Billing Partner

    You can view refund requests in the billing-partner interface for both live transactions and test transactions. Also, there’s a field for filtering specifically by the unique Refund ID number.

    Billing Partner Refund ID

    In the transaction page a new section, called Refunds, was added. It contains a summary of refund requests.

    Test Mode

    To use the Refund in test mode you will need to have transactions delivered with the “test-mode” parameter set to true, after sending the request for Refund is it possible to simulate the notification of success and failure in the billing-partner interface. In the Transaction Test menu it’s possible to find the transaction for which the refund request was made.

    Refund List

    In the refund list you can simulate the notification for Success and Failure by clicking in the respective button and a notification will be sent to URL informed on the notify-url refund parameter.

    Notification

    When a Refund is finished successfully or is rejected for some reason, the merchant will receive a notification in the notification url first sent when creating the refund. After receiving the notification, the merchant will have to consult the transaction (see section Transaction Search API) and could take an action accordingly its status.

    Base URL: notify-url parameter sent when creating the refund

    Method: POST

    Notification Object

    Parameter Description
    notification-type Assumes the value “refund”
    refund-id ID of the refund in UOL BoaCompra
    transaction-id ID of the transaction in UOL BoaCompra


    Body Example

    {
     "notification-type": "refund",
     "refund-id": 12345,
     "transaction-id": 75040384
    }
    

    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

    206XX - Refund

    Code Key Description
    20601 internal_server_error
    20604 partner_not_found The store-id sent does not exist
    20605 payment_does_not_accept_refund The payment method used in the transaction does not accept refunds
    20607 refund_already_requested A refund for the referred transaction is already being processed
    20608 refund_amount_is_greater_than_limit An amount smaller than the transaction value + refund already requested is required
    20609 refund_amount_is_greater_than_transaction The amount sent is greater than the transaction value
    20610 refund_not_found Refund not found
    20612 service_refund_access_not_authorized The merchant does not have permission to request refunds
    20613 transaction_is_reseller Merchant category does not allow refunds
    20614 transaction_not_found Transaction not found
    20615 transaction_status_not_accept_refund The current status of the transaction does not allow refunds
    20621 expired_refund_request Deadline for refund exceeded
    20622 partial_refund_not_allowed Partial refund not allowed
    20698 Property missing, invalid constraint / type or invalid data.
    20699 unknown_error

    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

    Payment Methods Available for Refund

    The list of payments and countries with refund available can be found on Available Payment List.