Subscriptions allow you to have a long term billing relationship with your customers.
You can in one payment process ask for a one time fee (a payment) plus an authorization to charge your customer in the future without requiring to come back to your website or take any action. As part of the checkout flow your customer authorizes you to debit it via the ProCheckout API up to a total amount every frequency periods. Allowed periods are DAY, WEEK and MONTH.
For monthly subscriptions (period=MONTH), you can charge in the same day every month. For months with a different number of days than the initial subscription month, you can charge in the last day of that month.
For example, if your customer subscribes between 29 and 31 of January, you can charge again on February 28th (note that this is not an exact month later).
The same if the subscription occurs on March 31st. You can charge again on April 30th.
You can charge multiple times in the same subscription period until the maximum authorized amount. For instance, in the example below you get authorization to debit up to 22.3 EUR each month. You can create as much charges as you need against this subscription but you can’t exceed your authorization within the given period. So if on 2030-09-02 you issue a 15 EUR charge and on 2030-09-24 you issue a 6 EUR charge, a 2 EUR charge on 2030-09-30 would not be authorized but on 2030-10-01 you would be allowed to issue a 22.3 EUR charge.
start_date is when you can issue the first charge against this subscription. ext_subscriptionid is your identifier for this particular subscription, equivalent to ext_invoiceid in payments.
Subscriptions can be accepted using bank cards or MB WAY (use only for monthly subscriptions). Each subscription method must be configured by our team for your wallets before it can be used.
Depending of the desired subscription method, you need to pass different fields to the API:
To allow subscriptions using MB Way, you must pass the customer mobile number in the request, using the ClientData structure. For bank cards, you should pass the email or the phone in the same structure to not be requested later in our checkout page.
In this example we ask for a subscription without an independent initial payment. If you require a separate payment such as a setup fee you can generate a checkout with both payment and subscription objects such as:
"payment": {...},
"subscription": {...},
"url_confirm": "http://...",
"url_cancel": "http://..."In this case both payment and subscription are processed as a single checkout so either both successed or fail.
For a simple 22.3 EUR subscription every month, check the examples below:
curl https://services.wallet.pt/api/v2/checkout \
-H "Content-Type: application/json" \
-H "Authorization: WalletPT 7a0eb41208209639eda9bf765b6cb04d59fb9e34" \
-d '{
"subscription": {
"amount": 22.3,
"currency": "EUR",
"frequency": 1,
"period": "MONTH",
"start_date": "2030-09-01",
"end_date": "2030-12-31",
"description": "Socks magazine subscription",
"ext_subscriptionid": "mag-2-xx45",
"client": {
"email":"foo@bar.com"
}
},
"url_cancel": "https://example.com/shop/cancel",
"url_confirm": "https://example.com/shop/confirm"
}'{
"id": "c3681596-c9e4-44f1-98dd-b36d00576fb9",
"url_confirm": "https://example.com/shop/confirm",
"url_cancel": "https://example.com/shop/cancel",
"exclude": [
"UNICRE",
"MB",
"MBWAY",
"PAYPAL",
"GPAY",
"APAY",
"SAMSUNG_PAY"
],
"subscription": {
"id": "1c2d8875-4e1c-423f-a2dd-85f68f6cebc9",
"amount": 22.3,
"currency": "EUR",
"frequency": 1,
"period": "MONTH",
"description": "Socks magazine subscription",
"ext_subscriptionid": "mag-2-xx45",
"start_date": "2030-09-01",
"end_date": "2030-12-31",
"status": "NEW"
},
"shipping": false,
"url_redirect": "https://wallet.pt/checkout/c3681596-c9e4-44f1-98dd-b36d00576fb9"
} curl https://services.wallet.pt/api/v2/checkout \
-H "Content-Type: application/json" \
-H "Authorization: WalletPT 7a0eb41208209639eda9bf765b6cb04d59fb9e34" \
-d '{
"subscription": {
"amount": 22.3,
"currency": "EUR",
"frequency": 1,
"period": "MONTH",
"start_date": "2030-09-01",
"end_date": "2030-12-31",
"description": "Socks magazine subscription",
"ext_subscriptionid": "mag-2-xx45",
"client": {
"phone": "+351960000000"
}
},
"url_cancel": "https://example.com/shop/cancel",
"url_confirm": "https://example.com/shop/confirm"
}' {
"id": "1b16c5a3-8a8a-4142-bb51-e847b9a0d5ec",
"exclude": [
"UNICRE",
"MB",
"PAYPAL",
"GPAY",
"APAY",
"SAMSUNG_PAY"
],
"subscription": {
"id": "52dd5811-9125-4595-a77f-23236ba80449",
"amount": 22.3,
"currency": "EUR",
"frequency": 1,
"period": "MONTH",
"description": "Socks magazine subscription",
"ext_subscriptionid": "mag-2-xx45",
"start_date": "2030-09-01",
"end_date": "2030-12-31",
"status": "NEW"
},
"shipping": false,
"url_cancel": "https://example.com/shop/cancel",
"url_confirm": "https://example.com/shop/confirm",
"url_redirect": "https://wallet.pt/checkout/1b16c5a3-8a8a-4142-bb51-e847b9a0d5ec"
}You should retain the subscription id as it allows you to create charges against this subscription and progress as usual on the ProCheckout flow and redirect the customer to url_redirect.
When the customer authorizes or declines the subscription you will get a callback.
If the subscription was authorized using a bank card:
Below, you can see a callback example of an authorized subscription:
{
"event": "APPROVED",
"subscription_id" : "fc1abf2d-31ba-46de-8996-d370d0f42441",
"ext_subscriptionid": "mag-2-xx45",
"subscription_end_date": "2030-12-31"
}Please note: The subscription end date can change, depending on the bank card validity date. The new subscription end date will be returned on a callback sent when this occurs.
If the subscription was authorized using MB WAY:
The “subscription_end_date” is also updated with the date defined at the MB WAY app. If you don’t define an “end_date” in the subscription request, this date will be used (the same if the end_date is after the MB WAY app date).
{
"event": "APPROVED",
"subscription_id": "1bf37811-c19f-4e15-8009-80714833d1df",
"ext_subscriptionid": "mag-2-xx45",
"subscription_end_date": "2029-07-31",
"type": "SUBSCRIPTION"
}Other callback is sent regarding to the related mandate. Please note that the “max_amount” may differ from your subscription amount. This “max_amount” is the one configured at the MB WAY app.
{
"event": "APPROVED",
"amount_available": 50,
"mandate_type": "SUBSCRIPTION",
"method": "MBWAY",
"subscription_id": "1bf37811-c19f-4e15-8009-80714833d1df",
"mandate_id": "03170538443723258152",
"type": "MANDATE",
"max_amount": 50,
"end_date": "2029-07-31"
}If your subscription has an one time fee, you will get a callback related with the payment operation too. The structure is documented here.
To create a charge against a subscription you POST a payment object to /api/v2/subscriptions/:id/charge. In this example we charge 22 EUR against the subscription created above.
curl https://services.wallet.pt/api/v2/subscriptions/fc1abf2d-31ba-46de-8996-d370d0f42441/charge \
-X POST \
-H "Content-Type: application/json" \
-H "Authorization: WalletPT 7a0eb41208209639eda9bf765b6cb04d59fb9e34" \
-d '{
"payment": {
"amount": 22,
"client": {
"address": {
"address": "Av. Fontes Pereira de Melo",
"city": "Lisboa",
"country": "pt",
"postalcode": "1100-000"
},
"email": "jsantos@email.com",
"name": "John Santos"
},
"currency": "EUR",
"ext_invoiceid": "mag-set2030-xxd3fs",
"items": [
{
"descr": "September Socks Magazine",
"name": "Socks Magazine",
"qt": 1,
"ref": 4325
}
]
}
}'Which returns immediately an object with the new charge id.
{
"amount": 22,
"currency": "EUR",
"ext_invoiceid": "mag-set2030-xxd3fs",
"id": "ffcda661-ae48-4bb0-bf43-15f810860f04",
"status": "NEW",
"subscription_id": "fc1abf2d-31ba-46de-8996-d370d0f42441"
}As with other payments processing is asynchronous and when the charge has been processed you will get a callback with the result of the payment.
This is an example of a callback for a successful payment of the above charge.
{
"amount": 22,
"charge_order_id": "ffcda661-ae48-4bb0-bf43-15f810860f04",
"currency": "EUR",
"event": "COMPLETED",
"ext_invoiceid": "mag-set2030-xxd3fs",
"ext_subscriptionid": "mag-2-xx45",
"subscription_id": "fc1abf2d-31ba-46de-8996-d370d0f42441"
}Subscriptions always start as NEW before being authorized.
If you want to create a subscription without an end_date, omit this field in your request.
They then progress to either APPROVED or FAILED depending on user acceptance. An APPROVED subscription is active and will accept charges.
A subscription will naturally progress to EXPIRED after its end_date (which can be changed according to the payment method used on it).
If the subscription is canceled by the customer it goes to CANCELED state. You the merchant can also cancel a subscription you no longer require in which case the subscription will be VOIDED. EXPIRED, VOIDED and CANCELED are final states and charges against subscription in these states will fail.
The following table sumarizes subscription states.
| State | Description |
|---|---|
| NEW | The subscription has not been accepted yet |
| APPROVED | The subscription has been accepted by the customer |
| FAILED | The subscription could not be activated via user action |
| EXPIRED | The subscription is no longer active because it’s past its end_date |
| VOIDED | The subscription was cancelled by the merchant (you) |
| CANCELED | The subscription was cancelled by the customer |
State changes to APPROVED, FAILED and CANCELED trigger callbacks such as
{
"event": "CANCELED",
"subscription_id" : "fc1abf2d-31ba-46de-8996-d370d0f42441",
"ext_subscriptionid": "mag-2-xx45",
"subscription_end_date": "2030-12-31"
}You should manage your subscriptions. Repeated charges against inactive subscriptions will always fail and will be considered bad customer relationship management.
MEO Wallet adheres to the REST collections pattern and both subscriptions and charges are collections you can GET, POST and DELETE the collection or members as described below.
| Field | Type | In/Out | Mandatory | Description |
|---|---|---|---|---|
| id | string | O | Y | subscription id |
| amount | number | I | Y | authorization limit |
| currency | string | I | Y | currency (only EUR supported) |
| frequency | integer | I | Y | number of billing periods (1 to 365) |
| period | string | I | Y | billing period (DAY, WEEK, MONTH) |
| start_date | date | I | Y | subscription start |
| end_date | date | I | N | subscription end |
| ext_subscriptionid | string | I | N | merchant reference for this subscription |
| description | string | I | N | optional description |
| client | Client | I | N | Use to pass the phone or the email. For MB Way subscriptions, it is mandatory to pass the phone |
| Field | Type | In/Out | Mandatory | Description |
|---|---|---|---|---|
| id | string | O | Y | charge order id |
| subscription_id | string | O | Y | subscription id |
| amount | number | O | Y | charged amount |
| currency | string | O | Y | currency (only EUR supported) |
| ext_invoiceid | string | O | Y | merchant reference for this charge |
| status | string | O | Y | charge order status |
| Field | Type | In/Out | Mandatory | Description |
|---|---|---|---|---|
| event | string | O | Y | subscription status change |
| subscription_id | string | O | Y | subscription id |
| ext_subscriptionid | string | O | Y | subscription id |
| subscription_end_date | date | O | Y | subscription end date |
| Field | Type | In/Out | Mandatory | Description |
|---|---|---|---|---|
| event | string | O | Y | charge order status change |
| charge_order_id | string | O | Y | charge order id |
| amount | number | O | Y | charged amount |
| currency | string | O | Y | currency (only EUR supported) |
| subscription_id | string | O | Y | subscription id |
| ext_subscriptionid | string | O | Y | merchant reference for this subscription |
| ext_invoiceid | string | O | Y | merchant reference for this charge |
| Request | GET /api/v2/subscriptions/:id |
|---|---|
| URL params | Subscription id |
| Data params | none |
| Returns | Subscription |
Gets all subscriptions with optional date range and pagination.
| Request | GET /api/v2/subscriptions |
|---|---|
| Query params | limit=[int], offset=[int] |
| Data params | none |
| Returns | Subscription Array |
{
"elements" : [
"subscription": {
"id": UUID,
"amount":DOUBLE,
"currency":"EUR",
"start_date": DATE,
"end_date": DATE,
"description" : STRING,
"status": (NEW|APPROVED|FAILED|EXPIRED|VOIDED|CANCELED),
"default_payment_method" : (WALLET|CC)
"card" : {...}
},
"subscription":{...},
"subscription":{...},
...
],
"total" : "14"
}Destroys a subscription progressing it to VOIDED state.
| Request | DELETE /api/v2/Subscriptions/:id |
|---|---|
| URL params | subscription id |
| Data params | none |
| Returns | Subscription |
Gets all charges against a specific subscription with optional date range and pagination.
| Request | GET /api/v2/subscriptions/:id/charge |
|---|---|
| Query params | limit=[int], offset=[int] |
| Data params | none |
| Returns | Charge Array |
{
"elements" : [
"charge_order" : {
"id" : UUID,
"subscrition_id" : UUID,
"amount" : DOUBLE,
"currency" : "EUR"
"date" : DATE,
"status" : (NEW|PROCESSING|FAIL|SUCCESS),
},
"charge_order" : {...},
"charge_order" : {...},
"charge_order" : {...},
...
],
"total" : "121"
}Charge status is one of the following
| Charge status | Description |
|---|---|
| NEW | The charge request passes basic validation and has been accepted |
| PROCESSING | The charge is being processed using the customer authorized payment methods |
| FAIL | The charge could not be completed because the customer has insufficient funds or other similar reason |
| SUCCESS | The charge was successful and your wallet was credited with the payment |
Get a charge by id
| Request | GET /api/v2/subscriptions/:id/charge/:charge_id |
|---|---|
| URL params | subscriptions id, charge id |
| Data params | none |
| Returns | Charge Order |
| Request | POST /api/v2/subscriptions/:id/charge |
|---|---|
| URL params | none |
| Data params | Payment |
| Returns | status object |