Fenige - PaymentHub 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), BLIK, Pay by Bank, 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 "Checkout and Pay" button. Transaction will be performed 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 PaymentHub 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 PaymentHub solution should have the option to pay using Fenige PaymentHub:

PaymentHub_chosen_payment.png

The end user is redirected to the Fenige PaymentHub application after selecting the "Checkout and Pay" option. At the same time Fenige PaymentHub SDK delivers the initial transaction data to the Fenige PaymentHub application and the new transaction session is created. The view of transaction initialization from the end user's point of view is presented below:

- in PLN

PaymentHub_payment_method_pln.png

The 'Card / Click to Pay' method is under implementation.

- in EUR

PaymentHub_payment_method_eur.png

The 'Card / Click to Pay' method is under implementation.


Card_mobile.png

Apple_pay_ mobile.png

Blik_mobile.png



Fenige PaymentHub 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 PaymentHub form and providing basic transaction metadata via the Fenige PaymentHub 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 PaymentHub 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 PaymentHub.

Info: It is required that the Customer has a created account in the Acquirer's system which settle his  transactions. Fenige PaymentHub 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 "Pay" button at the bottom of the screen. At this point, the card details are encrypted and sent to the Fenige PaymentHub backend. Encrypted card details are decrypted on Fenige PaymentHub 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 3DS chapter. The payment process using plain card details from the end user's perspective has been shown below:

Card_payment_data.png

Google Pay

Fenige as a PSP registered in the Google Pay™ allows to perform a payment with card token generated by Google. Using Fenige PaymentHub the end user can choose the Google Pay™ as the payment method from the Fenige PaymentHub payment methods list. The option to pay with Google Pay™ card token is available at the button shown below:

Google_pay.png

After clicking on the Google Pay™ payment option, the Google Pay™ Wallet popup is displayed to the end user on the PaymentHub 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 PaymentHub 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 3DS chapter. The payment process using Google Pay™ card payment token from the end user's perspective has been shown below:

Google_pay_payment_1.png

Google_pay_payment_2.png

Apple Pay

Fenige as a PSP registered in the Apple Pay™ allows to perform a payment with card token generated by Apple. Using Fenige PaymentHub the end user can choose the Apple Pay™ as the payment method from the Fenige PaymentHub payment methods list. The option to pay with Apple Pay™ card token is available at the button shown below:

Apple_pay.png
After clicking on the Apple Pay™ payment option, the Apple Pay™ Wallet popup is displayed to the end user on the PaymentHub Fenige checkout. After the end user selects the appropriate card from the Apple Pay™ Wallet, the card data is encrypted on the Apple Pay™ side and transferred to Fenige PaymentHub 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 3DS chapter. The payment process using Apple Pay™ card payment token from the end user's perspective has been shown below:

Apple_pay_payment_1.png

Apple_pay_payment_2.png

BLIK

Fenige PaymentHub also supports cardless payments using the BLIK code. The end user can choose the BLIK as the payment method from the Fenige PaymentHub payment methods list. The option to pay with BLIK code is available at the button shown below:

Blik.png
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 PaymentHub 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 perspective has been shown below:

Blik_payment.png

Pay by Bank

Fenige PaymentHub enables users to pay directly from their bank account without manually entering payment details. The user selects their bank, logs in, and authorizes the transfer, which is automatically processed to the recipient’s account. The process is secure and compliant with European open banking regulations and strong customer authentication (SCA). This payment method is available only in euros (EUR) and restricted to selected European countries. The option to pay with Pay by Bank code is available at the button shown below:

Pay_by_Bank.png
After selecting the payment method, the user enters their email address and chooses the country where their bank account is held, then selects their bank to continue the process. The payment process using Pay by Bank from the end user's perspective has been shown below:

Pay_by_Bank_payment.png

Allowed card networks

Listed below are the types of cards supported in transactions:

Card type

MASTERCARD

VISA

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).

Mastercard mock full card range
Begin End RC MAC Card Country Currency
5117960000000000 5117962249999999 CODE_00 x PL PLN
5117962250000000 5117964499999999 CODE_00 x DE EUR
5117964500000000 5117966749999999 CODE_00 x US USD
5117966750000000 5117968999999999 CODE_00 x GB GBP
5486000000000000 5486009999999999 CODE_05 x PL PLN
5402060000000000 5402069999999999 CODE_30 x PL PLN
5406603500000000 5406603599999999 CODE_05 03 PL PLN
5167680100000000 5167680199999999 CODE_63 x PL PLN
5296730000000000 5296730999999999 CODE_65 x PL PLN
5238140000000000 5238140999999999 CODE_1A x PL PLN
Visa mock full card range
Begin End RC Card Country Currency
4400430000000000 4400430099999999 CODE_00 PL PLN
4400430100000000 4400430199999999 CODE_00 DE EUR
4400430200000000 4400430299999999 CODE_00 US USD
4400430300000000 4400430349999999 CODE_00 GB GBP
4400430350000000 4400430399999999 CODE_00 UA UAH
4444184330000000 4444184339999999 CODE_05 PL PLN
4444184320000000 4444184329999999 CODE_30 PL PLN
4444184310000000 4444184319999999 CODE_N7 PL PLN
4539120000000000 4539120999999999 CODE_65 PL PLN
4567810000000000 4567810999999999 CODE_1A PL PLN

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:

Transaction Status Mapping with Descriptions
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 PaymentHub 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, Pay by Bank, BLIK).

After creating an account for the Customer, Fenige provides necessary data to the Customer. This data is required to use the PaymentHub Service API. Such data includes:

Api Key This key is required to identify the merchant in the 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 PaymentHub 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 PaymentHub. We provide an example button for PaymentHub, 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 PaymentHub 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 PaymentHub. 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

Type

Validation

Description

transactionId

String

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

openInNewTab

Boolean

Optional

When value will be true, payment page will be open in new window

apiKey

String

Not null, Not empty

This API key is generated by PaymentHub to authenticate the merchant in our system

amount

Number

Not null

Transaction amount (in pennies)

currencyCode

String

Not empty

Transaction currency

countryOfResidence

String

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.

allowedPaymentMethods

List<String>

Passing CARD here will directly display only the card form. If null is sent, the default payment configuration will be retrieved.

description

String

Optional

Transaction description

redirectUrl.successUrl

String

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

redirectUrl.failureUrl

String

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

redirectUrl.cancelUrl

String

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

sender.firstName

String

Optional. @Length(min = 2, max = 35), @Pattern(regexp = ^(?!\s)(?!.*\x20{2})(?!.*\p{C})(?!.*[\p{Z}&&[^\x20]])(?!.*\p{S})[^0-9!#|$^`\\~_%&\"'(){}*+,./:;<=>?@\t\n\]\[]*(?<!\s)$). Cannot contains tabulations and line breaks.

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

sender.lastName

String

Optional. @Length(min = 2, max = 35), @Pattern(regexp = ^(?!\s)(?!.*\x20{2})(?!.*\p{C})(?!.*[\p{Z}&&[^\x20]])(?!.*\p{S})[^0-9!#|$^`\\~_%&\"'(){}*+,./:;<=>?@\t\n\]\[]*(?<!\s)$). Cannot contains tabulations and line breaks.

The lastName field represents the user's last name. If the value is not provided, it will be retrieved from the user at a later stage of the payment process

sender.email

String

Optional. @Length(min = 1, max = 128) @Pattern(regexp = ^(?:[A-Za-z0-9]{1,}[\.!#$%&'*+/=?`{|}~^\-_]?){1,}[A-Za-z0-9_-]*@((?:[a-zA-Z0-9]+(?:-[a-zA-Z0-9]+)*\.){1,}[a-zA-Z]{2,})$)

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

sender.address.countryCode

String

Optional

Two character ISO 3166-1 alpha-2 code of country

sender.address.city

String

Optional

Name of the city where cardholder lives

sender.address.postalCode

String

Optional

Postal code of this address

sender.address.street

String

Optional

Street name in the city

sender.address.houseNumber

String

Optional

House number with optional flat number

Endpoints

Endpoints chapter contains description of endpoints for PaymentHub Service methods. Fenige provides two implementation environments: test - STAGING and production -PROD

Transaction Flow

Trx flow.png

Transaction statuses

The table below presents all possible transaction statuses:

Name

Description

IN_PROGRESS

Transaction waiting for execution.

FAILURE

Transaction was finished with status failure

SUCCESS

Transaction success was finished with status success

SUCCESS_WAITING_FOR_CLEARING

Transaction success was finished with status success, but is waiting for manual clearing

REVERSED

Transaction was in a status SUCCESS_WAITING_FOR_CLEARING and then was reversed by method REVERSE.

REFUNDED

Bank account was charged.

Response codes

Mastercard/VISA response codes (ISO 8583). Statuses in accordance with ISO-8583.

Response Code Reason Authorization Status
CODE_00 Approved or completed successfully APPROVED
CODE_01 Refer to card issuer DECLINED
CODE_02 Refer to card issuer’s special conditions DECLINED
CODE_03 Invalid merchant or service provider DECLINED
CODE_04 Pick up card (no fraud) DECLINED
CODE_05 Do not honor DECLINED
CODE_06 General error DECLINED
CODE_07 Pick up card, special condition (fraud account) DECLINED
CODE_08 Honor with ID DECLINED
CODE_09 Request in progress DECLINED
CODE_10 Approved for partial amount APPROVED
CODE_11 Approved (V.I.P) DECLINED
CODE_12 Invalid transaction DECLINED
CODE_13 Invalid amount DECLINED
CODE_14 Invalid account number (no such number) DECLINED
CODE_15 Invalid issuer/No such issuer DECLINED
CODE_16 Approved, update track 3 DECLINED
CODE_17 Customer cancellation DECLINED
CODE_18 Customer dispute DECLINED
CODE_19 Re-enter transaction DECLINED
CODE_20 Invalid response DECLINED
CODE_21 No action taken DECLINED
CODE_22 Suspected malfunction DECLINED
CODE_23 Unacceptable transaction fee DECLINED
CODE_24 File update not supported by receiver DECLINED
CODE_25 Unable to locate record in file DECLINED
CODE_26 Duplicate file update record DECLINED
CODE_27 File update field edit error DECLINED
CODE_28 File temporarily not available DECLINED
CODE_30 Format error DECLINED
CODE_31 Bank not supported by switch DECLINED
CODE_32 Completed partially DECLINED
CODE_33 Expired card DECLINED
CODE_34 Suspected fraud DECLINED
CODE_35 Card acceptor contact acquirer DECLINED
CODE_36 Restricted card DECLINED
CODE_37 Card acceptor call acquirer security DECLINED
CODE_38 Allowable PIN tries exceeded DECLINED
CODE_39 No credit account DECLINED
CODE_40 Requested function not supported DECLINED
CODE_41 Lost card, pick up (fraud account) DECLINED
CODE_42 No universal account DECLINED
CODE_43 Stolen card, pick up (fraud account) DECLINED
CODE_44 No investment account DECLINED
CODE_46 Closed account DECLINED
CODE_51 Not sufficient funds DECLINED
CODE_52 No checking account DECLINED
CODE_53 No savings account DECLINED
CODE_54 Expired card or expiration date missing DECLINED
CODE_55 Incorrect PIN or PIN missing DECLINED
CODE_56 No card record DECLINED
CODE_57 Transaction not permitted to cardholder DECLINED
CODE_58 Transaction not permitted to acquirer/terminal DECLINED
CODE_59 Suspected fraud DECLINED
CODE_60 Card acceptor contact acquirer DECLINED
CODE_61 Exceeds withdrawal amount limit DECLINED
CODE_62 Restricted card (invalid in region/country) DECLINED
CODE_63 Security violation DECLINED
CODE_64 Original amount incorrect / AML issue DECLINED
CODE_65 Exceeds withdrawal frequency limit DECLINED
CODE_66 Card acceptor call acquirer’s security DECLINED
CODE_67 Hard capture (pick up at ATM) DECLINED
CODE_68 Response received too late DECLINED
CODE_70 Contact issuer / PIN required DECLINED
CODE_71 PIN Not Changed DECLINED
CODE_72 Account Not Yet Activated DECLINED
CODE_74 PIN encryption error DECLINED
CODE_75 Allowable number of PIN tries exceeded DECLINED
CODE_76 Invalid “To Account” / Unsolicited reversal DECLINED
CODE_77 Invalid “From Account” DECLINED
CODE_78 Invalid account / Blocked new card DECLINED
CODE_79 Already reversed DECLINED
CODE_80 System not available DECLINED
CODE_81 Domestic debit not allowed / Cryptographic PIN error DECLINED
CODE_82 Policy / Negative CAM or CVV DECLINED
CODE_83 Fraud/Security (MC use only) DECLINED
CODE_84 Invalid Authorization Life Cycle DECLINED
CODE_85 No reason to DECLINED (e.g. CVV2 check) APPROVED
CODE_86 PIN Validation not possible DECLINED
CODE_87 No Cash Back Allowed DECLINED
CODE_88 Cryptographic failure DECLINED
CODE_89 Unacceptable PIN / Ineligible for info DECLINED
CODE_90 Cutoff in process DECLINED
CODE_91 Issuer or switch inoperative DECLINED
CODE_92 Routing not found DECLINED
CODE_93 Violation of law DECLINED
CODE_94 Duplicate transmission DECLINED
CODE_95 Reconcile error DECLINED
CODE_96 System malfunction DECLINED
CODE_A1 Additional authentication required DECLINED
CODE_B1 Surcharge not permitted (Visa US) DECLINED
CODE_B2 Surcharge not supported by issuer DECLINED
CODE_N0 Force STIP DECLINED
CODE_N3 Cash service not available DECLINED
CODE_N4 Cashback exceeds limit DECLINED
CODE_N5 Ineligible for resubmission DECLINED
CODE_N7 DECLINED for CVV2 failure DECLINED
CODE_N8 Transaction exceeds approval amount DECLINED
CODE_P2 Invalid biller information DECLINED
CODE_P5 PIN Change/Unblock request DECLINED
CODE_P6 Denied PIN change (unsafe) DECLINED
CODE_Q1 Card Authentication failed DECLINED
CODE_R0 Stop payment order DECLINED
CODE_R1 Revocation of authorization order DECLINED
CODE_R2 Transaction not qualify for Visa PIN DECLINED
CODE_R3 Revocation of all authorizations DECLINED
CODE_XA Forward to issuer DECLINED
CODE_XD Forward to issuer DECLINED
CODE_Z3 Unable to go online DECLINED
CODE_TBA Customer ID verification failed DECLINED
CODE_1A Additional authentication required (EU) DECLINED
CODE_6P Verification Failed (ID mismatch) DECLINED
CODE_4F Merchant country same as issuer (cross-border only) DECLINED
CODE_5C Transaction not supported/blocked DECLINED
CODE_9G Blocked by cardholder DECLINED

PaymentHub API methods

In this section, you will find API methods strictly related to business logic. These methods allow you to manage previously initiated transactions.

Authorization method:
API-KEY

Trx flow true.png

You can set this parameter to false, but you must remember to manually clear the transaction.

Trx flow false.png

Get transaction details

Authorization method:
Basic Auth
GEThttps://paytool-api-dev.fenige.pl/transactions/details/43ed2b94-792c-4e10-aca9-8cb7d69b1b85

Request details

Name

Type

Description

Request URL

Endpoint

https://paytool-api-dev.fenige.pl/transactions/details/{transactionId}

transactionId

String

Transaction unique Id in system

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 (possible variants):
Transaction status: SUCCESS
HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
{
    "requestUuid": "455bf4f8-76c5-4b90-9a08-2bf7ff594793",
    "transactionId": "455bf4f8-76c5-4b90-9a08-2bf7ff594793",
    "cofInitialUuid": "7317069a-ea85-464c-9197-e2010078eedd",
    "creationDate": "2025-10-02T13:51:42.003Z",
    "transactionStatus": "SUCCESS",
    "responseCode": "CODE_00",
    "authorizeRRN": "527511226228",
    "authorizeStan": "226228",
    "clearingStatus": "APPROVED",
    "clearingDate": "2025-10-02T14:18:06.544Z",
    "arn": "24350825275000001685324",
    "autoClear": false,
    "hiddenCardNumber": "411111******1111",
    "provider": "VISA",
    "bankName": "MOCK BANK VISA ECOMMERCE",
    "amount": 10.00,
    "currency": "PLN",
    "geographicScope": "DOMESTIC_PL",
    "firstName": "Card Holder",
    "lastName": "Name",
    "email": "test.testowy.97@gmail.com",
    "cavv": "AJkBAoEREQAAAAB4hABwcAAAAAA=",
    "clearingAmount": 10.00,
    "refunds": []
}
Transaction status: FAILURE
HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
{
    "transactionId": "d9030207-2b48-4fe4-8d78-6650f84f3990",
    "creationDate": "2025-10-02T13:32:20.284866+02:00",
    "transactionStatus": "FAILURE",
    "autoClear": false,
    "amount": 1200,
    "currency": "PLN",
    "errorMessage": "Failed to get currency for card"
}
Transaction status: SUCCESS_WAITING_FOR_CLEARING
HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
{
    "transactionId": "e11f06fa-a39a-4cca-b297-be534cf13d04",
    "creationDate": "2025-10-02T13:40:15.003Z",
    "transactionStatus": "SUCCESS_WAITING_FOR_CLEARING",
    "autoClear": true,
    "amount": 100,
    "currency": "PLN",
    "message": "Transaction authorized, waiting for clearing"
}

Response fields

Name

Type

Description

requestUuid

String

Request’s unique uuid in system

transactionId

String

Request’s unique uuid in PaymentHub

creationDate

String

Transaction creation date

cofInitialUuid

String

CoF Initial Uuid

createdDate

String

Transaction creation date

transactionStatus

String

Transaction Status

responseCode

String

Response code

authorizeRRN

String

Transaction Retrieval Reference Number

authorizeStan

String

Transaction System Trace Audit Number (STAN)

clearingStatus

String

Clearing status

clearingDate

String

Clearing creation date

arn

String

Acquirer Reference Number

autoClear

Boolean

Is auto clear enabled. Enabled if true, is not enabled if false. There is 7 days for execute clearing process if autoClear = false

hiddenCardNumber

String

Hidden card number

provider

String

Card provider

bankName

String

Bank name - the value available when the name for a given bank is present on the list of BINs

amount

Number

The total transfer amount

currency

String

Currency for transaction. Example: USD

geographicScope

String

Type of transaction scope (DOMESTIC, CROSSBORDER, DOMESTIC_PL, INTRA_EU, INTER)

firstName

String

First name of cardholder

lastName

String

Last name of cardholder

email

String

Cardholder’s email

cavv

String

Cardholder Authentication Verification Value

mpiStatus

String

MPI status

clearingAmount

Number

The clearing amount. This field is returned if this transaction has been cleared

refunds[].date

String

Refund date

refunds[].amount

Number

Refund amount

refunds[].arn

String

Refund acquirer reference number

refunds[].rrn

String

Refund retrieval reference number

refunds[].responseCode

String

Refund iso response code

refunds[].status

String

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

Authorization method:
Basic Auth
POST https://paytool-api-dev.fenige.pl/external/clear

Clearing is the process where e-commerce and issuers exchange 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

Type

Validation

Description

transactionId

String

Must not be null

This is the id of the entire transaction process

merchantUuid

String

Must not be null

Merchant’s unique uuid in system

clearingAmount

Number

@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

transactionStatus

String

Clearing status

completion.estimate

String

Completion estimate for clearing

Refund

Authorization method:
Basic Auth
POST https://paytool-api-dev.fenige.pl/external/transaction/refund

This method can be used for refund amount of a previously performed transaction. Each transaction can be refunded at least once. 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

Type

Description

transactionId

String

This is the id of the entire transaction process

amountToRefund

Number

Amount to refund (in pennies)

Response body:
HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
{
    "transactionStatus": "SUCCESS"
}

Response fields

Name

Type

Description

transactionStatus

String

Refund status

Reverse

Authorization method:
Basic Auth
POST https://paytool-api-dev.fenige.pl/external/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

Type

Validation

Description

transactionId

String

@Must not be null

This is the id of the entire transaction process

merchantUuid

String

@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

Type

Description

transactionStatus

String

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 PaymentHub and your infrastructure.

Cryptography

Public Key

GEThttps://paytool-api-dev.fenige.pl/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.payhub.merchant;
import com.nimbusds.jose.*;
import com.nimbusds.jose.crypto.RSAEncrypter;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.SerializationUtils;

import java.security.KeyFactory;
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 encrypt

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

Type

Validation

Description

email

String

Not empty

Sender email

phone

String

Optional

Phone sender

firstName

String

Not empty. @Length(min = 2, max = 35), @Pattern(regexp = ^(?!\s)[^0-9!#|$^`\\~_%&\"'(){}*+,./:;<=>?@\t\n\]\[]*(?< !\s)$). Cannot contains tabulations and line breaks.

First name sender

lastName

String

Not empty. @Length(min = 2, max = 35), @Pattern(regexp = ^(?!\s)[^0-9!#|$^`\\~_%&\"'(){}*+,./:;<=>?@\t\n\]\[]*(?< !\s)$). Cannot contains tabulations and line breaks.

Last name sender

card.cvc2

String

Length must be 3 characters, Not null

Cardholder’s card cvc2

card.cardNumber

String

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

card.cardExpirationDate

String

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

Type

Validation

Description

email

String

Not empty. @Length(min = 1, max = 128) @Pattern(regexp = ^(?:[A-Za-z0-9]{1,}[\.!#$%&'*+/=?`{|}~^\-_]?){1,}[A-Za-z0-9_-]*@((?:[a-zA-Z0-9]+(?:-[a-zA-Z0-9]+)*\.){1,}[a-zA-Z]{2,})$)

Sender email

phone

String

Optional

Phone sender

firstName

String

Not empty

First name sender

lastName

String

Not empty

Last name sender

token

Object

Not null

Token obtained from Google

token.signature

String

Not null

Token signature

token.intermediateSigningKey

Object

Not null

Token intermediate signing key

token.intermediateSigningKey.signedKey

String

Not null

Signed key

token.intermediateSigningKey.signatures[]

Array

Not null

Token signatures

token.protocolVersion

String

Not null

Protocol version

token.signedMessage

String

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

Type

Description

value

String

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

Authorization method:
API-KEY
POSThttps://paytool-api-dev.fenige.pl/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,
  "transactionRef": "27F3250GU3",
  "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

Type

Validation

Description

currencyCode

String

Not empty

Transaction currency

amount

Number

Not null

Transaction amount (in pennies)

receiverAmount

Number

Optional

Information field only. Field determine receiving amount of cash transferred in one hundredth of the currency. [1PLN = 100]

transactionRef

String

Optional, @Length(min = 0, max = 20)

Merchant defined transaction reference identifier

description

String

Optional

Simple description of transaction

merchantUrl

String

Optional

URL address of merchant web system

orderNumber

String

@Length(min = 0, max = 255)

Declarative number of order that is just purchased by cardholder, set by merchant, should be unique

formLanguage

String

Optional

Language of transaction process in web browser, use only lowercase

redirectUrl.successUrl

String

Optional

URL of merchant web service to forward after successful payment flow

redirectUrl.failureUrl

String

Optional

URL of merchant web service to forward after failure payment flow

redirectUrl.cancelUrl

String

Optional

URL of merchant web service to forward after cancel payment flow

sender.firstName

String

Optional. @Length(min = 2, max = 35), @Pattern(regexp = ^(?!\s)[^0-9!#|$^`\\~_%&\"'(){}*+,./:;<=>?@\t\n\]\[]*(?< !\s)$). Cannot contains tabulations and line breaks.

Sender first name. First name sent in preInitialization will not be required in the payment form by the end user.

sender.lastName

String

Optional. @Length(min = 2, max = 35), @Pattern(regexp = ^(?!\s)[^0-9!#|$^`\\~_%&\"'(){}*+,./:;<=>?@\t\n\]\[]*(?< !\s)$). Cannot contains tabulations and line breaks.

Sender last name. Last name sent in preInitialization will not be required in the payment form by the end user.

sender.email

String

Must be a well-formed email address. @Length(min = 1, max = 128) @Pattern(regexp = ^(?:[A-Za-z0-9]{1,}[\.!#$%&'*+/=?`{|}~^\-_]?){1,}[A-Za-z0-9_-]*@((?:[a-zA-Z0-9]+(?:-[a-zA-Z0-9]+)*\.){1,}[a-zA-Z]{2,})$)

Sender email. Email sent in preInitialization will not be required in the payment form by the end user.

sender.address.countryCode

String

Optional

Two character ISO 3166-1 alpha-2 code of country

sender.address.city

String

Optional

Name of the city where cardholder lives

sender.address.postalCode

String

Optional

Postal code of this address

sender.address.street

String

Optional

Street name in the city

sender.address.houseNumber

String

Optional

House number with optional flat number

autoClear

Boolean

Optional

In configuration merchant is set true. When u set false in request u will have 7 days for execute clearing process

typeOfAuthorization

String

Optional

Type of Authorization. Possible values: PURCHASE, COF. Available for card flow, default PURCHASE

preInitData.countryOfResidence

String

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.

preInitData.allowedPaymentMethods

List<String>

Optional

Passing CARD here will directly display only the card form. If null is sent, the default payment configuration will be retrieved.

preInitData.additionalData.note

String

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

Type

Description

transactionId

String

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"
}'

3DS

Initialize
Authorization method:
API-KEY
POSThttps://paytool-api-dev.fenige.pl/external-api/transactions/3ds

3DS process initialization

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

Type

Validation

Description

merchantUuid

String

Not null

Uuid merchant in PaymentHub

transactionId

String

Not null

Unique transaction id

correlationId

String

Not null

Unique correlation id

senderDataEncrypted

String

Not null

Encrypted sender data for payment(Card and Token) -> Cryptography

browserData

Object

Not null

Data from user browser to show 3DS template

browserData.ipAddress

String

Optional

Client IP address. Example: "1.1.1.1".

browserData.javaEnabledVal

String

Optional

Java support status in the browser. Example: "ENABLED".

browserData.javaScriptEnabled

Boolean

Optional

Whether JavaScript is enabled

browserData.windowSize

String

Optional

Browser window size. Example: "S_250X400".

browserData.acceptHeader

String

Optional

HTTP Accept header sent by the browser. Example: "Accept: application/json".

browserData.language

String

Optional

Preferred browser language. Example: "PL".

browserData.screenHeight

Integer

Optional

Screen height in pixels. Integer (px). Example: 200.

browserData.screenWidth

Integer

Optional

Screen width in pixels. Integer (px). Example: 200.

browserData.timeZone

Integer

Optional

User time zone. Offset from UTC in minutes. Example: 60.

browserData.userAgent

String

Optional

User-Agent header. Example: "Mozilla/5.0".

browserData.screenColorDepth

Integer

Optional

Screen color depth. Bits per pixel. Example: 24.

typeOfTransaction

String

Not null

Type of transaction. Possible values: ONE_TIME_PAYMENT, GOOGLE_PAY, APPLE_PAY, BLIK

methodNotificationUrl

String

Must not be empty

This field specifies the URL to which the ACS will post threeDSMethodData when the hidden iframe post form from browse

notificationUrl

String

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

Type

Description

epochTimestamp

String

The timestamp (in milliseconds since the epoch) when the session was created.

expiresAt

String

The timestamp (in milliseconds since the epoch) when the session expires.

merchantSessionIdentifier

String

A unique identifier for the merchant session.

nonce

String

A unique, random string generated for this session.

merchantIdentifier

String

The identifier for the merchant.

domainName

String

The domain name of the website where Apple Pay is being used.

displayName

String

The display name of the merchant.

signature

String

A cryptographic signature of the session data.

operationalAnalyticsIdentifier

String

An identifier used for operational analytics.

retries

String

The number of retries that have been attempted for this session.

pspId

String

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
Authorization method:
API-KEY
POSThttps://paytool-api-dev.fenige.pl/external-api/transactions/3ds/continue

3DS process 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

Type

Type

Description

merchantUuid

String

Not null

Uuid merchant in PaymentHub

transactionId

String

Not null

Unique transaction id

correlationId

String

Not null

Unique correlation id

senderDataEncrypted

String

Not null

Encrypted sender data for payment(Card and Token) -> Cryptography

typeOfTransaction

String

Not null

Type of transaction. Possible values: ONE_TIME_PAYMENT, GOOGLE_PAY, APPLE_PAY, BLIK

notificationUrl

String

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

Type

Description

epochTimestamp

String

The timestamp (in milliseconds since the epoch) when the session was created.

expiresAt

String

The timestamp (in milliseconds since the epoch) when the session expires.

merchantSessionIdentifier

String

A unique identifier for the merchant session.

nonce

String

A unique, random string generated for this session.

merchantIdentifier

String

The identifier for the merchant.

domainName

String

The domain name of the website where Apple Pay is being used.

displayName

String

The display name of the merchant.

signature

String

A cryptographic signature of the session data.

operationalAnalyticsIdentifier

String

An identifier used for operational analytics.

retries

String

The number of retries that have been attempted for this session.

pspId

String

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
Authorization method:
API-KEY
POSThttps://paytool-api-dev.fenige.pl/external-api/transactions/3ds/finalize

3DS process finalization

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

Type

Type

Description

merchantUuid

String

Not null

Uuid merchant in PaymentHub

transactionId

String

Not null

Unique transaction id

correlationId

String

Not null

Unique correlation id

senderDataEncrypted

String

Not null

Encrypted sender data for payment(Card and Token) -> Cryptography

typeOfTransaction

String

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

Type

Description

transactionId

String

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
Authorization method:
API-KEY
POSThttps://paytool-api-dev.fenige.pl/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==",
    "intermediateSigningKey": {
      "signedKey": "{\"keyExpiration\":\"1542323393147\",\"keyValue\":\"MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE/1+3HBVSbdv+j7NaArdgMyoSAM43yRydzqdg1TxodSzA96Dj4Mc1EiKroxxunavVIvdxGnJeFViTzFvzFRxyCw==\"}",
      "signatures": [
        "MEYCIQCO2EIi48s8VTH+ilMEpoXLFfkxAwHjfPSCVED/QDSHmQIhALLJmrUlNAY8hDQRV/y1iKZGsWpeNmIP+z+tCQHQxP0v"
      ]
    },
    "signedMessage": "{\"tag\":\"jpGz1F1Bcoi/fCNxI9n7Qrsw7i7KHrGtTf3NrRclt+U=\",\"ephemeralPublicKey\":\"BJatyFvFPPD21l8/uLP46Ta1hsKHndf8Z+tAgk+DEPQgYTkhHy19cF3h/bXs0tWTmZtnNm+vlVrKbRU9K8+7cZs=\",\"encryptedMessage\":\"mKOoXwi8OavZ\"}"
  },
  "threeDsData": {
    "cavv": "jEu04WZns7pbARAApU4qgNdJTag=",
    "eci": "01",
    "authenticationStatus": "02",
    "transactionXId": "Y",
    "authenticationId": "d543820d-683e-4589-86d9-6c9e40db4b53"
  },
  "language": "PL"
}

Request fields

Name

Type

Type

Description

transactionId

String

Not empty

This is the id of the entire transaction processfalse

correlationId

String

Not empty

Unique correlation id

sender

Object

Not null

Sender details

sender.firstName

String

Optional. @Length(min = 2, max = 35), @Pattern(regexp = ^(?!\s)[^0-9!#|$^`\\~_%&\"'(){}*+,./:;<=>?@\t\n\]\[]*(?< !\s)$). Cannot contains tabulations and line breaks.

Sender first name

sender.lastName

String

Optional. @Length(min = 2, max = 35), @Pattern(regexp = ^(?!\s)[^0-9!#|$^`\\~_%&\"'(){}*+,./:;<=>?@\t\n\]\[]*(?< !\s)$). Cannot contains tabulations and line breaks.

Sender last name

sender.email

String

Optional. @Length(min = 1, max = 128) @Pattern(regexp = ^(?:[A-Za-z0-9]{1,}[\.!#$%&'*+/=?`{|}~^\-_]?){1,}[A-Za-z0-9_-]*@((?:[a-zA-Z0-9]+(?:-[a-zA-Z0-9]+)*\.){1,}[a-zA-Z]{2,})$)

Sender email

token.signature

String

Not null

Token signature

token.intermediateSigningKey

Object

Not null

Token intermediate signing key

token.intermediateSigningKey.signedKey

String

Not null

Signed key

token.intermediateSigningKey.signatures[]

Array

Not null

Token signatures

token.protocolVersion

String

Not null

Protocol version

token.signedMessage

String

Not null

Signed message

threeDsData.cavv

String

Optional

Cardholder Authentication Verification Value.

threeDsData.eci

String

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

threeDsData.authenticationStatus

String

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

threeDsData.transactionXId

String

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

threeDsData.authenticationId

String

Optional

Unique identifier for 3ds verification

language

String

Must not be null

Preferred browser language. Example: "PL".

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

Type

Description

transactionId

String

This is the id of the entire transaction process

transactionStatus

String

Transaction status

message

String

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
Authorization method:
API-KEY
POSThttps://paytool-api-dev.fenige.pl/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

Type

Validation

Description

validationUrl

String

Not null

Url to open session in apple.

transactionId

String

Not empty

Unique transaction 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

Type

Description

epochTimestamp

String

The timestamp (in milliseconds since the epoch) when the session was created.

expiresAt

String

The timestamp (in milliseconds since the epoch) when the session expires.

merchantSessionIdentifier

String

A unique identifier for the merchant session.

nonce

String

A unique, random string generated for this session.

merchantIdentifier

String

The identifier for the merchant.

domainName

String

The domain name of the website where Apple Pay is being used.

displayName

String

The display name of the merchant.

signature

String

A cryptographic signature of the session data.

operationalAnalyticsIdentifier

String

An identifier used for operational analytics.

retries

String

The number of retries that have been attempted for this session.

pspId

String

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
Authorization method:
API-KEY
POSThttps://paytool-api-dev.fenige.pl/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

Type

Type

Description

transactionId

String

Not null

Unique transaction id

correlationId

String

Unique correlation id

token.paymentData.version

String

Not null

The version of the Apple Pay data format being used.

token.paymentData.version

String

Not null

The version of the Apple Pay data format being used.

token.paymentData.data

String

Not null

An encrypted string containing the payment information.

token.paymentData.signature

String

Not null

A cryptographic signature used to verify the authenticity of the payment data.

token.paymentData.header.ephemeralPublicKey

String

Not empty

The public key used to encrypt the payment data. This key is specific to the current session and is ephemeral (temporary).

token.paymentData.header.publicKeyHash

String

Not empty

A hash of the public key used for encryption.

token.paymentData.header.transactionId

String

Not empty

A unique identifier for the payment transaction.

token.paymentMethod.displayName

String

Not empty

The name of the payment method as displayed to the user.

token.paymentMethod.network

String

Not empty

The payment network associated with the card used (e.g., "visa").

token.paymentMethod.type

String

Not empty

The type of payment card (e.g., "credit").

token.transactionIdentifier

String

Not empty

A unique identifier for the payment transaction.

sender.firstName

String

Optional. @Length(min = 2, max = 35), @Pattern(regexp = ^(?!\s)[^0-9!#|$^`\\~_%&\"'(){}*+,./:;<=>?@\t\n\]\[]*(?< !\s)$). Cannot contains tabulations and line breaks.

Sender first name

sender.lastName

String

Optional. @Length(min = 2, max = 35), @Pattern(regexp = ^(?!\s)[^0-9!#|$^`\\~_%&\"'(){}*+,./:;<=>?@\t\n\]\[]*(?< !\s)$). Cannot contains tabulations and line breaks.

Sender last name

sender.email

String

Not empty. @Length(min = 1, max = 128) @Pattern(regexp = ^(?:[A-Za-z0-9]{1,}[\.!#$%&'*+/=?`{|}~^\-_]?){1,}[A-Za-z0-9_-]*@((?:[a-zA-Z0-9]+(?:-[a-zA-Z0-9]+)*\.){1,}[a-zA-Z]{2,})$)

Sender email

language.language

String

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

Type

Description

transactionId

String

This is the id of the entire transaction process

transactionStatus

String

Transaction status

message

String

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
Authorization method:
API-KEY
The first stage is a one-time initial transaction, which is a simple e-commerce payment but contains the customer's consent to store card data for subsequent purchases. Card data is stored in a secure Fenige environment. After completing the initial merchant receives on webhook the unique cofInitialUuid identifier needed to perform subsequent CoF transactions without having to enter card data. All transaction types support CoF (excluding BLIK). To initial CoF transaction should set 'typeOfAuthorization' field to 'COF' in the: Pre Initialization
CoF Subsequent
Authorization method:
Basic Auth
POSThttps://paytool-api-dev.fenige.pl/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

Type

Type

Description

transactionId

String

Not empty

This is the id of the entire transaction process, set random uuid value

cofInitialUuid

String

Not empty

CoF initial transaction identifier uuid, available when the 'typeOfAuthorization' field is set to 'COF' in the 'Pre Initialization' method

currencyCode

String

Not empty

Transaction currency

amount

Number

Not null

Transaction amount (in pennies)

receiverAmount

Number

Optional

Information field only. Field determine receiving amount of cash transferred in one hundredth of the currency. [1PLN = 100]

language

String

Not null

Language of transaction process

autoClear

Boolean

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

Type

Description

transactionId

String

This is the id of the entire transaction process

transactionStatus

String

Transaction status

message

String

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 Customer Engagement 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.

Example of 'X-SECRET-CHECKSUM' building
import hashlib

            # secret token established by client with Fenige employee
            secret = 'mNaU9TaK4m9myYYFBJgKu8slNH2fCKutJyzXwI'
            # transactionId received from webhook's request
            transactionId = 'c168a885-acfa-4a91-a1ad-ed7a042b7238'

            # concatenate strings in correct order
            concatenated = secret + transactionId

            # 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 transactionId from received request body of callback event 2. Hash with SHA256 function result of above operation

Example Webhook from PaymentHub
{
    "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"
}

Info: If you do not receive a webhook with transaction details within 2 minutes, you should use the
Get transaction details method to obtain the final status (SUCCESS, FAILURE, REFUNDED, SUCCESS_WAITING_FOR_CLEARING, REVERSED).

webhook payhub.png

FAQ

Here you can find most frequency asked questions about Fenige API
Frequent asking questions.