NAV
PHP C#

Introduction

The Paymentwindow is the easiest way to get a payment through for your order.

It simply requires a form that is submitted towards onpay.io containing the details of the payment to be made, after the customer has paid they are returned to an url selected by you.

Post form

<form method="post" action="https://onpay.io/window/v3/" accept-charset="UTF-8">
    <input type="hidden" name="onpay_gatewayid" value="20007895654">
    <input type="hidden" name="onpay_currency" value="DKK">
    <input type="hidden" name="onpay_amount" value="12000">
    <input type="hidden" name="onpay_reference" value="AF-847824">
    <input type="hidden" name="onpay_hmac_sha1" value="f31dc4b392c6a7a25815e3e2bc39bc0fe02cc5a7">
    <input type="hidden" name="onpay_accepturl" value="https://example.com/accept">
    <input type="submit" value="Start payment of 120.00 DKK">
</form>

The form should be rendered, and submitted in the cardholders browser, and submitted against https://onpay.io/window/v3/

Parameters

Below is a list of all parameters the window supports, any parameter not prefixed with onpay_ will be passed on to the different callbacks/redirects.

Parameter Value Description Example
onpay_gatewayid* [0-9]+ The unique gatewayid for your paymentgateway 20007895654
onpay_currency* [0-9]{3} or [A-Z]{3} The ISO4217 currency code, either 3 digit numeric or alpha code 1 DKK or 208
onpay_amount* [0-9]+ The amount for the order in minor units. Is required only when type is transaction 12000 For 120.00 DKK.
onpay_reference* [a-zA-Z0-9\-\.]{1,36} Has to be unique, your own internal reference, even tho both upper and lower case is accepted they are treated the same in the system AF-847824
onpay_hmac_sha1* [a-f0-9]+ A SHA1 HMAC of all parameteres ordered alphabetically and the shared secret set in the management panel. See here for more details on calculating the hash. a94a8fe5ccb19ba61c4c0873d391e987982fbbd3
onpay_accepturl* Valid URL Where to send the user after a successful reservation is made. https://example.com/accept
onpay_website* Valid URL URL to the website where the checkout process was started https://example.com/
onpay_type transaction or subscription Defaults to transaction. subscription is only supported by the following payment methods: card, applepay and googlepay transaction
onpay_method See Methods If none is provided, the user is presented with a choice of which method to use.
onpay_3dsecure forced If set to forced, then all creditcard transactions are required to run with 2-factor authentication if provided by the card brand.
onpay_language da, de, en, es, fo, fr, it, nl, no, pl or sv The language of the payment window. Defaults to English en
onpay_declineurl Valid URL Where to send the user in case payment failed, if this value is not set the accepturl will be used! https://example.com/decline
onpay_callbackurl Valid URL If set, onpay system will make a direct call to this URL to signal that a payment suceeded. See more here https://example.com/callback
onpay_design [a-zA-Z0-9 ]+ The name of the window design to use. Use if you have more than one design defined in the backend window1
onpay_expiration [0-9]+ Seconds that the payment will be available before expiring. Default is 1 day (86400 seconds). 4200
onpay_testmode [01] If set to 1 the window will run in testmode, provided that it has been enabled. It is only necessary to set this parameter if production mode is also enabled 1
onpay_info_* Additional info about the customer, see Info parameters
onpay_subscription_with_transaction [01] Set along with onpay_type=subscription and a valid value in onpay_amount(Which is then required). When set to 1, a transaction will be created from the subscription on completion, with the amount defined in onpay_amount. The value of onpay_amount must be more than 100. 1
onpay_cart_* Cart information, required on certain payment methods, see Cart parameters

Methods

The following methods are supported. When a specific method is sent to the payment window, the cardholder will be redirected to said method. If none is provided, the user is presented with a choice of which method to use.

Method Parameter Description Supports subscriptions
Anyday anyday Payment using Anyday. Only currency DKK allowed. No
Apple Pay applepay Payment using Apple Pay. Browser support required Yes
Credit card card Payment using credit cards. Yes
Google Pay googlepay Payment using Google Pay. Browser support required Yes
MobilePay Online mobilepay Payment using MobilePay Online. Currencies allowed: DKK NOK SEK GBP USD EUR. No
Swish swish Payment through Swish. Only currency SEK allowed. No
ViaBill viabill Payment using ViaBill. Currencies allowed: DKK EUR No
Vipps vipps Payment through Vipps. Only currency NOK allowed. No

Info parameters

Besides the payment specific parameters, it is mandated by the card-schemes that further details should be provided if they are available. This is used to conduct 3DSv2, the updated standard for cardholder authentication according to the rule set forth in PSD2.

The data is utilized by the card issuer to make a risk assessment on the transaction, and determine whether to do what is called a "frictionless flow". A frictionless flow, means that the cardholder will not be prompted to enter any data but the transaction will still be marked as validated with 3D-Secure.

Parameter Value Description Example
onpay_info_account_id \w{1,64} Account identifier, could be a customer number. ABC-455454
onpay_info_account_date_created date When the account was created at the merchant. 2020-02-15
onpay_info_account_date_change date When the account was last changed, this includes billing and shipping address. 2020-03-02
onpay_info_account_date_password_change date When the account last had its password changed. 2020-03-02
onpay_info_account_purchases [0-9]+ The number of completed purchases with this account in the last 6 months (excluding the current one). 3
onpay_info_account_attempts [0-9]+ The number of payment attempts on this account in the past 24 hours. 0
onpay_info_account_shipping_first_use_date date The date of when the shipping address was first used on this account. 2020-02-15
onpay_info_account_shipping_identical_name Y, N Indicates whether the account holder name matches the shipping details. Y
onpay_info_account_suspicious Y, N Indicates whether the merchant has experienced suspicious actitivy on the account previously (including fraud) N
onpay_info_account_attempts_day [0-9]+ Number of transactions attempted (successful or not) for this account, in the past 24 hours. 3
onpay_info_account_attempts_year [0-9]+ Number of transactions attempted (successful or not) for this account, in the past 365 days. 3
onpay_info_address_identical_shipping Y, N Indicates whether the billing and shipping address are the same, only relevant if actually shipping anything. Y
onpay_info_billing_address_city .{1,50} Billing address city Skanderborg
onpay_info_billing_address_country [0-9]{3} Billing address country code, in the numeric format from ISO-3166-1 208
onpay_info_billing_address_line1 .{1,50} First line of the address Højvangen 4
onpay_info_billing_address_line2 .{1,50} Second line of the address, if needed.
onpay_info_billing_address_line3 .{1,50} Third line of the address, if needed.
onpay_info_billing_address_postal_code \w{1,16} The postal code of the address. 8660
onpay_info_billing_address_state \w{1,3} The subdivision code of the address, according to ISO-3166-2 (Only the part after the country code, so US-NY becomes NY. Should only be used when relevant for the country. NY
onpay_info_shipping_address_city .{1,50} Shipping address city Skanderborg
onpay_info_shipping_address_country [0-9]{3} Shipping address country code, in the numeric format from ISO-3166-1 208
onpay_info_shipping_address_line1 .{1,50} First line of the address Højvangen 4
onpay_info_shipping_address_line2 .{1,50} Second line of the address, if needed.
onpay_info_shipping_address_line3 .{1,50} Third line of the address, if needed.
onpay_info_shipping_address_postal_code .{1,16} The postal code of the address. 8660
onpay_info_shipping_address_state .{1,3} The subdivision code of the address, according to ISO-3166-2 (Only the part after the country code, so US-NY becomes NY. Should only be used when relevant for the country. NY
onpay_info_name .{2,45} The name of the cardholder/customer Emil Pedersen
onpay_info_email .{1,254} The email address of the customer emil@example.org
onpay_info_phone_home_cc [0-9]{1,3} The country code part of the phone number 45
onpay_info_phone_home_number [0-9]{1,15} The actual phone number, without the country part. 37123456
onpay_info_phone_mobile_cc [0-9]{1,3} The country code part of the phone number 45
onpay_info_phone_mobile_number [0-9]{1,15} The actual phone number, without the country part. 37123456
onpay_info_phone_work_cc [0-9]{1,3} The country code part of the phone number 45
onpay_info_phone_work_number [0-9]{1,15} The actual phone number, without the country part. 37123456
onpay_info_delivery_email .{1,254} Only used for electronic delivery. emil@example.org
onpay_info_delivery_time_frame 01, 02, 03, 04 Indicates the delivery timeframe. 01 = Electronic, 02 = Same-day shipping, 03 = Overnight shipping, 04 = Two-day or more shipping 03
onpay_info_gift_card_amount [0-9]+ The total amount of all gift cards within the order, only major units. (DKK 123.45 is 123) 123
onpay_info_gift_card_count [0-9]+ The total quantity of gift cards within the order. 1
onpay_info_preorder Y, N Indicates if this order is a pre-order. A pre-order is an order for an item that has not yet been released to the market. N
onpay_info_preorder_date date For a pre-ordered purchase, the expected date that merchandise will be available 2020-04-01
onpay_info_reorder Y, N Indicates if this order is a re-order of a previous one N
onpay_info_shipping_method 01, 02, 03, 04, 05, 06, 07 The shipping method for the transaction, use the one that best describes the order. Physical goods takes precedence over digital, and then the most expensive if multiple shipping methods for same order. 01 = Ship to billing address, 02 = Ship to another verified address, 03 = Ship to other, 04 = "Ship to store" store address should be set in shipping address fields, 05 = Digital goods, 06 = Travel & event tickets, 07 = Other (digital services, electronic subscriptions, etc.) 01

Cart parameters

    <input type="text" name="onpay_cart_shipping_price" value="100">
    <input type="text" name="onpay_cart_shipping_tax" value="20">
    <input type="text" name="onpay_cart_shipping_discount" value="20">
    <input type="text" name="onpay_cart_handling_price" value="500">
    <input type="text" name="onpay_cart_handling_tax" value="100">
    <input type="text" name="onpay_cart_discount" value="50">
    <input type="text" name="onpay_cart_items[0][name]" value="Item1 name">
    <input type="text" name="onpay_cart_items[0][description]" value="Long description">
    <input type="text" name="onpay_cart_items[0][sku]" value="SKU">
    <input type="text" name="onpay_cart_items[0][price]" value="500">
    <input type="text" name="onpay_cart_items[0][tax]" value="100">
    <input type="text" name="onpay_cart_items[0][quantity]" value="5">
    <input type="text" name="onpay_cart_items[1][name]" value="Item2 name">
    <input type="text" name="onpay_cart_items[1][price]" value="500">
    <input type="text" name="onpay_cart_items[1][tax]" value="100">
    <input type="text" name="onpay_cart_items[1][quantity]" value="1">

Cart information can be provided, and on some methods it is mandated.

Recommendation is to always send the data when available, to ensure future demands from payment methods can be easily met.

Parameter Value Description Example
onpay_cart_shipping_price [0-9]+ The shipping price in minor units, including any taxes but before discount. 500
onpay_cart_shipping_tax [0-9]+ The tax on the shipping in minor units. 500
onpay_cart_shipping_discount [0-9]+ Any discount that should be subtracted from the shipping_price in minor units. 500
onpay_cart_handling_price [0-9]+ Handling price in minor units, includes all handling related fees 500
onpay_cart_handling_tax [0-9]+ The tax on the handling. 500
onpay_cart_discount [0-9]+ The discount for the order, in minor units. Will be subtracted from the total before matching with onpay_amount 0 or 5000
onpay_cart_items[0] array of objects An array of the different items in the cart, the number in the square bracket should be updated for each item. See example to the right. If more than 20 items, merge the 20th item together with the excess items, so there is never send more than 20 items.
onpay_cart_items[0][name]* .{1,127} Item name Item 1
onpay_cart_items[0][price]* [0-9]+ The per item price in minor units, including taxes. 100
onpay_cart_items[0][tax]* [0-9]+ The per item tax in minor units. 20
onpay_cart_items[0][quantity]* [0-9]+ The quantity of items 1
onpay_cart_items[0][description] .{1,127} Item description Longer description
onpay_cart_items[0][sku] .{1,127} SKU of the item AB47871

Callbacks/Redirects

All called url's will contain these parameters as URL query parameters, any system set to receive these URL's should gracefully handle additional parameters prefixed with onpay_.

Name Type Description Present
onpay_uuid string Unique identifier for the transaction/subscription Always
onpay_number number The transaction or subscription number Always
onpay_reference string The provided internal reference Always
onpay_amount number The amount for the transaction, in minor units Transactions only
onpay_currency string The ISO4217 numeric currency code Always
onpay_hmac_sha1 string A SHA1 HMAC, see here for more details on calculating the hash. Present on accepturl & callbackurl, never on decline. Conditional
onpay_method string The payment method used to complete the payment Always
onpay_errorcode string If payment succeeded the errorcode will be "0", in all other cases will contain an error code Always
onpay_3dsecure number Will be set to 1, if the payment was done with 3DSecure Conditional
onpay_testmode number Will be set to 1, if the payment was done in test mode Conditional
onpay_cardmask string Will contain the cardmask if a card payment was done, example 445566XXXXXX1234 Conditional
onpay_cardtype string Will contain the type of card used, if a card payment was done Conditional
onpay_cardcountry number Will contain the country code of the card ISO-3166-1, if a card payment was done. Conditional
onpay_acquirercode string On declines this parameter will contain the acquirer specific error code. Conditional
onpay_uuid_transaction string Unique identifier for transaction created from subscription Conditional
onpay_number_transaction number Number for transaction created from subscription Conditional

Accept url

Upon successful completion of the payment authorization, the cardholder will be redirected to this URL.

We recommend always checking the onpay_hmac_sha1 value, to avoid any tampering.

Decline url

If the cardholder fails to complete the payment authorization, they will be redirected to this URL.

Callback url

The system will do an out of band asynchronous call to this url, containing the same parameters as the accept url.

Be aware that callbacks are executed from a simple HTTP client, which is unable to render javascript or load any images.

Only HTTP and HTTPS url's are accepted (on standard ports 80 & 443), if using HTTPS which is highly recommended a valid certificate chain has to be present.

If delivering the callback URL fails, OnPay will retry sending the callback at the following intervals:

If the callback is not delivered successfully after 24 hours no more attempts will be made to deliver the callback.

SHA1 HMAC calculation

<?php
$secret = 'e88ebc73104651e3c8ee9af666c19b0626c9ecacd7f8f857e3633e355776baad92e67b7faf9b87744f8c6ce4303978ed65b4165f29534118c882c0fd95f52d0c';

function calculateSecret(array $params, $secret) {
    // Step 1, grab the onpay_* params and order them alphabetically
    $toHashArray = [];
    foreach ($params as $key => $value) {
        if (0 === strpos($key, 'onpay_') && 'onpay_hmac_sha1' !== $key) {
            $toHashArray[$key] = $value;
        }
    }

    ksort($toHashArray);

    // Step 2, convert to a query string, and lower case
    $queryString = strtolower(http_build_query($toHashArray));
    // Output: onpay_accepturl=https%3a%2f%2fexample.com%2faccept&onpay_amount=12000&onpay_currency=dkk&onpay_gatewayid=20007895654&onpay_reference=af-847824

    // Step 3 calculate the SHA1 HMAC
    $hmac = hash_hmac('sha1', $queryString, $secret);

    return $hmac;
}

$formParams = [
    'onpay_gatewayid' => '20007895654',
    'onpay_currency' => 'DKK',
    'onpay_amount' => '12000',
    'onpay_reference' => 'AF-847824',
    'onpay_accepturl' => 'https://example.com/accept',
    'unrelated_param' => 'bla bla bla',
];

echo calculateSecret($formParams, $secret);
// Output: 16586ad0b3446b58df92446296cf821500ac57d8


var secret = "e88ebc73104651e3c8ee9af666c19b0626c9ecacd7f8f857e3633e355776baad92e67b7faf9b87744f8c6ce4303978ed65b4165f29534118c882c0fd95f52d0c";
var formParams = new Dictionary<string, string>
{
    {"onpay_gatewayid", "20007895654"},
    {"onpay_currency", "DKK"},
    {"onpay_amount", "12000"},
    {"onpay_reference", "AF-847824"},
    {"onpay_accepturl", "https://example.com/accept"},
    {"unrelated_param", "bla bla bla"}
};


// Step 1, grab the onpay_* params and order them alphabetically
var onpayParams = formParams
    .Where(x => x.Key.StartsWith("onpay_"))
    .Where(x => x.Key != "onpay_hmac_sha1")
    .OrderBy(x => x.Key)
    .ToArray();


// Step 2, convert to a query string, and lowercase the result
var queryString = string.Join("&", onpayParams.Select(x => HttpUtility.UrlEncode(x.Key) + "=" + HttpUtility.UrlEncode(x.Value))).ToLower();
// Output: onpay_accepturl=https%3a%2f%2fexample.com%2faccept&onpay_amount=12000&onpay_currency=dkk&onpay_gatewayid=20007895654&onpay_reference=af-847824

// Step 3 calculate the SHA1 HMAC
var hashString = "";
using (var sha1 = new HMACSHA1(Encoding.UTF8.GetBytes(secret)))
{
    var hash = sha1.ComputeHash(Encoding.UTF8.GetBytes(queryString));

    hashString = string.Join("", hash.Select(x => x.ToString("x2")));
    // Output: 16586ad0b3446b58df92446296cf821500ac57d8
}

The SHA1 is calculated as an HMAC hash, over all onpay_* parameters.

  1. Order the onpay_* parameters alphabetically (excluding the onpay_hmac_sha1)
  2. Convert the list of parameters to a query string, and lower case the result
  3. Calculate SHA1 HMAC against the query string 2

Calculation test tool


Multiple formats supported:
- Querystring format. ( onpay_gatewayid=123456&onpay_currency=208&onpay_amount=12000... )
- HTML form. ( <form><input type="text" />... )
- 1 field per line. Field and value separated by " : " or " "(space)