Overview
Card payments are one of the most common payment methods. Mangopay provides multiple approaches to process card payments:- Card Registration: Securely tokenize cards for future use
- Direct Pay-in: Process payments directly with tokenized cards
- Web Pay-in: Redirect users to a secure payment page
- 3D Secure: Handle strong customer authentication
Card Registration Flow
Card registration allows you to securely collect and tokenize card details:Create Card Registration
Initialize a card registration object:
$cardRegistration = new MangoPay\CardRegistration();
$cardRegistration->UserId = $userId;
$cardRegistration->Currency = 'EUR';
$cardRegistration->CardType = 'CB_VISA_MASTERCARD';
try {
$createdCardReg = $api->CardRegistrations->Create($cardRegistration);
// Send these to your frontend
$cardRegistrationData = [
'id' => $createdCardReg->Id,
'accessKey' => $createdCardReg->AccessKey,
'preregistrationData' => $createdCardReg->PreregistrationData,
'cardRegistrationURL' => $createdCardReg->CardRegistrationURL
];
} catch (MangoPay\Libraries\ResponseException $e) {
echo "Error: " . $e->GetMessage();
}
Collect Card Data (Frontend)
On your frontend, collect card details and post to the card registration URL:
// Example frontend code (JavaScript)
const formData = new FormData();
formData.append('accessKeyRef', cardRegistrationData.accessKey);
formData.append('data', cardRegistrationData.preregistrationData);
formData.append('cardNumber', '4970100000000154');
formData.append('cardExpirationDate', '1230');
formData.append('cardCvx', '123');
fetch(cardRegistrationData.cardRegistrationURL, {
method: 'POST',
body: formData
})
.then(response => response.text())
.then(registrationData => {
// Send registrationData back to your server
});
Complete Registration (Backend)
Update the card registration with the returned data:
$cardRegistration = $api->CardRegistrations->Get($cardRegistrationId);
$cardRegistration->RegistrationData = $registrationData; // From frontend
try {
$updatedCardReg = $api->CardRegistrations->Update($cardRegistration);
if ($updatedCardReg->Status === 'VALIDATED') {
$cardId = $updatedCardReg->CardId;
echo "Card successfully registered: " . $cardId;
} else {
echo "Card registration failed: " . $updatedCardReg->ResultMessage;
}
} catch (MangoPay\Libraries\ResponseException $e) {
echo "Error: " . $e->GetMessage();
}
Processing Direct Card Payments
Once you have a registered card, you can process direct payments:$payIn = new MangoPay\PayIn();
$payIn->AuthorId = $userId;
$payIn->CreditedUserId = $userId;
$payIn->CreditedWalletId = $walletId;
// Debited funds
$payIn->DebitedFunds = new MangoPay\Money();
$payIn->DebitedFunds->Currency = 'EUR';
$payIn->DebitedFunds->Amount = 10000; // 100.00 EUR
// Fees
$payIn->Fees = new MangoPay\Money();
$payIn->Fees->Currency = 'EUR';
$payIn->Fees->Amount = 100; // 1.00 EUR
// Payment details
$payIn->PaymentType = 'CARD';
$payIn->PaymentDetails = new MangoPay\PayInPaymentDetailsCard();
$payIn->PaymentDetails->CardType = 'CB_VISA_MASTERCARD';
// Execution details
$payIn->ExecutionType = 'DIRECT';
$payIn->ExecutionDetails = new MangoPay\PayInExecutionDetailsDirect();
$payIn->ExecutionDetails->CardId = $cardId;
$payIn->ExecutionDetails->SecureModeReturnURL = 'https://your-site.com/payment-return';
try {
$createdPayIn = $api->PayIns->Create($payIn);
// Check if 3DS is required
if ($createdPayIn->SecureModeNeeded && $createdPayIn->SecureModeRedirectURL) {
// Redirect user to 3DS page
header('Location: ' . $createdPayIn->SecureModeRedirectURL);
exit;
}
// Check payment status
if ($createdPayIn->Status === 'SUCCEEDED') {
echo "Payment successful!";
} elseif ($createdPayIn->Status === 'FAILED') {
echo "Payment failed: " . $createdPayIn->ResultMessage;
}
} catch (MangoPay\Libraries\ResponseException $e) {
echo "Error: " . $e->GetMessage();
}
Web Card Pay-in
Redirect users to a Mangopay-hosted payment page:$payIn = new MangoPay\PayIn();
$payIn->AuthorId = $userId;
$payIn->CreditedUserId = $userId;
$payIn->CreditedWalletId = $walletId;
$payIn->DebitedFunds = new MangoPay\Money();
$payIn->DebitedFunds->Currency = 'EUR';
$payIn->DebitedFunds->Amount = 10000;
$payIn->Fees = new MangoPay\Money();
$payIn->Fees->Currency = 'EUR';
$payIn->Fees->Amount = 100;
// Payment details
$payIn->PaymentType = 'CARD';
$payIn->PaymentDetails = new MangoPay\PayInPaymentDetailsCard();
$payIn->PaymentDetails->CardType = 'CB_VISA_MASTERCARD';
// Execution details
$payIn->ExecutionType = 'WEB';
$payIn->ExecutionDetails = new MangoPay\PayInExecutionDetailsWeb();
$payIn->ExecutionDetails->ReturnURL = 'https://your-site.com/payment-return';
$payIn->ExecutionDetails->Culture = 'EN'; // Payment page language
$payIn->ExecutionDetails->TemplateURLOptions = new MangoPay\PayInCardTemplateURLOptions();
$payIn->ExecutionDetails->TemplateURLOptions->PAYLINE = 'https://your-site.com/custom-template';
try {
$createdPayIn = $api->PayIns->Create($payIn);
// Redirect user to payment page
header('Location: ' . $createdPayIn->ExecutionDetails->RedirectURL);
exit;
} catch (MangoPay\Libraries\ResponseException $e) {
echo "Error: " . $e->GetMessage();
}
Handling 3D Secure
3D Secure (3DS) provides additional security for card payments:function processCardPayment($api, $userId, $walletId, $cardId, $amount) {
$payIn = new MangoPay\PayIn();
$payIn->AuthorId = $userId;
$payIn->CreditedUserId = $userId;
$payIn->CreditedWalletId = $walletId;
$payIn->DebitedFunds = new MangoPay\Money();
$payIn->DebitedFunds->Currency = 'EUR';
$payIn->DebitedFunds->Amount = $amount;
$payIn->Fees = new MangoPay\Money();
$payIn->Fees->Currency = 'EUR';
$payIn->Fees->Amount = 0;
$payIn->PaymentType = 'CARD';
$payIn->PaymentDetails = new MangoPay\PayInPaymentDetailsCard();
$payIn->PaymentDetails->CardType = 'CB_VISA_MASTERCARD';
$payIn->ExecutionType = 'DIRECT';
$payIn->ExecutionDetails = new MangoPay\PayInExecutionDetailsDirect();
$payIn->ExecutionDetails->CardId = $cardId;
$payIn->ExecutionDetails->SecureModeReturnURL = 'https://your-site.com/3ds-return';
try {
$createdPayIn = $api->PayIns->Create($payIn);
// Check if 3DS authentication is needed
if ($createdPayIn->SecureModeNeeded) {
return [
'status' => '3DS_REQUIRED',
'redirectUrl' => $createdPayIn->SecureModeRedirectURL,
'payInId' => $createdPayIn->Id
];
}
// Payment completed without 3DS
return [
'status' => $createdPayIn->Status,
'payInId' => $createdPayIn->Id
];
} catch (MangoPay\Libraries\ResponseException $e) {
return [
'status' => 'ERROR',
'message' => $e->GetMessage()
];
}
}
// Usage
$result = processCardPayment($api, $userId, $walletId, $cardId, 10000);
if ($result['status'] === '3DS_REQUIRED') {
// Redirect user to 3DS page
header('Location: ' . $result['redirectUrl']);
exit;
} elseif ($result['status'] === 'SUCCEEDED') {
echo "Payment successful!";
} else {
echo "Payment failed";
}
Managing Cards
Get Card Details
try {
$card = $api->Cards->Get($cardId);
echo "Card alias: " . $card->Alias . "\n";
echo "Card type: " . $card->CardType . "\n";
echo "Expiration: " . $card->ExpirationDate . "\n";
echo "Active: " . ($card->Active ? 'Yes' : 'No') . "\n";
echo "Validity: " . $card->Validity;
} catch (MangoPay\Libraries\ResponseException $e) {
echo "Error: " . $e->GetMessage();
}
Deactivate a Card
$card = $api->Cards->Get($cardId);
$card->Active = false;
try {
$updatedCard = $api->Cards->Update($card);
echo "Card deactivated";
} catch (MangoPay\Libraries\ResponseException $e) {
echo "Error: " . $e->GetMessage();
}
Get User’s Cards
$pagination = new MangoPay\Pagination(1, 20);
try {
$cards = $api->Users->GetCards($userId, $pagination);
foreach ($cards as $card) {
echo "Card: " . $card->Alias . "\n";
echo "Type: " . $card->CardType . "\n";
echo "Active: " . ($card->Active ? 'Yes' : 'No') . "\n\n";
}
} catch (MangoPay\Libraries\ResponseException $e) {
echo "Error: " . $e->GetMessage();
}
Filter Active Cards
$pagination = new MangoPay\Pagination(1, 20);
$filter = new MangoPay\FilterCards();
$filter->Active = true;
$activeCards = $api->Users->GetCards($userId, $pagination, $filter);
Card Validation
Validate a card without processing a payment:$cardValidation = new MangoPay\CardValidation();
$cardValidation->AuthorId = $userId;
$cardValidation->SecureModeReturnURL = 'https://your-site.com/validation-return';
$cardValidation->IpAddress = $_SERVER['REMOTE_ADDR'];
$cardValidation->BrowserInfo = new MangoPay\BrowserInfo();
$cardValidation->BrowserInfo->AcceptHeader = $_SERVER['HTTP_ACCEPT'];
$cardValidation->BrowserInfo->JavaEnabled = false;
$cardValidation->BrowserInfo->Language = 'en-US';
$cardValidation->BrowserInfo->ColorDepth = 24;
$cardValidation->BrowserInfo->ScreenHeight = 1080;
$cardValidation->BrowserInfo->ScreenWidth = 1920;
$cardValidation->BrowserInfo->TimeZoneOffset = 0;
$cardValidation->BrowserInfo->UserAgent = $_SERVER['HTTP_USER_AGENT'];
try {
$validation = $api->Cards->ValidateCard($cardId, $cardValidation);
if ($validation->Status === 'SUCCEEDED') {
echo "Card is valid";
} elseif ($validation->SecureModeNeeded) {
header('Location: ' . $validation->SecureModeRedirectURL);
}
} catch (MangoPay\Libraries\ResponseException $e) {
echo "Error: " . $e->GetMessage();
}
Card Pre-authorizations
Hold funds on a card without capturing them immediately:$preAuth = new MangoPay\CardPreAuthorization();
$preAuth->AuthorId = $userId;
$preAuth->DebitedFunds = new MangoPay\Money();
$preAuth->DebitedFunds->Currency = 'EUR';
$preAuth->DebitedFunds->Amount = 10000; // Hold 100.00 EUR
$preAuth->CardId = $cardId;
$preAuth->SecureModeReturnURL = 'https://your-site.com/return';
try {
$createdPreAuth = $api->CardPreAuthorizations->Create($preAuth);
if ($createdPreAuth->Status === 'SUCCEEDED') {
echo "Pre-authorization successful: " . $createdPreAuth->Id;
// Later, capture the funds
// or cancel the pre-authorization
}
} catch (MangoPay\Libraries\ResponseException $e) {
echo "Error: " . $e->GetMessage();
}
Recurring Card Payments
Set up recurring payments:// Step 1: Create recurring registration
$registration = new MangoPay\PayInRecurringRegistration();
$registration->AuthorId = $userId;
$registration->CardId = $cardId;
$registration->CreditedUserId = $userId;
$registration->CreditedWalletId = $walletId;
$registration->FirstTransactionDebitedFunds = new MangoPay\Money();
$registration->FirstTransactionDebitedFunds->Currency = 'EUR';
$registration->FirstTransactionDebitedFunds->Amount = 10000;
$registration->FirstTransactionFees = new MangoPay\Money();
$registration->FirstTransactionFees->Currency = 'EUR';
$registration->FirstTransactionFees->Amount = 0;
$created = $api->PayIns->CreateRecurringRegistration($registration);
// Step 2: Create first payment (CIT - Customer Initiated Transaction)
$cit = new MangoPay\RecurringPayInCIT();
$cit->RecurringPayinRegistrationId = $created->Id;
$cit->DebitedFunds = new MangoPay\Money();
$cit->DebitedFunds->Currency = 'EUR';
$cit->DebitedFunds->Amount = 10000;
$cit->Fees = new MangoPay\Money();
$cit->Fees->Currency = 'EUR';
$cit->Fees->Amount = 0;
$firstPayment = $api->PayIns->CreateRecurringPayInRegistrationCIT($cit);
// Step 3: Create subsequent payments (MIT - Merchant Initiated Transaction)
$mit = new MangoPay\RecurringPayInMIT();
$mit->RecurringPayinRegistrationId = $created->Id;
$mit->DebitedFunds = new MangoPay\Money();
$mit->DebitedFunds->Currency = 'EUR';
$mit->DebitedFunds->Amount = 10000;
$mit->Fees = new MangoPay\Money();
$mit->Fees->Currency = 'EUR';
$mit->Fees->Amount = 0;
$recurringPayment = $api->PayIns->CreateRecurringPayInRegistrationMIT($mit);
Card Fingerprinting
Get cards with the same fingerprint:$card = $api->Cards->Get($cardId);
$fingerprint = $card->Fingerprint;
// Get all cards with same fingerprint
$pagination = new MangoPay\Pagination(1, 20);
$cardsWithSameFingerprint = $api->Cards->GetByFingerprint($fingerprint, $pagination);
foreach ($cardsWithSameFingerprint as $card) {
echo "Card: " . $card->Alias . " (User: " . $card->UserId . ")\n";
}
Best Practices
Never Store Card Data
Always use card registration to tokenize cards. Never store raw card details.
Implement 3DS
Always support 3D Secure for enhanced security and lower fraud rates.
Use Idempotency Keys
Prevent duplicate charges by using idempotency keys.
Handle All Statuses
Properly handle all payment statuses including pending, succeeded, and failed.
Error Handling
try {
$payIn = $api->PayIns->Create($cardPayIn, $idempotencyKey);
} catch (MangoPay\Libraries\ResponseException $e) {
$errorDetails = $e->GetErrorDetails();
foreach ($errorDetails as $error) {
switch ($error->Message) {
case 'Secure mode: 3DSecure authentication is not available':
echo "3DS authentication failed";
break;
case 'Card is inactive':
echo "This card cannot be used";
break;
case 'Transaction refused':
echo "Payment was declined by the bank";
break;
default:
echo "Error: " . $error->Message;
}
}
}
Testing Cards
Mangopay provides test card numbers for sandbox:Test Card Numbers:
- Success: 4970100000000154
- 3DS Required: 4970101122334422
- Insufficient funds: 4970100000000101
- Declined: 4970100000000119
// Example test payment
$testPayIn = new MangoPay\PayIn();
// ... configure payment ...
$testPayIn->ExecutionDetails->CardId = $testCardId; // Use test card
$result = $api->PayIns->Create($testPayIn);
Next Steps
Processing Pay-ins
Learn more about payment processing
Webhooks
Get real-time notifications for card payments