Cobrança com vencimento com QR Code dinâmico (duedate)

Criar uma cobrança Pix única, com data de vencimento e expiração, e opção de aplicar multas, juros, descontos e/ou abatimentos

Pré-requisitos para implementação:

  • Possuir uma chave API da Celcoin, para mais informações acessar esse link

  • Ter familiaridade com APIs Rest usando o protocolo OAuth 2.0.

  • Ter o produto/solução habilitada - caso queira contratar a funcionalidade, por favor, entre em contato com a nossa equipe comercial através do e-mail [email protected]. Para dúvidas técnicas, basta entrar em contato com o suporte através do link.

  • Ter uma chave Pix cadastrada - caso sua empresa não tenha, basta entrar em contato com o nosso suporte, solicitando a criação. Não realizamos o cadastro de chaves do tipo: CNPJ, e-mail, ou telefone, devido a possibilidade de fraudes.

Por que usar um QR Code de cobrança com vencimento (duedate)?

  • Além do valor, permite a inserção de mais informações na modalidade com vencimento, como as regras de cálculo de juros, multa, descontos, entre outras;

  • Pode receber APENAS UM pagamento;

  • Além do valor, permite a inserção de mais informações, como tempo de expiração e dados do devedor;

  • Conciliação via identificador, possibilitando associar a transação Pix à cobrança correlata;

  • Em sua estrutura interna, é configurada uma URL que é acessada no momento de sua leitura. Assim, as informações trazidas pela URL podem variar em função de diversos parâmetros;

  • O QR Code dinâmico contém somente as informações básicas do usuário recebedor. As demais estão em um webservice da instituição do recebedor, com base nessa URL.

Essa funcionalidade deve ser utilizada para realizar a criação de um QR Code de cobrança com valor e data de vencimento definidos, com possibilidade de aplicação de juros, multa, abatimento e descontos. Desta forma, o caso de uso poderia ser:

Como fintech, quero disponibilizar aos meus usuários a possibilidade de criar uma cobrança que aceite pagamento após a data de vencimento, onde ele preenche o valor, multa, juros e desconto para pagamento antecipado. E, então, será apresentado um QR Code e seu código "Pix Copia e Cola" para pagamento da cobrança.

Criando QR Code (location)

Para criar uma nova cobrança, é necessário a gerar um QR Code e atrelar a ele os dados da cobrança que deseja executar. Desta forma, o primeiro passo seria criar um BR Code location, utilizando a API Criar um QR Code (Location).

Modelo de request:

curl --location --request POST 'https://sandbox.openfinance.celcoin.dev/pix/v1/location' \
--header 'accept: application/json' \
--header 'Content-Type: application/json-patch+json' \
--header 'Authorization: Bearer {access_token}' \
--data-raw '{
  "clientRequestId": "9b26edb7cf254db09f5449c94bf13abc",
  "type": "COBV",
  "merchant": {
    "postalCode": "01201005",
    "city": "Barueri",
    "merchantCategoryCode": "0000",
    "name": "Celcoin Pagamentos"
  }
}'

Perceba que o campo type, deve ser preenchido com o valor COBV (cobrança com vencimento) e que o objeto merchant, precisa ser preenchido com CEP, cidade e nome da sua empresa. A propriedade merchantCategoryCode é um número de quatro dígitos, listado na ISO 18245. Caso não a utilize, deve ser preenchida com 0000.

Modelo de retorno:

{
    "status": "CREATED",
    "clientRequestId": "9b26edb7cf254db09f5449c94bf13abc",
    "merchant": {
        "postalCode": "01201005",
        "city": "Barueri",
        "merchantCategoryCode": "0000",
        "name": "Celcoin Pagamentos"
    },
    "url": "qrcode-h.pix.celcoin.com.br/pixqrcode/v2/cobv/dc0f2890238463c7224f10ad2edddb",
    "emv": "00020101021226930014br.gov.bcb.pix2571qrcode-h.pix.celcoin.com.br/pixqrcode/v2/bafd37238fa15e769be8584610caf15904000753039065802BR5823FORTUNA INSTITUICAO DE6007Barueri62070503***630475F1",
    "type": "COBV",
    "locationId": 12730563
}

Se a sua requisição for recebida com sucesso, o retorno da propriedade status será CREATED.

Sugerimos que seja armazenado em sua aplicação o locationId (código do QR code), EMV, pois você precisará desses valores para as próximas requisições.

Criando cobrança com vencimento

Em seguida, deve ser realizada uma requisição na API Criar cobrança com vencimento para vincular o QR Code criado, na requisição de location, a uma cobrança Pix com vencimento.

Para esta chamada é obrigatório preencher alguns campos:
clientRequestId - identificador único da sua aplicação para esse QR Code;
expirationAfterPayment - define a quantidade de dias, após o vencimento, até a expiração da cobrança;
debtor - esse objeto deve ser populado com os dados do pagador da cobrança, informando as propriedades name, cnpj, cpf, postalCode, city e e-mail;
receiver - esse objeto deve ser populado com os dados de quem irá receber o pagamento, informando as propriedades, name ou fantasyName, cnpj ou cpf, postalCode, city e e-mail;
locationId - esse id é gerado na chamada de Criar um BRCode (location);
amount - valor original da cobrança; e
key - chave Pix da sua conta celcoin, essa chave é gerada pela nossa equipe de suporte, uma vez que você tem sua conta homologada.

Essa API possibilita a criação de cobranças com descontos, abatimentos, multas e juros. Abaixo vou explicar como aplicar essas configurações dentro da requisição.

Desconto

Para configurar um desconto, é necessário definir a propriedade hasDiscount como true e definir qual será a modalidade do desconto na propriedade modality, que pode ser preenchida com as seguintes opções:

ValorDescrição
FIXED_VALUE_UNTIL_THE_DATES_INFORMEDValor fixo até a data informada
PERCENTAGE_DATE_REPORTEDPercentual até a data informada
AMOUNT_PER_CALENDAR_DAY_ADVANCEValor por dia corrido de antecipação
AMOUNT_ADVANCE_BUSINESS_DAYValor por dia útil de antecipação
PERCENTAGE_ADVANCE_CURRENT_DAYPercentual por dia corrido de antecipação
PERCENTAGE_ADVANCE_BUSINESS_DAYPercentual por dia útil de antecipação

Além disso, é necessário popular o array discountDateFixed com até 3 objetos amountDicount, onde é preciso informar duas propriedades: date (data da aplicação do desconto no formato yyyy-mm-dd) e amountPerc (valor ou porcentagem que será descontada do valor original, conforme a modalidade).

A data de cálculo para o pagamento deve ser comparada com o primeiro elemento da matriz que, obrigatoriamente, deve ser o mais antigo. Se a data for menor ou igual a essa data, aplica-se o valor de desconto (absoluto ou percentual) associado a esse elemento. Se a data for maior, compara-se com a data do segundo elemento e assim por diante (conforme disposto no Manual de Padrões para Iniciação do Pix).

Modelo de request:

curl --location --request POST 'https://sandbox.openfinance.celcoin.dev/pix/v1/collection/duedate' \
--header 'accept: application/json' \
--header 'Content-Type: application/json-patch+json' \
--header 'Authorization: Bearer {access_token}' \
--data-raw '{
  "clientRequestId": "9b26edb7cf254db09f5449c94bf13abc",
  "expirationAfterPayment": 10,
  "duedate": "2022-03-15 00:00:00",
  "debtor": {
    "name": "Fulano de Tal",
    "cnpj": "61360961000100",
    "city": "Barueri",
    "publicArea": "Avenida Brasil",
    "state": "SP",
    "postalCode": "01202003",
    "email": "[email protected]"
  },
  "receiver": {
    "name": "João da Silva",
    "cnpj": "60904237000129",
    "postalCode": "01202003",
    "city": "Barueri",
    "publicArea": "Avenida Brasil",
    "state": "SP",
    "fantasyName": "Nome de Comercial"
  },
  "locationId": 12730587,
  "amount": 15.63,
  "amountDicount": {
    "discountDateFixed": [
      {
        "date": "2022-03-10",
        "amountPerc": "1.00"
      }
    ],
    "hasDicount": true,
    "modality": "FIXED_VALUE_UNTIL_THE_DATES_INFORMED"
  },
  "key": "[email protected]"
}'

Modelo de retorno:

{
    "transactionIdentification": "kk6g232xel65a0daee4dd13kk9165237",
    "transactionId": 9165237,
    "clientRequestId": "9b26edb7cf254db09f5449c94bf13abc",
    "status": "ACTIVE",
    "lastUpdate": "2022-03-08T16:47:17.2473478+00:00",
    "payerQuestion": null,
    "additionalInformation": null,
    "debtor": {
        "name": "Fulano de Tal",
        "cpf": null,
        "cnpj": "61360961000100"
    },
    "amount": {
        "original": 15.63,
        "discount": {
            "discountDateFixed": [
                {
                    "date": "2022-03-10T00:00:00",
                    "amountPerc": "1.00"
                }
            ],
            "modality": "FIXED_VALUE_UNTIL_THE_DATES_INFORMED"
        },
        "abatement": null,
        "fine": null,
        "interest": null
    },
    "location": {
        "merchant": {
            "postalCode": "01201005",
            "city": "Barueri",
            "merchantCategoryCode": "0000",
            "name": "Celcoin Pagamentos"
        },
        "url": "qrcode-h.pix.celcoin.com.br/pixqrcode/v2/cobv/dc0f2890238463c7224f10ad2edddb",
        "emv": "00020101021226930014br.gov.bcb.pix2571qrcode-h.pix.celcoin.com.br/pixqrcode/v2/bafd37238fa15e769be8584610caf15904000753039065802BR5823FORTUNA INSTITUICAO DE6007Barueri62070503***630475F1",
        "type": "COBV",
        "locationId": "12730587",
        "id": null
    },
    "key": "[email protected]",
    "receiver": {
        "name": "João da Silva",
        "fantasyName": "Nome de Comercial",
        "cpf": null,
        "cnpj": "60904237000129"
    },
    "calendar": {
        "expirationAfterPayment": "10",
        "createdAt": "0001-01-01T00:00:00",
        "dueDate": "2022-03-15T00:00:00"
    },
    "createAt": "2022-03-08T16:47:17.2473478+00:00",

}

O campo Status informa o status atual da cobrança imediata, podendo ser:

  • "ACTIVE": ativo, mas ainda não teve pagamento;
  • "CONCLUDED": quando o pagamento já ocorreu;
  • "DELETED_BY_RECEIVING_USER": deletado por solicitação do usuário final;
  • "DELETED_BY_PSP": deletado por solicitação do participante do Pix.

Abatimento

O abatimento é uma dedução no valor original da cobrança, informado pelo recebedor.

Para aplicar um abatimento, é necessário popular o objeto amountAbatement, definindo a propriedade hasAbatement (informa se haverá ou não dedução) como true ,e informar qual será a modalidade do abatimento na propriedade modality, que pode assumir FIXED_VALUE (valor fixo) ou PERCENT (percentual). O total do abatimento deverá ser informado em amountPerc (valor ou percentual de abatimento, conforme a modalidade escolhida).

Modelo de request:

curl --location --request POST 'https://sandbox.openfinance.celcoin.dev/pix/v1/collection/duedate' \
--header 'Authorization: Bearer {access_token}' \
--header 'Content-Type: application/json' \
--data-raw '{
    "clientRequestId": "9b26edb7cf254db09f5449c94bf13abc",
    "expirationAfterPayment": 10,
    "duedate": "2022-04-29 00:00:00",
    "debtor": {
        "name": "Fulano de Tal",
        "cnpj": "61360961000100",
        "city": "Barueri",
        "publicArea": "Avenida Brasil",
        "state": "SP",
        "postalCode": "01202003",
        "email": "[email protected]"
    },
    "receiver": {
        "name": "João da Silva",
        "cnpj": "60904237000129",
        "postalCode": "01202003",
        "city": "Barueri",
        "publicArea": "Avenida Brasil",
        "state": "SP",
        "fantasyName": "Nome de Comercial"
    },
    "locationId": 12730590,
    "amount": 15.63,
    "amountAbatement": {
        "hasAbatement": true,
        "amountPerc": "5.00",
        "modality": "FIXED_VALUE"
    },
    "key": "[email protected]"
}'

Modelo de response:

{
    "transactionIdentification": "kk6g232xel65a0daee4dd13kk9165344",
    "transactionId": 9165344,
    "clientRequestId": "9b26edb7cf254db09f5449c94bf13abc",
    "status": "ACTIVE",
    "lastUpdate": "2022-03-08T17:48:56.6383606+00:00",
    "payerQuestion": null,
    "additionalInformation": null,
    "debtor": {
        "name": "Fulano de Tal",
        "cpf": null,
        "cnpj": "61360961000100"
    },
    "amount": {
        "original": 15.63,
        "discount": null,
        "abatement": {
            "amountPerc": "5.00",
            "modality": "FIXED_VALUE"
        },
        "fine": null,
        "interest": null
    },
    "location": {
        "merchant": {
            "postalCode": "01201005",
            "city": "Barueri",
            "merchantCategoryCode": "0000",
            "name": "Celcoin Pagamentos"
        },
        "url": "qrcode-h.pix.celcoin.com.br/pixqrcode/v2/cobv/dc0f2890238463c7224f10ad2edddb",
        "emv": "00020101021226930014br.gov.bcb.pix2571qrcode-h.pix.celcoin.com.br/pixqrcode/v2/bafd37238fa15e769be8584610caf15904000753039065802BR5823FORTUNA INSTITUICAO DE6007Barueri62070503***630475F1",
        "type": "COBV",
        "locationId": "12730590",
        "id": null
    },
    "key": "[email protected]",
    "receiver": {
        "name": "João da Silva",
        "fantasyName": "Nome de Comercial",
        "cpf": null,
        "cnpj": "60904237000129"
    },
    "calendar": {
        "expirationAfterPayment": "10",
        "createdAt": "0001-01-01T00:00:00",
        "dueDate": "2022-04-29T00:00:00"
    },
    "createAt": "2022-03-08T17:48:56.6383606+00:00",

}

Multa

A multa é um acréscimo no valor da cobrança, uma vez que a data do pagamento não foi atendida, ou seja, se o vencimento da fatura for no dia 09/03/2025 e ocorrer a tentativa de pagamento dias depois dessa data, será aplicada uma multa ao valor da cobrança. Esse valor pode ser um percentual do valor total ou um valor fixo.

Para atrelar a multa a um QR Code, é necessário preencher o objeto amountFine, definindo a propriedade hasFine, igual a true, indicando que, após a data de vencimento, será aplicada uma multa para esta cobrança.

O campo amountPerc, deve ser preenchido com o valor ou percentual da multa e, a propriedade modality , com a modalidade FIXED_VALUE (valor fixo) ou PERCENT (percentual).

Modelo de request:

curl --location --request POST 'https://sandbox.openfinance.celcoin.dev/pix/v1/collection/duedate' \
--header 'Authorization: Bearer {access_token}' \
--header 'Content-Type: application/json' \
--data-raw '{
    "clientRequestId": "9b26edb7cf254db09f5449c94bf13abc",
    "expirationAfterPayment": 10,
    "duedate": "2022-04-29 00:00:00",
    "debtor": {
        "name": "Fulano de Tal",
        "cnpj": "61360961000100",
        "city": "Barueri",
        "publicArea": "Avenida Brasil",
        "state": "SP",
        "postalCode": "01202003",
        "email": "[email protected]"
    },
    "receiver": {
        "name": "João da Silva",
        "cnpj": "60904237000129",
        "postalCode": "01202003",
        "city": "Barueri",
        "publicArea": "Avenida Brasil",
        "state": "SP",
        "fantasyName": "Nome de Comercial"
    },
    "locationId": 12730609,
    "amount": 15.63,
    "amountFine": {
        "hasFine": true,
        "amountPerc": "5.00",
        "modality": "FIXED_VALUE"
    },
    "key": "[email protected]"
}'

Modelo de retorno:

{
    "transactionIdentification": "kk6g232xel65a0daee4dd13kk9166775",
    "transactionId": 9166775,
    "clientRequestId": "9b26edb7cf254db09f5449c94bf13abc",
    "status": "ACTIVE",
    "lastUpdate": "2022-03-09T14:08:12.3807504+00:00",
    "payerQuestion": null,
    "additionalInformation": null,
    "debtor": {
        "name": "Fulano de Tal",
        "cpf": null,
        "cnpj": "61360961000100"
    },
    "amount": {
        "original": 15.63,
        "discount": null,
        "abatement": null,
        "fine": {
            "amountPerc": "5.00",
            "modality": "FIXED_VALUE"
        },
        "interest": null
    },
    "location": {
        "merchant": {
            "postalCode": "01201005",
            "city": "Barueri",
            "merchantCategoryCode": "0000",
            "name": "Celcoin Pagamentos"
        },
        "url": "qrcode-h.pix.celcoin.com.br/pixqrcode/v2/cobv/dc0f2890238463c7224f10ad2edddb",
        "emv": "00020101021226930014br.gov.bcb.pix2571qrcode-h.pix.celcoin.com.br/pixqrcode/v2/bafd37238fa15e769be8584610caf15904000753039065802BR5823FORTUNA INSTITUICAO DE6007Barueri62070503***630475F1",
        "type": "COBV",
        "locationId": "12730609",
        "id": null
    },
    "key": "[email protected]",
    "receiver": {
        "name": "João da Silva",
        "fantasyName": "Nome de Comercial",
        "cpf": null,
        "cnpj": "60904237000129"
    },
    "calendar": {
        "expirationAfterPayment": "10",
        "createdAt": "0001-01-01T00:00:00",
        "dueDate": "2022-04-29T00:00:00"
    },
    "createAt": "2022-03-09T14:08:12.3807504+00:00",

}

Juros

Para aplicar juros a uma cobrança, é necessário popular o objeto amountInterest, onde é preciso informar três propriedades:
hasInterest como true, para definir que serão aplicados juros após a data de vencimento;
amountPerc com o valor ou porcentagem que será somado ao valor original); e
modality com a modalidade de cálculo dos juros, que pode assumir uma das seguintes opções:

ValorDescrição
VALUE_CALENDAR_DAYSValor por dia (dias corridos)
PERCENTAGE_PER_DAY_CALENDAR_DAYSPercentual ao dia (1 dia corrido)
PERCENTAGE_PER_MONTH_CALENDAR_DAYSPercentual ao mês (30 dias corridos)
PERCENTAGE_PER_YEAR_CALENDAR_DAYSPercentual ao ano (360 dias corridos)
VALUE_WORKING_DAYSValor por dia (dias úteis)
PERCENTAGE_PER_DAYWORKING_DAYSPercentual ao dia (1 dia útil)
PERCENTAGE_PER_MONTH_WORKING_DAYSPercentual ao mês (21 dias úteis)
PERCENTAGE_PER_YEAR_WORKING_DAYSPercentual ao ano (252 dias úteis)

Note que é possível aplicar 8 maneiras diferentes de juros. Sendo assim, é necessário validar qual se aplica melhor ao seu modelo de negócio.

O calculo de dias úteis é feito sobre a "city" do recebedor preenchida no request.

Modelo de request:

curl --location --request POST 'https://sandbox.openfinance.celcoin.dev/pix/v1/collection/duedate' \
--header 'Authorization: Bearer {access_token}' \
--header 'Content-Type: application/json' \
--data-raw '{
    "clientRequestId": "9b26edb7cf254db09f5449c94bf13abc",
    "expirationAfterPayment": 10,
    "duedate": "2022-04-29 00:00:00",
    "debtor": {
        "name": "Fulano de Tal",
        "cnpj": "61360961000100",
        "city": "Barueri",
        "publicArea": "Avenida Brasil",
        "state": "SP",
        "postalCode": "01202003",
        "email": "[email protected]"
    },
    "receiver": {
        "name": "João da Silva",
        "cnpj": "60904237000129",
        "postalCode": "01202003",
        "city": "Barueri",
        "publicArea": "Avenida Brasil",
        "state": "SP",
        "fantasyName": "Nome de Comercial"
    },
    "locationId": 12730614,
    "amount": 15.63,
    "amountInterest": {
        "hasInterest": true,
        "amountPerc": "1.00",
        "modality": "VALUE_CALENDAR_DAYS"
    },
    "key": "[email protected]"
}'

Modelo de retorno:

{
    "transactionIdentification": "kk6g232xel65a0daee4dd13kk9167108",
    "transactionId": 9167108,
    "clientRequestId": "9b26edb7cf254db09f5449c94bf13abc",
    "status": "ACTIVE",
    "lastUpdate": "2022-03-09T14:54:58.6422915+00:00",
    "payerQuestion": null,
    "additionalInformation": null,
    "debtor": {
        "name": "Fulano de Tal",
        "cpf": null,
        "cnpj": "61360961000100"
    },
    "amount": {
        "original": 15.63,
        "discount": null,
        "abatement": null,
        "fine": null,
        "interest": {
            "amountPerc": "1.00",
            "modality": "VALUE_CALENDAR_DAYS"
        }
    },
    "location": {
        "merchant": {
            "postalCode": "01201005",
            "city": "Barueri",
            "merchantCategoryCode": "0000",
            "name": "Celcoin Pagamentos"
        },
        "url": "qrcode-h.pix.celcoin.com.br/pixqrcode/v2/cobv/dc0f2890238463c7224f10ad2edddb",
        "emv": "00020101021226930014br.gov.bcb.pix2571qrcode-h.pix.celcoin.com.br/pixqrcode/v2/bafd37238fa15e769be8584610caf15904000753039065802BR5823FORTUNA INSTITUICAO DE6007Barueri62070503***630475F1",
        "type": "COBV",
        "locationId": "12730614",
        "id": null
    },
    "key": "[email protected]",
    "receiver": {
        "name": "João da Silva",
        "fantasyName": "Nome de Comercial",
        "cpf": null,
        "cnpj": "60904237000129"
    },
    "calendar": {
        "expirationAfterPayment": "10",
        "createdAt": "0001-01-01T00:00:00",
        "dueDate": "2022-04-29T00:00:00"
    },
    "createAt": "2022-03-09T14:54:58.6422915+00:00",

}

Recomendamos que seja armazenada na sua aplicação as propriedades transactionId , e transactionIdentification, para conseguir receber da Celcoin os status da cobrança, através do seu webhook. E, para saber se o QR Code expirou ou não, as propriedades createAt e expirationAfterPayment.

Recebendo o status da cobrança com gatilho

O webhook é uma forma de receber informações de maneira assíncrona, onde geralmente são disparados gatilhos, no formato JSON, quando um evento acontece. Caso o pagamento ocorra com sucesso, a Celcoin dispara um gatilho (RECEIVEPIX) em seu webhook.

Para realizar a configuração de um webhook é necessário entrar em contato com a nossa equipe de suporte informando a url de seu webhook, senha e usuário, no formato BASIC, desta forma eles irão realizar o cadastro em nossa plataforma, para que seja possível o envio dos gatilhos.

Modelo de webhook RECEIVEPIX:

{
    "RequestBody": {
        "TransactionType": "RECEIVEPIX",
        "TransactionId": 56762766,
        "Amount": 150.55,
        "DebitParty": {
            "Account": "416781236",
            "Bank": "18236120",
            "Branch": "1",
            "PersonType": "NATURAL_PERSON",
            "TaxId": "01234567890",
            "AccountType": "CACC",
            "Name": "Fulano de Tal"
        },
        "CreditParty": {
            "Bank": "13935893",
            "Branch": "1",
            "Account": "123456789",
            "PersonType": "NATURAL_PERSON",
            "TaxId": "09876543210",
            "AccountType": "CACC",
            "Name": "Cicrano de Outro",
            "Key": "8ea152b1-ddee-ssaa-aass-ce98245349aa"
        },
        "EndToEndId": "E18236120202001199999s0149012FPC",
        "transactionIdentification": "kk6g232xel65a0daee4dd13kk54578675",
        "transactionIdBRCode": "54578675"
    }
}

No webhook (RECEIVEPIX ) retornarmos o campo transactionIdBrCode que se refere ao transactionid do QR Code gerado e o transactionIdentification. Ambos podem ser utilizados para validar o pagamento do QR Code.

❗️

É muito importante que o parceiro realize a validação entre o valor da cobrança e o valor informado no campo "Amount" do webhook de recebimento, com intuito de conciliar o montante esperado com o que efetivamente foi pago e evitar possíveis prejuízos.

Exemplo de aplicação

Criamos o protótipo de um aplicativo para exemplificar a utilização da API:

📘

Em ambiente de sandbox não é disparado o gatilho (RECEIVEPIX). Para receber, é necessário executar os testes em ambiente produtivo, com uma transação e pagamento de QR Code, usando saldo de sua conta bolsão Celcoin.