Status Change and Notifications

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

Workflow

Transaction Status Notification Change API

How it works

  1. PagSeguro notifies Merchant that a transaction status has changed
  2. Merchant requests the transaction information provided in the notification to PagSeguro
  3. PagSeguro responds back with the transaction information

📘

When to deliver the goods

In case PagSeguro responds the transaction as COMPLETE , the merchant needs to deliver the purchase to the End User.

Transaction Search API

  1. Merchant requests transaction information
  2. PagSeguro 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:

ParameterDescription
AcceptThis parameter informs the API version, data format (JSON) and encoding.
Default value is: application/vnd.boacompra.com.v1+json; charset=UTF-8
Accept-LanguageInput language. Default value is en-US.
AuthorizationTo create a request the following information is required: store-id, secret-key, URL Path (e.g. /transactions) and URL Query String (e.g. ?initial_date=yyyy-mm-dd).
The string-authorization is done using hmac-sha256-algorithm. The secret-key is the key parameter. The message parameter is formed by the URL Path and URL Query String concatenated.
Content-Typeapplication/json

📘

Store-id and secret-key are provided by your Account Manager.

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

Generating the headers

<?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',
        '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());
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("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));
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',
     "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', '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', 'Authorization': '{}'':{}'.format(self.storeId, self.generateAuthorization()), 'Accept-Language':'en-US'})

Transaction Status Change Notification

Whenever a transaction has its status changed, PagSeguro 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 COMPLETEstatus 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.

ParameterTypeDescription
transaction-codeStringTransaction code. It is the same as “transaction_id”.
notification-typeStringSent with the literal value "transaction" for this status change notification flow.
test-modeBooleanIndicates whether the transaction was created in sandbox environment

Firewall and allowlist settings

❗️

If you use a firewall or allowlists, please note that to receive our notifications, you MUST allowlist the following IPs:

  • 54.233.188.209
  • 18.228.56.27

🚧

This manual refers to the most recent version of status change notifications. You can contact our technical support team to activate it for your account if you have been integrated with a previous version. After that, both formats will be sent to your notification URL.

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=false

Test Environment

PagSeguro provides a sandbox(test-mode) environment for testing purposes, to create a testing transaction simply send the request to the sandbox base URL.

🚧

Base URL for Sandbox

https://api.sandbox.boacompra.com

For proper simulation of all status and integration flow, PagSeguro offers a panel. Please access the following URL with credentials provided by your Account Manager:
https://billing-partner.boacompra.com.

After logging in, search for your test transaction in the “Transactions test” menu:

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

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

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

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