> **Description:** Comprehensive technical documentation for integrating with the PSP API, including authentication, endpoints, request/response formats, error handling, and best practices for processing Vipps payments.

# Vipps PSP API guide

**End of life**

This API doesn't have any set end of life yet, but is receiving critical maintenance only. Long term support for PSPs will be served by the [ePayment API](https://developer.vippsmobilepay.com/docs/APIs/psp-epayment-api/README.md). No new integrations to this API will be approved.

API version: 3.0

The PSP API provides tokens that a Payment Service Provider (PSP) can use to charge a Vipps user's card.
Essentially, it functions as a "card token lookup service."
The PSP finalizes the payment and then informs Vipps of the transaction's success or failure.

## Process overview

When a customer wants to pay with Vipps, they only need to provide their phone number.
Then you, as the PSP, [initiate a payment request](#initiate-payment) through the PSP API.

The user simply enters their Norwegian mobile number
and approves the payment in their Vipps app.

In the Vipps app, the user can select the payment card they wish to use for the purchase.
Vipps then gives the PSP a token for that card, so they can process the payment.

The PSP processes the payment using the card token received from Vipps,
and the PSP informs Vipps about the status of the payment.

Settlements for PSP integrations are handled by the PSP,
but you can use the PSP API to initiate PSP payments.

```mermaid
sequenceDiagram
    autonumber
    PSP ->> Vipps: Initiate payment
    Vipps ->> Vipps: Get user/card details
    Vipps ->> PSP: Card token
    PSP ->> PSP: Process payment using token
    PSP ->> Vipps: Update status
```

  PSP initiates the payment with Vipps.
  Vipps retrieves the user's card details.
  Vipps sends a card token to the PSP.
  PSP processes the payment using the token.
  PSP updates Vipps with the payment status.

The following user flow provides illustrations: [Payments online](https://developer.vippsmobilepay.com/docs/APIs/psp-api/how-it-works/vipps-psp-api-how-it-works-online.md)

## Prerequisites

### Payment tokenisation

All PSPs must be able to process network tokens.
See the
[EMV® Payment Tokenisation](https://www.emvco.com/emv-technologies/payment-tokenisation/)
for more information.

### Service endpoint

Once the Vipps user has confirmed the payment in the Vipps app,
Vipps shares the network token with you by posting to the service endpoint you provide.

For details, see:

* [`makePaymentUrl`](https://developer.vippsmobilepay.com/docs/APIs/psp-api/vipps-psp-api.md#makepaymenturl)
* [`POST:makePaymentUrl`](https://developer.vippsmobilepay.com/redocusaurus/psp-swagger-id.yaml)

### PSP API implementation checklist

See: [PSP API Checklist](https://developer.vippsmobilepay.com/docs/APIs/psp-api/vipps-psp-api-checklist.md).

## PSP payment sequence

The following diagram illustrates the PSP payment sequence in detail:

```mermaid
sequenceDiagram
    autonumber
    participant EndUser as End user
    participant Merchant
    participant PSPFrontend as PSP Frontend
    participant PSPBackend as PSP Backend
    participant VippsBackend as Vipps Backend
    participant VippsLandingPage as Vipps landing page
    participant VippsApp as Vipps app
    participant TSP
    participant Acquirer

    EndUser ->> Merchant: Initiate payment
    Merchant ->> PSPFrontend: Initiate payment
    PSPFrontend ->> PSPBackend: Initiate payment
    PSPBackend ->> VippsBackend: Initiate payment
    VippsBackend ->> PSPBackend: Initiate success
    PSPBackend ->> PSPFrontend: Initiate success
    PSPFrontend ->> EndUser: Redirect user
    EndUser ->> VippsLandingPage: Confirm number
    VippsLandingPage ->> VippsBackend: Confirm number
    VippsBackend ->> VippsApp: Push notification / Deeplinking
    VippsApp ->> EndUser: Pending payment
    EndUser ->> VippsApp: Confirm payment request
    VippsBackend ->> TSP: Fetch card details
    VippsBackend ->> PSPBackend: Make payment request, with card token
    PSPBackend ->> Acquirer: Process payment
    PSPBackend ->> VippsBackend: Payment result
    VippsBackend ->> VippsApp: Payment result
    VippsApp ->> EndUser: Show result
    VippsApp ->> PSPFrontend: Redirect end user
    PSPFrontend ->> Merchant: Redirect end user
    Merchant ->> EndUser: Show order confirmation
```

  End user initiates payment with the merchant.
  Merchant initiates payment with PSP Frontend.
  PSP Frontend initiates payment with PSP Backend.
  PSP Backend initiates payment with Vipps Backend.
  Vipps Backend returns initiate success to PSP Backend.
  PSP Backend returns initiate success to PSP Frontend.
  PSP Frontend redirects end user to the Vipps landing page.
  End user confirms their phone number on the Vipps landing page.
  Vipps landing page confirms number with Vipps Backend.
  Vipps Backend sends a push notification or deep link to the Vipps app.
  Vipps app shows the pending payment to the end user.
  End user confirms the payment request in the Vipps app.
  Vipps Backend fetches card details from TSP.
  Vipps Backend sends a make payment request with card token to PSP Backend.
  PSP Backend processes the payment with the Acquirer.
  PSP Backend sends the payment result to Vipps Backend.
  Vipps Backend sends the payment result to the Vipps app.
  Vipps app shows the result to the end user.
  Vipps app redirects end user to PSP Frontend.
  PSP Frontend redirects end user to the merchant.
  Merchant shows order confirmation to the end user.

**Important:** Some users may close Vipps immediately after seeing the payment confirmation
screen in the app, therefore not being "redirected" back to the merchant. Because of this,
it is important for the merchant and the PSP to *not* base their transaction logic on the
user reaching the `pspRedirectUrl`.

For example: Check for "reserved" status with the PSP's API (*not* Vipps' API),
then do "capture" when the goods have been shipped/delivered.
See [capture regulations](https://developer.vippsmobilepay.com/docs/knowledge-base/reserve-and-capture.md#capture-regulations).

**Please note:** Vipps does not have more information about the payment than what the PSP
has sent. See the FAQ:
[How can I get details for a payment?](https://developer.vippsmobilepay.com/docs/APIs/psp-api/vipps-psp-api-faq.md#how-can-i-get-details-for-a-payment)

## Payment operations

All Vipps API calls are authenticated with an access token and an API subscription key.
Details are found under:
[Request an access token](https://developer.vippsmobilepay.com/docs/APIs/access-token-api/standard-authentication.md#step-2-request-an-access-token).

We recommend using the standard Vipps HTTP headers for all requests.

See [HTTP headers](https://developer.vippsmobilepay.com/docs/knowledge-base/http-headers.md) for details.

### Initiate payment

When a user chooses Vipps as the payment method, a payment request is initiated
by the PSP to the Vipps API. Vipps creates the payment and returns a link that does the following:

* For users on a mobile device, the Vipps app is opened.
* For other users, the [Vipps landing page](https://developer.vippsmobilepay.com/docs/knowledge-base/landing-page.md)
  is opened in a browser. The user can then enter their phone number and continue in the Vipps app on their phone.

The user then confirms the payment in Vipps.

Annotated Vipps PSP app screenshots. Payment screen: labeled with logo, sales unit name, merchant serial number, company name, and order description/orderId/reference fields; shows amount with Pay button. Receipt: shows payment marked as Paid with date, fee, and total.

* *Merchant name* - The name of the store, app, or service. Note that in the Vipps MobilePay business portal, this is labelled *sales unit name*.
* *Company name* - The legal name of the business.
* *Merchant Serial Number* - Identifier for the merchant.
* *Payment description* - Set via the `paymentText` field in the payment initiation request.

Initiate a payment with:
[`POST:/psp/v3/psppayments/init/`](https://developer.vippsmobilepay.com/redocusaurus/psp-swagger-id.yaml). For example:

```bash
curl -X POST "https://apitest.vipps.no/psp/v3/psppayments/init" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR-ACCESS-TOKEN" \
-H "Ocp-Apim-Subscription-Key: YOUR-PSP-SUBSCRIPTION-KEY" \
-H "PSP-ID: YOUR-PSP-ID" \
-H "Merchant-Serial-Number: YOUR-MSN" \
-H "Vipps-System-Name: acme" \
-H "Vipps-System-Version: 3.1.2" \
-d '{
  "pspTransactionId": "7686f7788898767977",
  "merchantOrderId": "abcABC-12345",
  "amount": "49900",
  "currency": "NOK",
  "pspRedirectUrl": "https://example.com",
  "makePaymentUrl": "https://callback.psp.com/cardCallback/7686f7788898767977",
  "makePaymentToken": "abcABC-12345",
  "paymentText": "Pair of socks",
  "isApp": false,
  "skipLandingPage": false,
  "minimumUserAge": 25
}'
```

Example response:

```json
{
  "errorMessage": {
    "errorId": 82,
    "errorText": "Refused by Issuer"
  },
  "paymentInfo": {
    "pspTransactionId": "7686f7788898767977",
    "status": "FAIL"
  }
}
```

If the request is not valid, [errors](#errors) will be returned.

A push notification will be presented in the Vipps app on the user's phone.
When the user approves the payment, Vipps automatically reserves the payment
and provides confirmation of the successful payment.

The user should be redirected back to the specified `pspRedirectUrl` URL under a "best effort" policy.
On that page, show the order confirmation.

**NOTE**

We cannot guarantee that the user will be redirected back to the same browser or session,
or that they will at all be redirected back. User interaction can be unpredictable,
and the user may choose to fully close the app or browser.

### Receive the user's card token

When the payment is confirmed in the Vipps app,
Vipps will share the user's card token with you by posting to the
[`POST:makePaymentUrl`](https://developer.vippsmobilepay.com/redocusaurus/psp-swagger-id.yaml).

Vipps requires a `HTTP 200 OK` response and a response body with
`"paymentInfo.status": "OK"`
for the POST request to the `makePaymentUrl`.
Vipps then sets the payment's status to RESERVED.
If we don't receive the expected response, the payment's status will be `FAILED`.

### Process the payment

This step is done by you, the PSP, using the card token.

After receiving the card data, you can use the card token to process the payment through the acquirer.

Vipps is not involved in the actual payment, Vipps only provides the PSP with the card token.

### Update the status of the payment

Update the status of the payment by sending the
[`POST:/psp/v3/psppayments/updatestatus`](https://developer.vippsmobilepay.com/redocusaurus/psp-swagger-id.yaml) request.
For example:

```bash
curl -X POST https://apitest.vipps.no/psp/v3/psppayments/updateStatus \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR-ACCESS-TOKEN" \
-H "Ocp-Apim-Subscription-Key: YOUR-SUBSCRIPTION-KEY" \
-H "PSP-ID: YOUR-PSP-ID" \
-H "Vipps-System-Name: acme" \
-H "Vipps-System-Version: 3.1.2" \
-d '{
  "transactions": [
   {
      "pspTransactionId": "abcABC12345",
      "status": "CAPTURED",
      "amount": "49900",
      "currency": "NOK",
      "paymentText": "Transaction updated"
   }
  ]
}'
```

**INFO**

When updating the status, it's important to use the correct `pspTransactionId`.
Our endpoint only does basic input validation, and the response is `HTTP 200 OK` as long as the request is correctly formatted.
The payment is updated asynchronously.
If the `pspTransactionId` is incorrect, the status of the payment will not be updated.

### Get the payment details

To see the details about a transaction, send the
[`GET:/psp/v3/psppayments/{pspTransactionId}/details`](https://developer.vippsmobilepay.com/redocusaurus/psp-swagger-id.yaml)
request.

```bash
curl -X GET https://apitest.vipps.no/psp/v3/psppayments/{pspTransactionId}/details \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR-ACCESS-TOKEN" \
-H "Ocp-Apim-Subscription-Key: YOUR-SUBSCRIPTION-KEY" \
-H "PSP-ID: YOUR-PSP-ID" \
-H "Vipps-System-Name: acme" \
-H "Vipps-System-Version: 3.1.2" \
```

Example response:

```json
{
"pspTransactionId": "abcABC12345",
"merchantOrderId": "abcABC-12345",
"transactionSummary": {
  "capturedAmount": 49900,
  "remainingAmountToCapture": 0,
  "refundedAmount": 0,
  "remainingAmountToRefund": 49900
},
"transactionLogHistory": [
   {}
  ]
}
```

## API details

### Details about initiating the payment

#### Vipps landing page

If the payment was started from a mobile device, the Vipps app should automatically open,
but if the payment is initiated from a desktop, the Vipps landing page will open.

Screenshot: Annotated Vipps PSP landing page. A label indicates the Merchant (sales unit) name field. The page shows a phone number input field and a Next button.

* *Merchant name* - The name of the store, app, or service. Note that in the Vipps MobilePay business portal, this is labelled *sales unit name*.
* *Customer phone number* - This field can be prefilled through a payment API,
  or can be empty, allowing the customer to enter their own phone number.

These values for merchant name and company name are set when you create the merchant.
For an explanation of the values as applies to you as a PSP,
see the [PSP Merchant API guide](https://developer.vippsmobilepay.com/docs/APIs/psp-merchant-api/psp-merchant-api-guide.md).
For a general description, see [General info: landing page](https://developer.vippsmobilepay.com/docs/knowledge-base/landing-page.md).

##### Skip landing page

*Only available for whitelisted sales units.*

**Please note:** This feature has to be enabled by Vipps for eligible sales units. The sales units must be whitelisted by Vipps.
Skipping the landing page is typically used at physical points of sale where there is no display available.

For more details, see
[General info: Skip the landing page](https://developer.vippsmobilepay.com/docs/knowledge-base/landing-page.md#skip-landing-page).

##### Lock phone number on landing page

This can be done when the merchant has verified the customer's identity.
The PSP must support getting the "fixed" phone number from the merchant.

This measure aims to prevent users from sending payment requests to unauthorized recipients,
and it is especially useful for selling digital assets or other products susceptible to fraud, such as gift cards and top-ups.

#### Payment confirmation

After the payment initiation, Vipps sends a push notification or redirects the user to
the Vipps app. The user logs in, selects payment source, and confirms the payment.

#### makePaymentUrl

Once the Vipps user has confirmed the payment in the Vipps app, Vipps shares the network token
with the PSP by posting to the `makePaymentUrl`:
[`POST:makePaymentUrl`](https://developer.vippsmobilepay.com/redocusaurus/psp-swagger-id.yaml).

Vipps requires a `HTTP 200 OK` response
and a response body with `"paymentInfo.status": "OK"`
for the POST request to the `makePaymentUrl`.
Vipps then sets the payment's status to `RESERVED`.

If Vipps does not receive the expected response, the payment's status will be `FAILED`.

The process of using POST to the `makePaymentUrl` is synchronous, and while Vipps
is waiting for a response from the PSP, the user will see a "spinner" in the
Vipps app.

After the successful POST to the `makePaymentUrl`,
the PSP uses the card token to process the payment through the acquirer.
This is the PSP's responsibility.
Vipps is not involved in the actual payment, Vipps only provides the
PSP with the card token.
Vipps does not have any information about the actual payment at this point.

The PSP then sends Vipps an update on the status of the payment:
[`POST:/psp/v3/psppayments/updatestatus`](https://developer.vippsmobilepay.com/redocusaurus/psp-swagger-id.yaml)

It is important that the PSP sends this update, so the user can see the
correct status of the payment in Vipps.
Without a status update from the PSP, the user will see an incorrect status.

The Vipps user receives confirmation of the payment in Vipps, and
Vipps redirects the end user to the `redirectUrl` provided during payment initiation.

**Please note:**

* The normal
  [timeouts](https://developer.vippsmobilepay.com/docs/knowledge-base/timeouts.md)
  apply to the PSP API. If the user does not act on the payment request within 10 minutes,
  Vipps will make a POST request towards the `makePaymentUrl` with a status of `timeout`.
* The `makePaymentUrl` has a timeout of **15 seconds**.
  If no response is received within this period, Vipps will mark the transaction as `FAILED`.
  This is a known issue with the current API.
  Future improvements to address this issue are planned.
* Some users may close Vipps immediately after seeing the payment confirmation,
  therefore not being "redirected" back to the merchant. Because of this, it is important for the
  merchant and the PSP to *not* base their transaction logic on the user reaching the `pspRedirectUrl`.

#### isApp

See
[General info: App flow recommendations](https://developer.vippsmobilepay.com/docs/knowledge-base/app-flow.md#deep-links).

### EMVCo Token processing

In order to give the best possible payment experience, the PSP API uses
EMVCo token-based processing.

The solution requires the PSP to have support for EMVCo token processing.

The `makePaymentUrl` call to the PSP sends the network token
and cryptogram in the following format. This is referred to as the `makePayment` request.

```json
Authorization: makePaymentToken
{
  "pspTransactionId": "7686f7788898767977",
  "merchantSerialNumber": "123456",
  "paymentState": "ACCEPTED/TIMEOUT/USER_CANCEL",
  "paymentInstrument": "TOKEN",
  "binNumber": "492556",
  "networkToken": {
    "number": "12345678901234",
    "expiryMonth": "12",
    "cryptogram": "AAAAAAAAAAAAAAA=",
    "tokenType": "VISA",
    "expiryYear": "2026",
    "eci": "07"
  }
}
```

Where `networkToken` is the Network token of the card, up to 16-19 digits.

#### Scheme specific details

##### Visa

Visa tokens must be processed with the acquirer submitting the TAVV cryptogram
in field 126.8. The cryptogram received with the Network Token will contain the
information for Delegated Authentication (DA) and the SCA factors used.

The Visa Token Service will during detokenization populate a flag for DA in field
34 to issuers and the Vipps TRID in field 123 Usage 2 Tag 03. In this way,
Issuers recognize Vipps originated transactions and will not soft-decline for
DS step-up unless the issuing bank has opted out of the Visa D-SCA program.
The expected ECI value for VISA requests is ECI-07.

##### Mastercard

A MasterCard transaction should be processed as an eCom token in accordance with
the acquirers instructions from Mastercard. Mastercard adds the Token Requestor ID
(TRID) to the authorization message. It will always be available in DE48, SE33, SF6.

#### Token requestor IDs

For Visa/Mastercard, the Token Requestor ID (TRID) is an eleven-digit number.
It is added by the scheme in the processing of the payments.

#### 3DSecure and network tokens

In order to start a 3DS session, simply use the Network Token Number instead of
the regular PAN. The scheme Directory Server maps the Network Token to the
underlying PAN before it requests the challenge session from the Issuing Bank's ACS.
CVC is not required in order to perform the 3DS session with a network token.

Once the 3DS CAVV cryptogram is acquired from the 3DS session, both the CAVV and
the token cryptogram must be submitted in the authorization request in the fields
specified by the acquirer. This is necessary to perform a valid authorization.

#### Magic numbers for EMVCo tokens

It is not possible to add payment cards in the test app.
Any request to the PSP API will return a Visa Token. However, this can be changed
by setting the amount in the `init` request.

No matter what is selected in the app,
the token returned by the `MakePayment` request will be:

| Amount Value (minor currency unit) | Token Number | Expiry | Cryptogram |
| ----------------- | -------------------------- | ------ | ---------------------------- |
| 2200             | 5226603115488031           | 05/30  | AlhlvxmN2ZKuAAESNFZ4GoABFA== |
| 3100             | Emulates Card not eligible |        |                              |
| 3200             | 4111111111111111           | 03/30  | uxToh3Ep6gsR8AAkvZALN19Iz34= |
| 4200             | 4895370013193500           | 03/30  | AlhlvxmN2ZKuAAESNFZ4GoABFA== |
| 4300             | 5226603115488031           | 03/30  | AlhlvxmN2ZKuAAESNFZ4GoABFA== |
| 4400             | 4895370012792682           | 12/30  | AgAAAAAAAIR8CQrXSohbQAAAAAA= |
| 5100             | 4268270087302871           | 09/30  | AgAAAAAAAIR8CQrXSohbQAAAAAA= |
| 5200             | 5413330089010442           | 12/30  | AgAAAAAAAIR8CQrXSohbQAAAAAA= |
| 5300             | 4895370013193500           | 03/30  | /wAAAAwAUkMTObMAAAAAgS0AAAA== |
| All other amounts | 4895370013193500           | 05/30  | AlhlvxmN2ZKuAAESNFZ4GoABFA== |

For instance:

`"amount": 3100,` Will emulate a card that is not eligible.

### Status updates

To provide a consistent end user experience, it is important that Vipps is
notified of changes to the payment status when it is captured, cancelled, or refunded:
[`POST:/psp/v3/psppayments/updatestatus`](https://developer.vippsmobilepay.com/redocusaurus/psp-swagger-id.yaml)

Vipps also provides an endpoint allowing you to check the payment status:
[`GET:/psp/v3/psppayments/{pspTransactionId}/details`](https://developer.vippsmobilepay.com/redocusaurus/psp-swagger-id.yaml)

**Please note:** For single payments, you do not need to send an update for the
reservation, since that is handled by the synchronous response to the
`makePayment` call.
For customers upgrading from the PSP API v1: It is ok to call
[`POST:/psp/v3/psppayments/updatestatus`](https://developer.vippsmobilepay.com/redocusaurus/psp-swagger-id.yaml)
with the v3 API on payments done with the v1 API.

### Cancelling pending transactions

A user might return to the PSP's checkout without logging in to the Vipps App,
or they might abort the transaction in the Vipps App.
Vipps's recommendation is that the PSP then cancels the transaction in their
backend and returns an error code.

```json
| 85 | Response received too late |
```

See: [Error codes from Vipps](#error-codes-from-vipps).

A typical flow would be:

1. The user selects Vipps as payment method.
2. The user returns without completing in the app (no `makePaymentUrl` request has been received by the PSP).
3. The PSP cancels the payment on their end and restarts the checkout.
4. The user might end up going back to the Vipps app. If that happens and a `makePaymentUrl` request is sent,
   the PSP responds with error code 85.

Example request:

```json
Authorization: makePaymentToken
{
  "pspTransactionId": "7686f7788898767977",
  "merchantSerialNumber": "123456",
  "paymentState": "ACCEPTED/TIMEOUT/USER_CANCEL",
  "paymentInstrument": "TOKEN",
  "binNumber": "492556",
  "networkToken": {
    "number": "12345678901234",
    "expiryMonth": "12",
    "cryptogram": "AAAAAAAAAAAAAAA=",
    "tokenType": "VISA",
    "expiryYear": "2026",
    "eci": "07"
  }
}
```

Example response:

```json
{
  "errorMessage": {
    "errorId": 82,
    "errorText": "Refused by Issuer"
  },
  "paymentInfo": {
    "pspTransactionId": "7686f7788898767977",
    "status": "FAIL"
  }
}
```

### Idempotency

Many API requests to Vipps APIs can be retried without any side effects
by providing `Request-Id`(or `Idempotency-key`) in the header of the
request.

See
[Idempotency header](https://developer.vippsmobilepay.com/docs/knowledge-base/http-headers.md#idempotency)
for more details.

### PSD2 compliance and Strong Customer Authentication (SCA)

#### 3DSecure fallback

In case of a soft decline (when the issuer requires 3DS), the PSP must host a
3DSecure session and must provide the URL to Vipps.

```mermaid
sequenceDiagram
    autonumber
    participant App
    participant VippsBackend
    participant PSP
    participant PSP3DSservice

    App ->> VippsBackend: Approve
    VippsBackend ->> PSP: MakePaymentRequest pspId X
    PSP ->> PSP3DSservice: Prepare to host 3DS session
    PSP ->> VippsBackend: PSP3DSservice url
    VippsBackend ->> App: PSP3DSservice url
    App ->> App : Open url in Iframe
    App ->> PSP3DSservice : User completes 3DSecure
    PSP3DSservice ->> PSP: Share 3DS session data
    App ->> App : Intercepts Redirect
    App ->> VippsBackend: Authenticate

    Note right of App: Authenticate is the internal<br/>Vipps terminology for a<br/>3DS flow

    VippsBackend ->> PSP: MakePaymentRequest pspId X
    PSP ->> PSP : Process Payment with 3ds session data
    PSP -->> VippsBackend : Payment Result
    VippsBackend -->> App: Display result
```

  App sends approval to Vipps Backend.
  Vipps Backend sends MakePaymentRequest (pspId X) to PSP.
  PSP prepares to host a 3DS session with its 3DS service.
  PSP sends the 3DS service URL to Vipps Backend.
  Vipps Backend sends the 3DS service URL to the App.
  App opens the URL in an iframe.
  User completes the 3DSecure challenge in the PSP 3DS service.
  PSP 3DS service shares 3DS session data with PSP.
  App intercepts the redirect.
  App sends Authenticate request to Vipps Backend (internal term for the 3DS flow).
  Vipps Backend sends MakePaymentRequest (pspId X) to PSP.
  PSP processes payment using the 3DS session data.
  PSP returns the payment result to Vipps Backend.
  Vipps Backend displays the result to the App.

The format of the `MakePaymentRequest` response provided by the PSP in case of
a soft decline:

```json
{
  "errorMessage": {
    "errorId": 1036,
    "errorText": "Soft Decline"
  },
  "paymentInfo": {
    "pspTransactionId": "7686f7788898767977",
    "status": "SOFT_DECLINE",
    "url3dSecure": "https://psp.com/3ds/123123"
  }
}
```

The Vipps App will then open the URL in a web view, letting the user complete
the 3DSecure flow. The PSP must host and retrieve any necessary data
from the session. Once the session is completed, the PSP must finish with a
redirect according to the `Operations.url` object sent in the initial
`makePayment` request, whereupon the app will close the iframe. Vipps will
then resend the `makePayment` request.

For example, if a 3DSecure session succeeds, you should redirect to the
`Operations.url` with the operation `3dssuccess`.

```json
{
  "operations": [
    {
      "url": "https://pe.vipps.no/payments/v1/web/softdecline-callback?token=abcdefg",
      "operation": "3dssuccess"
    }
  ]
}
```

Note that the `token` query parameter is critical.

When Vipps sends the status in the response to the second `makePayment`
request, it should never be `SOFT_DECLINE`, only `FAIL` or `OK`.
Once the status is returned, it will be displayed to the user as normal in the app.

```json
Authorization: makePaymentToken
{
  "pspTransactionId": "7686f7788898767977",
  "merchantSerialNumber": "123456",
  "confirmed": "YES/TIMEOUT/CANCEL",
  "paymentInstrument": "TOKEN",
  "binNumber": "492556",
  "networkToken": {
    "number": "12345678901234",
    "expiryMonth": "12",
    "cryptogram": "AAAAAAAAAAAAAAA=",
    "tokenType": "VISA",
    "expiryYear": "2026",
    "eci": "07"
  }
}
```

### URL validation

All URLs in the eCom API are validated with the
[Apache Commons UrlValidator](https://commons.apache.org/proper/commons-validator/apidocs/org/apache/commons/validator/routines/UrlValidator.html).

If `isApp` is true, any `pspRedirectUrl` is not validated with Apache Commons UrlValidator,
as the app-switch URL may be something like `vipps://`, which is not a valid URL.

The endpoints required by Vipps must be publicly available.

URLs that start with `https://localhost` will be rejected. If you want to use
localhost as fallback, please use `http://127.0.0.1`.
It is not possible to use `https://localhost` or
`http://127.0.0.1` for the callback, as the Vipps backend would then call itself.

Here is a simple Java class suitable for testing URLs,
using the dummy URL `https://example.com/vipps/fallback-result-page/acme-shop-123-order123abc`:

```java
import org.apache.commons.validator.routines.UrlValidator;

public class UrlValidate {
 public static void main(String[] args) {
  UrlValidator urlValidator = new UrlValidator();

  if (urlValidator.isValid("https://example.com/vipps/fallback-result-page/acme-shop-123-order123abc")) {
   System.out.println("URL is valid");
  } else {
   System.out.println("URL is invalid");
  }
 }
}
```

### Recommendations regarding handling redirects

Since Vipps is a mobile entity, the amount of control Vipps has over the redirect
back to the merchant after the purchase is completed is limited.
A merchant must not assume that Vipps will redirect to the exact same session and
for example rely entirely on cookies in order to handle the redirect event.
For example, the redirect could happen to another browser.

Examples of some, but not all, factors outside Vipps' control.

* Configurations set by the OS itself, for example the default browser.
* User configurations of browsers.
* Users closing app immediately upon purchase.

Therefore, Vipps recommends having a stateless approach in the site that is supposed to be the end session.
An example would be a polling-based result handling from a value in the redirect URL.

For demonstration purposes, an example that should be handled is:

1. User starts in a web session in a Chrome Browser.
1. A Vipps purchase is started, a redirect URL is defined by the Merchant.
1. The user completes the purchase.
1. The Vipps app redirects the user.
1. The OS defaults to a Safari Browser for the redirect.
1. The merchant handles the redirect without the customer noticing any discrepancies from the browser switch.

## Errors

### Responses and error codes from Vipps

#### HTTP responses from Vipps

This API returns the following HTTP statuses in the responses:

| HTTP status        | Description                                            |
| ------------------ | ------------------------------------------------------ |
| `200 OK`           | Request successful                                     |
| `400 Bad Request`  | Invalid request, see the error for details             |
| `401 Unauthorized` | Invalid credentials                                    |
| `403 Forbidden`    | Authentication ok, but credentials lack authorization |
| `404 Not Found`    | The resource was not found                             |
| `500 Server Error` | An internal Vipps problem                              |

#### Error codes from Vipps

This API returns the following error codes:

| Error code       | Error message | Description |
| ---------------- | ------------- | ----------- |
| `21`             | Merchant not available or active | |
| `42`             | Invalid payment model type | |
| `44`             | PSP Transaction ID already exists | |
| `51`             | Invalid request | |
| `51`             | Invalid `pspRedirectUrl` | |
| `99`             | `OrderId` already exists | |
| `amount`         | amount.less.than.one | |
| `currency`       | transaction.currency.invalid | |
| `makePaymentUrl` | Invalid `makePaymentUrl` | |
| `121`            | Agreement not found | The agreement does not exist |
| `122`            | Agreement not active | The agreement has been deactivated via the Delete agreement endpoint |
| `123`            | Connected payment source not active for Agreement | The connected card is no longer active or valid |
| `124`            | No Network token available for this Agreement | The connected card does not have an active network token available |

### Error codes from the PSP

The PSP should return errors with the following `errorId` and `errorText` fields, when applicable:

| `errorId` | `errorText` | Description (should not be included in response) |
| --------- | ----------- | ------------------------------------------------ |
| 71      | Invalid request | The request received from Vipps failed validation. |
| 72      | Different texts | For errors that are not in this list. Please include text describing the error. |
| 81      | No such issuer | The PSP were unable to identify the card issuer. |
| 82      | Refused by Issuer | Generic response for cards that were refused by issuer, without the PSP knowing why. |
| 83      | Suspected fraud | Suspected fraud. |
| 84      | Exceeds withdrawal amount limit | The amount exceeds an amount limit. Could be per transaction limit, or for a period. |
| 85      | Response received too late | A third party didn't respond in time for the `makePayment` or [Cancelling pending transactions](#cancelling-pending-transactions). |
| 86      | Expired card | Expired card. |
| 87      | Invalid card number (no such number) | The card provided is invalid. |
| 88      | Merchant does not allow credit cards | If the PSP supports disallowing credit cards. |
| 89      | Insufficient funds | Insufficient funds. |
| 91      | Internal error | Unhandled or unknown exception. |
| 93      | Status from Vipps:CANCEL | Response to Vipps sending `CANCEL`. Caused by customer cancelling the payment from the Vipps App, or in the Vipps landing page. |
| 93      | Status from Vipps:TIMEOUT | Response to Vipps sending `TIMEOUT`. Caused by customer not acting on the payment. This will happen within 5-10 minutes of the customer not acting. Vipps immediately processes and sends the `TIMEOUT` notification to the PSP |
| 93      | Status from Vipps:NO | Response to Vipps sending `NO`. Something failed during payment approval. Often caused by failure to retrieve and send `networkToken`. |
| 94      | Unhandled soft decline | Response to a Soft Decline from the bank that could not be processed or forwarded to the Vipps App. |

## Differences from previous versions

### Differences from PSP API v2 to v3

The PSP API v3 adds functionality for network tokens and allows PSPs to use the API to
obtain tokens from Vipps, not the actual card details.

Additionally, `$.makePaymentRequest.confirmed` has been renamed to `$.makePaymentRequest.paymentState`.

Values for this enum have changed accordingly:

| Old Value | New Value   |
| --------- | ----------- |
| Yes       | ACCEPTED    |
| TIMEOUT   | TIMEOUT     |
| CANCEL    | USER_CANCEL |
| NO        | USER_CANCEL |

### Differences from PSP API v1 to v2

* Added support for redirection of user after payment completion in the Vipps app
* Added support for providing the `makePaymentUrl` in the initiate payment call
* Improved authorization of the `makePaymentUrl` call by adding the `Authorization` header value
* Improved and more consistent parameter names in the API

## Questions

* See the [API reference](https://developer.vippsmobilepay.com/redocusaurus/psp-swagger-id.yaml) for full endpoint details.
* See the [FAQ](https://developer.vippsmobilepay.com/docs/APIs/psp-api/vipps-psp-api-faq.md) for common questions.
* For other questions, contact your Partner Manager or email [psp@vippsmobilepay.com](mailto:psp@vippsmobilepay.com).

> **Full site overview:** For every page in this documentation, read [https://developer.vippsmobilepay.com/llms.txt](https://developer.vippsmobilepay.com/llms.txt).
