# Overview

The **xMoney Hosted Checkout** is the simplest and most secure way to accept payments on
your website. This solution redirects your customers to a secure payment page hosted by xMoney
to complete their transaction.

This solution is ideal for merchants who:

- **Are not PCI DSS compliant**: Since xMoney handles the collection and processing of sensitive
card data, your servers never touch or store credit card numbers. This significantly reduces your compliance burden.
- **Want to offload security risks**: By redirecting the customer to our secure environment, you offload the complexity of securing sensitive payment data to xMoney.
- **Need a quick integration**: Requires minimal coding compared to custom integrations.


Once the payment is complete, the customer is redirected back to your store, and xMoney notifies your system of the transaction status.

## Checkout initialization

To initiate the xMoney checkout and redirect your customer for payment, you need to create an HTML form with two essential parameters: `jsonRequest` and `checksum`.

* **`jsonRequest`:** A JSON object containing all transaction details, base64 encoded.
* **`checksum`:** An alphanumeric sequence (base64 encoded) that verifies the JSON's integrity, preventing tampering.


Here's an example of a JSON object containing transaction details:


```json
{
  "siteId": 1,
  "customer": {
    "identifier": "your-unique-customer-id",
    "firstName": "John",
    "lastName": "Doe",
    "country": "RO",
    "city": "Bucharest",
    "email": "john.doe@test.com"
  },
  "order": {
    "orderId": "your-unique-order-id",
    "description": "Order Description",
    "type": "purchase",
    "amount": 2194.98,
    "currency": "RON"
  },
  "cardTransactionMode": "authAndCapture",
  "backUrl": "https://myshop.com/payment-back-url"
}
```

To calculate the `checksum` and `jsonRequest`, you will need to base64 encode the json, and calculate the hmac using your **Private Key**.

Here are some examples of how to calculate the base64 encoded json and checksum.

NodeJS

```javascript
const crypto = require('crypto');

function getBase64JsonRequest(orderData) {
    const jsonText = JSON.stringify(orderData);
    return Buffer.from(jsonText).toString('base64');
}

function getBase64Checksum(orderData, secretKey) {
    const hmacSha512 = crypto.createHmac('sha512', secretKey);
    hmacSha512.update(JSON.stringify(orderData));
    return hmacSha512.digest('base64');
}

// Sample order data
const orderData = {
    "siteId": 1,
    "customer": {
        "identifier": "your-unique-customer-id",
        "firstName": "John",
        "lastName": "Doe",
        "country": "RO",
        "city": "Bucharest",
        "email": "john.doe@test.com"
    },
    "order": {
        "orderId": "your-unique-order-id",
        "description": "Order Description",
        "type": "purchase",
        "amount": 2194.98,
        "currency": "RON"
    },
    "cardTransactionMode": "authAndCapture",
    "backUrl": "https://myshop.com/payment-back-url"
};

const secretKey = "your-private-key";

const base64JsonRequest = getBase64JsonRequest(orderData);
const base64Checksum = getBase64Checksum(orderData, secretKey);
```

PHP

```PHP
<?php

function getBase64JsonRequest(array $orderData) {
    return base64_encode(json_encode($orderData));
}

function getBase64Checksum(array $orderData, $secretKey) {
    $hmacSha512 = hash_hmac('sha512', json_encode($orderData), $secretKey, true);
    return base64_encode($hmacSha512);
}

// Sample order data
$orderData = [
    "siteId" => 1,
    "customer" => [
        "identifier" => "your-unique-customer-id",
        "firstName" => "John",
        "lastName" => "Doe",
        "country" => "RO",
        "city" => "Bucharest",
        "email" => "john.doe@test.com"
    ],
    "order" => [
        "orderId" => "your-unique-order-id",
        "description" => "Order Description",
        "type" => "purchase",
        "amount" => 2194.98,
        "currency" => "RON"
    ],
    "cardTransactionMode" => "authAndCapture",
    "backUrl" => "https://myshop.com/payment-back-url"
];

$secretKey = "your-private-key";

$base64JsonRequest = getBase64JsonRequest($orderData);
$base64Checksum = getBase64Checksum($orderData, $secretKey);
```

Once you have the `base64JsonRequest` and `base64Checksum`, generate an HTML form. You have two options for how the customer will be redirected to the xMoney checkout page:

Pay Button

```html
<!-- if using production env replace action with https://secure.xmoney.com -->
<form action="https://secure-stage.xmoney.com" method="POST" accept-charset="UTF-8">
  <input type="hidden" name="jsonRequest" value="${base64JsonRequest}">
  <input type="hidden" name="checksum" value="${base64Checksum}">
    
  <button type="submit">Pay Now</button>
</form>
```

**Description:** This form creates a "Pay Now" button. When the customer clicks this button, the form is submitted, and they are redirected to the xMoney secure checkout page.

Auto-submit

```html
<!-- if using production env replace action with https://secure.xmoney.com -->
<form name="myform1" action="https://secure-stage.xmoney.com" method="POST" accept-charset="UTF-8">
  <input type="hidden" name="jsonRequest" value="${base64JsonRequest}">
  <input type="hidden" name="checksum" value="${base64Checksum}">
</form>
<script>
  window.onload = function() {
    document.myform1.submit();
  };
</script>
```

**Description:** This form automatically submits itself using JavaScript upon page load. The customer is immediately redirected to the xMoney secure checkout page without needing to click a button.

Upon redirection, the customer will be presented with the xMoney hosted checkout page, as illustrated below:

Checkout hosted page
## Checkout parameters

Here's a list of all the parameters you can use to configure our hosted checkout page.


```json
{
  "$ref": "#/components/schemas/order.schema",
  "components": {
    "schemas": {
      "order.schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "$id": "order.schema.json",
        "description": "xMoney order schema",
        "type": "object",
        "properties": {
          "siteId": {
            "description": "Unique identifier of your site profile. Mandatory if more than one site is configured.",
            "type": "integer"
          },
          "customer": {
            "type": "object",
            "properties": {
              "identifier": {
                "description": "External identifier for the customer.",
                "type": "string",
                "maxLength": 92,
                "pattern": "^[0-9a-z\\-_\\.@\\s]+$"
              },
              "email": {
                "description": "Customer's email address.",
                "type": "string",
                "format": "email",
                "maxLength": 150
              },
              "firstName": {
                "description": "Customer's first name.",
                "type": "string",
                "maxLength": 100
              },
              "lastName": {
                "description": "Customer's last name.",
                "type": "string",
                "maxLength": 100
              },
              "country": {
                "description": "A two-character [ISO 3166-1 alpha-2](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2) country code.",
                "type": "string",
                "example": "RO"
              },
              "state": {
                "description": "State using ISO 3166-2:US for US and ISO 3166-2:CA for CA.",
                "type": "string"
              },
              "city": {
                "description": "Customer's city of residence.",
                "type": "string",
                "maxLength": 100
              },
              "address": {
                "description": "Customer's street address.",
                "type": "string",
                "maxLength": 150
              },
              "zipCode": {
                "description": "Zip code. See [Postal code definition](https://en.wikipedia.org/wiki/Postal_code).",
                "type": "string",
                "maxLength": 100,
                "pattern": "^[0-9a-z\\s\\-]+$"
              },
              "phone": {
                "description": "Customer's phone number.",
                "type": "string",
                "maxLength": 16
              }
            },
            "required": [
              "identifier",
              "email"
            ]
          },
          "order": {
            "type": "object",
            "properties": {
              "orderId": {
                "description": "External order identifier",
                "type": "string",
                "maxLength": 32,
                "pattern": "^[A-Za-z0-9_\\-.]+$"
              },
              "type": {
                "description": "Type of the order. Possible values are:\n\n* `purchase`: One-off payment.\n\n* `recurring`: A recurring order that will be billed automatically based on a defined interval. When using this type, the `intervalType` and `intervalValue` parameters are required.\n\n* `managed`: Merchant-managed order; rebilling is initiated by the merchant on request.\n\n*.",
                "type": "string",
                "enum": [
                  "purchase",
                  "recurring",
                  "managed"
                ]
              },
              "amount": {
                "description": "A string containing an exact monetary amount in the given currency. If you would want to charge €100.00 then you should provide `100.00`.",
                "type": "number"
              },
              "currency": {
                "description": "A three-character [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217) currency code.",
                "type": "string",
                "enum": [
                  "USD",
                  "EUR",
                  "GBP",
                  "CHF",
                  "RON",
                  "ILS"
                ]
              },
              "description": {
                "description": "Description of the goods or services included in the order.",
                "type": "string"
              },
              "items": {
                "description": "An array of order items, each representing a product or service included in the order.",
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "item": {
                      "description": "The name of the item.",
                      "type": "string",
                      "maxLength": 512
                    },
                    "unitPrice": {
                      "description": "The unit price of the item.",
                      "type": "number"
                    },
                    "units": {
                      "description": "The number of units of the item being ordered. Must be greater than zero.",
                      "type": "number"
                    },
                    "type": {
                      "description": "The type of item. Indicates whether the item is a physical good or a digital product/service.",
                      "type": "string",
                      "enum": [
                        "physical",
                        "digital"
                      ]
                    },
                    "code": {
                      "description": "A unique code identifying the item.",
                      "type": "string",
                      "maxLength": 64
                    },
                    "vatPercent": {
                      "description": "The VAT percentage applicable to the item. Must be a non-negative number.",
                      "type": "number",
                      "minimum": 0
                    },
                    "itemDescription": {
                      "description": "A detailed description of the item.",
                      "type": "string",
                      "maxLength": 500
                    }
                  },
                  "required": [
                    "item",
                    "unitPrice",
                    "units",
                    "type",
                    "code",
                    "vatPercent",
                    "itemDescription"
                  ]
                },
                "minItems": 1
              },
              "intervalType": {
                "description": "The type of recurring interval.",
                "type": "string",
                "enum": [
                  "day",
                  "month"
                ]
              },
              "intervalValue": {
                "description": "The value of the recurring interval. For example, if `intervalType` is `month` and `intervalValue` is `3`, the order will recur every 3 months.",
                "type": "integer",
                "maximum": 365
              },
              "trialAmount": {
                "description": "The amount to be charged for the initial (trial) payment. This value is also used to validate and store the payment method.",
                "type": "number"
              },
              "firstBillDate": {
                "description": "Use `firstBillDate` to specify the initial billing date when it differs from the regular recurring interval (defined by `intervalValue`). This is often used for trials. If `firstBillDate` is used, `trialAmount` must be greater than 0. Use [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) date, time and timezone offset.",
                "type": "string",
                "format": "date-time"
              }
            },
            "required": [
              "orderId",
              "type",
              "amount",
              "currency"
            ]
          },
          "invoiceEmail": {
            "description": "The email address to which the invoice will be sent.",
            "type": "string",
            "format": "email",
            "maxLength": 150
          },
          "cardTransactionMode": {
            "description": "Specifies how the card transaction is processed.\n\n* `auth`: Authorizes the card but does not capture the funds immediately. This is useful for verifying card details and holding funds before completing the purchase. A subsequent capture operation is required to settle the payment.\n\n* `authAndCapture`: Authorizes and immediately captures the funds. This is the standard mode for most transactions where payment is collected at the time of purchase.",
            "type": "string",
            "enum": [
              "auth",
              "authAndCapture"
            ]
          },
          "cardId": {
            "description": "The ID of a stored card belonging to the current customer. If provided, the payment will be made using this card.",
            "type": "integer"
          },
          "backUrl": {
            "description": "URL to which the cardholder will be redirected after completing a 3D Secure or digital wallet payment.",
            "type": "string",
            "format": "uri"
          },
          "customData": {
            "description": "Custom data associated with the order. This data will be included in the IPN (Instant Payment Notification) callback, allowing you to pass and retrieve application-specific information related to the order.",
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "example": {
              "order_id": "12345",
              "customer_tier": "gold",
              "campaign_id": "summer2024"
            }
          }
        }
      }
    }
  }
}
```