Skip to main content

Pay with Card Data

POST /payment

Prerequisites​

To use the "Pay with Card Data" feature, you need to have a JWE (JSON Web Encryption) key configured for your merchant account. Contact us at developers@straumur.is to obtain your JWE key and get started.

Attention

Handling encrypted card data comes with significant compliance requirements.

Merchants that choose this option must be PCI DSS certified and provide proof of certification to Straumur on a regular basis.

For most use cases, we recommend using Straumur Web Components, which are PCI-compliant by design and reduce the merchant’s compliance burden.

Test URL​

The payment request will be made to the following URL:

https://checkout-api.staging.straumur.is/api/v1/payment

This call will create a payment request with the provided encrypted card data.

Live environment

On live, use the same path on https://greidslugatt.straumur.is. Headers, request and response are identical. See Live environment.

Request Example​

{
"terminalIdentifier": "1adfe4a1b2c3",
"amount": 1000,
"currency": "ISK",
"reference": "9990QQAZ1221",
"shopperIp": "127.0.0.1",
"origin": "https://your-store.com/",
"channel": "Web",
"returnUrl": "https://your-store.com/additional_details",
"encryptedCardData": {
"encryptedValue": "eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMjU2R0NNIn0...",
"recurringProcessingModel": "CardOnFile",
"merchantShopperReference": "shopper_12345",
"brand": "visa"
}
}

Request Body Fields​

FieldTypeRequiredDescriptionExampleMin LengthMax Length
terminalIdentifierStringRequiredThe terminal identifier that uniquely identifies the terminal used for this request.

See Terminal Identifier for how to find it in the Merchant Portal and what to do if it's missing.
1adfe4a1b2c3
amountIntegerRequiredThe adjusted amount to be charged in minor units.127300--
currencyStringRequiredThe three-character ISO currency code.ISK33
referenceStringRequiredMerchant reference to uniquely identify a payment.9990QQAZ1221-200
shopperIpStringRequiredIP address of the shopper trying to make the payment.127.0.0.1-100
originStringRequiredLocation where the payment originates from. This must be in line with the channel provided.https://your-store.com/--
channelStringRequiredLocation where the payment originates from.

Accepted Values: Web, Android, IOS
Web--
returnUrlStringRequiredLocation where the shopper should be redirected if 3DS occurs. This must be in line with the channel provided.https://your-store.com/additional_details--
encryptedCardDataObjectRequiredThe encrypted card information for the payment.---

Encrypted Card Data Fields​

FieldRequiredDescriptionExample
encryptedValueRequiredThe JWE encrypted card data containing card number, expiry date and, if available, CVC. See When no CVC is available.eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMjU2R0NNIn0...
recurringProcessingModelOptionalThe type of transaction that will be processed with this encrypted card data. This field must be set if merchantShopperReference is used.CardOnFile
merchantShopperReferenceOptionalYour unique reference for the shopper to enable future recurring payments or card-on-file transactions. This field must be set if recurringProcessingModel is used.shopper_12345
brandConditionalThe card brand the shopper selected for the payment. Required when the encrypted card is co-badged and your account supports more than one of the identified brands.visa

Supported RecurringProcessingModel Values​

ValueDescription
CardOnFileCard details are stored for one-click purchases, omnichannel journeys, or subscriptions with non-fixed schedules.
SubscriptionTransactions for fixed or variable amounts following a fixed schedule.
UnscheduledCardOnFileUnscheduled transactions using stored card details, such as automatic top-ups based on predefined conditions.

Co-badged cards​

A co-badged (dual-brand) card carries two card scheme brands on the same plastic — for example, a Visa/Mastercard or a Visa/Maestro card. When you process a co-badged card via encrypted card data, you must let the cardholder choose which brand the payment should be routed through and pass that selection in the brand field.

EU compliance

For co-badged cards issued in the European Economic Area (EEA), EU Regulation 2015/751 (Article 8) requires that the cardholder is offered the choice of which brand to pay with whenever you support more than one brand on the card. The selected brand must be honoured by the acquirer.

Accepted values​

The brand value must match one of the brands returned by a BIN lookup for the card. Common values:

ValueBrand
visaVisa
mcMastercard
amexAmerican Express
maestroMaestro

When to send brand​

  • Required when the BIN lookup identifies the card as co-badged and your account supports more than one of the identified brands.
  • Optional and ignored when the card carries a single brand or you only support one of the available brands — omit the field and the acquirer will route through the only supported brand.

To detect whether a card is co-badged before sending the payment request, perform a BIN lookup against the first 6+ digits of the PAN and compare the returned brands against your accepted brand list.

External 3D Secure​

If you would like to use external 3D Secure authentication, please see the External 3D Secure page.

Configuring Encrypted Card Data on Frontend​

To implement encrypted card data on your frontend, you'll need to encrypt the card details using your JWE key before sending them to the payment API.

Getting Your JWE Key (X.509 Certificate)​

Contact us at developers@straumur.is to obtain your JWE key for encrypting card data.

Implementation Demo​

  1. Install and import a third-party JavaScript JWT library. The following example demonstrates using JOSE (JSON Object Signing and Encryption)

  2. Generate a public key from your X.509 certificate.

const certificate = `-----BEGIN CERTIFICATE-----
MIIDdTCCAl2gAwIBAgIUFakeSerialNumber1234567890abcdef...
-----END CERTIFICATE-----`;

const rsaPublicKey = await jose.importX509(certificate, "RSA-OAEP-256");
  1. Prepare the card data object for encryption
const objectToEncrypt = JSON.stringify({
cvc: "737",
number: "4444 3333 2222 1111",
expiryMonth: "03",
expiryYear: "2030",
generationtime: new Date().toISOString(),
});
info

Maintain the exact property order and casing: cvc, number, expiryMonth, expiryYear, generationtime

info

If the CVC/CVV is not available, see When no CVC is available.

info

The generationtime field should be a string representing the current JavaScript date in ISO 8601 format.

  1. Encrypt the card information
const encryptedData = await new jose.CompactEncrypt(new TextEncoder().encode(objectToEncrypt))
.setProtectedHeader({ alg: "RSA-OAEP-256", enc: "A256GCM", version: "1" })
.encrypt(rsaPublicKey);
  1. Include the encrypted value in your payment request as shown in the request example.
{
...
"encryptedCardData": {
"encryptedValue": encryptedData;
}
}

When no CVC is available​

If the CVC/CVV is not available, send cvc as an empty string in the card data object before encrypting it.

const objectToEncrypt = JSON.stringify({
cvc: "",
number: "4444 3333 2222 1111",
expiryMonth: "03",
expiryYear: "2030",
generationtime: new Date().toISOString(),
});
warning

The payment will fail if cvc is null, or if it contains a number of digits other than 3 or 4.

Test Refusal Reason​

In staging environment you can simulate different refusal scenarios to verify how your integration handles them.

To simulate a specific refusal, you need to send an additional field in the request requestedTestAcquirerResponseCode for which the system will return the associated refusal reason.

{
"terminalIdentifier": "1adfe4a1b2c3",
"amount": 1000,
"currency": "ISK",
// ...
"requestedTestAcquirerResponseCode": "22"
}
requestedTestAcquirerResponseCodeRefusal reason (reason on the webhook)Result code
1—Authorised
2RefusedRefused
5Blocked CardRefused
6Expired CardRefused
8Invalid Card NumberRefused
9Issuer UnavailableRefused
113D Not AuthenticatedRefused
12Not enough balanceRefused
20FRAUDRefused
24CVC DeclinedRefused
0UnknownError
22FRAUD-CANCELLEDCancelled

Any value from 0 to 46 is accepted; the full list is in Adyen's test result codes.

Keep in mind, you can only test refusal reasons in the staging/test environment. Sending this field on live environment will result in an error.

Responses​

Possible Result Code Values​

Result CodeDescription
AuthorisedThe payment was successfully authorised.
RedirectShopperThe issuer requires the shopper to provide authentication. Redirect the shopper to complete the authentication.
CancelledThe payment was cancelled (by either the shopper or your own system) before processing was completed.
ErrorThere was an error when the payment was being processed.
RefusedThe payment was refused.

Example - Authorised / Cancelled / Error / Refused Response​

info

Status Authorised means that the transaction has gone through.

You will also receive a webhook regarding this transaction with additional details.

{
"checkoutReference": "fp3afbpdtsw3jw1br7lxi0lcd4gnfq6wxdrueeq2cwlks5vahj",
"payfacReference": "T3WJMB84TFCCJ875",
"reference": "9990QQAZ1221",
"resultCode": "Authorised", // Cancelled, Error, Refused
"action": null,
"responseDateTime": "2025-01-04T09:50:14.343503Z",
"responseIdentifier": "e3605f81-6b09-4ce1-83ad-5a8d49f3cd44"
}

Example - RedirectShopper Response​

info

Status RedirectShopper means that the transaction requires the shopper to complete a 3DS check.

Please redirect the shopper to the action.url with the mentioned action.method. The action response will contain a GET method and a simple redirect will suffice.

After the shopper completes the 3DS, they will be redirected to the provided returnUrl in the request.

If the returnUrl provided was https://your-store.com/additional_details, then the user would be redirected to https://your-store.com/additional_details?redirectResult=Ab02b4c0....

You will need to call the payment/details endpoint with the query parameters from 3DS result.

{
"checkoutReference": "fp3afbpdtsw3jw1br7lxi0lcd4gnfq6wxdrueeq2cwlks5vahj",
"payfacReference": null,
"reference": "9990QQAZ1221",
"resultCode": "RedirectShopper",
"action": {
"method": "GET",
"url": "https://3ds-website-redirect.com/..."
},
"responseDateTime": "2025-01-04T09:50:14.343503Z",
"responseIdentifier": "e3605f81-6b09-4ce1-83ad-5a8d49f3cd44"
}

Response Fields​

This table outlines the response fields with their corresponding types, descriptions and examples.

FieldTypeDescriptionExample
checkoutReferenceStringThe reference to uniquely identify the checkout session.faf984ad76db7b2dea3f7bab
payfacReferenceStringStraumur reference to uniquely identify a payment.T3WJMB84TFCCJ875
referenceStringMerchant reference to uniquely identify a payment.9990QQAZ1221
resultCodeStringThe status of the payment. Can be authorized or a redirect shopper instruction.Authorised
actionObjectContains information about the 3DS action you need to consume.
responseDateTimeStringThe date and time when the response was generated.2024-09-04T09:50:14.343503Z
responseIdentifierStringThe unique identifier for the response.7be7111c-2e8e-4cd4-a5ba-f15bdfd177c1

Action Fields​

FieldTypeDescriptionExample
methodstringSpecifies the HTTP method, for example GET or POST.GET
urlstringSpecifies the URL to redirect to.https://3ds-website-redirect.com/...

Error Response​

Our error responses are standardised. Please see Errors, including troubleshooting for Origin, Return URL, and Terminal Identifier errors.

You can also find a detailed overview of our HTTP Status Codes.