Skip to main content

Distribute Payments

Make transactions with multiple payments to different beneficiaries in a single atomic operation. Perfect for marketplaces, commission-based platforms, and split payment scenarios.

Multi-Beneficiary Payments

All payments in a transaction succeed together or fail together - ensuring atomic operations.

Use Case: Marketplace Payment Split

Customer buys from multiple sellers in one checkout. Payment is automatically distributed to all sellers in a single transaction.

Example: Customer orders from 2 sellers:

  • €10 to Seller A (wallet 11111111)
  • €15 to Seller B (wallet 22222222)
  • Total: €25 from customer

Payment Flow


Benefits

  • Atomic Operations - Either all payments succeed or all fail
  • Single Confirmation - Customer confirms once for multiple beneficiaries
  • Automatic Distribution - Funds automatically distributed to all beneficiaries
  • Commission Support - Easy to add platform commission as separate payment

Key Concepts

Transaction: Groups multiple payments into one atomic operation

  • Single transaction_key for all payments
  • Single user confirmation
  • All-or-nothing execution

Payment: Individual payment to one beneficiary

  • Unique beneficiary (wallet_id)
  • Own amount and description
  • Part of parent transaction

Implementation Examples

<?php
require_once 'vendor/autoload.php';

use Paysera\WalletApi\ClientFactory;
use Paysera\WalletApi\Entity\Transaction;
use Paysera\WalletApi\Entity\Payment;
use Paysera\WalletApi\Entity\Item;
use Paysera\WalletApi\Entity\Money;
use Paysera\WalletApi\Entity\WalletIdentifier;

class MarketplacePayments
{
private $client;

public function __construct($clientId, $secret)
{
$factory = ClientFactory::create([
'auth' => [
'mac' => [
'mac_id' => $clientId,
'mac_secret' => $secret,
],
],
]);

$this->client = $factory->getWalletClient();
}

public function createMarketplacePayment($orderData)
{
$transaction = Transaction::create()
->setRedirectUri($orderData['redirect_uri']);

// Add payment for each seller
foreach ($orderData['sellers'] as $seller) {
$payment = $this->createSellerPayment($seller);
$transaction->addPayment($payment);
}

// Optional: Add platform commission
if (isset($orderData['commission'])) {
$commissionPayment = $this->createCommissionPayment(
$orderData['commission']
);
$transaction->addPayment($commissionPayment);
}

$created = $this->client->createTransaction($transaction);
return $created;
}

private function createSellerPayment($sellerData)
{
$beneficiary = WalletIdentifier::create()
->setId($sellerData['wallet_id']);

$payment = Payment::create()
->setDescription($sellerData['description'])
->setBeneficiary($beneficiary);

foreach ($sellerData['items'] as $itemData) {
$item = $this->createItem($itemData);
$payment->addItem($item);
}

return $payment;
}

private function createItem($itemData)
{
$price = Money::create()
->setAmountInCents($itemData['price'])
->setCurrency('EUR');

return Item::create()
->setTitle($itemData['title'])
->setDescription($itemData['description'])
->setPrice($price)
->setQuantity($itemData['quantity']);
}
}

// Usage
$marketplace = new MarketplacePayments('wkVd93h2uS', 'IrdTc8uQodU7PRpLzzLTW6wqZAO6tAMU');

$orderData = [
'redirect_uri' => 'https://yourmarketplace.com/payment-return',
'sellers' => [
[
'wallet_id' => 11111111,
'description' => 'Order from Seller A',
'items' => [
[
'title' => 'Product A1',
'description' => 'Description',
'price' => 1000,
'quantity' => 1,
],
],
],
[
'wallet_id' => 22222222,
'description' => 'Order from Seller B',
'items' => [
[
'title' => 'Product B1',
'description' => 'Description',
'price' => 1500,
'quantity' => 1,
],
],
],
],
'commission' => [
'wallet_id' => 33333333,
'amount' => 250,
],
];

$transaction = $marketplace->createMarketplacePayment($orderData);

Common Use Cases

1. Marketplace Platform

Scenario: Multi-vendor marketplace

Implementation: Payment per vendor + platform commission

$payments = [
['vendor_1',10],
['vendor_2',15],
['platform_fee',2.50],
];

2. Affiliate Commission Split

Scenario: Product sale with affiliate

Implementation: Payment to merchant (80%) + affiliate (20%)

3. Service Fee Collection

Scenario: Service booking with fee

Implementation: Service provider + platform fee + insurance (optional)


Advanced Topics

Best Practices

Do:

  • ✅ Validate wallet IDs before creating payments
  • ✅ Calculate commission server-side
  • ✅ Store transaction mapping in database
  • ✅ Handle all-or-nothing gracefully
  • ✅ Verify beneficiaries are active
  • ✅ Log all distributions

Don't:

  • ❌ Don't exceed limits on number of payments
  • ❌ Don't create duplicate payments to same beneficiary
  • ❌ Don't skip validation of amounts
  • ❌ Don't forget commission calculation
  • ❌ Don't ignore failed transactions
Database Schema
-- Marketplace orders
CREATE TABLE orders (
id INT PRIMARY KEY AUTO_INCREMENT,
customer_id INT NOT NULL,
total_amount INT NOT NULL,
commission_amount INT NOT NULL,
transaction_key VARCHAR(50),
status VARCHAR(20),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
INDEX idx_transaction (transaction_key)
);

-- Order items per seller
CREATE TABLE order_items (
id INT PRIMARY KEY AUTO_INCREMENT,
order_id INT NOT NULL,
seller_id INT NOT NULL,
seller_wallet_id INT NOT NULL,
product_name VARCHAR(255),
amount INT NOT NULL,
FOREIGN KEY (order_id) REFERENCES orders(id)
);
Commission Calculations

Percentage Commission:

function calculateCommission($orderTotal, $commissionRate = 0.10) {
return (int)($orderTotal * $commissionRate);
}

// Example: 10% of €25 = €2.50
$commission = calculateCommission(2500, 0.10); // 250 cents

Tiered Commission:

function getTieredCommission($amount) {
if ($amount < 5000) return $amount * 0.15; // 15%
elseif ($amount < 10000) return $amount * 0.10; // 10%
else return $amount * 0.05; // 5%
}
Error Handling

Insufficient funds:

try {
$transaction = $client->createTransaction($data);
} catch (ApiException $e) {
if ($e->getErrorCode() === 'insufficient_funds') {
return 'Insufficient balance for all payments';
}
}

Invalid beneficiary:

foreach ($sellers as $seller) {
if (!$this->isValidWallet($seller['wallet_id'])) {
throw new Exception("Invalid seller wallet: {$seller['wallet_id']}");
}
}
Testing
Production Testing

Wallet API does not have a sandbox environment. All testing must be done in production with real transactions.

Test Scenarios:

  1. Single payment - Verify basic flow
  2. Multiple payments - 2-3 beneficiaries
  3. With commission - Include platform fee
  4. Insufficient funds - Customer can't pay all
  5. Partial confirmation - Transaction behavior

Testing Strategy:

  • Use small test amounts (1-5 EUR)
  • Test with real wallet accounts
  • Monitor all transactions carefully
  • Verify distribution to all beneficiaries

Resources


Next Steps

  • Set up seller wallet validation
  • Implement commission calculation
  • Create distribution reports
  • Add payout scheduling
  • Monitor transaction success rates
Production Ready

Always validate beneficiary wallet IDs and calculate commissions server-side to prevent manipulation.