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:

Paytool_chosen_payment.png

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:

Paytool_payment_method.png

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:

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 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:

Google_pay.png

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:

Google_pay_payment.png

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:

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 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:

Blik_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
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
Visa mock full card range
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:

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

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

openInNewTab

String

Optional

Value on true will be open payment page in new tab

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

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

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

sender.email

String

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

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 Payment Hub 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.

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.

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/${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

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 retrival 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

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

requestUuid

String

This is the id of the entire transaction process

merchantUuid

String

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

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

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

Name

Description

transactionStatus

String

Refund status

Reverse

Authorization method
Basic Auth

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

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

Name

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

email

String

Not empty

Sender email

phone

String

Optional

Phone sender

firstName

String

Not empty

First name sender

lastName

String

Not empty

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

Name

Type

Description

email

String

Not empty

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

Name

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

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]

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

Not empty

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

sender.lastName

String

Not empty

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

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>

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

Name

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"
}'
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
Authorization method
API-KEY
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

merchantUuid

String

Not null

Uuid merchant in paymenthub

transacionId

String

Not null

Unique transacion id

senderDataEncrypted

String

Not null

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

browserData

String

Not null

Data from user browser to show 3DS template

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

Name

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

merchantUuid

String

Not null

Uuid merchant in paymenthub

transacionId

String

Not null

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

Name

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

merchantUuid

String

Not null

Uuid merchant in paymenthub

transacionId

String

Not null

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

Name

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

transactionId

String

Not empty

This is the id of the entire transaction processfalse

correlationId

String

Not empty

Unique correlation idfalse

sender

Object

Not null

Sender details

sender.firstName

String

Not empty

Sender first name

sender.lastName

String

Not empty

Sender last name

sender.email

String

Optional

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

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

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

validationUrl

String

Not null

Url to open session in apple.

transacionId

String

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

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

transacionId

String

Not null

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

Not empty

Sender first name

sender.lastName

String

Not empty

Sender last name

sender.email

String

Not empty

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

Name

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. To initial CoF transaction should set 'typeOfAuthorization' field to 'COF' in the: Pre Initialization
CoF Subsequent
Authorization method
API-KEY
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

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

Name

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

Example of 'X-SECRET-CHECKSUM' building
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

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