Skip to main content

MB WAY (Portugal)

tip

Accepting this payment channel requires an additional agreement with the acquiring agent designated by dpay.pl.

MB WAY is a popular mobile payment method in Portugal. The customer authorizes the payment directly in the MB WAY app on their phone by providing only their phone number.

How it works​

POST/api/v1_0/payments/registerComplete payment registration contract: parameters, checksum, and error codes.Full contract in the API Reference

Endpoint​

POST https://api-payments.dpay.pl/api/v1_0/payments/register
Content-Type: application/json
Rate limits

The payment registration endpoint supports up to 120 requests per minute.

Request parameters​

FieldTypeRequiredDescription
transactionTypestringYes"mb_way_direct"
servicestringYesService name from the dashboard
valuestringYesAmount in EUR
currency_codestringYes"EUR"
channelstringYes"373" - the MB WAY channel
emailstringYes (with channel)Customer's email address
client_namestringYes (with channel)Customer's first name
client_surnamestringYes (with channel)Customer's last name
accept_tosbooleanYes (with channel)Confirmation that the customer accepts the terms and conditions
phone_numberstringYesPhone number in +351XXXXXXXXX format
url_successstringYesURL after a successful payment
url_failstringYesURL after a failed payment
url_ipnstringYesURL for IPN notifications
checksumstringYesSHA-256 checksum
device_infoobjectYesCustomer device information (all fields listed below)
The channel field and accompanying fields

The channel field with the value "373" is required for transactionType: "mb_way_direct". Always send it, in test mode too - the simulator does not check it, but on a production service registration without channel fails. Providing the channel field also requires email, client_name, client_surname, and accept_tos. If any of them is missing, the request fails validation (HTTP 422).

EUR currency

MB WAY accepts EUR only. The service must have EUR enabled - if it does not, registration fails with Currency code "EUR" does not match the service currency code "PLN". In that case, contact your dpay.pl account manager.

Phone number format​

Use the standard international phone number format:

+351XXXXXXXXX

Where:

  • +351 - Portugal's country code
  • XXXXXXXXX - 9-digit phone number

Example: +351912345678

device_info object​

For mb_way_direct transactions, all fields below are required:

{
"browserAcceptHeader": "text/html,application/xhtml+xml",
"browserJavaEnabled": "false",
"browserLanguage": "pt-PT",
"browserColorDepth": 24,
"browserScreenHeight": 1080,
"browserScreenWidth": 1920,
"browserTZ": 0,
"browserUserAgent": "Mozilla/5.0 ...",
"systemFamily": "Windows",
"deviceID": "device-uuid-1234",
"applicationName": "Chrome",
"geoLocalization": "38.7223,-9.1393"
}
device_info field types

The browserJavaEnabled field is required and must be the string "true" or "false" (not a boolean). The browserColorDepth, browserScreenHeight, browserScreenWidth, and browserTZ fields are integers. If any field in the device_info object is missing, the request fails validation (HTTP 422).

browserJavaEnabled in the dpay SDKs

In the dpay SDKs, browserJavaEnabled is optional - if you do not set it, the SDK does not send it, and MB WAY registration fails validation (HTTP 422). Set it explicitly, for example withBrowserJavaEnabled(false) in PHP and Java, with_browser_java_enabled(False) in Python, with_browser_java_enabled(false) in Ruby, browserJavaEnabled: false in Node.js or BrowserJavaEnabled: dpay.Bool(false) in Go. The SDK converts the boolean into the required string.

Request example​

cURL​

curl -X POST https://api-payments.dpay.pl/api/v1_0/payments/register \
-H "Content-Type: application/json" \
-d '{
"transactionType": "mb_way_direct",
"service": "abc123",
"value": "14.99",
"currency_code": "EUR",
"channel": "373",
"email": "customer@example.com",
"client_name": "Joao",
"client_surname": "Silva",
"accept_tos": true,
"phone_number": "+351912345678",
"url_success": "https://myshop.example/success",
"url_fail": "https://myshop.example/failure",
"url_ipn": "https://myshop.example/api/ipn",
"checksum": "e3b0c44298fc1c149afb...",
"device_info": {
"browserAcceptHeader": "text/html,application/xhtml+xml",
"browserJavaEnabled": "false",
"browserLanguage": "pt-PT",
"browserColorDepth": 24,
"browserScreenHeight": 1080,
"browserScreenWidth": 1920,
"browserTZ": 0,
"browserUserAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)",
"systemFamily": "Windows",
"deviceID": "device-uuid-1234",
"applicationName": "Chrome",
"geoLocalization": "38.7223,-9.1393"
}
}'

PHP​

<?php
$service = getenv('DPAY_SERVICE');
$secretHash = getenv('DPAY_SECRET_HASH');

$value = '14.99';
$urlSuccess = 'https://myshop.example/success';
$urlFail = 'https://myshop.example/failure';
$urlIpn = 'https://myshop.example/api/ipn';

$checksum = hash('sha256',
$service . '|' . $secretHash . '|' . $value . '|' .
$urlSuccess . '|' . $urlFail . '|' . $urlIpn
);

$payload = json_encode([
'transactionType' => 'mb_way_direct',
'service' => $service,
'value' => $value,
'currency_code' => 'EUR',
'channel' => '373',
'email' => $_POST['email'],
'client_name' => $_POST['client_name'],
'client_surname' => $_POST['client_surname'],
'accept_tos' => true,
'phone_number' => '+351' . $_POST['phone_number'],
'url_success' => $urlSuccess,
'url_fail' => $urlFail,
'url_ipn' => $urlIpn,
'checksum' => $checksum,
'device_info' => [
'browserAcceptHeader' => 'text/html,application/xhtml+xml',
'browserJavaEnabled' => 'false',
'browserLanguage' => 'pt-PT',
'browserColorDepth' => 24,
'browserScreenHeight' => 1080,
'browserScreenWidth' => 1920,
'browserTZ' => 0,
'browserUserAgent' => $_SERVER['HTTP_USER_AGENT'],
'systemFamily' => 'Windows',
'deviceID' => $_POST['device_id'],
'applicationName' => 'Chrome',
'geoLocalization' => $_POST['geo'],
],
]);

$ch = curl_init('https://api-payments.dpay.pl/api/v1_0/payments/register');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $payload,
CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
CURLOPT_RETURNTRANSFER => true,
]);

$response = curl_exec($ch);
curl_close($ch);

$result = json_decode($response, true);

API response​

Success - awaiting confirmation​

{
"error": false,
"msg": "Internal processing",
"status": true,
"transactionId": "abc-def-123-456"
}

The status field is a boolean (true/false). The Internal processing response means the transaction has been accepted and the customer must now confirm the payment in the MB WAY app. The result arrives asynchronously (see Payment result).

Registration error (HTTP 400)​

Errors detected during registration, such as a missing phone number, use the following response format:

{
"status": "failed",
"message": "Phone number is required for MB Way Direct transactions.",
"errors": []
}

Payment rejection in the registration response​

When the payment is rejected already at registration, the transaction is cancelled and the error code and description are returned in additionalInfo:

{
"error": true,
"msg": "Transaction canceled",
"status": false,
"transactionId": "abc-def-123-456",
"additionalInfo": {
"error": "E0506",
"error_description": "Alias does not exist"
}
}

In production, this is how errors detected before the notification is sent to the MB WAY app are returned, for example a phone number not registered with MB WAY (E0506) or invalid request data (E0103). In test mode, all failure scenarios are returned in this format, with simulator codes (see Testing in test mode).

Payment result​

SituationIn productionIn test mode
The customer confirmed the paymentIPN and the payment.succeeded webhook after confirmation in the appIPN and the payment.succeeded webhook a few seconds after registration
The customer declined the payment in the app or did not confirm itUsually asynchronously, after the customer's decision or when the confirmation time runs out: the payment.failed webhook; occasionally immediately in the registration response (E0399)Immediately in the registration response (USER_DECLINED, TIMEOUT) and the payment.failed webhook
Number not registered, invalid dataImmediately in the registration response (for example E0506, E0103) and the payment.failed webhookImmediately in the registration response (ALIAS_NOT_FOUND, SYSTEM_ERROR) and the payment.failed webhook
IPN only on success

The IPN carries no status and is sent only after a successful payment. A decline or a missing confirmation is reported only by the payment.failed webhook - if you rely on IPN alone, you learn about a failed payment by querying the transaction status. For a decline returned in the registration response, the event has generic_decline in failure.code and the decline code (for example USER_DECLINED) in failure.provider_code (see Decline codes).

Form example​

<form id="mbway-form">
<label for="phone">Phone number (Portugal)</label>
<div style="display: flex; align-items: center;">
<span>+351</span>
<input
type="tel"
id="phone"
name="phone_number"
maxlength="9"
pattern="[0-9]{9}"
placeholder="912345678"
required
/>
</div>
<button type="submit">Pay with MB WAY</button>
</form>

<script>
document.getElementById('mbway-form').addEventListener('submit', async (e) => {
e.preventDefault();
const phone = document.getElementById('phone').value;

const response = await fetch('/api/pay/mb-way', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ phone_number: phone }),
});

const result = await response.json();
if (!result.error) {
// Show a message while waiting for confirmation
alert('Confirm the payment in the MB WAY app');
}
});
</script>

Testing in test mode​

In test mode, you can use special phone numbers to simulate different scenarios without having the MB WAY app:

Phone numberScenarioRegistration responseCode in additionalInfo.error
+351900000001Payment completed successfullyInternal processing, then IPN and payment.succeeded after a few seconds-
+351900000002Success after a longer waitInternal processing, IPN and payment.succeeded after a longer while-
+351900000400User rejected the payment in the appTransaction canceledUSER_DECLINED
+351900000401Timeout - no confirmationTransaction canceledTIMEOUT
+351900000402Phone number not registered with MB WAYTransaction canceledALIAS_NOT_FOUND
+351900000500System errorTransaction canceledSYSTEM_ERROR

In test mode, a decline and a timeout are returned immediately in the registration response - in production, the customer decides in the app, so the same result arrives asynchronously, with the payment.failed webhook (see Payment result). Example response for +351900000400:

{
"error": true,
"msg": "Transaction canceled",
"status": false,
"transactionId": "abc-def-123-456",
"additionalInfo": {
"error": "USER_DECLINED",
"error_description": "User declined the transaction"
}
}
Enter the test number exactly, with the plus sign

Enter the test number exactly as shown in the table, with a leading + (spaces and hyphens are removed). A number without +, for example 351900000400, is rejected with Phone number is required for MB Way Direct transactions., and a valid number outside the table (for example +351912345678) is treated by the simulator as unknown and results in a simulated successful payment.

The full list of test numbers and details is available on the Test environment page.

Common errors​

Message / codeWhere it appearsCauseSolution
Phone number is required for MB Way Direct transactions.message (HTTP 400)Missing phone number or a format that cannot be normalized (the number is rejected)Use the +351XXXXXXXXX format
Currency code "EUR" does not match the service currency code "PLN".message (HTTP 400)EUR is not enabled for the serviceAsk your dpay.pl account manager to enable EUR for the service
PLN currency code is not allowed for MB WAY DIRECT transactions.message (HTTP 400)PLN currency in an MB WAY requestUse currency_code: "EUR"
device_info.browserJavaEnabled validation errorHTTP 422The field is missing or is a boolean instead of a string (common with SDKs when the field is not set explicitly)Send "true" or "false"
USER_DECLINED, TIMEOUT, ALIAS_NOT_FOUND, SYSTEM_ERRORadditionalInfoSimulator scenarios in test modeSee Testing in test mode
E0506 - Alias does not existadditionalInfoPhone number not registered with MB WAYSuggest another payment method
E0508 - Alias not availableadditionalInfoAlias temporarily unavailableAsk the customer to try again
E0399 - Transaction declinedadditionalInfoPayment rejected (for example, no confirmation or the customer declined it)Ask the customer to try again
E0309 - Transaction not foundadditionalInfoTransaction unknown to the providerRegister the payment again
E0103 - Request validation failedadditionalInfoInvalid request dataCheck that all fields, including device_info, are present
E0099 - Operation not allowed for this aliasadditionalInfoOperation not allowed for this phone numberSuggest another payment method
info

MB WAY is available exclusively to customers with a Portuguese phone number and the MB WAY app installed.