eCom API guide
Only available for Vipps. All new integrations should use the ePayment API.
API version: 2.0.0.
All new integrations should use the ePayment API. See the eCom to ePayment Migration guide for help migrating older integrations.
Payment flows
The eCom API offers these types of flows:
Information about how to retrieve settlements is provided in Knowledge base: Settlements.
Regular payment flow
This is the typical flow, where the user adds items to a shopping cart, enters the shipping address and pays.
The flow is as follows:
- The customer selects Vipps as the method of payment and enters their mobile number into the app or website.
- The merchant initiates the payment command, which the customer confirms the purchase through their Vipps app.
- If the purchase is approved, the merchant registers the sale in their system.
This diagram shows a simplified payment flow:
For examples of how eCommerce can work, see:
See Flow details for more in-depth details about using this flow in the browser, phone, or app.
Express checkout payment flow
Express Checkout (Hurtigkasse) expands upon the regular payment flow with the user selecting a shipping option and sharing their address with the merchant through the Vipps app.
Try it out on the Express checkout demo page.
See Express checkout payments for more details.
In-store flow
The In-store flow is the same as the regular flow except that the phone number is provided to the service provider who then initiates the payment through their Point of Sale (POS) system. See eCommerce API: How it works in the store for more information.
Checkout flow
The Checkout flow is the same as the regular flow except that, instead of confirming the purchase in the Vipps app, the customer consents to sharing their personal information (e.g., address, phone, and payment information). They then complete the purchase from the website where their information is automatically prefilled.
API endpoints
The eCom API offers functionality for online payments. Payments are supported in both web browsers and in native apps (via deep-linking).
Operation | Description | Endpoint |
---|---|---|
Initiate payment | Payment initiation, the first request in the payment flow. This reserves an amount. | POST:/ecomm/v2/payments |
Capture payment | When an amount has been reserved, and the goods are (about to be) shipped, the payment must be captured. | POST:/ecomm/v2/payments/{orderId}/capture |
Cancel payment | The merchant may cancel a reserved amount, but not on a captured amount. | PUT:/ecomm/v2/payments/{orderId}/cancel |
Refund payment | The merchant may refund a captured amount. | POST:/ecomm/v2/payments/{orderId}/refund |
Get payment details | The full history of the payment. | GET:/ecomm/v2/payments/{orderId}/details |
Get order status | Deprecated, use Get payment details. | Deprecated, use GET:/ecomm/v2/payments/{orderId}/details |
Necessary endpoint from other APIs:
Operation | Description | Endpoint |
---|---|---|
Get Access token | Fetch the access token | POST:/accesstoken/get |
For integrating with the eCom API, see the eCom API checklist.
We recommend using the standard HTTP headers for all requests.
See Knowledge base: HTTP headers for details.
All API calls are authenticated with an access token and an API subscription key. See Get an access token in the Getting started guide, for details.
Initiate
Payment amounts must be in NOK, be non-zero and larger than 1 NOK (1 NOK = 100 øre).
Amounts are specified in minor units. For Norwegian kroner (NOK) that means 1 kr = 100 øre. Example: 499 kr = 49900 øre.
When you initiate a payment, it will normally only be reserved until you capture it.
This has some benefits:
- If a payment has been reserved, the merchant can
make a
PUT:/ecomm/v2/payments/acme-shop-123-order123abc/cancel
call to immediately release the reservation. - It is possible to reserve a higher amount and only capture a part of it (useful for electric car charging stations, etc.). It is also possible to capture the full amount with multiple captures ("partial capture").
Detailed example
API Specification:
POST:/ecomm/v2/payments
A minimal example:
{
"customerInfo": {},
"merchantInfo": {
"merchantSerialNumber": "123456",
"callbackPrefix": "https://example.com/vipps/callbacks-for-payment-update-from-vipps",
"fallBack": "https://example.com/vipps/fallback-result-page-for-both-success-and-failure/acme-shop-123-order123abc"
},
"transaction": {
"orderId": "acme-shop-123-order123abc",
"amount": 20000,
"transactionText": "One pair of Vipps socks"
}
}
An express payment example with more parameters provided:
{
"customerInfo": {
"mobileNumber": "48059528"
},
"merchantInfo": {
"authToken": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1Ni <snip>",
"callbackPrefix": "https://example.com/vipps/callbacks-for-payment-update-from-vipps",
"consentRemovalPrefix": "https://example.com/vipps/consents/",
"fallBack": "https://example.com/vipps/fallback-result-page-for-both-success-and-failure/acme-shop-123-order123abc",
"merchantSerialNumber": 123456,
"shippingDetailsPrefix": "https://example.com/vipps/shipping/",
"paymentType": "eComm Express Payment",
"staticShippingDetails": [
{
"isDefault": "N",
"priority": 1,
"shippingCost": 99,
"shippingMethod": "Walking",
"shippingMethodId": "123abc"
},
{
"isDefault": "Y",
"priority": 2,
"shippingCost": 199,
"shippingMethod": "Running",
"shippingMethodId": "321abc"
}
]
},
"transaction": {
"amount": 20000,
"orderId": "acme-shop-123-order123abc",
"timeStamp": "2018-12-12T11:18:38.246Z",
"transactionText": "One pair of Vipps socks"
}
}
Please note: The phone number is optional and should only be sent if it is
already known.
Users should never be asked for the phone number, as they will
either be automatically app-switched to the Vipps app, or they will be presented
with the
landing page.
If the customer's phone number is needed by the merchant: Use scope
and the
Userinfo API.
Important: Do not send sensitive information in the transactionText
field.
See:
transactionText
for recommendations of what to use in this field.- Datatilsynet, Norwegian Data Protection Authority for information about which types of information is sensitive (in Norwegian).
For questions relating to capturing the response, see Reserve and capture.
Additional implementation details (e.g., Callbacks, rate limiting) are in the Integration details section.
The Vipps deeplink URL
Vipps responds to the
POST:/ecomm/v2/payments
request with a URL.
The URL is normally a https://
URL, which automatically opens the Vipps app, if the
app is installed (and the landing page, if not).
It is possible to perform manual handling of the interaction between the user's Vipps app and the Vipps backend, although this is not recommended. For details, see Knowledge base: App flow recommendations.
Payment identification
A payment is uniquely identified by the combination of merchantSerialNumber
and orderId
:
merchantSerialNumber
: The merchant's Vipps ID. Example:123456
.orderId
: Must be unique for themerchantSerialNumber
. Example:acme-shop-123-order123abc
. See:orderId
recommendations.
Payment retries
If a user cancels or does not act on a payment, there is no way to "retry" the payment.
The initiate call is not idempotent, so the closest to a "retry"
is to make a new initiate call with a new orderId
. Vipps has no concept
of relation between orders, so the "retry" payment is in no way connected
to the first payment attempt.
Payment parameter recommendations
For some hints about what to use for the parameter values, see these pages in the Knowledge base:
The landing page
When a user is directed to the url
sent in the response to
POST:/ecomm/v2/payments
,
they will either be taken to the Vipps app or to the
Landing page.
Other relevant information
See below for helpful information, for example:
Reserve
When you initiate a payment, it will be reserved until you capture it:
- When a payment is reserved it means the customer has approved the payment. The funds are still in the customer's account, but not available to spend on other things.
- When a payment is captured it means the funds are moved from customer's account to merchant's account.
- Captured funds will be settled to the merchant's settlement account after two business days. See Settlements for more details.
When the user confirms the purchase in Vipps, the payment status changes to RESERVE
.
The respective amount will be reserved for future capturing.
Capture
The eCom API supports reserve capture and direct capture:
- Reserve capture is the default, and works for all types if payments. When you initiate a payment, it will be reserved until you capture it. The capture can be done a few seconds later, or several days later.
- Direct capture is available in the eCom API for historical reasons, but not available in the newer ePayment API. When direct capture is configured for a sales unit, all payment reservations will instantly be captured, without the need for a separate capture request. This is provided for legacy reasons and was intended for situations where the product or service is immediately provided to the customer, and there is absolutely no chance that the service is not available or sold out, e.g. digital services. We have since moved away from this, and strongly recommend that all integrations use the ePayment API and reserve capture. Direct capture requires additional compliance checks of the merchant.
You should capture as soon as is legally possible, because some banks will release the funds after some days, making it difficult to capture later. If it's not captured within the payment capture deadlines, it will be automatically cancelled.
However, be aware that it isn't legal to capture before the product or service is provided to the customer, as per the capture regulations.
It's completely fine to use reserve capture almost exactly like direct capture: Just do the capture immediately after the reservation. The user experience is exactly the same.
Important things to consider for cancellations and refunds:
- If a payment has been reserved (as with "reserve capture"), the merchant can make a "cancel" API request to immediately release the reservation and make available in the customer's account. This may be useful even in situations where it's "impossible" that the goods/service is sold out.
- If a payment has been captured (as with "direct capture"), the merchant has to make a "refund" API request, and it then takes several days before the amount is available in the customer's account.
- With "reserve capture" it is possible to reserve a higher amount and only capture a part of it (useful for electric car charging stations, etc.). It is also possible to capture the full amount with multiple captures ("partial capture").
Capture is done with
POST:/ecomm/v2/payments/{orderId}/capture
.
Use the idempotency key, X-Request-Id
, in the capture call. Then, if a capture
request fails for any reason, it can be retried with the same idempotency key.
You can use any unique ID for your X-Request-Id
.
See the X-Request-Id in the capturePaymentUsingPOST specification for details.
To perform a normal capture of the entire amount, amount
can be
omitted from the API request (i.e., not sent at all), set to null
or set to 0
.
When doing a
partial capture,
you need to specify the amount
.
It is important to check the response of the /capture
call. The capture is only successful when the response is HTTP 200 OK
.
Capture can be made up to 180 days after reservation.
Attempting to capture an older payment will result in a
HTTP 400 Bad Request
.
Types of capture
Reserve capture
Reserve capture is the normal flow.
When the end user approves an initiated payment, it will be reserved until you capture it. When the order is reserved, the amount is marked as reserved by the bank, but not transferred.
Direct capture
Important: Direct capture is available in the eCom API for historical reasons, but not available in the newer ePayment API.
When direct capture is activated, all payment reservations will instantly be captured.
With direct capture, Vipps MobilePay is responsible for the customer receiving the purchased product. Because of this, direct capture requires additional compliance checks.
A sales unit can only have one capture type, and it must be configured by Vipps MobilePay. You can't turn direct capture on or off as a merchant.
We strongly recommend using "reserve capture" in all situations.
Please note: We only offer "direct capture" for merchants that use Vipps MobilePay through a partner, and for merchants that have a Key Account Manager. "Direct capture" must be requested by the partner from the partner manager, or by KAM merchants from the Key Account Manager.
Please note: The Checkout API does not support "direct capture".
See the FAQ:
- When should I use "Direct Capture"?
- How can I check if I have "reserve capture" or "direct capture"?
Partial capture
Partial capture may be used in cases where a partial order is shipped or for other reasons. It may be called as many times as required while there is a remaining amount that is reserved and has not yet been captured.
For this API, it is also possible to do a partial capture and send an optional parameter to explicitly free the remaining amount immediately.
More information about capture
See Knowledge base: reserve and capture for more details about the types of captures.
You should charge the customer when the product or service is delivered. For more details, see capture regulations.
Specific questions:
Cancel
The Cancel request allows the merchant to cancel a reserved or initiated transaction.
Please note that it is not possible to cancel a request that is over 180 days old.
Attempting to cancel an older payment will result in a HTTP 400 Bad Request
.
The payment flow can be aborted under certain circumstances:
- When the user cancels (rejects) the initiated payment in Vipps.
- When the merchant cancels.
- Timeouts: If the user does not confirm, etc.
After cancellation, the order gets a new status:
- If an order is cancelled by the merchant while it's in the
RESERVE
state, the status becomesVOID
. - If an order is cancelled by the merchant while it's in the
INITIATE
state, the status becomesCANCEL
. - If an order is cancelled by the user, the status becomes
CANCEL
.
Detailed example
PUT:/ecomm/v2/payments/acme-shop-123-order123abc/cancel
{
"merchantInfo": {
"merchantSerialNumber": "123456"
},
"transaction": {
"transactionText": "No socks for you!"
}
}
Response:
{
"orderId": "acme-shop-123-order123abc",
"transactionInfo": {
"amount": 20000,
"transactionText": "No socks for you!",
"status": "Cancelled",
"transactionId": "5001420063",
"timeStamp": "2018-11-14T15:31:10.004Z"
},
"transactionSummary": {
"capturedAmount": 0,
"remainingAmountToCapture": 0,
"refundedAmount": 0,
"remainingAmountToRefund": 0
}
}
Cancelling a pending order
If you wish to cancel a transaction before the customer can confirm the payment
in Vipps, you can send a
PUT:/ecomm/v2/payments/{orderId}/cancel
request while the transaction is in the INITIATE
stage.
This may be useful in face-to-face situations where a customer's phone runs out
of battery, or if the customer suddenly changes their mind and wants to buy
more and the amount for the payment increases.
This should not be considered a consistent or guaranteed operation,
as the /cancel
request depends on actions taken by the user in the app.
If the
PUT:/ecomm/v2/payments/{orderId}/cancel
request is successful, the payment state in the response will be: CANCELLED
.
Warning The
GET:/ecomm/v2/payments/{orderId}/details
endpoint however will returnCANCEL
, notCANCELLED
.
A call to
GET:/ecomm/v2/payments/{orderId}/details
for the same order will return the following, regardless of whether the
transaction has been reserved before the cancellation: CANCEL
.
Note If the order is in the state
RESERVED
and then cancelled by the merchant, the status will beVOID
.
Please note: If the user is already in a 3-D Secure session, the payment cannot be cancelled as described above.
Cancelling a partially captured order
If you wish to cancel an order that you have partially captured, send a
PUT:/ecomm/v2/payments/{orderId}/cancel
request with shouldReleaseRemainingFunds: true
in the body.
The payment must be RESERVED
for this to take effect.
If shouldReleaseRemainingFunds
is not set, it will default to false
.
When shouldReleaseRemainingFunds
is set to false
,
any request to cancel after a partial or full capture has been performed will be rejected.
This is a useful and recommended feature, as it releases any reserved balance as soon as the card issuer and/or bank permits.
Detailed example
{
"merchantInfo": {
"merchantSerialNumber": "123456"
},
"transaction": {
"transactionText": "No socks for you!"
},
"shouldReleaseRemainingFunds": true
}
Response:
{
"orderId": "acme-shop-123-order123abc",
"transactionInfo": {
"amount": 20000,
"transactionText": "No socks for you!",
"status": "Cancelled",
"transactionId": "5001420063",
"timeStamp": "2018-11-14T15:31:10.004Z"
},
"transactionSummary": {
"capturedAmount": 10000,
"remainingAmountToCapture": 0,
"refundedAmount": 0,
"remainingAmountToRefund": 10000
}
}
Please note: Once this operation has been performed, there will be zero funds remaining to capture. Do not call this endpoint until you are sure you have captured all you need.
Refund
All integrations with the eCom API must support refunds.
The merchant can initiate a refund of the captured amount. The refund can be a partial or full.
It usually takes 2-3 bank days until the money is in the customer's account, depending on the bank(s). It can take much longer, up to 10 days, and depends on the bank(s).
Partial refunds are done by specifying an amount
which is lower than the
captured amount. The refunded amount cannot be larger than the captured amount.
In a capture request, the merchant may also use the X-Request-Id
header. See Idempotency for details.
Refunds can be made up to 365 days after reservation.
Attempting to refund an older payment will result in a
HTTP 400 Bad Request
.
Detailed example
POST:/ecomm/v2/payments/acme-shop-123-order123abc/refund
{
"merchantInfo": {
"merchantSerialNumber": "123456"
},
"transaction": {
"amount": 20000,
"transactionText": "Refund of Vipps socks"
}
}
Response:
{
"orderId": "acme-shop-123-order123abc",
"transaction": {
"amount": 20000,
"transactionText": "Refund of Vipps socks",
"status": "Refund",
"transactionId": "5600727726",
"timeStamp": "2018-11-14T15:23:02.286"
},
"transactionSummary": {
"capturedAmount": 20000,
"remainingAmountToCapture": 0,
"refundedAmount": 20000,
"remainingAmountToRefund": 0
}
}
For details about cancelling the remaining reservation after a partial capture, see Cancelling a partially captured order
See also FAQ: Refunds.
Get payment details
GET:/ecomm/v2/payments/{orderId}/details
retrieves the full history of a payment and the status of the operations.
Payment states
# | From-state | To-state | Description | Operation |
---|---|---|---|---|
0 | - | Initiate | Payment initiation | INITIATE |
1 | - | The merchant has initiated the payment | INITIATE | |
- | The user has accepted the payment and amount has been reserved | RESERVE | ||
- | Cancel | The user has cancelled the order | CANCEL | |
2 | Reserve | Capture | The merchant captures the payment and ships | CAPTURE |
- | Cancel | The merchant has cancelled the order | VOID | |
3 | Capture | -- | A final state: Payment fully processed | CAPTURE |
- | Refund | The merchant has refunded the money to the user | REFUND | |
4 | Cancel | -- | A final state: Payment cancelled | - |
5 | Refund | -- | A final state: Payment refunded | - |
Requests and responses
Please note that the response from
GET:/ecomm/v2/payments/{orderId}/details
always contains the entire history of payments for the order, not just the current status.
Important: The operationSuccess
field indicates whether an operation was successful or not.
Response | Description |
---|---|
INITIATE | Payment initiated by merchant |
RESERVE | Payment reserved by user accepting the payment in Vipps |
CAPTURE | Payment captured by merchant (after RESERVE ) |
REFUND | Payment refunded by merchant (after CAPTURE ) |
CANCEL | Payment cancelled by user in Vipps |
SALE | Payment captured with direct capture by merchant |
VOID | Payment cancelled by merchant |
Detailed example
{
"orderId": "acme-shop-123-order123abc",
"transactionSummary": {
"capturedAmount": 20000,
"remainingAmountToCapture": 0,
"refundedAmount": 20000,
"remainingAmountToRefund": 0,
"bankIdentificationNumber": 492560
},
"transactionLogHistory": [
{
"amount": 20000,
"transactionText": "Refund of Vipps socks",
"transactionId": "5600727726",
"timeStamp": "2018-11-14T15:23:02.286Z",
"operation": "REFUND",
"requestId": "1542208972",
"operationSuccess": true
},
{
"amount": 20000,
"transactionText": "One pair of Vipps socks",
"transactionId": "5001420058",
"timeStamp": "2018-11-14T15:22:46.680Z",
"operation": "CAPTURE",
"requestId": "1542208966",
"operationSuccess": true
},
{
"amount": 20000,
"transactionText": "One pair of Vipps socks",
"transactionId": "5001420062",
"timeStamp": "2018-11-14T15:21:22.126Z",
"operation": "RESERVE",
"requestId": "",
"operationSuccess": true
},
{
"amount": 20000,
"transactionText": "One pair of Vipps socks",
"transactionId": "5001420062",
"timeStamp": "2018-11-14T15:21:04.697Z",
"operation": "INITIATE",
"requestId": "",
"operationSuccess": true
}
]
}
Please note:
- The
transactionSummary
will not be part of the response if the user does not react to the landing page or app-switch. - The
bankIdentificationNumber
will only be part oftransactionSummary
in the response of theGET:/ecomm/v2/payments/{orderId}/details
endpoint. - If paymentType is set to
eComm Express Payment
you will getshippingDetails
anduserDetails
in addition totransactionLogHistory
andtransactionSummary
. - If you initiate the payment with a
scope
to use with the Userinfo API you will also get auserDetails
object containing the user's information:
"userDetails": {
"bankIdVerified": 0,
"email": "user@example.com",
"firstName": "Ada",
"lastName": "Lovelace",
"mobileNumber": "12345678",
"userId": "c06c4afe-d9e1-4c5d-939a-177d752a0944"
}
See Knowledge base: Polling guidelines.
Flow details
Phone and mobile browser flow
A payment is initiated with a call to
POST:/ecomm/v2/payments
.
Triggered by the payment initiation, the landing page will automatically detect if it is being invoked on a phone, and whether Vipps is installed on the phone. If Vipps is installed, Vipps will automatically be opened.
Vipps installed
- Vipps is invoked (with app-switch).
- The user accepts or rejects the payment request in Vipps.
- The Vipps backend makes a call to the merchant's
callbackPrefix
with information about the payment. - Once payment process is completed, Vipps redirects to the
fallBack
URL that merchant provided earlier (see above).
Vipps not installed
- The landing page (in the browser) prompts the user for the phone number.
- The Vipps backend sends a push notification to the user's phone, and also displays a notification on the landing page for the user to continue the payment in Vipps on the phone.
- The user accepts or rejects the payment in Vipps.
- The Vipps backend makes a call to the merchant's
callbackPrefix
with information about the payment. - Once the payment process is completed, Vipps redirects to the
fallBack
URL that the merchant provided earlier.
Please note:
- Vipps cannot guarantee that the user will get to the
fallBack
URL, since the user may switch away from Vipps or "kill" the app, or there may be network or battery problems, etc. before the URL is opened. If the merchant relies 100 % on users visiting thefallback
URL, there will be problems: The user has completed the payment, but the merchant ignores it. - If the user has started the payment in an embedded browser, such as in
Facebook or Instagram, it is not possible for Vipps to open the
fallBack
URL in the embedded browser. The phone OS will always open URLs in the default browser. See: Knowledge base: Recommendations regarding handling redirects. - Because of the above, a successful payment must not rely on session cookies in the browser.
- Vipps cannot guarantee a particular sequence of callback and fallback, as this depends on user actions, network connectivity/speed, etc. Because of this, it is not possible to base an integration on a specific sequence of events.
- URLs must be valid. See: Knowledge base: URL Validation
Desktop flow
- The landing page will be opened in the desktop browser.
- The landing page will prompt for the user’s phone number. If the phone number is known, it should be prefilled by the merchant.
- Vipps sends a push notification the user's phone, with a notification on the landing page to continue the payment in Vipps on the phone.
- The user accepts or rejects the payment in Vipps.
- The Vipps backend makes a call to the merchant's
callbackPrefix
with information about the payment. See: Callbacks. - Once the payment process is completed, the landing page will redirect to the
fallBack
URL that merchant provided earlier.
Payments initiated in an app
If payments are always initiated in the merchant's native app, there is no need to pass any additional parameters. Vipps will handle everything automatically.
It is also possible to send the optional isApp
parameter, but this
comes with extra responsibility. For details, see
Knowledge base: App flow recommendations.
Express checkout payments
Express Checkout allows the user to select a shipping option and share their address with the merchant through the Vipps app.
Express Checkout is designed for shipping products with a delivery address and a shipping method. It's mandatory for the user to select the address and shipping method to ensure that the item is delivered to the right place in the right way.
Vipps Hurtigkasse works this way, as seen from the user's side:
- The user clicks the Vipps Hurtigkasse button.
- The user consents to sharing address information in Vipps.
- The user confirms the amount, delivery address and delivery method in Vipps.
- If you only need the user's information, you should use a normal payment and the Userinfo API.
- It is not possible to specify
scope
with Express checkout. - If you only need the user's information, you should use Profile sharing. You should avoid asking the customer in a pub for the shipping method for the drinks, etc.
To perform an express checkout, the merchant needs to specify
"paymentType": "eComm Express Payment"
in the
POST:/ecomm/v2/payments
call, and support the
POST:[shippingDetailsPrefix]/v2/payments/{orderId}/shippingDetails
and
DELETE:[consentRemovalPrefix]/v2/consents/{userId}
endpoints.
Express checkout API endpoints required on the merchant side
The below endpoints are provided by the merchant and consumed by Vipps during Express Checkout payments. These endpoints are not required when using regular checkout.
These endpoints are to be implemented by merchants in order for Vipps to make calls to them. The documentation is included in the API specification for reference only - these endpoints are not callable at Vipps.
Operation | Description | Endpoint |
---|---|---|
Get shipping details | Used to fetch shipping information, 10-second timeout | POST:[shippingDetailsPrefix]/v2/payments/{orderId}/shippingDetails |
Transaction Update | A callback to the merchant for receiving post-payment information. | POST:[callbackPrefix]/v2/payments/{orderId} |
Remove user consent | Used to inform merchant when the Vipps user removes consent to share information. | DELETE:[consentRemovalPrefix]//v2/consents/{userId} |
Shipping and static shipping details
The shipping methods presented to the user in Vipps are fetched from the merchant's
POST:[shippingDetailsPrefix]/v2/payments/{orderId}/shippingDetails
endpoint.
If the shipping methods and cost can be known in advance, the staticShippingDetails
field in
POST:/ecomm/v2/payments
may be used to provide the shipping details up front, and thereby avoid an
extra round-trip between the Vipps backend and the merchant's server.
When using staticShippingDetails
the shipping costs for the available
shipping methods are then sent directly, eliminating the need for the user to
first select shipping method and then for the merchant to calculate the cost for it.
We recommend using staticShippingDetails
if possible, as it gives a faster
payment process and a better user experience. It also eliminates timeout problems
caused by delays in the merchant's or shipping partner's calculations of cost.
Detailed example of get shipping details
The
POST:[shippingDetailsPrefix]/v2/payments/{orderId}/shippingDetails
API endpoint on the merchant's side allows Vipps to get the shipping cost and
method based on the provided address and product details.
This endpoint is required for Express Checkout.
Request:
{
"addressId": 3960,
"addressLine1": "Dronning Eufemias gate 42",
"addressLine2": null,
"country": "Norway",
"city": "OSLO",
"postCode": "0191",
"addressType": "H"
}
Response:
{
"addressId": 3960,
"orderId": "123456abc",
"shippingDetails": [
{
"isDefault": "N",
"priority": 1,
"shippingCost": 99,
"shippingMethod": "Walking",
"shippingMethodId": "123abc"
},
{
"isDefault": "Y",
"priority": 2,
"shippingCost": 199,
"shippingMethod": "Running",
"shippingMethodId": "321abc"
}
]
}
Sequence diagram with and without staticShippingDetails
:
To get information about the payment, use callbacks and polling.
Remove User Consent
Vipps complies with GDPR, and requires the user's consent before any information
is shared with the merchant. The merchant must provide a URL (consentRemovalPrefix
)
that Vipps can call to delete the data. Vipps allows the user to later
remove this consent (via the Vipps app: Profile > Security > Access to your information > Companies that remember you).
The personal information shared with the merchant is available for 7 days after reservation.
After this, all customer information will be replaced with "[Expired]"
in subsequent calls to
GET:/ecomm/v2/payments/{orderId}/details
.
The
DELETE:[consentRemovalPrefix]/v2/consents/{userId}
API endpoint on the merchant's side allows Vipps to send an end user's consent
removal request to the merchant.
This endpoint is required for Express Checkout.
When receiving this request,
the merchant is obliged to handle the user details as per the GDPR guidelines.
The request path will include a userId
that Vipps will have provided as
part of callback and also made accessible through GET:/ecomm/v2/payments/{orderId}/details
.
Profile sharing
Vipps offers the possibility for merchants to ask for the user's profile information as part of the payment flow.
To enable the possibility to fetch profile information for a user, the merchant can add a scope
parameter to the initiate call:
POST:/ecomm/v2/payments
.
See
Userinfo API guide.
Profile sharing call-by-call guide
Scenario: You want to complete a payment and get the name and phone number of a customer. Details about each step are described in the sections below.
- Retrieve the access token:
POST:/accesstoken/get
. - Add scope to the transaction object and include the scope you wish to get
access to (valid scope) before calling
POST:/ecomm/v2/payments
Include the scopes you need access to (e.g., "name address email phoneNumber birthDate"), separated by spaces. - The user consents to the information sharing and perform the payment in Vipps.
- Retrieve the
sub
by callingGET:/ecomm/v2/payments/{orderId}/details
- Using the sub from step 4, call
GET:/vipps-userinfo-api/userinfo/{sub}
to retrieve the user's information.
An example similar to this, but with ePayment, is shown in the Userinfo quick start guide.
Please note: The sub
is added asynchronously, so if the /details
request
is made within (milli)seconds of the payment approval in the app, it may not be
available. If that happens, simply make another /details
request.
See
Polling guidelines
in the Knowledge base for more recommendations.
Get userinfo
Once the user completes the session, a unique identifier sub
can be retrieved from the
GET:/ecomm/v2/payments/{orderId}/details
endpoint.
Example sub
format:
"sub": "c06c4afe-d9e1-4c5d-939a-177d752a0944",
This sub
is a link between the merchant and the user and can be used to retrieve
the user's details from the Userinfo API:
GET:/vipps-userinfo-api/userinfo/{sub}
See: Userinfo API.
Integration details
Callbacks
Callbacks allow Vipps to send the merchant information about the payment. Callback are made for the following events:
- Payment successful
- Payment failed
- Payment rejected
- Payment timed out
Please note: Callback offer a faster user experience than polling, but you
can't rely on callbacks alone. You must also poll
GET:/ecomm/v2/payments/{orderId}/details
.
See Knowledge base: Polling for polling guidelines.
Important:
- Vipps makes one attempt at a callback and cannot guarantee that it succeeds, as it depends on network, firewalls and other factors that Vipps cannot control. If the communication is broken during the process for some reason and Vipps is not able to execute callback to the merchant's server, the callback will not be retried.
- Vipps callbacks require a response within 3 seconds; otherwise, they will time out.
- Callback URLs must use HTTPS.
The callback request body is different for the different payment types:
"eComm Regular Payment"
: The callback contains the order and transaction details."eComm Express Payment"
: The callback contains the order and transaction details and in addition the user details and shipping details.- If Profile sharing is used: The callback is the same as for
"eComm Express Payment"
.
See:
Callback URLs
The callback URLs are generated by appending the orderId
to the callbackPrefix
sent in the
POST:/ecomm/v2/payments/{orderId}
call. The callbackPrefix
is for an API endpoint on the merchant's side.
See the API specifications.
For example, if your callbackPrefix
is https://example.com/vipps/callback
and the
orderId
is acme-shop-123-order123abc
, Vipps will append /v2/payments/acme-shop-123-order123abc
(note the leading slash)
to https://example.com/vipps/callback
and make a callback to
https://example.com/vipps/callback/v2/payments/acme-shop-123-order123abc
.
Again:
callbackPrefix
+/v2/payments/
+{orderId}
https://example.com/vipps/callback
+/v2/payments/
+acme-shop-123-order123abc
Important:
- URLs must be valid. For details, see Knowledge base: URL Validation.
- Vipps does not support sending requests to all ports, so to be safe use common port numbers such as: 80, 443, 8080.
- Vipps does not support callback URLs that return
HTTP 301 Redirect
,HTTP 302 Permanently Moved
orHTTP 307 Temporary Redirect
. Vipps will not follow to aLocation
. The callback URLs must be directly reachable.
Detailed example
Below are two examples of payment update callbacks with
POST:[callbackPrefix]/v2/payments/{orderId}
.
Example: "eComm Regular Payment"
callback:
{
"merchantSerialNumber": 123456,
"orderId": "acme-shop-123-order123abc",
"transactionInfo": {
"amount": 20000,
"status": "RESERVED",
"timeStamp": "2018-12-12T11:18:38.246Z",
"transactionId": "5001420062"
}
}
Example: "eComm Express Payment"
callback:
{
"merchantSerialNumber": 123456,
"orderId": "acme-shop-123-order123abc",
"shippingDetails": {
"address": {
"addressLine1": "Dronning Eufemias gate 42",
"addressLine2": "Att: Rune Garborg",
"city": "OSLO",
"country": "NO",
"zipCode": "0191" // Postcode (apologies for not using postCode as elsewhere)
},
"shippingCost": 99,
"shippingMethod": "By cannon",
"shippingMethodId": "53DBB6BA-89DB-4997-B444-5E9F1681E3D3"
},
"transactionInfo": {
"amount": 20000,
"status": "RESERVE",
"timeStamp": "2018-12-12T11:18:38.246Z",
"transactionId": "5001420062"
},
"userDetails": {
"firstName": "Ada",
"lastName": "Lovelace",
"email": "user@example.com",
"mobileNumber": "12345678",
"userId": "1234567"
}
}
Please note: Regular payments use RESERVED
, but express payments use
RESERVE
. We apologize for this, but it is technical debt, and it cannot be
corrected in this version of the API, as that would break backwards compatibility.
How to test your own callbacks
We recommend using HTTPie for testing your callbacks.
-
Create a JSON file with the callback request payload based on the example for
POST:[callbackPrefix]/v2/payments/{orderId}
:{
"merchantSerialNumber": 123456,
"orderId": "acme-shop-123-order123abc",
"transactionInfo": {
"amount": 20000,
"status": "RESERVED",
"timeStamp": "2018-12-12T11:18:38.246Z",
"transactionId": "5001420062"
}
}Save this JSON file as
callback.json
. -
Build your callback URL. In this example, the
callbackPrefix
ishttps://example.com/vipps/callback
, and theorderId
isacme-shop-123-order123abc
. -
Test the callback by making a POST request to your callback URL with the JSON file as request body:
POST https://example.com/vipps/callback/v2/payments/acme-shop-123-order123abc < callback.json
-
If it does not return
HTTP 200 OK
, your callback handling does not work, and you must correct it.
Authorization for callbacks
If you provide the authToken
when initiating a payment with
POST:/ecomm/v2/payments/{orderId}
,
the authToken
will be sent as an Authorization
header in the callback and
shipping details requests. Please note that this is unrelated to the
authentication required by the Vipps API.
API spec:
POST:[callbackPrefix]/v2/payments/{orderId}
Vipps callback servers
The callbacks from Vipps are made from the servers described in Vipps request servers.
Please make sure that requests from these servers are allowed through firewalls, etc.
Callback statuses
These are the statuses provided by Vipps in the callbacks by
[callbackPrefix]/v2/payments/{orderId}
:
Callback type | Response | Description |
---|---|---|
Regular checkout | RESERVED | Payment reserved by user accepting the payment in Vipps. |
SALE | Payment captured with direct capture by merchant (after RESERVED ). | |
RESERVE_FAILED | Reserve capture failed because of insufficient funds, invalid card or similar. | |
SALE_FAILED | Direct capture failed because of insufficient funds, invalid card or similar. | |
CANCELLED | Payment cancelled by the user in Vipps. | |
REJECTED | User did not act on the payment (timeout, etc.). | |
Express checkout | RESERVE | Payment reserved by user accepting the payment in Vipps (it is correct that this is different from RESERVED for regular checkout - sorry.) |
SALE | Payment captured with direct capture, by merchant (after RESERVE ). | |
RESERVE_FAILED | Reserve failed because of insufficient funds, invalid card or similar. | |
SALE_FAILED | Direct failed because of insufficient funds, invalid card or similar. | |
CANCELLED | Payment cancelled by user in Vipps. | |
REJECTED | User did not act on the payment (timeout, etc.). |
For a full history of a payment, use
[callbackPrefix]/v2/payments/{orderId}/details
.
See Get payment details for more information.
See: Knowledge base: Timeouts.
eCom API HTTP response codes
This API returns the following HTTP statuses in the responses:
200 OK
201 Created
204 No Content
400 Bad Request
401 Unauthorized
403 Forbidden
404 Not Found
409 Conflict
429 Too Many Requests
500 Server Error
For more information about the HTTP response codes and JSON object in the responses, see HTTP response codes and errors in the Knowledge base.
For details about the specific eCom errors and responses, see Errors, as well as the ePayment OpenAPI specification.
Errors
Error object in the response
See also eCom API HTTP response codes.
[
{
"errorGroup": "Payment",
"errorMessage": "Refused by issuer because of expired card",
"errorCode": "44"
}
]
{
"statusCode": 401,
"message": "Access denied due to invalid subscription key. Make sure to provide a valid key for an active subscription."
}
Error groups
Error groups | Description |
---|---|
Authentication | Authentication Failure because of wrong credentials provided |
Payment | Failure while doing a payment authorization |
InvalidRequest | Request contains invalid parameters |
VippsError | Internal Vipps application error |
User | Error related to the Vipps user (Example: Not a Vipps user) |
Merchant | Errors regarding the merchant |
Error codes
Please note: Vipps is only allowed to provide all of these errors through
the API, and that we have to send VippsError
(99) in cases where we are not
allowed to provide more details. The same goes for errors from our PSP: We
may not be allowed to pass on the details to merchants.
In case of errors: Use Get payment details to retrieve all the information about the payment.
Error group | Error Code | Error Message (and some explaining text for some errors) |
---|---|---|
Payment | 41 | "The user does not have a valid card." The customer must add a card. |
Payment | 42 | "Refused by the issuer." The customer must contact the issuer, typically the bank. |
Payment | 43 | "Refused by the issuer: Invalid amount." |
Payment | 44 | "Refused by the issuer: Expired card." The customer must add a card. |
Payment | 45 | "Reservation failed, reason unknown." Most common: The customer has not acted upon the payment. We can't know the reason for this. See Timeouts. |
Payment | 51 | "Cannot cancel an orderId that has already been captured." Cannot cancel, do a refund instead. |
Payment | 52 | "Cancellation failed, reason unknown." Cancel failed. |
Payment | 53 | "Cannot cancel an orderId that is not reserved." |
Payment | 61 | "The total capture amount exceeds the reserved amount. You cannot capture a higher amount than the user has accepted. Check the payment details". This is in rare cases caused by rounding errors on the merchant's side. Check the payment details. |
Payment | 62 | "The amount you tried to capture is not reserved. The user must accept the payment before capture can be done." |
Payment | 63 | "Capture failed an unknown reason. Retrieve the payment details to see the full details." Use payment details to see the exact status. |
Payment | 71 | "Cannot refund a higher amount than the captured amount." This is in rare cases caused by rounding errors on the merchant's side. |
Payment | 72 | "Cannot refund a reserved order. The orderId can be canceled instead." Cancel instead. |
Payment | 73 | "Cannot refund a canceled order." |
Payment | 74 | "Refund failed during debit from the merchant's account." |
Payment | 93 | Captured amount must be the same in an idempotent retry. The same Idempotency-Key can't be used with different request payloads. |
Payment | 95 | "Payments can only be refunded up to 365 days after reservation. See the FAQ." or "Direct capture is not allowed. See the Checkout documentation." See Reserve and capture. |
Payment | 98 | "Payments can only be captured up to 180 days after reservation. See the FAQ." Payments can only be captured up to 180 days after reservation. See Reserve and capture. |
Payment | 1082 | This person is not BankID verified. This only applies for test users. |
VippsError | 91 | "The transaction is not allowed." Typically shown when attempting to capture a cancelled order. |
VippsError | 92 | "The transaction has already been processed." |
VippsError | 93 | "The capture request must be identical to the previous request(s) in an idempotent retry." or "The refund request must be identical to the previous request(s) in an idempotent retry." |
VippsError | 94 | Order locked and is already processing. This can occur for a short period of time if a bank has problems, and Vipps needs to wait and/or clean up. Retry the same request later, with the same idempotency key. |
VippsError | 98 | "Too many concurrent requests. See the FAQ." Used only to prevent obviously incorrect API use. See Rate limiting. |
VippsError | 99 | "Internal error. In some cases, this is caused by an incorrect API request. Please check the request." In practice this is always due to a combination of a bad request from the merchant and inadequate validation at our end. See Why do I get HTTP 500 Internal Server Error?. |
user | 81 | "The phone number is either incorrectly formatted (see the API specification), is not a Vipps user, or the user cannot pay businesses. Vipps cannot give more details." We can't give all the details, as we can't reveal if the user is blocked, is too young to pay businesses, etc. |
user | 82 | "The user's app version is not supported." The user must upgrade the app. |
Merchant | 31 | "The merchant is blocked. The merchant can contact customer service for details." We can't reveal the details. See Why do I get Merchant unavailable, deleted, deactivated or not allowed to make payments . |
Merchant | 32 | "The receiving limit of merchant is exceeded." The merchant has received more money than allowed. The merchant can contact customer service for details. |
Merchant | 33 | "The merchant's payment request limit is exceeded." The merchant has requested more money than allowed. Can contact customer service for details. |
Merchant | 34 | "Duplicate orderId. The orderId must be unique for each MSN. It has already been used for this MSN." The orderId has already been used for another payment for this MSN. The orderId must be unique for the MSN. Follow the orderId recommendations. |
Merchant | 35 | "The orderId 'acme-shop-123-order123abc' does not exist for MSN 654321." Follow the orderId recommendations. |
Merchant | 36 | "The merchant's agreement has not been signed." The merchant can contact customer service for details. |
Merchant | 37 | "The merchant and/or sales unit is unavailable, deleted, deactivated or blocked for payments." We can't reveal the details. See Why do I get Merchant unavailable, deleted, deactivated or not allowed to make payments |
Merchant | 38 | "The sales unit is not allowed to skip the landing page. See the FAQ." See the landing page. |
Merchant | 39 | "The sales unit is not allowed to initiate long-living payments." |
Merchant | 51 | "The Nin scope is not allowed." See who can get access. |
Merchant | 97 | "The sales unit is not allowed to perform payments. See the FAQ." Typically shown for a merchant that has only applied for Login API, and has not been through the required compliance checks for making payments. See Why do I get "Merchant Not Allowed for Ecommerce Payment". |
InvalidRequest | - | The field name will be the error code. Contains a description about what exactly the field error is. |
See also the ePayment OpenAPI specification.
Rate limiting
We have added rate limiting to our APIs (HTTP 429 Too Many Requests) to prevent fraudulent and wrongful behavior, and to increase the stability and security of our APIs. The limits should not affect normal behavior, but please contact us if you notice any unexpected behavior.
The "Key" column specifies what we consider to be the unique identifier, and what we "use to count". The limits are of course not total limits.
API | Limit | Key | Explanation |
---|---|---|---|
Initiate | 2 per minute | orderId + MSN | Two calls per minute for each unique orderId |
Cancel | 5 per minute | orderId + MSN | Five calls per minute for each unique orderId |
Capture | 5 per minute | orderId + MSN | Five calls per minute for each unique orderId |
Refund | 5 per minute | orderId + MSN | Five calls per minute for each unique orderId |
120 per minute | orderId + subscription key | 120 calls per minute for each unique orderId | |
Details | 120 per minute | orderId + subscription key | 120 calls per minute for each unique orderId |
Please note: The "Key" column is important. The above means that we allow two
Initiate
calls per minute per unique orderId for that MSN. This
is to prevent too many initiate calls for the same payment. The overall limit
for number of different payments is far higher than 2. The same goes for
Capture:
You can make five capture calls per minute for
one unique orderId
, and the limit for capture calls for different orderId
values
is far higher.
Partner keys
In addition to the normal authentication, we offer partner keys which let a partner make API calls on behalf of a merchant.
See: Partner keys.
Idempotency
In a capture request, the merchant may also use the X-Request-Id
header.
This header is an idempotency header ensuring that, if the merchant retries
a request with the same X-Request-Id
, the retried request will not make
additional changes.
See the Idempotency header for more details.
Example Request:
POST:/ecomm/v2/payments/acme-shop-123-order123abc/capture
{
"merchantInfo": {
"merchantSerialNumber": "123456"
},
"transaction": {
"amount": 20000,
"transactionText": "Socks on the way! Tracking code: abc-tracking-123"
}
}
Response:
{
"orderId": "acme-shop-123-order123abc",
"transactionInfo": {
"amount": 20000,
"timeStamp": "2018-11-14T15:22:46.736Z",
"transactionText": "Socks on the way! Tracking code: abc-tracking-123",
"status": "Captured",
"transactionId": "5001420058"
},
"transactionSummary": {
"capturedAmount": 20000,
"remainingAmountToCapture": 0,
"refundedAmount": 0,
"remainingAmountToRefund": 20000
}
}
Exception handling
The section below explains how Vipps handles different exception and errors. See also HTTP response codes and errors.
Connection timeout
Defining a socket timeout period is the common measure to protect server resources and is expected. However, the time needed to fulfil a service requests depends on several systems, which impose longer timeout period than usually required.
We recommend setting no less than 1 second socket connection timeout and 5 seconds socket read timeout while communicating with Vipps.
A good practice is, if/when the socket read timeout occurs, to call
GET:/ecomm/v2/payments/{orderId}/details
and check status of last transaction in transaction history prior
to executing the service call again.
Callback aborted or interrupted
If the communication is broken during payment process for some reason, either because of network problems, that the user abruptly closes the app or something else, and Vipps is not able to execute callback, the callback will not be retried.
In other words, if the merchant doesn’t receive any confirmation on payment
request call within callback time frame, merchant must call
GET:/ecomm/v2/payments/{orderId}/details
to get the response of payment request.
PSP connection issues
In cases of communication problems with Vipps' PSP, the response from Vipps will be an error (see HTTP response codes and errors).
The merchant should then call
GET:/ecomm/v2/payments/{orderId}/details
to check if the transaction request is processed before making a new call,
using same idempotency key (see Idempotency).
Clean-up strategies
Vipps recommends merchants implement a robust clean up strategy for all orders where the goods or services are not issued to the user.
An example case would be:
Bank X is having issues and transactions for their customers are slow (15+ seconds) for a significant period of time. As a result of this the user decides to close the Vipps app while the transaction is being processed, they do not then see the final result in the Vipps app. This transaction will eventually result in a successful reservation. The user then returns to the Merchants app, but as the entry was not via an expected app-switch from the Vipps app, state is not correctly resumed. The user attempts a second payment, which this time goes through in a timely manner, and upon app-switch back the user is issued their goods/services.
The user has now two reservations and only received goods/services once. It is the merchant's responsibility here to ensure the first order, for which no goods/services were issued, should be cancelled to remove the reservation from the customers account.
Vipps recommends polling
GET:/ecomm/v2/payments/{orderId}/details
until either a REJECT
, USER_CANCEL
, RESERVE
or SALE
status is received,
and then performing the appropriate action based on the status of product issuing.
The user should also be notified that the merchant has issued any product to
ensure they do not naturally retry the purchase. This includes using SMS/email
strategy if it is unclear that the user in on the merchant's website/app to see confirmation.
Recommendations for handling very high traffic
At peak traffic, like Black Friday, it is especially important to have a robust integration.
We strongly recommend using "reserve capture", and not "direct capture", so it is possible to cancel a payment without making a refund.
- Make sure you poll
GET:/ecomm/v2/payments/{orderId}/details
, and do not rely on the callback from Vipps, and also don't rely on the user reaching the callback URL. - Consider if you should cancel or complete the payment if the payment takes
much longer than normal, so much that the user may give up.
- If you sell a ticket: It may be good to always issue the ticket if the user has approved the payment, even if the processing of the payment takes much longer than normal and the user "gives up".
- If you sell food at a restaurant: If the payment takes so long that the user gives up and tries to order again: It may be smart to cancel the previous order, even though the user did approve the payment.
It is also important that the merchant's and/or partner's systems are able to handle the peak traffic.
See also:
App integration
Configure your app or website to trigger Vipps (sometimes called "app-switching").
This may be done in two ways:
- From a mobile or desktop browser. See Desktop flow
- From an iOS or Android native app
After the user has finished (or cancelled) the payment in the Vipps app, they should be returned to your app or website through the specified fallBack
URL.
When the user arrives back in your app or website, perform a call to the payment details endpoint to check the state of the transaction. While some state of the eCom operation can be derived from things like whether or not user returned successfully from the Vipps app, the most reliable approach to know the state of the payment is always to query the eCom API once the user arrive back in the merchant app/website.
App switching
We recommend that you always use the universal links/asset links (starting with https
) as they contain built-in logic to handle both desktop and mobile flow.
They are more secure than the deep link flow and provide a better user experience.
- On Apple, we recommend universal links.
- On Android, we recommend digital asset links.
Please see Knowledge base: App flow recommendations for more details.
Legacy information
This information is outdated. We recommend that you use universal links or asset links now for improved security.
On Apple, we recommend universal links. On Android, we recommend asset links, also called "App links". See Knowledge base: App flow recommendations.
- The merchant must pass the URL scheme of the app into the
fallBack
field in the initiate payment request. See App-switch on iOS and App-switch on Android for specifics. - The merchant app should open Vipps deeplink received from the initiate payment request.
- Once the operation in Vipps is completed, Vipps will redirect the user to the deeplink specified in the
fallBack
field. - The merchant app should query the payment details endpoint for updated status on the payment once user returns from Vipps.
Please note: Vipps will append a status at the end of the fallback URL. For example, if your fallBack
URL is merchantApp://result?myAppData
, Vipps
will append the status like: merchantApp://result?myAppData&status=301
or merchantApp://result?myAppData&status=100
. This status is deprecated, and should no longer be used. Query the payment details endpoint for latest status instead.
App-switch on iOS
Vipps on iOS requires a URL scheme in order to support app-switch.
See the official Apple documentation: Defining a Custom URL Scheme for Your App
Switch from merchant app to Vipps
Below is sample code to open iOS Vipps application with deeplinkURL
.
NSString *url = deeplinkURL; // Use the deeplinkURL provided in the API response
if ([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:url]]) {
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:url]]; }
else {
// No Vipps app installed: Open app store page.
// Once user installs Vipps, calling app needs to initiate deeplinking again in order to get the callback
[[UIApplication sharedApplication] openURL:[NSURL URLWithString: @"https://itunes.apple.com/no/app/Vipps-by-dnb/id984380185"]];
}
Example of a deeplinkURL
:
vipps://?token=eyJraWQiOiJqd3RrZXkiLCJhbGciOiJSUzI1NiJ9.ey <snip>
Please note: For production it's vipps://
, but for our test environment it's vippsMT://
.
Redirect back to the merchant app from Vipps app
Once the operation in Vipps is completed, Vipps will open the fallback URL.
For app-to-app integration, merchant app needs to be registered for a URL scheme
and pass the URL scheme in fallBack
URL in the Vipps backend API.
The Vipps mobile application will use the URL to launch the merchant application.
App-switch on Android
Vipps is launched with a standard intent, using the URL returned from the eCom
API when the payment is created (e.g., "url": "vipps://?token=eyJraWQiOiJqd3RrZXki.."
).
Example of how to open Vipps:
package com.example.app
import android.app.Activity
import android.content.Intent
import android.content.pm.PackageManager
import android.net.Uri
class MyActivity : Activity() {
companion object {
const val vippsPackageName = "no.dnb.vipps"
const val vippsRequestCode: Int = TODO("insert your own custom identifier for tracking vipps app intents")
}
// use deeplinkUrl from ecom response payload
fun openVippsApp(deeplinkUrl: String) {
try {
val pm = applicationContext.packageManager
val packageInfo = pm.getPackageInfo(vippsPackageName, PackageManager.GET_ACTIVITIES)
val intent = Intent(Intent.ACTION_VIEW, Uri.parse(deeplinkUrl))
startActivityForResult(intent, vippsRequestCode)
} catch (e: PackageManager.NameNotFoundException) {
// No Vipps app installed! Open the Vipps page on Google Play
val playStoreUrl = "https://play.google.com/store/apps/details?id=$vippsPackageName"
val intent = Intent(Intent.ACTION_VIEW).setData(Uri.parse(playStoreUrl))
startActivity(intent)
}
}
}
Switching back to the merchant app from Vipps app
Once the user has paid (or cancelled), Vipps supports two ways to return to the merchant native app:
1: Let Vipps deeplink back into the merchant app using their URL scheme (e.g., merchantapp://). This is the default/suggested approach.
2: Just close Vipps, fall back to the merchant app, pick up the thread again there in onActivityResult()
.
In both cases, the merchant app should query the eCom API for updated status on the payment once user returns from Vipps.
Return to merchant app by actively deeplinking into it from Vipps
With this approach, the merchant app has to have its own URL scheme registered so Vipps can actively open the merchant app again after payment/cancellation.
In the example below, MainActivity
is the receiving activity and Vipps opens it once the payment is done.
To receive a call back from Vipps to an activity, a filter has to be set for that activity. In the merchant app, set a filter in the Manifest file:
<activity android:name=".MainActivity" android:label="@string/app_name" android:launchMode="singleInstance">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="sampleApps" />
</intent-filter>
</activity>
Please note: The scheme should be same specified in fallBack
URL sent to the eCom API when the payment is created.
The Vipps application will send the result to the merchant app by
starting a new activity with the fallBack
URL as a URL parameter in the intent.
The merchant app can make their receiving activity a singleInstance
to handle the response in same activity.
The receiving MainActivity
has to override the onNewIntent
method to handle
result send by Vipps:
override fun onNewIntent(intent: Intent) {
// Call the eCom API, check the status of the eCom payment
}
Redirect back to merchant app by simply closing Vipps
With this approach, the merchant app does not have to register/handle deeplink URLs.
In order to use this approach, when creating the payment in the merchant has to pass fallback attribute like this:
"fallBack": "INTENT"
(and only "INTENT", no parameters etc.)
This will cause Vipps to simply close after a successful or cancelled eCom payment, and fall back to the calling merchant app.
The merchant app activity that resumes again (after Vipps closes) has to override onActivityResult
method to pick up the thread again here. Example:
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent) {
// Call the eCom API, check the status of the eCom payment
}
Testing
To facilitate automated testing in
The Vipps Test Environment (MT)
the eCom API provides a "force approve" endpoint to avoid manual
payment confirmation in the Vipps app:
POST:/ecomm/v2/integration-test/payments/{orderId}/approve
The "force approve" endpoint allows developers to approve a payment through the Vipps eCom API without the use of Vipps. This is useful for automated testing. The endpoint is only available in our test environment.
Important: All test users must manually approve at least one payment in Vipps (using the app) before "force approve" can be used for that user. If this has not been done, you will get an error. This is because the user needs to be registered as "BankID verified" in the backend, and this happens automatically in the test environment when using Vipps (the app), but not with "force approve".
Please note: Vipps Hurtigkasse (express checkout) and skipLandingPage
is
not supported by the force approve endpoint.
See Knowledge base: Recommendations regarding handling redirects.