Fenige - Payment Hub Service
Introduction
Fenige PaymentHub is a payment gateway allowing Customers to initiate transactions easily by placing a hosted payment button on their website or requesting a payment link via the API provided by PaymentHub. Transactions take place in a secure environment managed by PaymentHub. This solution lets Customers' users pay with: Bank cards (Visa and Mastercard), Google Pay™ Apple Pay™ When users select Google Pay™ or Apple Pay™ and make a purchase, the customer receives an encrypted card payment token, which is encrypted on the Google Pay™ or Apple Pay™ side using Fenige's public key. The customer then provides this encrypted token to Fenige using the PaymentHub service, and Fenige handles the entire transaction process. To use this service, customers must be registered as merchants with Google Pay™ and Apple Pay™ to receive a card payment token, and they must have an active agreement with Fenige to process transactions.
Tip: Fenige demo application
is available here. To initiate transaction please provide
testapikey
in the merchant API key input field and then click "Pay with Paymenthub" button.
Transaction will be perfrormed in test mode - the payer's balance will not be charged.
Quick Tour of a Simple Integration with Paymenthub
In this short guide to Fenige Paymenthub, you will learn about the basic flow of this payment method. It's worth going through this guide, as it may help you better understand the technical details later on. Fenige provides a Payment Hub Service API, implemented according to the REST model. This API offers methods to process transactions using cards, payment tokens obtained from Google Pay™ and Apple Pay, and to authenticate cardholders using the 3D Secure protocol. The Fenige team actively supports customers with integration.
Transaction initialization
The first step of the each transaction always takes place in the Customer application. A Customer integrated with the Fenige Paytool solution should have the option to pay using Fenige Paytool:
The end user is redirected to the Fenige Paytool application after selecting the "Pay with Paytool" option. At the same time Fenige Paytool SDK delivers the initial transaction data to the Fenige Paytool application and the new transaction session is created. The view of transaction initiatialization from the end user's point of view is presented below:
Fenige Paytool is fully responsible for the execution of the transaction and 3DS authentication process. The Customer only initialize transaction by redirecting the end user to the Fenige Paytool form and providing basic transaction metadata via the Fenige Paytool SDK plugged into his application.
Payment methods
Fenige as a PSP provides several different payment methods in its solution. What payment methods will be available in the Fenige Paytool application depends on the Customer's decision. This decision is made during the onboarding process and is editable. The end user, seeing the available payment methods, can choose the option that is most convenient for him. This chapter describes all payment methods supported by Fenige Paytool.
Info: It is required that the Customer has a created account in the Acquirer's system which settle his transactions. Fenige Paytool solution has been implemented so that it is possible to process transactions with the participation of various Acquirers. If the Customer requires the settlement of the transaction by a new Acquirer – to which Fenige is not integrated – there will be required new integration between Fenige and the new Acquirer. The specification of the new Acquirer should be provided by the Customer.
Plain card number
After clicking on the payment option using plain card details, the end user is redirected to the above mentioned payment form. Now he is able to provide the appropriate card details and clicks the "Confirm and proceed the payment" button at the bottom of the screen. At this point, the card details are encrypted and sent to the Fenige Paytool backend. Encrypted card details are decrypted on Fenige Paytool Backend layer with Fenige PSP private key and sent to the Acquirer in transaction request At this moment 3DS authentication process may be required to perform. For more detailed information about the 3DS authentication process please visit the ThreeDS chapter. The payment process using plain card details from the end user's perpective has been shown below:
Google Pay
Fenige as a PSP registered in the Google Pay™ allows to perform a payment with card token generated by Google. Using Fenige Paytool the end user can choose the Google Pay™ as the payment method from the Fenige Paytool payment methods list. The option to pay with Google Pay™ card token is available at the button shown below:
After clicking on the Google Pay™ payment option, the Google Pay™ Wallet popup is displayed to the end user on the Paytool Fenige checkout. After the end user selects the appropriate card from the Google Pay™ Wallet, the card data is encrypted on the Google Pay™ side and transferred to Fenige Paytool server. There, the data is then decrypted and transferred to Acquirer in the transaction request. At this moment 3DS process may be required to perform. For more detailed information about the 3DS authentication process please visit the ThreeDS chapter. The payment process using Google Pay™ card payment token from the end user's perpective has been shown below:
Apple Pay
Warning! Implemenation is work in progress...
Blik
Fenige Paytool also supports cardless payments using the Blik code. The end user can choose the Blik as the payment method from the Fenige Paytool payment methods list. The option to pay with Blik code is available at the button shown below:
After selecting this
payment method, the end user must provide his e-mail address in the proper field in displayed popup and then
confirm the willingness to make the transaction. Blik as an external service, in response to a request,
opens a view that allows end user to enter the 6 digits code. This step of the process takes place outside
the Fenige Paytool system. The 6 digits Blik code is generated in the end user's bank application. The
payment process using Blik code from the end user's perpective has been shown below:
Allowed card networks
Listed below are the types of cards supported in transactions:
Card type |
|
|
Mocks for tests
Mock cards
Here are test cards with a defined ResponseCode running only on the STAGING environment.
Please note that these are just card ranges, you need to generate a valid card number that will be included in this card range (e.g. using any online generator that
generates cards based on bin - first 6 digits).
Begin | End | RC | MAC |
---|---|---|---|
5117960000000000 | 5117968999999999 | CODE_00 | x |
5486000000000000 | 5486009999999999 | CODE_05 | x |
5402060000000000 | 5402069999999999 | CODE_30 | x |
5406603500000000 | 5406603599999999 | CODE_05 | 03 |
5167680100000000 | 5167680199999999 | CODE_63 | x |
Begin | End | RC |
---|---|---|
4400430000000000 | 4400430399999999 | CODE_00 |
4444184330000000 | 4444184339999999 | CODE_05 |
4444184320000000 | 4444184329999999 | CODE_30 |
4444184310000000 | 4444184319999999 | CODE_N7 |
Mock 3DS
The range of card BINs supporting 3DS 2.X for Mastercard is: 500000-549999 Visa is : 400000-449999
In the test environment, you have the option of calling different transactionStatus, depending on the amount
field. For example:
Purchase Amount Range | Transaction Status | Description |
---|---|---|
(1, 1000) | Y | Authentication/account verification successful. |
(1001, 2000) | A | Attempts processing performed; not authenticated/verified, but a proof of attempted authentication/verification is provided. |
(2001, 3000) | C | Challenge required; additional authentication is required using the CReq/CRes. |
(3001, 4000) | N | Not authenticated/account not verified; transaction denied. |
(4001, 5000) | U | Authentication/account verification could not be performed; technical or other problem as indicated in ARes or RReq. |
(5001, 6000) | I | Informational only; 3DS Requestor challenge preference acknowledged. |
Onboarding
Register in Fenige
The onboarding process takes place mainly on Fenige side. However, in order to perform onboarding, the Customer must provide some information needed to correctly configure account in Payment Hub Service. Configuration includes following information:
Customer name | Basically, it's the name of the Customer's company, his online shop and so on. |
Postback URL | This is the address to which information will be send to the Customer about the transaction made by a given user. This parameter is not required if the Customer does not want to receive notifications regarding the transaction. For more information about Postback URL please check Use cases chapter. |
Notification to the user | It is a flag that defines whether e-mail notifications was sent to the User. Such e-mail contains the transaction status, transaction execution date, transaction identifier, date and amount. The Customer decides whether Fenige will send such e-mails or not. |
Redirect Url | Is the URL to which the user is redirected after completing a specific action or process. |
Merchant website url | Is the URL to customer website. |
Available payment methods | Customer inform which methods payments want have enabled on payment page(Card, Google Pay, Apple Pay, Blik). |
After creating an account for the Customer, Fenige provides necessary data to the Customer. This data is required to use the Payment Hub Service API. Such data includes:
Api Key | This key is necessary to be identity in paymenthub system. |
Username | This value is optional, but required to authorization when customer want get status from fenige api. |
Password | This value is optional, but required to authorization when customer want get status from fenige api. |
Authorization data on STAGING and PROD environments differ in password. The login and the gateway Id is the same on both environments.
Integration with Payment Hub Service
SDK
Initialization - Add the following script to your website:
SDK script - staging
<script type="module" src="https://paytool-dev.fenige.pl/paytool.js"> </script>This script contains information about the default payment button for paytool. We provide an example button for paytool, but you can edit it in any way you want. Here you will also find the address to which the user will be transferred after selecting the paytool option. The script code to connect:
Paytool.js
var c=(o,n,t)=>{if(!n.has(o))throw TypeError("Cannot "+t)};var u=(o,n,t)=>(c(o,n,"read from private field"),t?t.call(o):n.get(o)),r=(o,n,t)=>{if(n.has(o))throw
TypeError("Cannot add the same private member more than once");n instanceof WeakSet?n.add(o):n.set(o,t)},b=(o,n,t,e)=>(c(o,n,"write to private field"),e?e.call(o,t):n.set(o,t),t);var
d=(o,n,t)=>(c(o,n,"access private method"),t);import{r as f,j as s,t as k,b as w,e as j}from"./assets/toClassName-27ff9a21.js";const E=`:host
{
display: inline-block;
}
button {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen,
Ubuntu, Cantarell, 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
background: #1b74ff;
border: none;
border-radius: 24px;
padding: 12px 24px;
color: white;
font-weight: bold;
cursor: pointer;
user-select: none;
transition: background 200ms ease-out;
overflow: hidden;
position: relative;
}
button.loading span:first-child {
opacity: 0;
}
button.loading span:last-child {
position: absolute;
inset: 0;
display: flex;
justify-content: center;
align-items: center;
}
button:hover {
background: #2d7eff;
}
button:focus {
background: #196aee;
transition: none;
}
button:disabled {
background: #c5c5c5;
color: #878787;
cursor: default;
}
`;function
S({payTool:o,data:n}){const[t,e]=f.useState(!1),[m,h]=f.useState(!1),g=()=>{t||!n||(e(!0),o.init(n).catch(()=>{h(!0),setTimeout(x,2e3)}))},x=()=>{h(!1),e(!1)};return
s.jsxs(s.Fragment,{children:[s.jsx("style",{children:E}),s.jsxs("button",{onClick:g,className:k({loading:t}),disabled:!(n!=null&&n.amount),children:[s.jsx("span",{children:"Pay
with Payhub"}),t&&s.jsx("span",{children:m?"Error":"Loading..."})]})]})}class y{async init({apiKey:n,...t}){const
e=await w.post("transactions/pre-initialization",t,{headers:{"api-key":n}});location.href=`https://paytool-dev.fenige.pl/${e.data.transactionId}`}}var
l,a,i,p;class v extends HTMLElement{constructor(){super();r(this,i);r(this,l,new y);r(this,a,void 0);this.attachShadow({mode:"open"})}set
data(t){d(this,i,p).call(this,t)}connectedCallback(){b(this,a,j.createRoot(this.shadowRoot)),d(this,i,p).call(this,null)}}l=new WeakMap,a=new WeakMap,i=new
WeakSet,p=function(t){u(this,a).render(s.jsx(S,{payTool:u(this,l),data:t}))};customElements.get("paytool-button")||customElements.define("paytool-button",v);window.Paytool=y;
The type="module" attribute is currently required, because the SDK utilizes modern JavaScript code splitting syntax.
After add script on app you should prepare data to send to paytool. Underneath is only basic code html:
Paymenthub request - example html code
<!DOCTYPE html><html lang="en">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<script
type="module"
src="https://paytool-dev.fenige.pl/paytool.js"></script>
</head>
<body>
<paytool-button></paytool-button>
<script>window.addEventListener('DOMContentLoaded', function () {
var paytool = document.querySelector('paytool-button');
paytool.data = {
apiKey: 'YOUR_API_KEY',
currencyCode: 'CURRENCY_CODE'
amount: 9999,
receiverAmount: 'RECEIVER_AMOUNT'
description: 'DESCRIPTION'
merchantUrl: 'MERCHANT_URL'
orderNumber: 'ORDER_NUMBER'
formLanguage: 'EN'
redirectUrl: {
successUrl: 'FIRST_NAME'
failureUrl: 'FIRST_NAME'
sender: {
firstName: 'FIRST_NAME'
lastName: 'LAST_NAME'
address: {
countryCode: 'COUNTRY_CODE'
city: 'CITY'
postalCode: 'POSTAL_CODE'
street: 'STREET'
houseNumber: 'HOUSE_NUMBER'
transactionConfigurationId: 'TRANSACTION_CONFIGURATION_ID'
};
});
</script>
</body>
</html>
After meeting the above requirements in section the payment method, the Paymenthub Fenige button become visible, which will redirect the user to our website.
Example html: |
<!DOCTYPE html>
<html lang="en">
<head
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<script type="module" src="https://paytool-dev.fenige.pl/paytool.js"</script>
</head>
<body>
<paytool-button></paytool-button>
<script>
window.addEventListener('DOMContentLoaded', function () {
var paytool = document.querySelector('paytool-button');
paytool.data = {
transactionId: e76ce9ad-92a9-43b3-8ed5-4c68bba08a87,
apiKey: TEST,
openInNewTab: true,
amount: 9999,
currencyCode: PLN,
countryOfResidence: PL,
allowedPaymentMethods: [CARD],
description: test transaction,
redirectUrl: {
successUrl: https://paytool-dev.fenige.pl/demo/?success=1,
failureUrl: https://paytool-dev.fenige.pl/demo/?success=0,
cancelUrl: https://paytool-dev.fenige.pl/demo/?success=0
},
sender: {
firstName: John,
lastName: Doe,
email: test@fenige.pl
address: {
countryCode: PL
city: Lublin
postalCode: 24-100
street: Karola Olszewskiego
houseNumber: 10
};
};
});
</script>
</body>
</html>
Request fields |
|||
Name |
Name |
Type |
Description |
|
|
Optional |
This UUID is the ID of the entire transaction process. If you do not send this, it will be generated automatically and returned in the response. In case you decide to send this value, it must be unique |
|
|
Optional |
When value will be true, payment page will be open in new window |
|
|
Not null, Not empty |
This API key is generated by PaymentHub to authenticate the merchant in our system |
|
|
Optional |
Value on true will be open payment page in new tab |
|
|
Not null |
Transaction amount (in pennies) |
|
|
Not empty |
Transaction currency |
|
|
Length(min = 2, max = 2) |
Country code in accordance with ISO 3166-1 Alpha-2. Is required for terminal crypto. Country of residence sent in preInitialization will not be required in the payment form by the end user. |
|
|
Passing CARD here will directly display only the card form. If null is sent, the default payment configuration will be retrieved. |
|
|
|
Optional |
Transaction description |
|
|
Optional |
The successUrl field will be responsible for redirecting the user after a transaction. If it is not provided, a default value from the configuration will be used |
|
|
Optional |
The failureUrl field will be responsible for redirecting the user after a transaction. If it is not provided, a default value from the configuration will be used |
|
|
Optional |
The cancelUrl field will be responsible for redirecting the user after a transaction. If it is not provided, a default value from the configuration will be used |
|
|
Optional |
The firstName field represents the user's first name. If the value is not provided, it will be retrieved from the user at a later stage of the payment process |
|
|
Optional |
The lastName field represents the user's first name. If the value is not provided, it will be retrieved from the user at a later stage of the payment process |
|
|
Optional |
The email field represents the user's email. If the value is not provided, it will be retrieved from the user at a later stage of the payment process |
|
|
Optional |
Two character ISO 3166-1 alpha-2 code of country |
|
|
Optional |
Name of the city where cardholder lives |
|
|
Optional |
Postal code of this address |
|
|
Optional |
Street name in the city |
|
|
Optional |
House number with optional flat number |
Endpoints
Endpoints chapter contains description of endpoints for Payment Hub Service
methods. Fenige provides two implementation environments: test - STAGING
and production -PROD
Transaction Flow
Transaction statuses
The table below presents all possible transaction statuses:
Name |
Description |
|
Transaction waiting for execution. |
|
Transaction was finished with status failure |
|
Transaction success was finished with status success |
|
Transaction success was finished with status success, but is waiting for manual clearing |
|
Transaction was in a status SUCCESS_WAITING_FOR_CLEARING and then was reversed by method REVERSE. |
|
Bank account was charged. |
Payment Hub API methods
In this section, you will find API methods strictly related to business logic. These methods allow you to manage previously initiated transactions.
Paymelink
Paymelink allows you to generate a payment link. In the request, there is a parameter called autoClear, which is set to true by default. This means that the transaction will be automatically cleared by Fenige within a few hours.
You can set this parameter to false, but you must remember to manually clear the transaction.
HTTP/1.1 200 OK
POST /external-api/paymelink HTTP/1.1
API-KEY: apiKey
Content-Type: application/json
Host: paytool-api-dev.fenige.pl
{
"preInitData":{
"transactionId":"fef48a14-f06a-44b7-b110-6ec468019375",
"currencyCode":"PLN",
"amount": 2599,
"receiverAmount": 2599,
"description":"test",
"customerUrl":"https://www.fenige.com",
"orderNumber":"a66026ab-e9f3-4aca-9fb1-25fa3c511a1b",
"redirectUrl":{
"successUrl":"https://default-success.url.com",
"failureUrl":"https://default-failure.url.com",
"cancelUrl":"https://default-cancel.url.com"
},
"formLanguage":"en",
"sender":{
"firstName":"test",
"lastName":"test",
"email" : "test@fenige.pl"
"address":{
"countryCode":"PL",
"city":"Lublin",
"postalCode":"20-149",
"street":"test",
"houseNumber":"1234"
}
},
"autoClear":false,
"merchantUuid" : "f762a329-c138-4475-b4fa-3a397a37e448",
"countryOfResidence" : "PL",
"allowedPaymentMethods" : ["CARD"]
}
}
Request fields |
|||
Name |
Name |
Type |
Description |
|
|
@Must not be null |
This is the id of the entire transaction process |
|
|
@Must not be null |
Transaction currency |
|
|
@Must not be null |
Transaction amount in pennies |
|
|
@Optional field, @Must be greater or equals 0 if exists |
Declared amount. Fenige Information field (in pennies) |
|
|
@Must not be null |
Transaction description |
|
|
Merchant website url |
|
|
|
Order number |
|
|
|
@Must not be null |
Url to redirect user after success transaction |
|
|
@Must not be null |
Url to redirect user after failure transaction |
|
|
@Must not be null |
Url to redirect user after cancel transaction |
|
|
@Must not be null |
Language in paymenthub website |
|
|
First name of payer. First name sent in preInitialization will not be required in the payment form by the end user. |
|
|
|
Last name of payer. Last name sent in preInitialization will not be required in the payment form by the end user. |
|
|
|
Must be a well-formed email address |
Email of payer. Email sent in preInitialization will not be required in the payment form by the end user. |
|
|
Country code |
|
|
|
Name of city |
|
|
|
Postal code |
|
|
|
Name of street |
|
|
|
House number |
|
|
|
@Must not be null |
Is auto clear enabled. Enabled if true, is not enabled if false. There is 7 days for execute clearing process if autoClear = false |
|
|
Is necceseary when you have more than one merchant in payhub service |
|
|
|
Length(min = 2, max = 2) |
Country code in accordance with ISO 3166-1 Alpha-2. Is required for terminal crypto. Country of residence sent in preInitialization will not be required in the payment form by the end user. |
|
|
Passing CARD here will directly display only the card form. If null is sent, the default payment configuration will be retrieved. |
Response body: |
HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
{
"value": "https://paytool-dev.fenige.pl/e8930814-6d5b-4dd2-a511-ac9a1a5326c4",
"transactionId": "e8930814-6d5b-4dd2-a511-ac9a1a5326c4",
"expirationTime": "1748862371"
}
Response fields |
||
Name |
Name |
Description |
|
|
Link to payment |
|
|
This is the id of the entire transaction process |
|
|
Expiration time of link to payment (in seconds of unix timestamp) |
Get transaction details
GET https://paytool-api-dev.fenige.pl/transactions/details/${transactionId}
|
This method is optional and does not affect the process of the transaction itself. Nevertheless, Fenige recommends using this method. In case of any problem with the connection, it allows the Customer to know the current status of a given transaction. This method is secured by Customer's account credentials (basic authorization). Customer's account is created by Fenige during the onboarding process.
Request headers: |
|||
Type |
Value |
Constraints |
Description |
Authorization: |
Basic bG9naW46cGFzc3dvcmQ= |
Required |
Customer's account credentials |
Content-Type |
application/json |
Required |
Content type of the request |
Response body: |
HTTP/1.1 200 OK
X-XSS-Protection: 1; mode=block
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
X-Frame-Options: DENY
Content-Type: application/json
Transfer-Encoding: chunked
Date: Fri, 06 Dec 2024 10:43:13 GMT
Content-Length: 1530
{
"requestUuid" : "f219f12f-9d3b-49d4-b45a-81a26936fe37",
"transactionId" : "f219f12f-9d3b-49d4-b45a-81a26936fe37",
"cofInitialUuid" : "5f6cca83-d4a7-466c-ba66-11b606e209b1",
"creationDate" : "2024-12-06T11:43:10.362Z",
"transactionStatus" : "SUCCESS",
"responseCode" : "CODE_00",
"authorizeRRN" : "014011103023",
"authorizeStan" : "103023",
"clearingStatus" : "APPROVED",
"clearingDate" : "2024-12-06T11:43:10.362Z",
"arn" : "05411640143500000019325",
"autoClear" : true,
"hiddenCardNumber" : "545313******4417",
"provider" : "MASTERCARD",
"bankName" : "Electronic commercial bank"
"amount" : 100.0,
"currency" : "USD",
"geographicScope" : "DOMESTIC_PL",
"firstName" : "John",
"lastName" : "Doe",
"email" : "test@fenige.pl",
"cavv" : "jEu04WZns7pbARAApU4qgNdJTag=",
"mpiStatus" : "Finalize: Y",
"clearingAmount" : 100.0,
"refunds" : [ {
"amount" : 1.0,
"status" : "REFUNDED",
"arn" : "74350824095000000006387",
"rrn" : "428910113225",
"date" : "2024-12-06T11:43:10.362Z",
"responseCode" : "CODE_00"
} ]
}
Response fields |
||
Name |
Name |
Description |
|
|
Request’s unique uuid in system |
|
|
Request’s unique uuid in PaymentHub |
|
|
Transaction creation date |
|
|
CoF Initial Uuid |
|
|
Transaction creation date |
|
|
Transaction Status |
|
|
Response code |
|
|
Transaction Retrieval Reference Number |
|
|
Transaction System Trace Audit Number (STAN) |
|
|
Clearing status |
|
|
Clearing creation date |
|
|
Acquirer Reference Number |
|
|
Is auto clear enabled. Enabled if true, is not enabled if false. There is 7 days for execute clearing process if autoClear = false |
|
|
Hidden card number |
|
|
Card provider |
|
|
Bank name - the value available when the name for a given bank is present on the list of BINs |
|
|
The total transfer amount |
|
|
Currency for transaction. Example: USD |
|
|
Type of transaction scope (DOMESTIC, CROSSBORDER, DOMESTIC_PL, INTRA_EU, INTER) |
|
|
First name of cardholder |
|
|
Last name of cardholder |
|
|
Cardholder’s email |
|
|
Cardholder Authentication Verification Value |
|
|
MPI status |
|
|
The clearing amount. This field is returned if this transaction has been cleared |
|
|
Refund date |
|
|
Refund amount |
|
|
Refund acquirer reference number |
|
|
Refund retrival reference number |
|
|
Refund iso response code |
|
|
Refund status |
method cURL example: |
curl 'https://paytool-api-dev.fenige.pl/transactions/extendedDetails/e11f06fa-a39a-4cca-b297-be534cf13d04' -i -X
GET \
--header 'Content-Type: application/json' \
--header 'Authorization: Basic ZmVuaWdlOmtyenlrYWN6''
Clearing
Clearing is the process where e-commerce and issuers exchanges information about transaction data. It includes sending information about transactions from the e-commerce to the issuer for posting to the cardholder’s account. Using this method, we can just process transaction clearing. It is possible to execute clearing with full payment amount and partial payment amount. Notice that there is 28 days to execute clearing process if field 'autoClear' in payment request is set as 'false'. In the case of Mastercard, false flag means that the transaction is treated as a pre-authorization and, according to the organization's requirements, the clearing time is 30 days from the time of authorization.
HTTP/1.1 200 OK
POST /external/clear HTTP/1.1
Authorization: Basic dXNlcjpwYXNzd29yZA==
Content-Type: application/json
Content-Length: 145
Host: paytool-api-dev.fenige.pl
{
"transactionId" : "e732767c-402d-42af-8a11-63fe7f8bff91",
"merchantUuid" : "e59b470b-bdb1-4043-a856-86b624c2a607",
"clearingAmount" : 700
}
Request fields |
|||
Name |
Name |
Type |
Description |
|
|
This is the id of the entire transaction process |
|
|
|
Merchant’s unique uuid in system |
|
|
|
@Must be at least 1 |
Amount of payment (in pennies) to partial clearing |
Response body: |
HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
{
"completion": {
"estimate": "2024-06-08T23:21:37.536848384"
},
"transactionStatus": "SUCCESS"
}
Response fields |
||
Name |
Type |
Description |
|
|
Clearing status |
|
|
Completion estimate for clearing |
Refund
This method can be use for refund amount of a previously performed transaction. Each one transaction can be refund once at least. Total amount of refund cannot exceed the payment amount. It is important to know, that you can make a refund of transaction that is cleared for now.
HTTP/1.1 200 OK
POST /external/transaction/refund HTTP/1.1
Authorization: Basic dXNlcjpwYXNzd29yZA==
Content-Type: application/json
Content-Length: 145
Host: paytool-api-dev.fenige.pl
{
"transactionId" : "d77b4fd4-5a90-4e36-84b7-a75346d04ca0",
"amountToRefund" : 100
}
Request fields |
|||
Name |
Name |
Type |
Description |
|
|
This is the id of the entire transaction process |
|
|
|
Amount to refund (in pennies) |
Response body: |
HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
{
"transactionStatus": "SUCCESS"
}
Response fields |
||
Name |
Name |
Description |
|
|
Refund status |
Reverse
This method could be used in order to cancel payment of correctly registered transaction in system before. To process reversal method, the transaction must not be cleared. In response, we receive detailed information about the reversal.
HTTP/1.1 200 OK
POST /external/reverse HTTP/1.1
Authorization: Basic dXNlcjpwYXNzd29yZA==
Content-Type: application/json
Content-Length: 145
Host: paytool-api-dev.fenige.pl
{
"transactionId" : "e732767c-402d-42af-8a11-63fe7f8bff91",
"merchantUuid" : "e59b470b-bdb1-4043-a856-86b624c2a607"
}
Request fields |
|||
Name |
Name |
Type |
Description |
|
|
@Must not be null |
This is the id of the entire transaction process |
|
|
@Must not be null |
Merchant’s unique uuid in system |
Response body: |
HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
{
"transactionStatus": "SUCCESS"
}
Response fields |
||
Name |
Name |
Description |
|
|
Reversal status |
Paymenthub Backend to Backend integration
In this section, you will find a description of the methods related to the technical integration of server-to-server communication between Payment Hub and your infrastructure.
Cryptography
Public Key
GET /external-api/public-key
|
Public key is necessary for encrypt payload for 3DS. Below there are two payloads to encrypt for 3DS. Important is remembered about structure.
curl --location --request GET 'https://paytool-api-dev.fenige.pl/external-api/public-key' \
--header 'Content-Type: application/json' \
--header 'API-KEY: *******' \
Jwe Encryption
Use example code to encrypt payload token or card by public key.
{
package pl.fenige.paytool.merchant;
import com.nimbusds.jose.*;
import com.nimbusds.jose.crypto.RSAEncrypter;
import lombok.RequiredArgsConstructor;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.SerializationUtils;
import org.springframework.stereotype.Service;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.X509EncodedKeySpec;
import java.time.Instant;
import java.util.Base64;
public class JweEncrypt {
private static final String ALGORITHM = "RSA";
private final KeyFactory keyFactory;
public JweEncrypt() throws NoSuchAlgorithmException {
keyFactory = KeyFactory.getInstance(ALGORITHM);
}
public String encryptPayload(String payload) throws Exception {
X509EncodedKeySpec encodedKeySpec = new X509EncodedKeySpec(Base64.getDecoder().decode(getPublicKey()));
RSAPublicKey rsaPublicKey = (RSAPublicKey) keyFactory.generatePublic(encodedKeySpec);
JWEHeader.Builder headerBuilder = new JWEHeader.Builder(JWEAlgorithm.RSA_OAEP_256, EncryptionMethod.A256GCM);
JWEHeader header = headerBuilder.type(JOSEObjectType.JOSE)
.customParam("iat",
Instant.now()
.getEpochSecond())
.keyID(DigestUtils.sha1Hex(rsaPublicKey.getEncoded()))
.build();
JWEObject jweObject = new JWEObject(header, new Payload(SerializationUtils.serialize(payload)));
jweObject.encrypt(new RSAEncrypter(rsaPublicKey));
return jweObject.serialize();
}
/* Public key received from PayHub */
public String getPublicKey() {
return "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAo7vHPuwRxESCI7mVlj/Q";
}
}
}
Payload to decrypt
Implement logic from Jwe Encryption and use it to encrypt payload
Request body for card: |
{
"email" : "test.test@fenige.pl",
"phone" : "1986296729",
"firstName": "John",
"lastName": "Test",
"card": {
"cvc2": "123"
"cardNumber" : "1111111111111111",
"cardExpirationDate" : "12/20",
}
}
Request fields |
|||
Name |
Name |
Type |
Description |
|
|
Not empty |
Sender email |
|
|
Optional |
Phone sender |
|
|
Not empty |
First name sender |
|
|
Not empty |
Last name sender |
|
|
Length must be 3 characters, Not null |
Cardholder’s card cvc2 |
|
|
Card number length must be between 12 and 19, Must not be blank, Must not be null |
Full cardholder’s card number must be between 12-digits and 19-digits |
|
|
Must match the regular expression ^(0[1-9]|1[0-2])\/?([0-9]{2})$, Must not be empty, Must not be null |
Expiration date of card mm/yy |
Request body for token: |
{
"email" : "test.test@fenige.pl",
"phone" : "1986296729",
"firstName": "John",
"lastName": "Test",
"token": {
"protocolVersion":"ECv2",
"signature":"MEQCIH6Q4OwQ0jAceFEkGF0JID6sJNXxOEi4r+mA7biRxqBQAiAondqoUpU/bdsrAOpZIsrHQS9nwiiNwOrr24RyPeHA0Q\u003d\u003d",
"intermediateSigningKey":{
"signedKey": "{\"keyExpiration\":\"1542323393147\",\"keyValue\":\"MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE/1+3HBVSbdv+j7NaArdgMyoSAM43yRydzqdg1TxodSzA96Dj4Mc1EiKroxxunavVIvdxGnJeFViTzFvzFRxyCw\\u003d\\u003d\"}",
"signatures": ["MEYCIQCO2EIi48s8VTH+ilMEpoXLFfkxAwHjfPSCVED/QDSHmQIhALLJmrUlNAY8hDQRV/y1iKZGsWpeNmIP+z+tCQHQxP0v"]
},
"signedMessage":"{\"tag\":\"jpGz1F1Bcoi/fCNxI9n7Qrsw7i7KHrGtTf3NrRclt+U\\u003d\",\"ephemeralPublicKey\":\"BJatyFvFPPD21l8/uLP46Ta1hsKHndf8Z+tAgk+DEPQgYTkhHy19cF3h/bXs0tWTmZtnNm+vlVrKbRU9K8+7cZs\\u003d\",\"encryptedMessage\":\"mKOoXwi8OavZ\"}"
}
}
Request fields |
|||
Name |
Name |
Type |
Description |
|
|
Not empty |
Sender email |
|
|
Optional |
Phone sender |
|
|
Not empty |
First name sender |
|
|
Not empty |
Last name sender |
|
|
Not null |
Token obtained from Google |
|
|
Not null |
Token signature |
|
|
Not null |
Token intermediate signing key |
|
|
Not null |
Signed key |
|
|
Not null |
Token signatures |
|
|
Not null |
Protocol version |
|
|
Not null |
Signed message |
Response body: |
HTTP/1.1 200 OK
Content-Length: 209
Content-Type: application/json;charset=UTF-8
{
"value": "eyJ0eXAiOiJKT......y77upmxJJrB97htA"
}
Response fields |
||
Name |
Name |
Description |
|
|
Encrypted sender data |
method cURL example: |
curl 'https://paytool-api-dev.fenige.pl/external-api/public-key' -i -X POST \
-H 'API-KEY: 'apiKey' \
-H 'Content-Type: application/json' \
-d '{
"email" : "test.test@fenige.pl",
"homePhone" : "1986296729",
"mobilePhone" : "1986296729",
"workPhone" : "1986296729",
"firstName": "John",
"lastName": "Test",
"cvc2": "123",
"card": {
"cardNumber" : "1111111111111111",
"cardExpirationDate" : "12/20",
"cvc2": "123"
}'
Pre Initialization
POST /transactions/pre-initialization
|
Before executing each transaction, you must initiate transactions in payhub. In response, you obtain transactionId which should be used when requesting a payment.
Request body: |
HTTP/1.1 200 OK
POST /transactions/pre-initialization HTTP/1.1
API-KEY: apiKey
Content-Type: application/json
Content-Length: 145
Host: paytool-api-dev.fenige.pl
{
"currencyCode": "PLN",
"amount": 1000,
"receiverAmount": 1000,
"description": "Test transaction",
"merchantUrl": "https://www.fenige.com",
"orderNumber": "#12773",
"formLanguage": "pl",
"redirectUrl": {
"successUrl": "https://www.fenige.com",
"failureUrl": "https://www.fenige.com",
"cancelUrl": "https://www.fenige.com"
},
"sender": {
"firstName": "firstName",
"lastName": "lastName",
"email" : "test@fenige.pl,
"address": {
"countryCode": "PL",
"city": "Lublin",
"postalCode": "20-103",
"street": "Rusałka",
"houseNumber": "17a"
}
},
"autoClear": true,
"typeOfAuthorization": "PURCHASE",
"countryOfResidence" : "PL",
"allowedPaymentMethods" : ["CARD"],
"additionalData": {
"note": "Note content"
}
}
Request fields |
|||
Name |
Name |
Type |
Description |
|
|
Not empty |
Transaction currency |
|
|
Not null |
Transaction amount (in pennies) |
|
|
Optional |
Information field only. Field determine receiving amount of cash transferred in one hundredth of the currency. [1PLN = 100] |
|
|
Optional |
Simple description of transaction |
|
|
Optional |
URL address of merchant web system |
|
|
@Length(min = 0, max = 255) |
Declarative number of order that is just purchased by cardholder, set by merchant, should be unique |
|
|
Optional |
Language of transaction process in web browser, use only lowercase |
|
|
Optional |
URL of merchant web service to forward after successful payment flow |
|
|
Optional |
URL of merchant web service to forward after failure payment flow |
|
|
Optional |
URL of merchant web service to forward after cancel payment flow |
|
|
Not empty |
Sender first name. First name sent in preInitialization will not be required in the payment form by the end user. |
|
|
Not empty |
Sender last name. Last name sent in preInitialization will not be required in the payment form by the end user. |
|
|
Must be a well-formed email address |
Sender email. Email sent in preInitialization will not be required in the payment form by the end user. |
|
|
Optional |
Two character ISO 3166-1 alpha-2 code of country |
|
|
Optional |
Name of the city where cardholder lives |
|
|
Optional |
Postal code of this address |
|
|
Optional |
Street name in the city |
|
|
Optional |
House number with optional flat number |
|
|
Optional |
In configuration merchant is set true. When u set false in request u will have 7 days for execute clearing process |
|
|
Optional |
Type of Authorization. Possible values: PURCHASE, COF. Available for card flow, default PURCHASE |
|
|
Length(min = 2, max = 2) |
Country code in accordance with ISO 3166-1 Alpha-2. Is required for terminal crypto. Country of residence sent in preInitialization will not be required in the payment form by the end user. |
|
|
Passing CARD here will directly display only the card form. If null is sent, the default payment configuration will be retrieved. |
|
|
|
Optional, Length(min = 0, max = 150) |
Additional note to transaction |
Response body: |
HTTP/1.1 200 OK
Content-Length: 209
Content-Type: application/json;charset=UTF-8
{
"transactionId" : "08ea8e28-0aad-45eb-8368-f15bdadd5eba"
}
Response fields |
||
Name |
Name |
Description |
|
|
This is the id of the entire transaction process |
curl 'https://paytool-api-dev.fenige.pl/transactions/pre-initialization' -i -X POST \
-H 'API-KEY: 'apiKey' \
-H 'Content-Type: application/json' \
-d '{
"currencyCode": "PLN",
"amount": 1000,
"receiverAmount": 1000,
"description": "Test transaction",
"merchantUrl": "https://www.fenige.com",
"orderNumber": "#12773",
"formLanguage": "pl",
"redirectUrl": {
"successUrl": "https://www.fenige.com",
"failureUrl": "https://www.fenige.com",
"cancelUrl": "https://www.fenige.com"
},
"sender": {
"firstName": "firstName",
"lastName": "lastName",
"email": "test@fenige.pl",
"address": {
"countryCode": "PL",
"city": "Lublin",
"postalCode": "20-103",
"street": "Rusałka",
"houseNumber": "17a"
}
},
"autoClear": true,
"countryOfResidence": "PL"
}'
GET /transactions/pre-initialization/{transactionId}
|
curl --location --request GET
'https://paytool-api-dev.fenige.pl/transactions/pre-initialization/{transactionId}' \
--header 'Content-Type: application/json' \
--header 'API-KEY: apikey'
3DS
Initialize
POST /external-api/transactions/3ds
|
Request body: |
HTTP/1.1 200 OK
POST /external-api/transactions/3ds HTTP/1.1
API-KEY: apiKey
Content-Type: application/json
Content-Length: 145
Host: paytool-api-dev.fenige.pl
{
"merchantUuid": "bb402ef8-a42e-4c6b-b490-41bb4ef23620",
"transactionId": "632d4e68-5a23-4d68-80fd-b7511657351c",
"correlationId": "08ea8e28-0aad-45eb-8368-f15bdadd5eba",
"senderDataEncrypted": "eyJ0eXAiOiJKT1NFIiwiZW5jIjoiQTI1NkdDTSIsImlhdCI6NTAsImFsZyI6IlJTQS1PQUVQLTI1NiIsImtpZCI6IjY3ZTU1ZTNkMmQ3NWEzYjc4NjcyNTY5MTkwYmU3ZTFmOTY3NGQ2ZTIifQ.kE1CFJ4TzECCI4c4Nc8rbuY6YxIKZj7NFCZDZogA912H7QFpkWjIePzFMFqUpm_KnjQ7BJ0UpLuFdZ2N0cX1LVww07tfZ23dkgHxzioGHfbM-ZkxgyRSU37dc1f_CvqiTSEHq0CGyANJw4GdHqEb2rXdV8p-ILyoXFeycyFOtrrQWKbNUclJNXLR9wMNhsgpMl_Rg7renUG7CtXBfNJ3JLWvZFFo4sc0SSClRxFFiEjMWKh3OJC4jQ73y1n1f6LmFeLXHK1UJuZMlck3UrH0wIkaJHkDB8LVcL6mQIz11kfsrjGaKare9lpfzZWbBHKeHILG5YtJZlzogkGfD_LRMw.5RDrh7tA1Lrve0mw.6yb1leILd9QcwOAyylZ2rhlcy084HP6nyqMQ-Fol0JS9y5UbLnH2sSUJehxQgQQ33eC_rSx8IVRaOCEjMrLy-hBBgWoyt-zc5sKH-ppU5Q0tDmd9YhienKs1Zd7Siv3Pv9G6FJyq56nFyuhE9UIKiCz4ul73uWbuC8lhG8leq8pU_X3Ody4PZQJ2Eo3UNAJrCTY4o831kP42lJZ0aHMlWrE9wiHH0bMAi-YO7JYI0D1SuKRFHBeAsAH3NrPY5TOCiFFrk0lBLhBRHVLGDfBHRuqp1J_ydwJ0A0hLCZLuPG4b1nnLGfiuyUbLnlKBHYeV8pNqqQuJa62_CvFFxlTeM-wK7Gf7oAaM8Iid9K3u3Z2eFOROSc8VBG3LcOh2ebOFiMpVJwrwDvTJukSRo0SnLY5f4JsWOQvA.1dpCfqy77upmxJJrB97htA",
"browserData": {
"ipAddress" : "1.1.1.1",
"javaEnabledVal" : "ENABLED",
"javaScriptEnabled" : true,
"windowSize" : "S_250X400",
"acceptHeader" : "Accept: application/json",
"language" : "PL",
"screenHeight" : 200,
"screenWidth" : 200,
"timeZone" : "60",
"userAgent" : "Mozilla/5.0",
"screenColorDepth" : "24"
},
"typeOfTransaction": "GOOGLE_PAY",
"methodNotificationUrl" : "https://methodNotificationUrl.com",
"notificationUrl" : "https://notificationUrl.com"
}
Request fields |
|||
Name |
Name |
Type |
Description |
|
|
Not null |
Uuid merchant in paymenthub |
|
|
Not null |
Unique transacion id |
|
|
Not null |
Encrypted sender data for payment(Card and Token) -> Cryptography |
|
|
Not null |
Data from user browser to show 3DS template |
|
|
Not null |
Type of transaction. Possible values: ONE_TIME_PAYMENT, GOOGLE_PAY, APPLE_PAY, BLIK |
|
|
Must not be empty |
This field specifies the URL to which the ACS will post threeDSMethodData when the hidden iframe post form from browse |
|
|
Not null |
This property specifies the URL to which the final challenge response is POSTed |
Response body OK: |
HTTP/1.1 200 OK
Content-Length: 209
Content-Type: application/json;charset=UTF-8
{
"threeDsFlow":1722820731786,
"acsUrl":1722824331786,
"cReq":"3f9034jf9j9j3490fj09j903",
"challengeHtmlFormBase64":"f34f",
"threeDsSessionData":"ID",
"threeDsMethodData":"paytool.fenige.pl",
"threeDsMethodUrl":"fenige"
}
Response fields |
||
Name |
Name |
Description |
|
|
The timestamp (in milliseconds since the epoch) when the session was created. |
|
|
The timestamp (in milliseconds since the epoch) when the session expires. |
|
|
A unique identifier for the merchant session. |
|
|
A unique, random string generated for this session. |
|
|
The identifier for the merchant. |
|
|
The domain name of the website where Apple Pay is being used. |
|
|
The display name of the merchant. |
|
|
A cryptographic signature of the session data. |
|
|
An identifier used for operational analytics. |
|
|
The number of retries that have been attempted for this session. |
|
|
The Payment Service Provider Identifier. |
method cURL example: |
curl 'https://paytool-api-dev.pl/external-api/session/apple' -i -X POST \
-H 'API-KEY: 'apiKey' \
-H 'Content-Type: application/json' \
--data-raw '{
"validationUrl": "https://apple-pay-gateway.apple.com/paymentservices/startSession",
"transactionId": "ef0bb789-a281-43d7-991e-c02852b72d06"
}'
Continue
POST /external-api/transactions/3ds/continue
|
Request body: |
HTTP/1.1 200 OK
POST /external-api/transactions/3ds/continue HTTP/1.1
API-KEY: apiKey
Content-Type: application/json
Content-Length: 145
Host: paytool-api-dev.fenige.pl
{
"merchantUuid": "bb402ef8-a42e-4c6b-b490-41bb4ef23620",
"transactionId": "632d4e68-5a23-4d68-80fd-b7511657351c",
"correlationId": "08ea8e28-0aad-45eb-8368-f15bdadd5eba",
"senderDataEncrypted": "eyJ0eXAiOiJKT1NFIiwiZW5jIjoiQTI1NkdDTSIsImlhdCI6NTAsImFsZyI6IlJTQS1PQUVQLTI1NiIsImtpZCI6IjY3ZTU1ZTNkMmQ3NWEzYjc4NjcyNTY5MTkwYmU3ZTFmOTY3NGQ2ZTIifQ.kE1CFJ4TzECCI4c4Nc8rbuY6YxIKZj7NFCZDZogA912H7QFpkWjIePzFMFqUpm_KnjQ7BJ0UpLuFdZ2N0cX1LVww07tfZ23dkgHxzioGHfbM-ZkxgyRSU37dc1f_CvqiTSEHq0CGyANJw4GdHqEb2rXdV8p-ILyoXFeycyFOtrrQWKbNUclJNXLR9wMNhsgpMl_Rg7renUG7CtXBfNJ3JLWvZFFo4sc0SSClRxFFiEjMWKh3OJC4jQ73y1n1f6LmFeLXHK1UJuZMlck3UrH0wIkaJHkDB8LVcL6mQIz11kfsrjGaKare9lpfzZWbBHKeHILG5YtJZlzogkGfD_LRMw.5RDrh7tA1Lrve0mw.6yb1leILd9QcwOAyylZ2rhlcy084HP6nyqMQ-Fol0JS9y5UbLnH2sSUJehxQgQQ33eC_rSx8IVRaOCEjMrLy-hBBgWoyt-zc5sKH-ppU5Q0tDmd9YhienKs1Zd7Siv3Pv9G6FJyq56nFyuhE9UIKiCz4ul73uWbuC8lhG8leq8pU_X3Ody4PZQJ2Eo3UNAJrCTY4o831kP42lJZ0aHMlWrE9wiHH0bMAi-YO7JYI0D1SuKRFHBeAsAH3NrPY5TOCiFFrk0lBLhBRHVLGDfBHRuqp1J_ydwJ0A0hLCZLuPG4b1nnLGfiuyUbLnlKBHYeV8pNqqQuJa62_CvFFxlTeM-wK7Gf7oAaM8Iid9K3u3Z2eFOROSc8VBG3LcOh2ebOFiMpVJwrwDvTJukSRo0SnLY5f4JsWOQvA.1dpCfqy77upmxJJrB97htA",
"typeOfTransaction": "GOOGLE_PAY",
"notificationUrl" : "https://notificationUrl.com"
}
Request fields |
|||
Name |
Name |
Type |
Description |
|
|
Not null |
Uuid merchant in paymenthub |
|
|
Not null |
Unique transacion id |
|
|
Not null |
Encrypted sender data for payment(Card and Token) -> Cryptography |
|
|
Not null |
Type of transaction. Possible values: ONE_TIME_PAYMENT, GOOGLE_PAY, APPLE_PAY, BLIK |
|
|
Not null |
This property specifies the URL to which the final challenge response is POSTed |
Response body OK: |
HTTP/1.1 200 OK
Content-Length: 209
Content-Type: application/json;charset=UTF-8
{
"threeDsFlow":1722820731786,
"acsUrl":1722824331786,
"cReq":"3f9034jf9j9j3490fj09j903",
"challengeHtmlFormBase64":"f34f",
"threeDsSessionData":"ID",
"threeDsMethodData":"paytool.fenige.pl",
"threeDsMethodUrl":"fenige"
}
Response fields |
||
Name |
Name |
Description |
|
|
The timestamp (in milliseconds since the epoch) when the session was created. |
|
|
The timestamp (in milliseconds since the epoch) when the session expires. |
|
|
A unique identifier for the merchant session. |
|
|
A unique, random string generated for this session. |
|
|
The identifier for the merchant. |
|
|
The domain name of the website where Apple Pay is being used. |
|
|
The display name of the merchant. |
|
|
A cryptographic signature of the session data. |
|
|
An identifier used for operational analytics. |
|
|
The number of retries that have been attempted for this session. |
|
|
The Payment Service Provider Identifier. |
method cURL example: |
curl 'https://paytool-api-dev.pl/external-api/session/apple' -i -X POST \
-H 'API-KEY: 'apiKey' \
-H 'Content-Type: application/json' \
--data-raw '{
"validationUrl": "https://apple-pay-gateway.apple.com/paymentservices/startSession",
"transactionId": "ef0bb789-a281-43d7-991e-c02852b72d06"
}'
Finalize
POST /external-api/transactions/3ds/finalize
|
Request body: |
HTTP/1.1 200 OK
POST /external-api/transactions/3ds/finalize HTTP/1.1
API-KEY: apiKey
Content-Type: application/json
Content-Length: 145
Host: paytool-api-dev.fenige.pl
{
"merchantUuid": "bb402ef8-a42e-4c6b-b490-41bb4ef23620",
"transactionId": "632d4e68-5a23-4d68-80fd-b7511657351c",
"correlationId": "08ea8e28-0aad-45eb-8368-f15bdadd5eba",
"senderDataEncrypted": "eyJ0eXAiOiJKT1NFIiwiZW5jIjoiQTI1NkdDTSIsImlhdCI6NTAsImFsZyI6IlJTQS1PQUVQLTI1NiIsImtpZCI6IjY3ZTU1ZTNkMmQ3NWEzYjc4NjcyNTY5MTkwYmU3ZTFmOTY3NGQ2ZTIifQ.kE1CFJ4TzECCI4c4Nc8rbuY6YxIKZj7NFCZDZogA912H7QFpkWjIePzFMFqUpm_KnjQ7BJ0UpLuFdZ2N0cX1LVww07tfZ23dkgHxzioGHfbM-ZkxgyRSU37dc1f_CvqiTSEHq0CGyANJw4GdHqEb2rXdV8p-ILyoXFeycyFOtrrQWKbNUclJNXLR9wMNhsgpMl_Rg7renUG7CtXBfNJ3JLWvZFFo4sc0SSClRxFFiEjMWKh3OJC4jQ73y1n1f6LmFeLXHK1UJuZMlck3UrH0wIkaJHkDB8LVcL6mQIz11kfsrjGaKare9lpfzZWbBHKeHILG5YtJZlzogkGfD_LRMw.5RDrh7tA1Lrve0mw.6yb1leILd9QcwOAyylZ2rhlcy084HP6nyqMQ-Fol0JS9y5UbLnH2sSUJehxQgQQ33eC_rSx8IVRaOCEjMrLy-hBBgWoyt-zc5sKH-ppU5Q0tDmd9YhienKs1Zd7Siv3Pv9G6FJyq56nFyuhE9UIKiCz4ul73uWbuC8lhG8leq8pU_X3Ody4PZQJ2Eo3UNAJrCTY4o831kP42lJZ0aHMlWrE9wiHH0bMAi-YO7JYI0D1SuKRFHBeAsAH3NrPY5TOCiFFrk0lBLhBRHVLGDfBHRuqp1J_ydwJ0A0hLCZLuPG4b1nnLGfiuyUbLnlKBHYeV8pNqqQuJa62_CvFFxlTeM-wK7Gf7oAaM8Iid9K3u3Z2eFOROSc8VBG3LcOh2ebOFiMpVJwrwDvTJukSRo0SnLY5f4JsWOQvA.1dpCfqy77upmxJJrB97htA",
"typeOfTransaction": "GOOGLE_PAY"
}
Request fields |
|||
Name |
Name |
Type |
Description |
|
|
Not null |
Uuid merchant in paymenthub |
|
|
Not null |
Unique transacion id |
|
|
Not null |
Encrypted sender data for payment(Card and Token) -> Cryptography |
|
|
Not null |
Type of transaction. Possible values: ONE_TIME_PAYMENT, GOOGLE_PAY, APPLE_PAY, BLIK |
Response body OK: |
HTTP/1.1 200 OK
Content-Length: 209
Content-Type: application/json;charset=UTF-8
{
"transactionId":1722820731786
}
Response fields |
||
Name |
Name |
Description |
|
|
Transaction identifier will be returned when transaction was successful |
method cURL example: |
curl 'https://paytool-api-dev.pl/external-api/session/apple' -i -X POST \
-H 'API-KEY: 'apiKey' \
-H 'Content-Type: application/json' \
--data-raw '{
"validationUrl": "https://apple-pay-gateway.apple.com/paymentservices/startSession",
"transactionId": "ef0bb789-a281-43d7-991e-c02852b72d06"
}'
Transaction
Google Pay
POST /external-api/transactions/google-pay
|
The method allows e-commerce payment using a token obtained from Google Pay™. The method also accepts additional parameters such as transaction item ID or payer details.
Request body: |
HTTP/1.1 200 OK
POST /external-api/transactions/google-pay HTTP/1.1
API-KEY: apiKey
Content-Type: application/json
Content-Length: 145
Host: paytool-api-dev.fenige.pl
{
"transactionId": "08ea8e28-0aad-45eb-8368-f15bdadd5eba",
"correlationId": "e72abf5c-e9fd-45ff-95bb-ccdb6f3c41ce",
"sender": {
"firstName": "firstName",
"lastName": "lastName",
"email": "emaiL@email.pl"
},
"token": {
"protocolVersion":"ECv2",
"signature":"MEQCIH6Q4OwQ0jAceFEkGF0JID6sJNXxOEi4r+mA7biRxqBQAiAondqoUpU/bdsrAOpZIsrHQS9nwiiNwOrr24RyPeHA0Q\u003d\u003d",
"intermediateSigningKey":{
"signedKey": "{\"keyExpiration\":\"1542323393147\",\"keyValue\":\"MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE/1+3HBVSbdv+j7NaArdgMyoSAM43yRydzqdg1TxodSzA96Dj4Mc1EiKroxxunavVIvdxGnJeFViTzFvzFRxyCw\\u003d\\u003d\"}",
"signatures": ["MEYCIQCO2EIi48s8VTH+ilMEpoXLFfkxAwHjfPSCVED/QDSHmQIhALLJmrUlNAY8hDQRV/y1iKZGsWpeNmIP+z+tCQHQxP0v"]
},
"signedMessage":"{\"tag\":\"jpGz1F1Bcoi/fCNxI9n7Qrsw7i7KHrGtTf3NrRclt+U\\u003d\",\"ephemeralPublicKey\":\"BJatyFvFPPD21l8/uLP46Ta1hsKHndf8Z+tAgk+DEPQgYTkhHy19cF3h/bXs0tWTmZtnNm+vlVrKbRU9K8+7cZs\\u003d\",\"encryptedMessage\":\"mKOoXwi8OavZ\"}"
},
"threeDsData": {
"cavv": "jEu04WZns7pbARAApU4qgNdJTag=",
"eci": "01",
"authenticationStatus": "02",
"transactionXId": "Y",
"authenticationId": "d543820d-683e-4589-86d9-6c9e40db4b53"
}
}
Request fields |
|||
Name |
Name |
Type |
Description |
|
|
Not empty |
This is the id of the entire transaction process |
|
|
Not empty |
Unique correlation id |
|
|
Not null |
Sender details |
|
|
Not empty |
Sender first name |
|
|
Not empty |
Sender last name |
|
|
Optional |
Sender email |
|
|
Not null |
Token signature |
|
|
Not null |
Token intermediate signing key |
|
|
Not null |
Signed key |
|
|
Not null |
Token signatures |
|
|
Not null |
Protocol version |
|
|
Not null |
Signed message |
|
|
Optional |
Cardholder Authentication Verification Value. |
|
|
Optional |
Electronic Commerce Indicator: 5 (Visa) or 2 (SecureCode) - The cardholder was successfully authenticated. 6 (Visa) or 1 (SecureCode) - Authentication was attempted, but the cardholder was not enrolled |
|
|
Optional |
Authentication status: Y - (Full Authentication) - The customer was successfully authenticated. A - (Successful Attempted Authentication) - Authentication was not available, but functionality was available to generate a proof of authentication attempt. U - (Technical or other problem) - No liability shift, consider whether to proceed with the transaction |
|
|
Optional |
Server transaction Id generated by DS. Required for 3DS 2.x version. The transactionXId is the field that defines the 3DS version. The presence of this field in the HTTP request specifies that the transaction will be processed with 3DS 2.x. TransactionXId can be obtained by executing the /authentication method |
|
|
Optional |
Unique identifier for 3ds verification |
Response body OK: |
HTTP/1.1 200 OK
Content-Length: 209
Content-Type: application/json;charset=UTF-8
{
"transactionId" : "08ea8e28-0aad-45eb-8368-f15bdadd5eba",
"transactionStatus" : "SUCCESS",
"message" : ""
}
Response body 3DS REQUIRED: |
HTTP/1.1 422 Unprocessable Entity
Content-Length: 500
Content-Type: application/json;charset=UTF-8
{
"date": "2024-07-25T14:23:01.434097335+02:00",
"traceId": "a04adc20-9921-4791-b526-2b4a165ee7a9",
"errorType": "THREE_DS_REQUIRED",
"message": "Google Pay token payment with PAN_ONLY authMethod parameter - 3DS is required"
}
Response fields |
||
Name |
Name |
Description |
|
|
This is the id of the entire transaction process |
|
|
Transaction status |
|
|
Additional information when transaction status is failure, possible field values: "Google Pay token payment with PAN_ONLY authMethod parameter - 3DS is required" or "Transaction with eci = 07. 3ds is required to finish transaction." |
method cURL example: |
curl 'https://paytool-api-dev.pl/external-api/transactions/google-pay' -i -X POST \
-H 'API-KEY: 'apiKey' \
-H 'Content-Type: application/json' \
-d '{
"amount": 1000,
"transactionId": "08ea8e28-0aad-45eb-8368-f15bdadd5eba",
"description": "Test transaction",
"browserIp": "41.11.22.1",
"currency": "PLN",
"deposit": false,
"sender": {
"firstName": "firstName",
"lastName": "lastName",
"email": "emaiL@email.pl"
},
"token": {
"protocolVersion":"ECv2",
"signature":"MEQCIH6Q4OwQ0jAceFEkGF0JID6sJNXxOEi4r+mA7biRxqBQAiAondqoUpU/bdsrAOpZIsrHQS9nwiiNwOrr24RyPeHA0Q\u003d\u003d",
"intermediateSigningKey":{
"signedKey": "{\"keyExpiration\":\"1542323393147\",\"keyValue\":\"MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE/1+3HBVSbdv+j7NaArdgMyoSAM43yRydzqdg1TxodSzA96Dj4Mc1EiKroxxunavVIvdxGnJeFViTzFvzFRxyCw\\u003d\\u003d\"}",
"signatures": ["MEYCIQCO2EIi48s8VTH+ilMEpoXLFfkxAwHjfPSCVED/QDSHmQIhALLJmrUlNAY8hDQRV/y1iKZGsWpeNmIP+z+tCQHQxP0v"]
},
"signedMessage":"{\"tag\":\"jpGz1F1Bcoi/fCNxI9n7Qrsw7i7KHrGtTf3NrRclt+U\\u003d\",\"ephemeralPublicKey\":\"BJatyFvFPPD21l8/uLP46Ta1hsKHndf8Z+tAgk+DEPQgYTkhHy19cF3h/bXs0tWTmZtnNm+vlVrKbRU9K8+7cZs\\u003d\",\"encryptedMessage\":\"mKOoXwi8OavZ\"}"
}
}'
Apple Pay
Open Session
POST /external-api/session/apple
|
Opening of the session in apple is necessary to complete get apple pay token.
Request body: |
HTTP/1.1 200 OK
POST /external-api/transactions/google-pay HTTP/1.1
API-KEY: apiKey
Content-Type: application/json
Content-Length: 145
Host: paytool-api-dev.fenige.pl
{
"validationUrl": "https://apple-pay-gateway.apple.com/paymentservices/startSession",
"transactionId": "08ea8e28-0aad-45eb-8368-f15bdadd5eba"
}
Request fields |
|||
Name |
Name |
Type |
Description |
|
|
Not null |
Url to open session in apple. |
|
|
Not empty |
Unique transacion id |
Response body OK: |
HTTP/1.1 200 OK
Content-Length: 209
Content-Type: application/json;charset=UTF-8
{
"epochTimestamp":1722820731786,
"expiresAt":1722824331786,
"merchantSessionIdentifier":"3f9034jf9j9j3490fj09j903",
"nonce":"f34f",
"merchantIdentifier":"ID",
"domainName":"paytool.fenige.pl",
"displayName":"fenige",
"signature":"sfgergweewrfgwerfwewe5545g5gh5",
"operationalAnalyticsIdentifier":"fenige:3v23v423b5423r4c",
"retries":0,
"pspId":"3v23v423b5423r4c"
}
Response fields |
||
Name |
Name |
Description |
|
|
The timestamp (in milliseconds since the epoch) when the session was created. |
|
|
The timestamp (in milliseconds since the epoch) when the session expires. |
|
|
A unique identifier for the merchant session. |
|
|
A unique, random string generated for this session. |
|
|
The identifier for the merchant. |
|
|
The domain name of the website where Apple Pay is being used. |
|
|
The display name of the merchant. |
|
|
A cryptographic signature of the session data. |
|
|
An identifier used for operational analytics. |
|
|
The number of retries that have been attempted for this session. |
|
|
The Payment Service Provider Identifier. |
method cURL example: |
curl 'https://paytool-api-dev.pl/external-api/session/apple' -i -X POST \
-H 'API-KEY: 'apiKey' \
-H 'Content-Type: application/json' \
--data-raw '{
"validationUrl": "https://apple-pay-gateway.apple.com/paymentservices/startSession",
"transactionId": "ef0bb789-a281-43d7-991e-c02852b72d06"
}'
Apple Pay
POST /external-api/transactions/apple-pay
|
The method allows e-commerce payment using a token obtained from Apple Pay™.
Request body: |
HTTP/1.1 200 OK
POST /external-api/transactions/apple-pay HTTP/1.1
API-KEY: apiKey
Content-Type: application/json
Content-Length: 145
Host: paytool-api-dev.fenige.pl
{
"transactionId": "e11f06fa-a39a-4cca-b297-be534cf13d04",
"correlationId": "ef0bb789-a281-43d7-991e-c02852b72d06",
"token": {
"paymentData": {
"version" : "EC_v1",
"data" : "XaRkK......N89bg",
"signature" : "ldlK9......sCHPm",
"header" : {
"ephemeralPublicKey" : "MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAI0BFh8UeAb...KvcD",
"publicKeyHash" : "E1gMBWx/Tr8j1ZB7k1MxJL95y7E...",
"transactionId" : "E8CDB9F5-89B14D9F8A983B6A3B7E40EE"
}
},
"paymentMethod" : {
"displayName" : "Visa",
"network" : "visa",
"type" : "credit"
},
"transactionIdentifier" : "E8CDB9F589B14D9F8A983B6A3B7E40EE"
},
"sender": {
"firstName" : "test",
"lastName" : "test",
"email" : "test.test@fenige.pl"
},
"language":{
"language" : "PL"
}
}
Request fields |
|||
Name |
Name |
Type |
Description |
|
|
Not null |
Unique transacion id |
|
|
Unique correlation id |
|
|
|
Not null |
The version of the Apple Pay data format being used. |
|
|
Not null |
The version of the Apple Pay data format being used. |
|
|
Not null |
An encrypted string containing the payment information. |
|
|
Not null |
A cryptographic signature used to verify the authenticity of the payment data. |
|
|
Not empty |
The public key used to encrypt the payment data. This key is specific to the current session and is ephemeral (temporary). |
|
|
Not empty |
A hash of the public key used for encryption. |
|
|
Not empty |
A unique identifier for the payment transaction. |
|
|
Not empty |
The name of the payment method as displayed to the user. |
|
|
Not empty |
The payment network associated with the card used (e.g., "visa"). |
|
|
Not empty |
The type of payment card (e.g., "credit"). |
|
|
Not empty |
A unique identifier for the payment transaction. |
|
|
Not empty |
Sender first name |
|
|
Not empty |
Sender last name |
|
|
Not empty |
Sender email |
|
|
Not null |
Language of transaction process |
Response body OK: |
HTTP/1.1 200 OK
Content-Length: 209
Content-Type: application/json;charset=UTF-8
{
"transactionId" : "08ea8e28-0aad-45eb-8368-f15bdadd5eba",
"transactionStatus" : "SUCCESS",
"message" : ""
}
Response fields |
||
Name |
Name |
Description |
|
|
This is the id of the entire transaction process |
|
|
Transaction status |
|
|
Additional information when transaction status is failure |
method cURL example: |
curl 'https://paytool-api-dev.pl/external-api/transactions/apple-pay' -i -X POST \
-H 'API-KEY: 'apiKey' \
-H 'Content-Type: application/json' \
-d '{
"transactionId": "e11f06fa-a39a-4cca-b297-be534cf13d04",
"correlationId": "ef0bb789-a281-43d7-991e-c02852b72d06",
"token": {
"paymentData": {
"version" : "EC_v1",
"data" : "XaRkK......N89bg",
"signature" : "ldlK9......sCHPm",
"header" : {
"ephemeralPublicKey" : "MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAI0BFh8UeAb...KvcD",
"publicKeyHash" : "E1gMBWx/Tr8j1ZB7k1MxJL95y7E...",
"transactionId" : "E8CDB9F5-89B14D9F8A983B6A3B7E40EE"
}
},
"paymentMethod" : {
"displayName" : "Visa",
"network" : "visa",
"type" : "credit"
},
"transactionIdentifier" : "E8CDB9F5-89B1-4D9F-8A98-3B6A3B7E40EE"
},
"sender": {
"firstName" : "test",
"lastName" : "test",
"email" : "test.test@fenige.pl"
},
"language":{
"language" : "PL"
}
}'
CoF
CoF Initial
CoF Subsequent
POST /external/transactions/cof/subsequent
|
The second phase is the subsequent transaction, which requires a successful initial transaction containing the consent to store card data. Merchant provides the cofInitialUuid parameter received in the initial transaction, which defines the customer's card data saved in the transaction. Subsequent transactions are intended for multiple execution.
Request body: |
HTTP/1.1 200 OK
POST /external/transactions/cof/subsequent HTTP/1.1
Authorization: Basic dXNlcjpwYXNzd29yZA==
Content-Type: application/json
Content-Length: 145
Host: paytool-api-dev.fenige.pl
{
"cofInitialUuid":"fb2d81d4-e284-441b-8aa2-d6ccceee9e9a",
"transactionId":"47dc49a9-c42f-48d1-b583-feaf0ac3aad9",
"currencyCode":"PLN",
"amount":"100",
"language":"pl-PL",
"autoClear":"true"
}
Request fields |
|||
Name |
Name |
Type |
Description |
|
|
Not empty |
This is the id of the entire transaction process, set random uuid value |
|
|
Not empty |
CoF initial transaction identifier uuid, available when the 'typeOfAuthorization' field is set to 'COF' in the 'Pre Initialization' method |
|
|
Not empty |
Transaction currency |
|
|
Not null |
Transaction amount (in pennies) |
|
|
Optional |
Information field only. Field determine receiving amount of cash transferred in one hundredth of the currency. [1PLN = 100] |
|
|
Not null |
Language of transaction process |
|
|
Optional |
In configuration merchant is set true. When u set false in request u will have 7 days for execute clearing process |
Response body OK: |
HTTP/1.1 200 OK
Content-Length: 209
Content-Type: application/json;charset=UTF-8
{
"transactionId": "47dc49a9-c42f-48d1-b583-feaf0ac3aad9",
"transactionStatus": "SUCCESS"
}
Response fields |
||
Name |
Name |
Description |
|
|
This is the id of the entire transaction process |
|
|
Transaction status |
|
|
Additional information when transaction status is failure |
method cURL example: |
curl 'https://paytool-api-dev.pl/external/transactions/cof/subsequent' -i -X POST \
-H 'Authorization: Basic ZmVuaWdlOmtyenlrYWN6'
-H 'Content-Type: application/json' \
-d '{
"cofInitialUuid":"fb2d81d4-e284-441b-8aa2-d6ccceee9e9b",
"transactionId":"a717366f-504d-4750-b267-5400b2bc14da",
"currencyCode":"PLN",
"amount":"100",
"language":"pl-PL",
"autoClear":"true"
}'
Webhooks
To use the webhooks functionality, you must notify Fenige Sales Department by email. Then an URL address and a secret token will be configured, thanks to which communication between the Fenige side and the client side will be more secure. After configuring the above-mentioned properties, you will receive Secret Token and then you can handle webhooks from the Fenige system. The URL must be specified by the client, requests from the Fenige system will be directed to this address. The Secret Token will be set by the Fenige employee and sent to the client.
import hashlib
# secret token established by client with fenige employee
secret = 'mNaU9TaK4m9myYYFBJgKu8slNH2fCKutJyzXwI'
# transactionUuid received from webhook's request
transactionUuid = 'c168a885-acfa-4a91-a1ad-ed7a042b7238'
# concatenate strings in correct order
concatenated = secret + transactionUuid
# use SHA256 hashing function
hashed = hashlib.sha256(concatenated.encode('utf-8')).hexdigest()
# then compare 'hashed' variable with content of 'X-SECRET-CHECKSUM' header
Info: Your server after receiving Webhook Event must return HTTP status 200 OK. Otherwise, the Fenige server will retry the request. There is 3 attempts for requesting your API. Repeated requests will be executing in 5 seconds intervals excluding timeout from client server.
Info: In order to protect client API by polling or other undesirable actions, the Fenige system uses headers. If you want to use Webhook events, you need to do the header handling on your side.
Info: Thanks to the 'X-SECRET-CHECKSUM' header you can compare the hash on your backend side to eliminate attempts of unwanted requests. To build 'X-SECRET-CHECKSUM' header: 1. Concatenate secret token established by you and Fenige’s employee with transactionUuid from received request body of callback event 2. Hash with SHA256 function result of above operation
{ "transactionId": "35451011-399a-45bc-8391-a09a01d2a17d", "cofInitialUuid": "79e47300-aee2-4182-bf42-d920c15320ec", "orderNumber": "1", "transactionStatus": "SUCCESS", "amount": 100, "message": "Transaction finish with success", "currency": { "currencyName": "PLN" }, "externalTransactionId": "35451011-399a-45bc-8391-a09a01d2a17d" }