Estorno | Deeplink
Estorno V2¶
O deeplink getnet://pagamento/v2/refund deverá ser utilizado somente por Sub-Adquirentes.
Em transações de Sub-Adquirentes é estritamente necessário o envio de informações que indiquem o Estabelecimento Comercial que realizou a transação.
Dessa forma, se faz necessário o envio das Tags especificadas na tabela abaixo, no campo extraData deste novo deeplink.
Request
| Obrigatoriedade | Parâmetro | Formato | Descrição |
|---|---|---|---|
| OPCIONAL | amount | String | 12 dígitos representando o valor, considerando os últimos 2 dígitos como casas decimais. Exemplo: "000000001234" é equivalente R$ 12,34. |
| OPCIONAL | transactionDate | String | Data da transação a ser estornada. Por padrão será o dia corrente. Enviar no formato: “dd/MM/yyyy” |
| OPCIONAL | cvNumber | String | Número do CV da transação a ser estornada. É o mesmo campo que o pagamento retorna. |
| OPCIONAL | originTerminal | String | Número lógico do terminal que efetuou a transação a ser estornada. Este parâmetro só pode ser utilizado caso a funcionalidade de Préautorização esteja habilitada no estabelecimento. Quando este parâmetro não é informado, seráutilizado o número lógico do terminal que está executando o procedimento. |
| OPCIONAL | allowPrintCurrentTransaction | boolean | Ao habilitar este parâmetro, o aplicativo Pagamento não vai imprimir os comprovantes do estabelecimento e do cliente. Seu aplicativo ficará responsável pela impressão dos comprovantes. Mais detalhes na seção Responsabilidade de Impressão. Para desabilitar: “false” Para habilitar: “true” Default: “false” |
| OBRIGATÓRIO | extraData | String | Parametro reservado para envio de informações adicionais relativas à transação. Estes dados serão propagados na autorização da transação. Mais detalhes na seção Sub-Adquirentes. |
Response
Não existem mudanças nos dados retornados.
Tags Sub-Comércio¶
Estão descritas abaixo as Tags necessárias numa transação de Sub Adquirente. Para informações mais detalhadas, consultar Sub-Adquirentes.
| Tag | Descrição | Tipo | Tamanho |
|---|---|---|---|
| 0350 | Soft Descriptor Descrição do subcomércio. Tamanho da estrutura: 22 bytes fixos Dados Soft Descriptor: VAR(1)*VAR(2) VAR(1) pode ter tamanho 3, 7 ou 12 caracteres: XXX*YYYYYYYYYYYYYYYYYY XXXXXXX*YYYYYYYYYYYYYY XXXXXXXXXXXX*YYYYYYYYY Obs.: Caracteres não permitidos podem ser transformados em outros similares ou excluídos. Exemplo: "ç" por "C" Caracteres permitidos: A - Z 0 - 9 % $ , . / & ( ) + - = < > * Espaços Exemplo: SUBADQ *LOJA SANTANDER |
ANS | 22 |
| 0351 | MCC Dinâmico MCC do subcomércio. O estabelecimento terá previamente cadastrado em seu ambiente os MCC que utilizará em seu Gateway. Desta forma, fica ao critério do apenas trafegar por esta TAG a informação recebida do Gateway. Caracteres permitidos: 0 - 9 Exemplo:9999 |
N | 4 |
| 0538 | ID do subcomércio Id de identificação do subcomércio Caracteres permitidos: A - Z 0 - 9 Exemplo:1248ADC |
AN | 15 |
| 0539 | Cidade do Subcomércio Obs.: Caracteres não permitidos podem ser transformados em outros similares ou excluídos. Exemplo: "ç" por "C" Caracteres permitidos: A - Z Exemplo:PORTO ALEGRE |
N | 13 |
| 0540 | Estado do Subcomércio Caracteres permitidos: A - Z Exemplo:RS |
N | 2 |
| 0541 | CEP do Subcomércio Caracteres permitidos: 0 - 9 Exemplo:90550142 |
N | 8 |
| 0542 | CNPJ ou CPF do Subcomércio A aplicação deve validar se é um CNPJ ou CPF válido, sendo o tamanho de 14 para CNPJ e 11 para CPF. Caracteres permitidos: 0 - 9 Exemplo CNPJ:12345678901234 Exemplo CPF:12345678901 |
AN | 14 |
| 0543 | Logradouro do Subcomércio Obs.: Caracteres não permitidos podem ser transformados em outros similares ou excluídos. Exemplo: "ç" por "C" Caracteres permitidos: A - Z 0 - 9 % $ , . / & ( ) + - = < > * Espaços Exemplo:R. DOM PEDRO II, 545 |
AN | 40 |
| 0544 | Telefone do Subcomércio Número de telefone de Atendimento ao Cliente do subcomércio. As três primeiras posições devem ser dedicadas ao DDD do estado do subcomercio. Exemplo:05140088008 |
LLLVAR | 16 |
| 0545 | URL do Subcomércio URL do site do parceiro. Caso o subcomércio não tenha site, não enviar a TAG na requisição. Exemplo:https://www.exemplo.com.br |
LLLVAR | 255 |
| 0546 | Razão Social do Subcomércio Razão Social da Pessoa Jurídica (CNPJ)registrado na Receita Federal. Em casosde Pessoa Física (CPF) enviar o nome registrado na Receita Federal. Caracteres permitidos: A - Z 0 - 9 % $ , . / & ( ) + - = < > * Espaços Exemplo:GETNET ADQUIRENCIA E SERVICOS PARA MEIOS DEPAGAMENTO S.A |
LLLVAR | 80 |
Descrição de tipos:
ANS - Alfanúmerico podendo conter letras, números e símbolos.
AN - Alfanúmerico podendo conter letras e números.
A - Alfabético contendo apénas letras.
N - Númerico contendo apénas números.
LLLVAR - Alfanúmerico longo podendo conter letras, números e símbolos.
Estorno V1¶
O deeplink getnet://pagamento/v1/refund irá iniciar o app de Pagamento na tela de estorno.
Se a requisição for enviada com todos os parâmetros preenchidos, a próxima tela a ser mostrada será a de inserir o cartão para realizar o estorno.
Se a requisição for enviada com parâmetros faltando, a próxima tela a ser mostrada será a de preenchimento manual dos parâmetros restantes. Ao preencher os parâmetros e tocar no botão Continuar, a tela de inserir o cartão será mostrada.
O estorno também pode ser realizado diretamente no aplicativo Pagamento, acessando a opção Estorno e preenchendo os dados manualmente.
O parâmetro originTerminal da requisição e o campo “Terminal de origem” da tela de Estorno do aplicativo Pagamento só podem ser utilizados caso a funcionalidade de Pré-autorização esteja habilitada no estabelecimento. Quando este parâmetro não é informado, será utilizado o número lógico do terminal que está executando o procedimento.
O estorno de pagamento através do deeplink ou do aplicativo Pagamento, pode ser realizado apenas no mesmo dia. Caso o estabelecimento queira estornar uma transação que foi realizada no dia anterior, este deve entrar em contato com a Getnet.
Abaixo seguem as tabelas de requisição e resposta e seus respectivos parâmetros:
Request
| Obrigatoriedade | Parâmetro | Formato | Descrição |
|---|---|---|---|
| OPCIONAL | amount | String | 12 dígitos representando o valor, considerando os últimos 2 dígitos como casas decimais. Exemplo: "000000001234" é equivalente R$ 12,34. |
| OPCIONAL | transactionDate | String | Data da transação a ser estornada. Por padrão será o dia corrente. Enviar no formato: “dd/MM/yyyy” |
| OPCIONAL | cvNumber | String | Número do CV da transação a ser estornada. É o mesmo campo que o pagamento retorna. |
| OPCIONAL | originTerminal | String | Número lógico do terminal que efetuou a transação a ser estornada. Este parâmetro só pode ser utilizado caso a funcionalidade de Préautorização esteja habilitada no estabelecimento. Quando este parâmetro não é informado, seráutilizado o número lógico do terminal que está executando o procedimento. |
| OPCIONAL | allowPrintCurrentTransaction | boolean | Ao habilitar este parâmetro, o aplicativo Pagamento não vai imprimir os comprovantes do estabelecimento e do cliente. Seu aplicativo ficará responsável pela impressão dos comprovantes. Mais detalhes na seção Responsabilidade de Impressão. Para desabilitar: “false” Para habilitar: “true” Default: “false” |
Response
| Quando retorna? | Parâmetro | Formato | Descrição |
|---|---|---|---|
| SEMPRE | result | String | Resultado da transação, conforme a Tabela de Resultados das Funcionalidades. |
| OPCIONAL | resultDetails | String | Texto com detalhes do retorno, conforme a Tabela de Resultados das Funcionalidades. |
| SEMPRE | amount | String | 12 dígitos representando o valor, considerando os últimos 2 dígitos como casas decimais. Exemplo: 000000001234 = R$ 12,34 |
| OPCIONAL | gmtDateTime | String | Data e hora GMT da transação (MMDDhhmmss). Este campo representa o horário GMT |
| OPCIONAL | nsu | String | Código de autorização da transação da Getnet – ele é único por terminal (CV impresso no comprovante, não pode se repetir no mesmo dia) |
| OPCIONAL | nsuLocal | String | NSU gerado no terminal (DOC impresso no comprovante, incremental por dia) |
| OPCIONAL | nsuLastSuccessfullMessage | String | Último NSU da GetNet gerado com sucesso |
| OPCIONAL | authorizationCode | String | Código único de autorização (AUT impresso no comprovante, pode se repetir) * Este campo é de responsabilidade dabandeira * |
| OPCIONAL | cardBin | String | Os 6 primeiros dígitos do cartão |
| OPCIONAL | cardLastDigits | String | Os 4 últimos dígitos do cartão |
| OPCIONAL | refundTransactionDate | String | Data da transação estornada. No formato: “ddMMyyyy” |
| OPCIONAL | refundCvNumber | String | Número do CV da transação estornada. É o mesmo campo que o pagamento retorna. |
| SEMPRE | refundOriginTerminal | String | Número lógico do terminal que efetuou a transação estornada |
| OPCIONAL | cardholderName | String | Retorna o nome do portador gravado no cartão, se disponível. |
| OPCIONAL(*) | splitPayloadResponse | String | (*) Retorna quando é feito um estorno de transações com Split de Pagamento. Mais detalhes na seção Payload do Split de Pagamento. |
| OPCIONAL | automationSlip | String | Neste parâmetro enviamos as informações que devem ser incluídas nos Comprovantes Impressos do estabelecimento e do cliente. Seu aplicativo só é obrigado a imprimir esses campos caso você opte por usar a funcionalidade Responsabilidade de Impressão, pois nesse caso o aplicativo Pagamento não irá imprimir os comprovantes. Mais detalhes na seção Dados do Comprovante. |
Exemplo de implementação
public class MainActivity extends AppCompatActivity {
private final int REQUEST_CODE = 1001;
private final String ARG_RESULT = "result";
private final String ARG_RESULT_DETAILS = "resultDetails";
private final String ARG_AMOUNT = "amount";
@Override
protected void onCreate(@Nullable Bundle savedInstanceState){
super.onCreate(savedInstanceState);
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("getnet://pagamento/v1/refund"));
startActivityForResult(intent, REQUEST_CODE);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data){
super.onActivityResult(requestCode, resultCode, data);
if(REQUEST_CODE == requestCode && RESULT_OK == resultCode){
String result = data.getStringExtra(ARG_RESULT);
String resultDetails = data.getStringExtra(ARG_RESULT_DETAILS);
String amount = data.getStringExtra(ARG_AMOUNT);
}
}
}
class MainActivity : AppCompatActivity() {
private val REQUEST_CODE = 1001
private val ARG_RESULT = "result"
private val ARG_RESULT_DETAILS = "resultDetails"
private val ARG_AMOUNT = "amount"
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val intent = Intent(Intent.ACTION_VIEW, Uri.parse("getnet://pagamento/v1/refund"))
startActivityForResult(intent, REQUEST_CODE)
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (REQUEST_CODE == requestCode && resultCode == RESULT_OK) {
val result = data?.getStringExtra(ARG_RESULT)
val resultDetails = data?.getStringExtra(ARG_RESULT_DETAILS)
val amount = data?.getStringExtra(ARG_AMOUNT)
}
}
}
import React, { useState, useLayoutEffect } from 'react';
import { View, Text } from 'react-native';
import * as IntentLauncher from 'expo-intent-launcher';
const RESULT_OK = -1;
const RESULT_CANCELED = 0;
const ACTION_VIEW = 'android.intent.action.VIEW';
export default function MainComponent() {
const ARG_RESULT = "result";
const ARG_RESULT_DETAILS = "resultDetails";
const ARG_AMOUNT = "amount";
const [resultCode, setResultCode] = useState<number>();
const [resultData, setResultData] = useState({});
const launchIntent = async(deeplink: string, bundle: {}) => {
const intentParams = { ...bundle, data: deeplink }; //Unindo URI Deeplink com o bundle no intentParams
try {
const activityResult = await IntentLauncher.startActivityAsync(ACTION_VIEW, intentParams);
if (activityResult.data && activityResult.resultCode == RESULT_OK) {
if(activityResult.extra) {
const JSON_obj = JSON.parse(JSON.stringify(activityResult.extra))
const result = JSON_obj[ARG_RESULT];
const resultDetails = JSON_obj[ARG_RESULT_DETAILS];
const amount =JSON_obj[ARG_AMOUNT];
setResultData(JSON_obj);
setResultCode(activityResult.resultCode);
}
}
} catch (error) {
console.error(error);
}
};
useLayoutEffect(() => {
const intentParams = {};
//Dispara o Deeplink assim que a tela termina de ser carregada
launchIntent('getnet://pagamento/v1/refund', intentParams);
}, []);
return (
<View>
<Text>Result Code: {resultCode}</Text>
<Text>Result Data: {JSON.stringify(resultData)}</Text>
</View>
);
}
Para utilizar o deeplink, será necessário fazer uso do código nativo:
package com.example.deeplink_test
import androidx.annotation.NonNull
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
import io.flutter.plugin.common.MethodChannel.MethodCallHandler
import io.flutter.plugin.common.MethodChannel.Result
import android.app.Activity
import android.content.Intent
import android.net.Uri
import android.os.Bundle
import android.util.Log
class MainActivity: FlutterActivity(), MethodCallHandler {
private val CHANNEL = "sample.android/deeplink"
private lateinit var channel: MethodChannel
private var callback: Result? = null
private var requestCode: Int = -1
override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
channel = MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).apply {
setMethodCallHandler(this@MainActivity)
}
}
override fun onMethodCall(call: MethodCall, result: Result) {
var action = ""
var deeplink = ""
var bundle = Bundle()
when(call.method) {
"startActivityForResult" -> {
callback = result
val params = call.arguments as? Map<String, Any>
params?.run {
for ((key, value) in params) {
when(key.toString()) {
"action" -> action = value.toString()
"data" -> deeplink = value.toString()
"requestCode" -> requestCode = value.toString().toInt()
"arguments" -> {
bundle.apply{
for((argKey, argValue) in (value as Map<String, Any>)) {
when(argValue) {
is String -> putString(argKey, argValue as String)
is Int -> putInt(argKey, argValue as Int)
is Boolean -> putBoolean(argKey, argValue as Boolean)
}
}
}
}
}
}
val intent = Intent(action, Uri.parse(deeplink)).apply {
putExtras(bundle)
}
startActivityForResult(intent, requestCode)
}
}
else -> result.notImplemented()
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
when(requestCode) {
this.requestCode -> {
when(resultCode) {
Activity.RESULT_OK -> {
data?.getExtras()?.let { extras ->
val resultMap = hashMapOf<String, Any?>()
for(key in extras.keySet()) {
resultMap[key] = extras.get(key)
}
callback?.success(resultMap)
}
} else -> callback?.error("ERROR", "No valid return from DeepLink", null)
}
} else -> callback?.error("ERROR", "Activity result was not OK", null)
}
}
}
E com o código nativo criado, podemos chamar ele através do startIntent abaixo:
import 'dart:developer';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatefulWidget {
const MyApp({super.key,});
@override
State<MyApp> createState() {
return _MyAppState();
}
}
class _MyAppState extends State<MyApp> {
static const int REQUEST_CODE = 10001;
static const String ARG_RESULT = 'result';
static const String ARG_RESULT_DETAILS = 'resultDetails';
static const String ARG_AMOUNT = 'amount';
int? resultCode;
var deeplinkResult = '';
static const platform = MethodChannel('sample.android/deeplink');
void startIntent(String deeplink, Map<String, String> bundle) async {
try {
final intent = {
'requestCode': REQUEST_CODE,
'action': 'android.intent.action.VIEW',
'data': deeplink,
'arguments': bundle,
};
var result = await platform.invokeMethod('startActivityForResult', intent);
if (result != null) {
var resultMap = Map<String, dynamic>.from(result);
var resultValue = resultMap[ARG_RESULT];
var resultDetailsValue = resultMap[ARG_RESULT_DETAILS];
var amountValue = resultMap[ARG_AMOUNT];
setState(() {
resultCode = 1;
});
}
} catch (e) {
log('Error launching intent: $e');
}
}
void _sendDeeplink() {
Map<String, String> intentParams = {};
startIntent('getnet://pagamento/v1/refund', intentParams);
}
@override
void initState() {
super.initState();
_sendDeeplink();
}
@override
Widget build(BuildContext context) {
return ();
}
}