Skip to main content

Manual Transfer Confirmation with GUI

Learn how to create transfers that require user confirmation through the Paysera web interface - perfect for user-initiated payments where verification is needed.

Overview

Manual confirmation creates transfers that User must approve through the Paysera web interface. This is ideal when:

  • User needs to verify payment details
  • Additional security verification required
  • Compliance requires user confirmation
  • Two-factor authentication needed
User-Friendly

Manual confirmation provides users with a familiar Paysera interface for reviewing and approving transactions.

Prerequisites

Before you begin:

  • ✅ Standard API credentials
  • ✅ Understanding of Transfer Statuses
  • ✅ Callback URL configured (recommended)

Workflow

1. Create Transfer

2. Redirect User to confirmation_url

3. User Reviews & Approves Transfer

4. User Redirected to redirect_url

5. Transfer Status: done

Step-by-Step Guide

Create a transfer without auto_confirm:

POST /transfer/rest/v1/transfers HTTP/1.1
Host: wallet.paysera.com
Content-Type: application/json
Authorization: MAC id="client_id", ts="...", nonce="...", mac="..."

{
"amount": {
"amount": "100.00",
"currency": "EUR"
},
"beneficiary": {
"type": "bank",
"name": "John Doe",
"bank_account": {
"iban": "LT123456789012345678"
}
},
"payer": {
"account_number": "EVP9876543210"
},
"purpose": {
"details": "Payment for invoice #12345"
},
"redirect_url": "https://your-site.com/payment/success"
}

Key Parameters:

  • redirect_url - Where to send user after confirmation (optional)
  • NO auto_confirm parameter (or set to false)

Complete Code Examples

<?php
use Paysera\Client\TransferClient;

// Initialize client
$client = TransferClient::create([
'auth' => [
'mac' => [
'mac_id' => getenv('PAYSERA_CLIENT_ID'),
'mac_secret' => getenv('PAYSERA_MAC_KEY'),
],
],
]);

try {
// Create transfer for manual confirmation
$transfer = $client->createTransfer([
'amount' => [
'amount' => '100.00',
'currency' => 'EUR',
],
'beneficiary' => [
'type' => 'bank',
'name' => 'John Doe',
'bank_account' => [
'iban' => 'LT123456789012345678',
],
],
'payer' => [
'account_number' => 'EVP9876543210',
],
'purpose' => [
'details' => 'Payment for invoice #12345',
],
'redirect_url' => 'https://your-site.com/payment/success',
]);

echo "Transfer created: " . $transfer->getId() . "\n";
echo "Status: " . $transfer->getStatus() . "\n";
echo "Confirmation URL: " . $transfer->getConfirmationUrl() . "\n";

// Redirect user to confirmation page
header("Location: " . $transfer->getConfirmationUrl());
exit;

} catch (Exception $e) {
echo "Error: " . $e->getMessage() . "\n";
// Show error to user
showErrorPage($e->getMessage());
}

Use Cases

User pays for order with manual confirmation:

function processCheckout($orderId, $userId) {
$order = getOrder($orderId);
$user = getUser($userId);

// Create transfer
$transfer = $client->createTransfer([
'amount' => [
'amount' => $order->total,
'currency' => $order->currency,
],
'beneficiary' => [
'type' => 'paysera',
'name' => 'Your Shop Name',
'paysera_account' => [
'account_number' => config('shop.account'),
],
],
'payer' => [
'account_number' => $user->paysera_account,
],
'purpose' => [
'details' => "Order #" . $orderId,
],
'redirect_url' => url("/orders/{$orderId}/success"),
]);

// Store transfer ID
$order->transfer_id = $transfer->getId();
$order->save();

// Redirect to confirmation
return redirect($transfer->getConfirmationUrl());
}

Handling Callbacks

Set up callback endpoint to receive status updates:

// callback.php
<?php

$transferId = $_POST['transfer_id'] ?? null;
$status = $_POST['status'] ?? null;
$date = $_POST['date'] ?? null;

if (!$transferId || !$status) {
http_response_code(400);
exit('Invalid callback data');
}

try {
// Get transfer from database
$order = Order::where('transfer_id', $transferId)->first();

if (!$order) {
logger()->warning("Callback for unknown transfer: {$transferId}");
http_response_code(200);
exit('OK');
}

// Update order based on status
switch ($status) {
case 'done':
$order->status = 'paid';
$order->paid_at = now();
sendOrderConfirmation($order);
break;

case 'rejected':
$order->status = 'payment_rejected';
sendPaymentRejectedEmail($order);
break;

case 'failed':
$order->status = 'payment_failed';
break;
}

$order->save();

// Return success
http_response_code(200);
echo 'OK';

} catch (Exception $e) {
logger()->error('Callback error', [
'transfer_id' => $transferId,
'error' => $e->getMessage(),
]);
http_response_code(500);
exit('Error');
}

Error Handling

Handle when user rejects payment:

// In your success/return handler
if ($transfer->getStatus() === 'rejected') {
// User cancelled payment
logger()->info("User cancelled transfer: {$transfer->getId()}");

// Show friendly message
return view('payment.cancelled', [
'message' => 'You cancelled the payment. You can try again anytime.',
'retry_url' => route('checkout'),
]);
}

Security Considerations

// Whitelist allowed redirect URLs
$allowedDomains = ['your-site.com', 'shop.your-site.com'];

$redirectUrl = $request->input('redirect_url');
$domain = parse_url($redirectUrl, PHP_URL_HOST);

if (!in_array($domain, $allowedDomains)) {
throw new SecurityException('Invalid redirect URL');
}

Comparison Table

FeatureManual ConfirmationAutomatic Confirmation
User InteractionRequiredNone
SecurityUser verifiesSystem controlled
SpeedUser dependentInstant
Use CaseUser paymentsBackground automation
PermissionsStandardSpecial permission
User ExperienceFamiliar Paysera UISeamless

Additional Resources

Support

Need help with complex integrations?

Contact: tech_support@paysera.com