PHPackages                             swedbank-spp/swedbank-payment-portal - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Payment Processing](/categories/payments)
4. /
5. swedbank-spp/swedbank-payment-portal

ActiveLibrary[Payment Processing](/categories/payments)

swedbank-spp/swedbank-payment-portal
====================================

The Swedbank Payment Portal API Library provides access to the online banking system through which e-commerce transactions can be initiated and fulfilled by facilitating the exchange of bank data.

v0.9.4.1(3y ago)36100.9k↓38.9%20[8 issues](https://github.com/Swedbank-SPP/swedbank-payment-portal/issues)[1 PRs](https://github.com/Swedbank-SPP/swedbank-payment-portal/pulls)MITPHPCI failing

Since Sep 8Pushed 3y ago8 watchersCompare

[ Source](https://github.com/Swedbank-SPP/swedbank-payment-portal)[ Packagist](https://packagist.org/packages/swedbank-spp/swedbank-payment-portal)[ RSS](/packages/swedbank-spp-swedbank-payment-portal/feed)WikiDiscussions master Synced 1mo ago

READMEChangelog (10)Dependencies (7)Versions (42)Used By (0)

Swedbank Payment Portal
=======================

[](#swedbank-payment-portal)

About
-----

[](#about)

Swedbank developed and maintaining API library to help and speed up merchant integrations in to e-shop.

Benefit to merchant
-------------------

[](#benefit-to-merchant)

Usually Swedbank Payment Portal integration is done using technical specification (API documentation). Developers need to analyse it, prepare specific software architecture, logic to send and receive payment request messages towards Swedbank Payment Portal. By having library developer can **save lot of development time** and just reuse code and logic already created by us. This greatly speed up integration process on Merchant side and of course **substantially saving the integration costs**.

This library supports Swedbank payment types:

- Cards integration type HPS;
- Banklinks;
- PayPal Express Checkout;

Requirements
------------

[](#requirements)

Minimum PHP version required 7.1 and above.

Installation Instruction
------------------------

[](#installation-instruction)

### Projects with composer installed

[](#projects-with-composer-installed)

This is recommended way of installation. Add dependency in your `composer.json`:

```
"require": {
    "swedbank-spp/swedbank-payment-portal": "^0.9"
}
```

and run "composer update" in command prompt or shell.

Alternative you can execute "composer require swedbank-spp/swedbank-payment-portal" from your command prompt or shell.

### Projects which doesn`t have composer installed

[](#projects-which-doesnt-have-composer-installed)

- First download composer to your project root folder (  )
- Run command: php composer.phar init
- Press Enter until command completes ("composer.json" file will be created)
- Open "composer.json" and replace "require": {} with:

```
"require": {
    "swedbank-spp/swedbank-payment-portal": "^0.9"
 }
```

- Run command: php composer.phar update (after success "vendor" folder will be created)
- In your project index.php please include php line require\_once(\_\_DIR\_\_.'/vendor/autoload.php'); that way you’ll register composer default autoloader to your project.
- Done. From now you can use Swedbank Payment Portal library.

Integration
-----------

[](#integration)

### Credentials

[](#credentials)

To be able to test Swedbank payment system you will need to get credentials for development and production environment. Only to test is enouth test credentials.

### Banklink integration

[](#banklink-integration)

Here is a sequence diagram which illustrates full banklink process. You can see that for Banklink integration you’ll need to call only three methods in a library “initPayment()”, “handlePendingTransaction()” and “checkPendingTransactions()”.

[![alt tag](https://github.com/Swedbank-SPP/swedbank-payment-portal/raw/master/ignore/diagram_4.png)](https://github.com/Swedbank-SPP/swedbank-payment-portal/raw/master/ignore/diagram_4.png)

#### Notification

[](#notification)

Notification is used by banks to inform merchants about transaction statuses. Event notifications are communicated via a POST to a pre-configured merchant event URL. This URL must be different from the success and failure URL’s specified in the purchase setup requests. Multiple event notification URL’s can be configured on your Payment Gateway account, should the merchant require these messages to be delivered to a number of locations. The format of these event notifications is XML. Upon successful delivery of an event notification to an event URL, the merchant application must acknowledge receipt of such notification with an OK post back response to the Payment Gateway. The event notification mechanism is utilised to notify merchants of payment event statuses throughout the lifecycle of a transaction. For Banklink purchase transactions, the following event notifications could be delivered: AUTHORISED, REQUIRES\_INVESTIGATION, CANCELLED. When a merchant receives the above event notifications, they are expected to respond with the following XML: OK In the event that the Payment Gateway does not receive a confirmation of receipt, the gateway will retry multiple times to send the notification. Using SPP library you need to call BankLinkService.handleNotification($xmlData) method to handle notification. “handleNotification” will parse XML and updates appropriate transaction status in the system. Also callback which was given in “initPayment” will be called if transaction resolves. Security note: Notification URL must be known and be accessible only from SPP server IP address. Configure your server to deny all other requests to that URL.

Usage example:

```
function someControllerAction() {  // this method must be called whenever Notification URL is accessed.
      $xml = file_get_contents("php://input"); // POST raw data
      try {
          $spp->getBankLinkGateway()->handleNotification($xm);
      } catch (\Exception $e) {
          // here log any exceptions if occurs, because if you will not respond
          // with “OK” SPP will repeatedly submit notifications.
      }
      echo "OK";
}
```

### Payment Card (HPS) integration

[](#payment-card-hps-integration)

Payment Card HPS integration is the same as Banklink.

[![alt tag](https://github.com/Swedbank-SPP/swedbank-payment-portal/raw/master/ignore/diagram_5.png)](https://github.com/Swedbank-SPP/swedbank-payment-portal/raw/master/ignore/diagram_5.png)

### PayPal integration (Express Checkout)

[](#paypal-integration-express-checkout)

PayPal integration is also the same as HPS and banklink.

[![alt tag](https://github.com/Swedbank-SPP/swedbank-payment-portal/raw/master/ignore/diagram_7.png)](https://github.com/Swedbank-SPP/swedbank-payment-portal/raw/master/ignore/diagram_7.png)

Cron job operations
-------------------

[](#cron-job-operations)

System should call “checkPendingTransactions” operation on each minute. This will trigger status checking of transactions which are in PENDING state. Status checking operation time for each transaction is not related to cron job calling interval. Each transaction is queried in 30 minutes intervals. These settings can be changed in a library. One exception is for Banklink payment of Nordea: The first status querying of Nordea transaction is done only after 1 minute when user hits success URL, and later querying (if needed) after 30 minutes. These pending transaction checking is done only for Banklink and Payment Card HPS pending transactions as these transactions in some circumstances cannot be directly resolved (e.g. user didn’t get redirected to success url due internet problems).

Testing
-------

[](#testing)

Test transactions can be performed by using the test data in this section to process test transactions. The response received from the Payment Gateway will depend on the card number used. The responses are simulated and are intended to allow testing of common scenarios when processing Credit and Debit cards.

It is recommended that the following scenarios are tested as a minimum:

- Successful Authorisation including 3-D Secure authentication with different amounts
- Unsuccessful Authorisation
- Failed 3-D Secure authentication

Each merchant must ensure the interaction between the Payment Gateway and their own e-commerce system is behaving as expected.

Below are card numbers that are behaving on a predefined way. They are an excellent help when integrating and in testing/debugging of various scenarios.

Please note – magic cards are provided for Accreditation only and NOT intended for use in the Production Environment.

### MasterCard Test Data

[](#mastercard-test-data)

Test Card NumberReturn CodeDescriptionSample Message55734700000000011Authorised with random auth codeAUTH CODE557347000000002714Test Server ResponsePayment Gateway Busy Please Retry5573470000000035440Test Server ResponsePayment Gateway Busy5573470000000050661Test Server ResponseUnknown Error5573470000000068653Test Server ResponseFailure at Bank### Maestro Test Data

[](#maestro-test-data)

Test Card NumberReturn CodeDescriptionSample Message50016301000112481Authorised with random auth codeAUTH CODE50016301000112557Test Server ResponseDECLINED50016301000112637Test Server ResponseDECLINED### Visa Test Data

[](#visa-test-data)

Test Card NumberReturn CodeDescriptionSample Message49294983114050011Authorised with random auth codeAUTH CODE49780561000000197Decline the transactionDECLINED### Test Data for 3-D Secure

[](#test-data-for-3-d-secure)

Any of the magic card numbers can be used while integrating 3-D Secure. The response will be determined first by the 3-D Secure configuration on your account, and then by the expiry month of the test card number.

In order to generate specific responses, please use the card expiry **month** shown below:

Test card expiry monthTest system response01Card is enrolled02Card is not enrolled03No result received from the directory server043DS Invalid VERes from DS - Failed to parse VERes053DS Invalid VERes from DS - invalid protocol value 'SET'063DS invalid VEReq07Unable to verify08Card is enrolledany other valueUnable to verifyAll library is under “SwedbankPaymentPortal” namespace. Main entry point for a library is “SwedbankPaymentPortal” class.

Here is a short example how to initialize a library:

```
use SwedbankPaymentPortal\Options\CommunicationOptions;
use SwedbankPaymentPortal\Options\ServiceOptions;
use SwedbankPaymentPortal\SharedEntity\Authentication;
use SwedbankPaymentPortal\SwedbankPaymentPortal;

$options = new ServiceOptions(
    new CommunicationOptions('https://accreditation.datacash.com/Transaction/acq_a'),
    new Authentication( 'login', 'password' )
);

$spp = new SwedbankPaymentPortal($options);
```

After that you can retrieve all payment services which are needed.

Next step is to retrieve your needed payment service by calling one of a methods of “SwedbankPaymentPortal” object.

Example:

```
$paypal   = $spp->getPayPalGateway();
$banklink = $spp->getBankLinkGateway();
$hps      = $spp->getPaymentCardHostedPagesGateway();
```

Whatever service you’ll retrieve all services contains a method “initPayment” which is a main payment initialization point.

**Update:**

To help other which projects do not have any dependency containers we’ve added couple static methods in a library which helps for global library initialization.

```
SwedbankPaymentPortal::init(ServiceOptions $options); // you must call this once to initialize library
$spp = SwedbankPaymentPortal::getInstance();  // method will return an object of SwedbankPaymentPortal.
```

Please use these methods if your system do not have any dependency container to simplify process.

Success / Failure URL Handling
==============================

[](#success--failure-url-handling)

Whatever payment method you’ll use there is a need to specify success/failure URL for each “initPayment” call.

Success or Failure URL should be your custom page with appropriate message to user. Swedbank Payment Portal will redirect a customer to that URL in case of success or failure of purchase operation. Swedbank Payment Portal library is using additional server to server verification of success or failure of operation so you must call one of methods which finalizes a payment inside a library:

```
$spp->getBankLinkGateway()->handlePendingTransaction($orderId);
 $spp->getPayPalGateway()->handlePendingTransaction($orderId);
 $spp->getPaymentCardHostedPagesGateway()->hpsQuery($orderId);
```

(please look at sequence diagrams above to see what library methods must be called on each step)

Finalization will trigger a callbacks which you’ve been given in “initPayment” method calls.

So, to fully complete a transaction you must know what payment method was used and what is an order ID of that payment and that information must be included in your success/failure URL. E.g: [http://yoururl.com/success.html?payment=banklink&amp;orderid={order\_id}](http://yoururl.com/success.html?payment=banklink&orderid=%7Border_id%7D)

> Warning: entering to success URL doesn’t mean that purchase was 100% completed. Never do any order completion logic inside success url action! That logic must go in Callbacks.

Callback setup
==============

[](#callback-setup)

The main idea is that purchase process is fully asynchronous and you’ll be notified some time in future by callback method which you’ve had given during payment initialization(“initPayment”). Here is a short description about what is a callback.

Callback is an object which has implemented CallbackInterface. CallbackInterface contains one method

```
public function handleFinishedTransaction(
   TransactionResult $transactionResult,
   TransactionFrame $transactionFrame,
   PaymentCardTransactionData $paymentCardTransactionData = null
);
```

and it will be called when transaction resolves (success or failure).

$transactionResult can be one of these values TransactionResult::success(), TransactionResult::failure(), TransactionResult::unfinished().

$transactionFrame - contains a request and a response of a last request which determined success/failure.

$paymentCardTransactionData - contains payment card information (expiry date, pan, authorization code). This parameter is optional and will be available only on HPS or HCC payment methods.

Because transactions is asynchronous that callback will be called some time in future on the different process so callback must be a PHP serializable object and must implement serialize() and unserialize() methods.

When a library calls a “handleFinishedTransaction” it will unserialize a callback to it’s previous state (time when had called “initPayment”).

If you need some additional information inside “handleFinishedTransaction” call the best way is to pass that information in callback constructor and implement serialize which persists that data.

For example it can be invoice id, order id, user id and other information which is required for your operations after transaction completion.

**Update:**

We have included default implementation of CallbackInterface called `**UrlCallback**` which now on you can use as Callback in “initPayment” (for all payment methods).

Example:

```
$spp->getBankLinkGateway()->initPayment(
    $purchaseRequest,
    UrlCallback::create(“http://yourdomain.com/some_secret_complete_handler?order_id={$orderId}”)
);
```

UrlCallback will call the given url using HTTP POST operation, with these POST fields: “status” one of these: SUCCESS or FAIL or UNFINISHED.

**Security note:**Thsi link should be secret and not accessable from outside. To improve security you need to add IP filtration for CalbackURL. The only IP allowed to call this URL should be 127.0.0.1

E-Receipt for Payment Card transactions
=======================================

[](#e-receipt-for-payment-card-transactions)

After payment card transaction completion the third argument of “handleFinishedTransaction” method will be set. Third argument will contain object of PaymentCardTransactionData.

“PaymentCardTransactionData” consists of:

- pan
- expiryDate
- authorzationCode
- merchantReference
- fulfillDate

This information must be included in e-receipt which must be generated after purchase using payment cards.

Banklink payments
=================

[](#banklink-payments)

Here is a table of available banks and what serviceType and paymentMethod you need to specify in purchase request:

**Bank****serviceType****paymentMethod**SWEDBANK AB (SWEDEN)ServiceType::swdBank()PaymentMethod::swedbank()NORDEA BANK AB (SWEDEN)ServiceType::nrdSwd()PaymentMethod::nordea()SVENSKA HANDELSBANKEN AB (SWEDEN)ServiceType::undefined()PaymentMethod::svenska()SKANDINAVISKA ENSKILDA BANKEN AB (SWEDEN)ServiceType::sebSwd()PaymentMethod::seb()SWEDBANK AS (ESTONIA)ServiceType::estBank()PaymentMethod::swedbank()SEB AS Pank (ESTONIA)ServiceType::sebEst()PaymentMethod::seb()Nordea Bank AB Estonia Branch (ESTONIA)ServiceType::nrdEst()PaymentMethod::nordea()SWEDBANK AS (LATVIA)ServiceType::ltvBank()PaymentMethod::swedbank()SEB AS banka (LATVIA)ServiceType::sebLtv()PaymentMethod::seb()AS CITADELE BANKA (LATVIA)ServiceType::undefined()PaymentMethod::citadele()SWEDBANK AB (LITHUANIA)ServiceType::litBank()PaymentMethod::swedbank()SEB AB bankas (LITHUANIA)ServiceType::sebLit()PaymentMethod::seb()AB DNB BANKAS (LITHUANIA)ServiceType::undefined()PaymentMethod::dnb()NORDEA BANK AB LITHUANIA BRANCH (LITHUANIA)ServiceType::nrdLit()PaymentMethod::nordea()DANSKE BANK AS LITHUANIA BRANCH (LITHUANIA)ServiceType::undefined()PaymentMethod::danske()Example how to initiate banklink payment:

```
$purchaseAmount = 1500; // 15 Eur 00 ct
$merchantReferenceId = "Invoice01234";

$purchaseRequest = (new PurchaseBuilder())
   ->setDescription("SPP demoshop Order $merchantReferenceId")
   ->setAmountValue($purchaseAmount)
   ->setAmountExponent(2)
   ->setAmountCurrencyCode(978)// for EUR
   ->setConsumerEmail("customer@email.com")
   ->setServiceType(ServiceType::swdBank())
   ->setPaymentMethod(PaymentMethod::swedbank())
   ->setSuccessUrl("SPP") // see chapter “Success / Failure URL Handling” for more info
   ->setFailureUrl("SPP")
   ->setMerchantReference($merchantReferenceId)
   ->setLanguage("lt")
   ->setPageSetId(1)
   ->getPurchaseRequest();

   $response = $spp->getBankLinkGateway()->initPayment(
       $purchaseRequest,
       new Swedbank_Ordering_Handler_PaymentCompletedCallback(
           $merchantReferenceId
       )
   );
```

HPS Example using calback
=========================

[](#hps-example-using-calback)

Replace sppdemoshop.eu to your shop address.

**callback.php**This is example of callback. Callback function need be available in setup call and final process.

```
use SwedbankPaymentPortal\BankLink\CommunicationEntity\HPSQueryResponse\HPSQueryResponse;
use SwedbankPaymentPortal\BankLink\CommunicationEntity\NotificationQuery\ServerNotification;
use SwedbankPaymentPortal\CallbackInterface;
use SwedbankPaymentPortal\CC\PaymentCardTransactionData;
use SwedbankPaymentPortal\SharedEntity\Type\TransactionResult;
use SwedbankPaymentPortal\Transaction\TransactionFrame;

class Swedbank_Ordering_Handler_PaymentCompletedCallback implements CallbackInterface
{

   private $merchantReferenceId;

   public function __construct($merchantReferenceId)
   {
       $this->merchantReferenceId = $merchantReferenceId;
   }

   /**
    * Method for handling finished transaction which ended because of the specified response status.
    *
    * @param TransactionResult         $status
    * @param TransactionFrame          $transactionFrame
    * @param PaymentCardTransactionData $creditCardTransactionData
    */
   public function handleFinishedTransaction(TransactionResult $status,
        TransactionFrame $transactionFrame,
        PaymentCardTransactionData $creditCardTransactionData = null)
   {
       if ($status == TransactionResult::success()) {
           // success no you can put flag payment done
       } else if ($status == TransactionResult::failure()) {
           // failure. Do some action here
       } else {
           // unfinished payment
       }
   // This is only for debug. You can log into file if needed.
       mail('YourEmail@domain.lt',
       'DONE', print_r($status, true).print_r($transactionFrame, true).print_r($creditCardTransactionData, true));

   }

   public function serialize()
   {
       return json_encode(
           [
               'merchantReferenceId' => $this->merchantReferenceId
           ]
       );
   }

   public function unserialize($serialized)
   {
       $data = json_decode($serialized);

       $this->merchantReferenceId = $data->merchantReferenceId;
   }
}
```

**hps.php**This is setup script

```
// in autoloader and library needed for HPS payment
include dirname(__FILE__) . '/../SwedbankPaymentPortal/vendor/autoload.php';

use SwedbankPaymentPortal\Options\CommunicationOptions;
use SwedbankPaymentPortal\Options\ServiceOptions;
use SwedbankPaymentPortal\SharedEntity\Authentication;
use SwedbankPaymentPortal\SwedbankPaymentPortal;
use SwedbankPaymentPortal\SharedEntity\Amount;
use SwedbankPaymentPortal\CC\HPSCommunicationEntity\SetupRequest\SetupRequest;
use SwedbankPaymentPortal\CC\HPSCommunicationEntity\SetupRequest\Transaction;
use SwedbankPaymentPortal\CC\Type\ScreeningAction;
use SwedbankPaymentPortal\CC\Type\TransactionChannel;
use SwedbankPaymentPortal\CC\HPSCommunicationEntity\SetupRequest\Transaction\TxnDetails;
use SwedbankPaymentPortal\CC\HPSCommunicationEntity\SetupRequest\Transaction\ThreeDSecure;
use SwedbankPaymentPortal\CC\HPSCommunicationEntity\SetupRequest\Transaction\CardTxn;

include dirname(__FILE__) . '/callback.php';

$auth = new Authentication('*********', '*********'); // VtID and password
// Generating unique merchant reference. To generate merchant reference
//please use your one logic. This is only example.
$merchantReferenceId = 'ID235r' . strtotime('now');
$purchaseAmount = '4.99'; // Euro and cents needs to be separated by dot.

$options = new ServiceOptions(
       new CommunicationOptions(
       'https://accreditation.datacash.com/Transaction/acq_a' //this is test environment
       // for production/live use this URL: https://mars.transaction.datacash.com/Transaction
       ), $auth
);

SwedbankPaymentPortal::init($options);  // getPaymentCardHostedPagesGateway()->initPayment(
       $setupRequest,
       new Swedbank_Ordering_Handler_PaymentCompletedCallback($merchantReferenceId)
);
$url = $response->getCustomerRedirectUrl(); // Getting redirect url
header('Location: ' . $url); // redirecting card holder to card input form.
```

**hps\_confirm.php**This is final payment process

```
namespace SwedbankPaymentPortal;

include dirname(__FILE__).'/../SwedbankPaymentPortal/vendor/autoload.php';

use SwedbankPaymentPortal\Options\CommunicationOptions;
use SwedbankPaymentPortal\Options\ServiceOptions;
use SwedbankPaymentPortal\SharedEntity\Authentication;
use SwedbankPaymentPortal\SwedbankPaymentPortal;

include dirname(__FILE__) . '/callback.php';

$orderId = $_GET['order_id'];
$way  = $_GET['way'];

if ($way == 'confirmed'){
  $auth = new Authentication('*********','***********');
  $options = new ServiceOptions(
      new CommunicationOptions(
        'https://accreditation.datacash.com/Transaction/acq_a' //this is test environment
		// for production/live use this URL: https://mars.transaction.datacash.com/Transaction
      ),
   $auth
  );
  SwedbankPaymentPortal::init($options);  // handlePendingTransaction($orderId);
  // now you can show user "thank you for your payment, but don't put flag
  //flag need to put inside callback

  echo 'Thank you';
} else if ($way == 'expiry'){
	echo 'Session expired';
	// do same logic if seesion expired
} else { // cancelled
	echo 'Payment cancelled';
	// do some action for cancel logic
}
```

HPS Example using UrlCalback
============================

[](#hps-example-using-urlcalback)

Replace sppdemoshop.eu to your shop address. Use this only if you can't use above example.

**hps\_url\_calback\_hps.php**

```
namespace SwedbankPaymentPortal;
// in autoloader and library needed for HPS payment
include dirname(__FILE__).'/SwedbankPaymentPortal/vendor/autoload.php';

use SwedbankPaymentPortal\Options\CommunicationOptions;
use SwedbankPaymentPortal\Options\ServiceOptions;
use SwedbankPaymentPortal\SharedEntity\Authentication;
use SwedbankPaymentPortal\SwedbankPaymentPortal;

use SwedbankPaymentPortal\SharedEntity\Amount;
use SwedbankPaymentPortal\CC\HPSCommunicationEntity\SetupRequest\SetupRequest;
use SwedbankPaymentPortal\CC\HPSCommunicationEntity\SetupRequest\Transaction;
use SwedbankPaymentPortal\CC\Type\ScreeningAction;
use SwedbankPaymentPortal\CC\Type\TransactionChannel;
use SwedbankPaymentPortal\CC\HPSCommunicationEntity\SetupRequest\Transaction\TxnDetails;
use SwedbankPaymentPortal\CC\HPSCommunicationEntity\SetupRequest\Transaction\ThreeDSecure;
use SwedbankPaymentPortal\CC\HPSCommunicationEntity\SetupRequest\Transaction\CardTxn;

$auth = new Authentication('8*****','********'); // VtID and password
// Generating unique merchant reference. To generate merchant reference
//please use your one logic. This is only example.
$merchantReferenceId = 'ID235r'.strtotime('now');
$purchaseAmount = '4.99'; // Euro and cents needs to be separated by dot.

$options = new ServiceOptions(
   new CommunicationOptions(
       'https://accreditation.datacash.com/Transaction/acq_a' //this is test environment
   	// for production/live use this URL: https://mars.transaction.datacash.com/Transaction
   ),
  $auth
);

SwedbankPaymentPortal::init($options);  // getPaymentCardHostedPagesGateway()->initPayment(
  $setupRequest,
  // This url card holder won't be redirected. This url will be called by cronjob to finalize transaction.
 UrlCallback::create("http://sppdemoshop.eu/secretprocesor.php?order_id={$merchantReferenceId}")
);
$url=$response->getCustomerRedirectUrl(); // Getting redirect url
header('Location: '.$url); // redirecting card holder to card input form.
die();
```

**confirm.php**

```
include dirname(__FILE__).'/SwedbankPaymentPortal/vendor/autoload.php';

use SwedbankPaymentPortal\Options\CommunicationOptions;
use SwedbankPaymentPortal\Options\ServiceOptions;
use SwedbankPaymentPortal\SharedEntity\Authentication;
use SwedbankPaymentPortal\SwedbankPaymentPortal;

$orderId = $_GET['order_id'];
$way  = $_GET['way'];

if ($way == 'confirmed'){
$auth = new Authentication('8******','******');
$options = new ServiceOptions(
    new CommunicationOptions(
      'https://accreditation.datacash.com/Transaction/acq_a' //this is test environment
  	// for production/live use this URL: https://mars.transaction.datacash.com/Transaction
    ),
 $auth
);
SwedbankPaymentPortal::init($options);  // handlePendingTransaction($orderId);
// now you can show user "thank you for your payment, but don't put flag
//what this payment is done. This is done in secretprocesor.php file

echo 'Thank you';
} else if ($way == 'expiry'){
  // do same logic if seesion expired
} else { // cancelled
  // do some action for cancel logic
}
```

**secretprocesor.php**This file newer will be loaded in browser. This will be called by cron job.

```
$orderId = $_GET['order_id'];

if($_POST['status'] === 'SUCCESS') {
  	//Do action for success. This is final confirmations of success
  	// now you can set flag what payment is success
  } else if($_POST['status'] === 'FAIL') {
  	// Do action if failed
  } else if($_POST['status'] === 'UNFINISHED'){
  	// Do action if unfinished
  } else {
      // log this attempt
  }

```

Bank link
=========

[](#bank-link)

Replace sppdemoshop.eu to your shop address.

**banklink\_setup.php**

```
// in autoloader and library needed for banklink payment
include dirname(__FILE__) . '/../SwedbankPaymentPortal/vendor/autoload.php';

use SwedbankPaymentPortal\Options\CommunicationOptions;
use SwedbankPaymentPortal\Options\ServiceOptions;
use SwedbankPaymentPortal\SharedEntity\Authentication;
use SwedbankPaymentPortal\SwedbankPaymentPortal;

use SwedbankPaymentPortal\BankLink\PurchaseBuilder;
use SwedbankPaymentPortal\BankLink\CommunicationEntity\Type\PaymentMethod;
use SwedbankPaymentPortal\BankLink\CommunicationEntity\Type\ServiceType;

include dirname(__FILE__) . '/callback.php';

$auth = new Authentication('*******', '********'); // VtID and password
// Generating unique merchant reference. To generate merchant reference
//please use your one logic. This is only example.
$merchantReferenceId = 'ID235r' . strtotime('now');

$options = new ServiceOptions(
        new CommunicationOptions(
        'https://accreditation.datacash.com/Transaction/acq_a' //this is test environment
        // for production/live use this URL: https://mars.transaction.datacash.com/Transaction
        ), $auth
);

SwedbankPaymentPortal::init($options);  // setAmountValue($purchaseAmount)
    ->setAmountExponent(2)
    ->setAmountCurrencyCode(978)// for EUR
    ->setConsumerEmail("customer@email.com")
    /*
ServiceType::swdBank() - SWEDBANK AB (SWEDEN)
ServiceType::nrdSwd() - NORDEA BANK AB (SWEDEN)
ServiceType::sebSwd() - SKANDINAVISKA ENSKILDA BANKEN AB (SWEDEN)
ServiceType::estBank() - SWEDBANK AS (ESTONIA)
ServiceType::sebEst() - SEB AS Pank (ESTONIA)
ServiceType::nrdEst() - Nordea Bank AB Estonia Branch (ESTONIA)
ServiceType::ltvBank() - SWEDBANK AS (LATVIA)
ServiceType::sebLtv() - SEB AS banka (LATVIA)
ServiceType::litBank() - SWEDBANK AB (LITHUANIA)
ServiceType::sebLit() - SEB AB bankas (LITHUANIA)
ServiceType::nrdLit() - NORDEA BANK AB LITHUANIA BRANCH (LITHUANIA)
*/
    ->setServiceType(ServiceType::litBank())
/*
PaymentMethod::swedbank() - SWEDBANK AB (SWEDEN)
PaymentMethod::nordea() - NORDEA BANK AB (SWEDEN)
PaymentMethod::svenska() - SVENSKA HANDELSBANKEN AB (SWEDEN)
PaymentMethod::seb() - SKANDINAVISKA ENSKILDA BANKEN AB (SWEDEN)
PaymentMethod::swedbank() - SWEDBANK AS (ESTONIA)
PaymentMethod::seb() - SEB AS Pank (ESTONIA)
PaymentMethod::nordea() - Nordea Bank AB Estonia Branch (ESTONIA)
PaymentMethod::swedbank() - SWEDBANK AS (LATVIA)
PaymentMethod::seb() - SEB AS banka (LATVIA)
PaymentMethod::citadele() - AS CITADELE BANKA (LATVIA)
PaymentMethod::swedbank() - SWEDBANK AB (LITHUANIA)
PaymentMethod::seb() - SEB AB bankas (LITHUANIA)
PaymentMethod::dnb() - AB DNB BANKAS (LITHUANIA)
PaymentMethod::nordea() - NORDEA BANK AB LITHUANIA BRANCH (LITHUANIA)
PaymentMethod::danske() - DANSKE BANK AS LITHUANIA BRANCH (LITHUANIA)
*/
    ->setPaymentMethod(PaymentMethod::swedbank())
    ->setSuccessUrl('http://sppdemoshop.eu/test/banklink_confirm.php?way=confirmed&order_id=' . $merchantReferenceId) // see chapter “Success / Failure URL Handling” for more info
    ->setFailureUrl('http://sppdemoshop.eu/test/banklink_confirm.php?way=cancelled&order_id=' . $merchantReferenceId)
    ->setMerchantReference($merchantReferenceId)
    ->setLanguage("lt")
    ->setPageSetId(1) // Always 1
    ->getPurchaseRequest();

    $response = $spp->getBankLinkGateway()->initPayment(
        $purchaseRequest,
        new Swedbank_Ordering_Handler_PaymentCompletedCallback(
            $merchantReferenceId
        )
    );

$url = $response->getCustomerRedirectUrl(); // Getting redirect url
header('Location: ' . $url); // redirecting card holder to card input form.
```

**callback.php**

```
use SwedbankPaymentPortal\BankLink\CommunicationEntity\HPSQueryResponse\HPSQueryResponse;
use SwedbankPaymentPortal\BankLink\CommunicationEntity\NotificationQuery\ServerNotification;
use SwedbankPaymentPortal\CallbackInterface;
use SwedbankPaymentPortal\CC\PaymentCardTransactionData;
use SwedbankPaymentPortal\SharedEntity\Type\TransactionResult;
use SwedbankPaymentPortal\Transaction\TransactionFrame;

class Swedbank_Ordering_Handler_PaymentCompletedCallback implements CallbackInterface
{

    private $merchantReferenceId;

    public function __construct($merchantReferenceId)
    {
        $this->merchantReferenceId = $merchantReferenceId;
    }

    /**
     * Method for handling finished transaction which ended because of the specified response status.
     *
     * @param TransactionResult         $status
     * @param TransactionFrame          $transactionFrame
     * @param PaymentCardTransactionData $creditCardTransactionData
     */
    public function handleFinishedTransaction(TransactionResult $status,
         TransactionFrame $transactionFrame,
         PaymentCardTransactionData $creditCardTransactionData = null)
    {
        if ($status == TransactionResult::success()) {
            // success no you can put flag payment done
        } else if ($status == TransactionResult::failure()) {
            // failure. Do some action here
        } else {
            // unfinished payment
        }
	// This is only for debug. You can log into file if needed.
        mail('YourEmail@domain.lt',
	    'DONE', print_r($status, true).print_r($transactionFrame, true).print_r($creditCardTransactionData, true));

    }

    public function serialize()
    {
        return json_encode(
            [
                'merchantReferenceId' => $this->merchantReferenceId
            ]
        );
    }

    public function unserialize($serialized)
    {
        $data = json_decode($serialized);

        $this->merchantReferenceId = $data->merchantReferenceId;
    }
}
```

**banklink\_confirm.php**

```
namespace SwedbankPaymentPortal;

include dirname(__FILE__).'/../SwedbankPaymentPortal/vendor/autoload.php';

use SwedbankPaymentPortal\Options\CommunicationOptions;
use SwedbankPaymentPortal\Options\ServiceOptions;
use SwedbankPaymentPortal\SharedEntity\Authentication;
use SwedbankPaymentPortal\SwedbankPaymentPortal;

include dirname(__FILE__) . '/callback.php';

$orderId = $_GET['order_id'];
$way  = $_GET['way'];

if ($way == 'confirmed'){
  $auth = new Authentication('******', '*****');
  $options = new ServiceOptions(
      new CommunicationOptions(
        'https://accreditation.datacash.com/Transaction/acq_a' //this is test environment
		// for production/live use this URL: https://mars.transaction.datacash.com/Transaction
      ),
   $auth
  );
  SwedbankPaymentPortal::init($options);  // handlePendingTransaction($orderId);
  // now you can show user "thank you for your payment, but don't put flag
  //flag need to put inside callback

  echo 'Thank you';
} else { // cancelled
	echo 'Payment cancelled';
	// do some action for cancel logic
}
```

Paypal example
==============

[](#paypal-example)

Replace sppdemoshop.eu to your shop address.

**paypal\_setup.php**

```
// include autoloader and library needed for paypal payment
include dirname(__FILE__) . '/../SwedbankPaymentPortal/vendor/autoload.php';

use SwedbankPaymentPortal\Options\CommunicationOptions;
use SwedbankPaymentPortal\Options\ServiceOptions;
use SwedbankPaymentPortal\SharedEntity\Authentication;
use SwedbankPaymentPortal\SwedbankPaymentPortal;
use SwedbankPaymentPortal\SharedEntity\Amount;

use SwedbankPaymentPortal\PayPal\CommunicationEntity\ShippingAddress;
use SwedbankPaymentPortal\PayPal\CommunicationEntity\SetExpressCheckoutRequest\Transaction;
use SwedbankPaymentPortal\PayPal\CommunicationEntity\SetExpressCheckoutRequest\Transaction\TxnDetails;
use SwedbankPaymentPortal\PayPal\CommunicationEntity\SetExpressCheckoutRequest\SetExpressCheckoutRequest;
use SwedbankPaymentPortal\PayPal\Type\PayPalBool;

include dirname(__FILE__) . '/callback.php';
include dirname(__FILE__) . '/logger.php';

$auth = new Authentication('*******', '*********'); // VtID and password
// Generating unique merchant reference. To generate merchant reference
//please use your one logic. This is only example.
$merchantReferenceId = 'ID235r' . strtotime('now');
$purchaseAmount = '4.99'; // Euro and cents needs to be separated by dot.

$options = new ServiceOptions(
        new CommunicationOptions(
        'https://accreditation.datacash.com/Transaction/acq_a' //this is test environment
        // for production/live use this URL: https://mars.transaction.datacash.com/Transaction
        ), $auth, new Swedbank_Client_Logger()
);

SwedbankPaymentPortal::init($options);  // getPayPalGateway()->initPayment(
    $request,
    new Swedbank_Ordering_Handler_PaymentCompletedCallback(
        $merchantReferenceId
    )
);

$url = $response->getCustomerRedirectUrl(false); // Getting redirect url. False - if test enviroment, true - if live enviroment

header('Location: ' . $url); // redirecting card holder to card input form.
```

**paypal\_confirm.php**

```
include dirname(__FILE__).'/../SwedbankPaymentPortal/vendor/autoload.php';

use SwedbankPaymentPortal\Options\CommunicationOptions;
use SwedbankPaymentPortal\Options\ServiceOptions;
use SwedbankPaymentPortal\SharedEntity\Authentication;
use SwedbankPaymentPortal\SwedbankPaymentPortal;
use SwedbankPaymentPortal\SharedEntity\Amount;
use SwedbankPaymentPortal\PayPal\CommunicationEntity\ShippingAddress;
use SwedbankPaymentPortal\PayPal\CommunicationEntity\SetExpressCheckoutRequest\Transaction;
use SwedbankPaymentPortal\PayPal\CommunicationEntity\SetExpressCheckoutRequest\Transaction\TxnDetails;
use SwedbankPaymentPortal\PayPal\CommunicationEntity\SetExpressCheckoutRequest\SetExpressCheckoutRequest;
use SwedbankPaymentPortal\PayPal\Type\PayPalBool;

include dirname(__FILE__) . '/callback.php';
include dirname(__FILE__) . '/logger.php';

$orderId = $_GET['order_id'];
$way  = $_GET['way'];

if ($way == 'confirmed'){
  $auth = new Authentication('*********', '*********');
  $options = new ServiceOptions(
      new CommunicationOptions(
        'https://accreditation.datacash.com/Transaction/acq_a' //this is test environment
		// for production/live use this URL: https://mars.transaction.datacash.com/Transaction
      ),
   $auth, new Swedbank_Client_Logger()
  );
  SwedbankPaymentPortal::init($options);  // handlePendingTransaction($orderId);
  // now you can show user "thank you for your payment, but don't put flag
  //flag need to put inside callback

  echo 'Thank you';
} else { // cancelled
	echo 'Payment cancelled';
	// do some action for cancel logic
}
```

Debugging / logging xml
=======================

[](#debugging--logging-xml)

To log xml needed to modify code.

```
include 'swedbank_logger.php';
```

Add logger object to ServiceOptions

```
$options = new ServiceOptions(
      new CommunicationOptions(
        'https://accreditation.datacash.com/Transaction/acq_a' //this is test environment
		// for production/live use this URL: https://mars.transaction.datacash.com/Transaction
      ),
   $auth, new Swedbank_Client_Logger()
  );
```

**swedbank\_logger.php**

```
use SwedbankPaymentPortal\Logger\LoggerInterface;

class Swedbank_Client_Logger implements LoggerInterface
{
    public function __construct()
    {
    }

    /**
     * @param string                                                                                                                                                                                                                                                                                                                                                 $requestXml
     * @param string                                                                                                                                                                                                                                                                                                                                                 $responseXml
     * @param object|\SwedbankPaymentPortal\BankLink\CommunicationEntity\HPSQueryRequest\HPSQueryRequest|\SwedbankPaymentPortal\BankLink\CommunicationEntity\PaymentAttemptRequest\PaymentAttemptRequest|\SwedbankPaymentPortal\BankLink\CommunicationEntity\PurchaseRequest\PurchaseRequest|\SwedbankPaymentPortal\BankLink\CommunicationEntity\TransactionQueryRequest\TransactionQueryRequest $requestObject
     * @param object|\SwedbankPaymentPortal\BankLink\CommunicationEntity\PaymentAttemptResponse\PaymentAttemptResponse|\SwedbankPaymentPortal\BankLink\CommunicationEntity\PurchaseResponse\PurchaseResponse|\SwedbankPaymentPortal\BankLink\CommunicationEntity\TransactionQueryResponse\TransactionQueryResponse|\SwedbankPaymentPortal\SharedEntity\HPSQueryResponse\HPSQueryResponse         $responseObject
     * @param \SwedbankPaymentPortal\SharedEntity\Type\TransportType                                                                                                                                                                                                                                                                                                        $type
     */
    public function logData(
        $requestXml,
        $responseXml,
        $requestObject,
        $responseObject,
        \SwedbankPaymentPortal\SharedEntity\Type\TransportType $type
    ) {

        $requestType = $type->id();
        $request = $this->prettyXml($requestXml);
        $response = $responseXml;

		file_put_contents(dirname(__FILE__) . '/../../../storage/logs/swedbank.log', "\n-----\n$requestType\n$request\n\n$response\n", FILE_APPEND | LOCK_EX);
    }

    /**
     * Method formats given XML into pretty readable format
     *
     * @param $xml
     *
     * @return string
     */
    private function prettyXml($xml)
    {
        $doc = new DomDocument('1.0');
        $doc->loadXML($xml);
        $doc->preserveWhiteSpace = false;
        $doc->formatOutput       = true;

        $prettyXml = $doc->saveXML();

        return $prettyXml;
    }
}
```

Query card payment
==================

[](#query-card-payment)

**query\_example.php**

```
namespace SwedbankPaymentPortal;
// in autoloader and library needed for HPS payment
include dirname(__FILE__).'/vendor/autoload.php';

use SwedbankPaymentPortal\Options\CommunicationOptions;
use SwedbankPaymentPortal\Options\ServiceOptions;
use SwedbankPaymentPortal\SharedEntity\Authentication;
use SwedbankPaymentPortal\SwedbankPaymentPortal;

$auth = new Authentication('xxxxxxxxxx','xxxxxxxxxx'); // VtID and password

//Merchant referance was used for payment
$merchantReferenceId = 'XXXXXXXXXXX';

$options = new ServiceOptions(
   new CommunicationOptions(
       'https://accreditation.datacash.com/Transaction/acq_a' //this is test environment
   	// for production/live use this URL: https://mars.transaction.datacash.com/Transaction
   ),
  $auth
);

SwedbankPaymentPortal::init($options);  // query($merchantReferenceId);

```

Cancel or Refund card payment
=============================

[](#cancel-or-refund-card-payment)

**cancel\_example.php**

```
namespace SwedbankPaymentPortal;
// in autoloader and library needed for HPS payment
include dirname(__FILE__).'/vendor/autoload.php';

use SwedbankPaymentPortal\Options\CommunicationOptions;
use SwedbankPaymentPortal\Options\ServiceOptions;
use SwedbankPaymentPortal\SharedEntity\Authentication;
use SwedbankPaymentPortal\SwedbankPaymentPortal;

$auth = new Authentication('xxxxxxxxxx','xxxxxxxxxx'); // VtID and password

//Merchant referance was used for payment
$merchantReferenceId = 'XXXXXXXXXXX';

$options = new ServiceOptions(
   new CommunicationOptions(
       'https://accreditation.datacash.com/Transaction/acq_a' //this is test environment
   	// for production/live use this URL: https://mars.transaction.datacash.com/Transaction
   ),
  $auth
);

SwedbankPaymentPortal::init($options);  // query($merchantReferenceId);

//var_dump($response);
$response = $spp->getPaymentCardHostedPagesGateway()->hpsCancel($response['QueryTxnResult']['datacash_reference']);
//check if cancell was successful if not do refund

//$response = $spp->getPaymentCardHostedPagesGateway()->hpsRefund($response['QueryTxnResult']['datacash_reference'], '3.23');
```

Refund card payment
===================

[](#refund-card-payment)

**refund.php**

```
// in autoloader and library needed for HPS payment
include dirname(__FILE__) . '/SwedbankPaymentPortal/vendor/autoload.php';

use SwedbankPaymentPortal\Options\CommunicationOptions;
use SwedbankPaymentPortal\Options\ServiceOptions;
use SwedbankPaymentPortal\SharedEntity\Authentication;
use SwedbankPaymentPortal\SwedbankPaymentPortal;

$auth = new Authentication('***********','***********'); // VtID and password

//Merchant referance was used for payment
$merchantReferenceId = 'XXXXXXXXXXXXXXX';

$options = new ServiceOptions(
    new CommunicationOptions(
        'https://accreditation.datacash.com/Transaction/acq_a' //this is test environment
    // for production/live use this URL: https://mars.transaction.datacash.com/Transaction
    ),
    $auth
);

SwedbankPaymentPortal::init($options);  // query($merchantReferenceId);

$ref = $response['QueryTxnResult']['datacash_reference'];
var_dump($ref); //string(16) "3400900025177762"

$amount = $response['QueryTxnResult']['amount'];
var_dump($amount); //string(5) "10.00"

//
$response = $spp->getPaymentCardHostedPagesGateway()->hpsRefund($ref, '0.50');
//Read parameter "status" if status == ACCEPTED then OK else failed
var_dump($response);
/*
 array(10) {
  ["@attributes"]=>
  array(1) {
    ["version"]=>
    string(1) "2"
  }
  ["MAC"]=>
  array(1) {
    ["outcome"]=>
    string(6) "ACCEPT"
  }
  ["acquirer"]=>
  string(22) "Swedbank Baltic Latvia"
  ["datacash_reference"]=>
  string(16) "3300900025177767"
  ["merchantreference"]=>
  string(16) "3400900025177762"
  ["mid"]=>
  string(10) "1000000000"
  ["mode"]=>
  string(4) "LIVE"
  ["reason"]=>
  string(8) "ACCEPTED"
  ["status"]=>
  string(1) "1"
  ["time"]=>
  string(10) "1549357106"
}
 */

$response = $spp->getPaymentCardHostedPagesGateway()->hpsRefund($ref, '15.00');

var_dump($response);
//Read parameter "status" if status == ACCEPTED then OK else failed
/*
 array(7) {
  ["@attributes"]=>
  array(1) {
    ["version"]=>
    string(1) "2"
  }
  ["datacash_reference"]=>
  string(16) "3900900025177769"
  ["merchantreference"]=>
  string(16) "3400900025177762"
  ["mode"]=>
  string(4) "LIVE"
  ["reason"]=>
  string(26) "Refund amount > orig 10.00"
  ["status"]=>
  string(2) "34"
  ["time"]=>
  string(10) "1549357108"
}
 */

$response = $spp->getPaymentCardHostedPagesGateway()->hpsRefund($ref, '2.00');
//Read parameter "status" if status == ACCEPTED then OK else failed
var_dump($response);
/*
 array(10) {
  ["@attributes"]=>
  array(1) {
    ["version"]=>
    string(1) "2"
  }
  ["MAC"]=>
  array(1) {
    ["outcome"]=>
    string(6) "ACCEPT"
  }
  ["acquirer"]=>
  string(22) "Swedbank Baltic Latvia"
  ["datacash_reference"]=>
  string(16) "3700900025177770"
  ["merchantreference"]=>
  string(16) "3400900025177762"
  ["mid"]=>
  string(10) "1000000000"
  ["mode"]=>
  string(4) "LIVE"
  ["reason"]=>
  string(8) "ACCEPTED"
  ["status"]=>
  string(1) "1"
  ["time"]=>
  string(10) "1549357108"
}
 */

```

###  Health Score

40

—

FairBetter than 88% of packages

Maintenance16

Infrequent updates — may be unmaintained

Popularity43

Moderate usage in the ecosystem

Community21

Small or concentrated contributor base

Maturity65

Established project with proven stability

 Bus Factor1

Top contributor holds 86% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~54 days

Recently: every ~310 days

Total

40

Last Release

1420d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/ae6fb9743d669bdd92c4216bdabf16ced85ef550b454ec6ceb4cc991c55b9aaf?d=identicon)[antanas\_a](/maintainers/antanas_a)

![](https://www.gravatar.com/avatar/de49d1ad3b08d5ea2414d5463bde80cb29aa6d3fd25e4bc4a79f53cfd48565da?d=identicon)[Raimonds\_K](/maintainers/Raimonds_K)

---

Top Contributors

[![Swedbank-SPP](https://avatars.githubusercontent.com/u/19687454?v=4)](https://github.com/Swedbank-SPP "Swedbank-SPP (43 commits)")[![edgarsn](https://avatars.githubusercontent.com/u/6625918?v=4)](https://github.com/edgarsn "edgarsn (3 commits)")[![maijs](https://avatars.githubusercontent.com/u/187887?v=4)](https://github.com/maijs "maijs (2 commits)")[![Arkiant](https://avatars.githubusercontent.com/u/1246874?v=4)](https://github.com/Arkiant "Arkiant (1 commits)")[![JanisE](https://avatars.githubusercontent.com/u/1469104?v=4)](https://github.com/JanisE "JanisE (1 commits)")

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/swedbank-spp-swedbank-payment-portal/health.svg)

```
[![Health](https://phpackages.com/badges/swedbank-spp-swedbank-payment-portal/health.svg)](https://phpackages.com/packages/swedbank-spp-swedbank-payment-portal)
```

###  Alternatives

[sylius/sylius

E-Commerce platform for PHP, based on Symfony framework.

8.4k5.6M651](/packages/sylius-sylius)[shopware/platform

The Shopware e-commerce core

3.3k1.5M3](/packages/shopware-platform)[sulu/sulu

Core framework that implements the functionality of the Sulu content management system

1.3k1.3M152](/packages/sulu-sulu)[prestashop/prestashop

PrestaShop is an Open Source e-commerce platform, committed to providing the best shopping cart experience for both merchants and customers.

9.0k15.4k](/packages/prestashop-prestashop)[ec-cube/ec-cube

EC-CUBE EC open platform.

78527.0k1](/packages/ec-cube-ec-cube)[horstoeko/zugferd

A library for creating and reading european electronic invoices

4174.3M18](/packages/horstoeko-zugferd)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
