Refunding a payment

We approach refunds as a multistep process, users (including api users) with the refund:request role can request a refund, this will create a refund request in the system. Users with the refund:approve role can then approve the refund request, this will create a refund in the system. The refund will then be processed by the system and the funds will be returned to the customer.

1. Authenticating against the API

Authenticating against the API

import axios from 'axios';
const getToken = async () => {
const response = await axios({
method: 'post',
url: 'https://api.felloh.com/token',
headers: {
'Content-Type': 'application/json'
},
data: JSON.stringify({
public_key: process.env.PUBLIC_KEY,
private_key: process.env.PRIVATE_KEY,
},
),
});
return response.data.data;
};
const { token } = await getToken();
use GuzzleHttp\Client;
function getToken() {
$client = new Client();
$response = $client->post('https://api.felloh.com/token', [
'headers' => [
'Content-Type' => 'application/json',
],
'json' => [
'public_key' => getenv('PUBLIC_KEY'),
'private_key' => getenv('PRIVATE_KEY'),
],
]);
$data = json_decode($response->getBody(), true);
return $data['data'];
}
$token = getToken()['token'];
import requests
import os
def get_token():
url = 'https://api.felloh.com/token'
public_key = os.environ.get('PUBLIC_KEY')
private_key = os.environ.get('PRIVATE_KEY')
payload = {
'public_key': public_key,
'private_key': private_key
}
headers = {
'Content-Type': 'application/json'
}
response = requests.post(url, json=payload, headers=headers)
response.raise_for_status()
token = response.json()['data']
return token
token = get_token()
print(token)
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
class Program
{
static async Task Main()
{
var token = await GetToken();
Console.WriteLine(token);
}
static async Task<string> GetToken()
{
using (var httpClient = new HttpClient())
{
var url = "https://api.felloh.com/token";
var publicKey = Environment.GetEnvironmentVariable("PUBLIC_KEY");
var privateKey = Environment.GetEnvironmentVariable("PRIVATE_KEY");
var requestData = new
{
public_key = publicKey,
private_key = privateKey
};
var jsonContent = new StringContent(Newtonsoft.Json.JsonConvert.SerializeObject(requestData), Encoding.UTF8, "application/json");
var response = await httpClient.PostAsync(url, jsonContent);
response.EnsureSuccessStatusCode();
var responseData = await response.Content.ReadAsStringAsync();
var token = Newtonsoft.Json.JsonConvert.DeserializeObject<dynamic>(responseData).data;
return token;
}
}
}

you will need to authenticate against our api and get the bearer token, you can then use this for all future calls against the API.

You will need to get your public and private keys from the dashboard and them set these either in the environment or via another method.

More information on authentication can be found here.

2. Generating a refund request

Creating a refund request

import axios from 'axios';
const transactionID = '226009ab-ffe9-4c80-922b-982e8e7849f8';
const amount = 90;
const response = await axios(
{
method: 'post',
url: `https://api.felloh.com/agent/transactions${transactionID}/refund`,
data: { amount },
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer <YOUR TOKEN HERE>`,
},
},
);
use GuzzleHttp\Client;
function createPaymentLinks($token, $amount) {
$url = "https://api.felloh.com/agent/transactions/226009ab-ffe9-4c80-922b-982e8e7849f8/refund";
$data = [
'amount' => $amount,
];
$client = new Client();
$response = $client->post($url, [
'json' => $data,
'headers' => [
'Content-Type' => 'application/json',
'Authorization' => "Bearer $token",
],
]);
$data = json_decode($response->getBody(), true);
return $data;
}
$token = "<YOUR TOKEN HERE>";
$response = createPaymentLinks($token, 90);
import requests
def refund_transaction(token, transaction_id, amount):
url = f'https://api.felloh.com/agent/transactions/{transaction_id}/refund'
payload = {
'amount': amount
}
headers = {
'Content-Type': 'application/json',
'Authorization': f'Bearer {token}'
}
response = requests.post(url, json=payload, headers=headers)
response.raise_for_status()
result = response.json()['data']
return result
transaction_id = '226009ab-ffe9-4c80-922b-982e8e7849f8'
amount = 90
result = refund_transaction('<YOUR TOKEN HERE>', transaction_id, amount)
print(result)
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
class Program
{
static async Task Main()
{
var token = "<YOUR TOKEN HERE>";
var transactionId = "226009ab-ffe9-4c80-922b-982e8e7849f8";
var amount = 90;
var response = await RefundTransaction(token, transactionId, amount);
Console.WriteLine(response);
}
static async Task<string> RefundTransaction(string token, string transactionId, int amount)
{
using (var httpClient = new HttpClient())
{
var url = $"https://api.felloh.com/agent/transactions/{transactionId}/refund";
var requestData = new
{
amount
};
var jsonContent = new StringContent(Newtonsoft.Json.JsonConvert.SerializeObject(requestData), Encoding.UTF8, "application/json");
httpClient.DefaultRequestHeaders.Add("Content-Type", "application/json");
httpClient.DefaultRequestHeaders.Add("Authorization", $"Bearer {token}");
var response = await httpClient.PostAsync(url, jsonContent);
response.EnsureSuccessStatusCode();
var responseData = await response.Content.ReadAsStringAsync();
var result = Newtonsoft.Json.JsonConvert.DeserializeObject<dynamic>(responseData).data;
return result;
}
}
}

This will generate a refund request in the system, this will be visible in the dashboard or via the refund endpoint, which can then be approved by a user or via the API.

API documentation for this endpoint can be found here.

3. Listing all refunds

Listing all refunds

import axios from 'axios';
const response = await axios(
{
method: 'post',
url: 'https://api.felloh.com/agent/refunds',
data: {
organisation: 'X9876',
skip: 10,
take: 20
},
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer <YOUR TOKEN HERE>`,
},
},
);
use GuzzleHttp\Client;
function searchSuppliers($token, $organization, $skip, $take) {
$url = "https://api.felloh.com/agent/refunds";
$client = new Client();
$response = $client->post($url, [
'json' => [
'organisation' => $organization,
'skip' => $skip,
'take' => $take,
],
'headers' => [
'Content-Type' => 'application/json',
'Authorization' => "Bearer $token",
],
]);
return $response->getBody();
}
$token = "<YOUR TOKEN HERE>";
$organization = 'X9876';
$skip = 10;
$take = 20;
$response = searchSuppliers($token, $organization, $skip, $take);
import requests
def create_refund(token):
url = 'https://api.felloh.com/agent/refunds'
payload = {
'organisation': 'X9876',
'skip': 10,
'take': 20
}
headers = {
'Content-Type': 'application/json',
'Authorization': f'Bearer {token}'
}
response = requests.post(url, json=payload, headers=headers)
response.raise_for_status()
result = response.json()['data']
return result
result = create_refund('<YOUR TOKEN HERE>')
print(result)
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
class Program
{
static async Task Main()
{
var token = "<YOUR TOKEN HERE>";
var response = await CreateRefund(token);
Console.WriteLine(response);
}
static async Task<string> CreateRefund(string token)
{
using (var httpClient = new HttpClient())
{
var url = "https://api.felloh.com/agent/refunds";
var requestData = new
{
organisation = "X9876",
skip = 10,
take = 20
};
var jsonContent = new StringContent(Newtonsoft.Json.JsonConvert.SerializeObject(requestData), Encoding.UTF8, "application/json");
httpClient.DefaultRequestHeaders.Add("Content-Type", "application/json");
httpClient.DefaultRequestHeaders.Add("Authorization", $"Bearer {token}");
var response = await httpClient.PostAsync(url, jsonContent);
response.EnsureSuccessStatusCode();
var responseData = await response.Content.ReadAsStringAsync();
var result = Newtonsoft.Json.JsonConvert.DeserializeObject<dynamic>(responseData).data;
return result;
}
}
}

Calling this endpoint will allow you to list all refunds in the system. This will allow you to get the authorisation_code for the refund you want to approve.

This can also be found be calling the transaction endpoint, which will now have a refund object attached to it, with its authorisation code.

4. Authorise the refund

Authorising a refund

import axios from 'axios';
const authroisationCode = '8004d669-2875-45b6-a2ce-d08ae79029ae';
const response = await axios(
{
method: 'get',
url: `https://api.felloh.com/agent/refunds/${authroisationCode}/authorise`,
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer <YOUR TOKEN HERE>`,
},
},
);
use GuzzleHttp\Client;
function authoriseRefund($token, $authroisationCode) {
$url = "https://api.felloh.com/agent/refunds/${authroisationCode}/authorise";
$client = new Client();
$response = $client->get($url, [
'headers' => [
'Content-Type' => 'application/json',
'Authorization' => "Bearer $token",
],
]);
$data = json_decode($response->getBody(), true);
return $data;
}
$token = "<YOUR TOKEN HERE>";
$authroisationCode = '8004d669-2875-45b6-a2ce-d08ae79029ae';
$response = authoriseRefund($token, $authroisationCode);
import requests
def authorise_refund(token, authorisation_code):
url = f'https://api.felloh.com/agent/refunds/{authorisation_code}/authorise'
headers = {
'Content-Type': 'application/json',
'Authorization': f'Bearer {token}'
}
response = requests.get(url, headers=headers)
response.raise_for_status()
result = response.json()['data']
return result
authorisation_code = '8004d669-2875-45b6-a2ce-d08ae79029ae'
result = authorise_refund('<YOUR TOKEN HERE>', authorisation_code)
print(result)
using System;
using System.Net.Http;
using System.Threading.Tasks;
class Program
{
static async Task Main()
{
var token = "<YOUR TOKEN HERE>";
var authorisationCode = "8004d669-2875-45b6-a2ce-d08ae79029ae";
var response = await AuthoriseRefund(token, authorisationCode);
Console.WriteLine(response);
}
static async Task<string> AuthoriseRefund(string token, string authorisationCode)
{
using (var httpClient = new HttpClient())
{
var url = $"https://api.felloh.com/agent/refunds/{authorisationCode}/authorise";
httpClient.DefaultRequestHeaders.Add("Content-Type", "application/json");
httpClient.DefaultRequestHeaders.Add("Authorization", $"Bearer {token}");
var response = await httpClient.GetAsync(url);
response.EnsureSuccessStatusCode();
var responseData = await response.Content.ReadAsStringAsync();
var result = Newtonsoft.Json.JsonConvert.DeserializeObject<dynamic>(responseData).data;
return result;
}
}
}

Once the refund has been approved, you can then call the authorise endpoint, this will then send the refund to the acquirer for processing.

More information can be found regarding the approval and decline methods can be found here.