Creating and managing payment requests

When working with payment requests use a MERCHANT access token.

Creating payment requests

The following example demonstrates the first step in receiving payments, creating a payment request.

Note, setting the "PaymentMethodTypes" field to "card,pisp", as shown below, gives the payer the choice of using either card or payment initiation services.

using System.Net.Http.Json;

const string baseUrl = "<<SANDBOX_URL>>paymentrequests";

// Payment requests use MERCHANT tokens (remember to keep these safe and secure).
var jwtToken = Environment.GetEnvironmentVariable("NOFRIXION_MERCHANT_TOKEN");

var client = new HttpClient();

client.DefaultRequestHeaders.Add("Accept", "application/json");
client.DefaultRequestHeaders.Add("Authorization", $"Bearer {jwtToken}");

var paymentRequest = new Dictionary<string, string>();
paymentRequest.Add("MerchantID", "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx");
paymentRequest.Add("Amount", "0.99");
paymentRequest.Add("Currency", "EUR");
paymentRequest.Add("CustomerID", "C202202024158");
paymentRequest.Add("OrderID", "Sample order");
// The methods below allow the purchaser to choose from those listed - BTC lightning payments coming soon!
paymentRequest.Add("PaymentMethodTypes", "card,pisp");
paymentRequest.Add("Description", "API Payment request");
// URLs to integrate with merchant's site (required for card payments)
paymentRequest.Add("BaseOriginUrl", "https://some.origin.url");
paymentRequest.Add("CallbackUrl", "https://some.callback.url");
// PISP specific fields
paymentRequest.Add("PispAccountID", "A120P0JR");
paymentRequest.Add("PispRecipientReference", "Recipient ref");
// Card specific fields
paymentRequest.Add("CardAuthorizeOnly", "true");
paymentRequest.Add("CardCreateToken", "false");
paymentRequest.Add("IgnoreAddressVerification", "true");
paymentRequest.Add("CardIgnoreCVN", "true");
paymentRequest.Add("SuccessWebHookUrl", "https://myserver.org");
// Shipping and billing address data can also be included in the payment request
// => see https://api-sandbox.nofrixion.com/swagger/index.html for a complete reference.

HttpContent postData = new FormUrlEncodedContent(paymentRequest);
try
{
    HttpResponseMessage response = await client.PostAsync(baseUrl, postData);
    if (response.IsSuccessStatusCode)
    {
        // "Created" on success
        Console.WriteLine(response.StatusCode);
        // JSON object with payment request details will be in the response body
        Console.WriteLine(await response.Content.ReadFromJsonAsync<PaymentRequest>());
    }
    else
    {
        // HTTP error codes will return a MoneyMoov API problem object
        Console.WriteLine(await response.Content.ReadFromJsonAsync<ApiProblem>());
    }
}
catch (Exception e)
{
    Console.WriteLine($"Error: {e.Message}");
}

// type definition for response data
record PaymentRequest(string id, string merchantID, decimal amount, string currency, string customerID,
                string orderID, string paymentMethodTypes, string description, string pispAccountID, string shippingFirstName,
                string shippingLastName, string shippingAddressLine1, string shippingAddressLine2, string shippingAddressCity,
                string shippingAddressCounty, string shippingAddressPostCode, string shippingAddressCountryCode,
                string shippingPhone, string shippingEmail, string baseOriginUrl, string callbackUrl, bool cardAuthorizeOnly,
                bool cardCreateToken, bool ignoreAddressVerification, bool cardIgnoreCVN, string pispRecipientReference);

record ApiProblem(string type, string title, int status, string detail);
// These modules allow the code to run on Node.js, they aren't required if running in a browser.
const fetch = require('cross-fetch');
const FormData = require('form-data');

// Remember, the JWT access token must be securely store - this example uses an environment variable
const jwtToken = process.env.NOFRIXION_MERCHANT_TOKEN;

const baseUrl = '<<SANDBOX_URL>>paymentrequests';

// Example form data
const form = new FormData();
form.append('MerchantID', 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx');
form.append('Amount', '0.99');
form.append('Currency', 'EUR');
form.append('CustomerID', 'C202202024158');
form.append('OrderID', 'Sample order');
form.append('PaymentMethodTypes', 'card,pisp'); // BTC lightning payments coming soon!
form.append('Description', 'API Payment request');
// URLs to integrate with merchant's site (required for card payments)
form.append('OriginUrl', 'https://some.origin.url');
form.append('CallbackUrl', 'https://some.callback.url');
// PISP specific fields
form.append('PispAccountID', 'A120P0JR');
form.append('PispRecipientReference', 'Recipient ref');
// Card specific fields
form.append('CardAuthorizeOnly', 'true');
form.append('CardCreateToken', 'false');
form.append('IgnoreAddressVerification', 'true');
form.append('CardIgnoreCVN', 'true');
// Shipping and billing address data can also be included in the payment request
// => see https://api-sandbox.nofrixion.com/swagger/index.html for a complete reference.

const options = {
    method: 'POST',
    headers: {
        Accept: 'application/json',
        Authorization: 'Bearer ' + jwtToken
    },
    body: form
};

fetch(baseUrl, options)
    .then(response => response.json())
    // the response JSON contains the newly created payment request details.
    .then(responseJson => console.log(responseJson))
    .catch(err => console.error(err));
# The 'requests' library for Python can be used to make calls to the MoneyMoov API in
# popular python frameworks such as Django and Flask.
import requests
import os

# Remember, the JWT access token must be securely stored ('os' module above allows storage in environment variable)
# ... and when dealing with payment requests, use a MERCHANT token!
jwtToken = os.environ['NOFRIXION_MERCHANT_TOKEN']

baseUrl = "<<SANDBOX_URL>>paymentrequests"

headers = {
    "Accept": "application/json",
    "Authorization": f"Bearer {jwtToken}"
}

paymentRequestData = {
    "MerchantID": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
    "Amount": "0.99",
    "Currency": "EUR",
    "CustomerID": "C202202024158",
    "OrderID": "Sample order",
    #The methods below allow the purchaser to choose from those listed - BTC lightning payments coming soon!
    "PaymentMethodTypes": "card,pisp",
    "Description": "API Payment request",
    #URLs to integrate with merchant's site (required for card payments)
    "OriginUrl": "https://some.origin.url",
    "CallbackUrl": "https://some.callback.url",
    #PISP specific fields
    "PispAccountID": "A120P0JR",
    "PispRecipientReference": "Recipient ref",
    #Card specific fields
    "CardAuthorizeOnly": "true",
    "CardCreateToken": "false",
    "IgnoreAddressVerification": "true",
    "CardIgnoreCVN": "true"
    #Shipping and billing address data can also be included in the payment request
    #=> see https://api-sandbox.nofrixion.com/swagger/index.html for a complete reference.
}

try:
    response = requests.request("POST", baseUrl, headers=headers, data=paymentRequestData)

    if response.ok:
        # On successful payment request creation, the API returns the payout object
        print(response.json())
    else:
        # If not OK, response contains MoneyMoov problem (https://docs.nofrixion.com/reference/error-messages)
        print(response.json())

except Exception as ex:
    print(ex)

Many optional fields such as the billing and shipping addresses were omitted from the examples above, for full details see the API reference on the PaymentRequests POST action.

Once you have collected the relevant payment information, the NoFrixion PayFrame provides a convenient way for customers to complete payment.

Viewing and updating payment requests

A payment request can be retrieved by specifying the payment request ID when using the paymentrequestss/{id} GET action.

using System.Net.Http.Json;

const string baseUrl = "<<SANDBOX_URL>>paymentrequests";

// Payment requests use MERCHANT tokens (remember to keep these safe and secure).
var jwtToken = Environment.GetEnvironmentVariable("NOFRIXION_MERCHANT_TOKEN");

var client = new HttpClient();

client.DefaultRequestHeaders.Add("Accept", "application/json");
client.DefaultRequestHeaders.Add("Authorization", $"Bearer {jwtToken}");

string paymentRequestID = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx";

try
{
    HttpResponseMessage response = await client.GetAsync($"{baseUrl}/{paymentRequestID}");
    if (response.IsSuccessStatusCode)
    {
        // returns a JSON object containing payment request details
        var paymentRequest = await response.Content.ReadFromJsonAsync<PaymentRequest>();
        Console.WriteLine(paymentRequest);
    }
    else
    {
        // HTTP error codes will return a MoneyMoov API problem object
        Console.WriteLine(await response.Content.ReadFromJsonAsync<ApiProblem>());
    }


}
catch (Exception e)
{
    Console.WriteLine($"Error: {e.Message}");
}

// type definition for response data
record PaymentRequest(string id, string merchantID, decimal amount, string currency, string customerID,
                string orderID, string paymentMethodTypes, string description, string pispAccountID, string shippingFirstName,
                string shippingLastName, string shippingAddressLine1, string shippingAddressLine2, string shippingAddressCity,
                string shippingAddressCounty, string shippingAddressPostCode, string shippingAddressCountryCode,
                string shippingPhone, string shippingEmail, string baseOriginUrl, string callbackUrl, bool cardAuthorizeOnly,
                bool cardCreateToken, bool ignoreAddressVerification, bool cardIgnoreCVN, string pispRecipientReference);

record ApiProblem(string type, string title, int status, string detail);
// These modules allow the code to run on Node.js, they aren't required if running in a browser.
const fetch = require('cross-fetch');

// Remember, the JWT access token must be securely store - this example uses an environment variable
const jwtToken = process.env.NOFRIXION_MERCHANT_TOKEN;

const baseUrl = '<<SANDBOX_URL>>paymentrequests';

const options = {
    method: 'GET',
    headers: {
        Accept: 'application/json',
        Authorization: 'Bearer ' + jwtToken
    }
};

var paymentRequestID = 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx';

fetch(`${baseUrl}/${paymentRequestID}`, options)
    .then(response => response.json())
    // the response JSON contains the payment request details.
    .then(responseJson => console.log(responseJson))
    .catch(err => console.error(err));
# The 'requests' library for Python can be used to make calls to the MoneyMoov API in
# popular python frameworks such as Django and Flask.
import requests
import os

# Remember, the JWT access token must be securely stored ('os' module above allows storage in environment variable)
# ... and when dealing with payment requests, use a MERCHANT token!
jwtToken = os.environ['NOFRIXION_MERCHANT_TOKEN']

baseUrl = "<<SANDBOX_URL>>paymentrequests"
paymentRequestID = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"

headers = {
    "Accept": "application/json",
    "Authorization": f"Bearer {jwtToken}"
}

try:
    response = requests.request("GET", f"{baseUrl}/{paymentRequestID}", headers=headers)

    if response.ok:
        #  If successful, the API returns the payment request object
        print(response.json())
    else:
        # If not OK, response contains MoneyMoov problem (https://docs.nofrixion.com/reference/error-messages)
        print(response.json())

except Exception as ex:
    print(ex)

Payment requests can be updated using the paymentrequests/{id} PUT action as follows:

using System.Net.Http.Json;

const string baseUrl = "<<SANDBOX_URL>>paymentrequests";

// Payment requests use MERCHANT tokens (remember to keep these safe and secure).
var jwtToken = Environment.GetEnvironmentVariable("NOFRIXION_MERCHANT_TOKEN");

var client = new HttpClient();

client.DefaultRequestHeaders.Add("Accept", "application/json");
client.DefaultRequestHeaders.Add("Authorization", $"Bearer {jwtToken}");

string paymentRequestID = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx";

var paymentRequest = new Dictionary<string, string>();
paymentRequest.Add("MerchantID", "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx");
paymentRequest.Add("Amount", "0.99");
paymentRequest.Add("Currency", "GBP");
paymentRequest.Add("CustomerID", "C202202024158");
paymentRequest.Add("OrderID", "Sample order");
paymentRequest.Add("PaymentMethodTypes", "card,pisp"); // BTC lightning payments coming soon!
paymentRequest.Add("Description", "Updated payment request.");
// URLs to integrate with merchant's site (required for card payments)
paymentRequest.Add("BaseOriginUrl", "https://some.origin.url");
paymentRequest.Add("CallbackUrl", "https://some.callback.url");
// PISP specific fields
paymentRequest.Add("PispAccountID", "A120P0JQ");
paymentRequest.Add("PispRecipientReference", "Recipient ref");
// Card specific fields
paymentRequest.Add("CardAuthorizeOnly", "true");
paymentRequest.Add("CardCreateToken", "false");
paymentRequest.Add("IgnoreAddressVerification", "true");
paymentRequest.Add("CardIgnoreCVN", "true");
// Shipping and billing address data can also be included in the payment request
// => see https://api-sandbox.nofrixion.com/swagger/index.html for a complete reference.

HttpContent postData = new FormUrlEncodedContent(paymentRequest);
try
{
    HttpResponseMessage response = await client.PutAsync($"{baseUrl}/{paymentRequestID}", postData);
    if (response.IsSuccessStatusCode)
    {
        // JSON object with payment request details will be in the response body
        Console.WriteLine(await response.Content.ReadFromJsonAsync<PaymentRequest>());
    }
    else
    {
        // HTTP error codes will return a MoneyMoov API problem object
        Console.WriteLine(await response.Content.ReadFromJsonAsync<ApiProblem>());
    }
}
catch (Exception e)
{
    Console.WriteLine($"Error: {e.Message}");
}

// type definition for response data
record PaymentRequest(string id, string merchantID, decimal amount, string currency, string customerID,
                string orderID, string paymentMethodTypes, string description, string pispAccountID, string shippingFirstName,
                string shippingLastName, string shippingAddressLine1, string shippingAddressLine2, string shippingAddressCity,
                string shippingAddressCounty, string shippingAddressPostCode, string shippingAddressCountryCode,
                string shippingPhone, string shippingEmail, string baseOriginUrl, string callbackUrl, bool cardAuthorizeOnly,
                bool cardCreateToken, bool ignoreAddressVerification, bool cardIgnoreCVN, string pispRecipientReference);

record ApiProblem(string type, string title, int status, string detail);
// These modules allow the code to run on Node.js, they aren't required if running in a browser.
const fetch = require('cross-fetch');
const FormData = require('form-data');

// Remember, the JWT access token must be securely store - this example uses an environment variable
const jwtToken = process.env.NOFRIXION_MERCHANT_TOKEN;

const baseUrl = '<<SANDBOX_URL>>paymentrequests';

// Example form data
const form = new FormData();
form.append('MerchantID', 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx');
form.append('Amount', '1.99');
form.append('Currency', 'EUR');
form.append('CustomerID', 'C202202024158');
form.append('OrderID', 'Sample order');
form.append('PaymentMethodTypes', 'card,pisp'); // BTC lightning payments coming soon!
form.append('Description', 'Updated payment request');
// URLs to integrate with merchant's site (required for card payments)
form.append('OriginUrl', 'https://some.origin.url');
form.append('CallbackUrl', 'https://some.callback.url');
// PISP specific fields
form.append('PispAccountID', 'A120P0JR');
form.append('PispRecipientReference', 'Recipient ref');
// Card specific fields
form.append('CardAuthorizeOnly', 'true');
form.append('CardCreateToken', 'false');
form.append('IgnoreAddressVerification', 'true');
form.append('CardIgnoreCVN', 'true');
// Shipping and billing address data can also be included in the payment request
// => see https://api-sandbox.nofrixion.com/swagger/index.html for a complete reference.

const options = {
    method: 'PUT',
    headers: {
        Accept: 'application/json',
        Authorization: 'Bearer ' + jwtToken
    },
    body: form
};

var paymentRequestID  = 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'

fetch(`${baseUrl}/${paymentRequestID}`, options)
    .then(response => response.json())
    // the response JSON contains the updated payment request details.
    .then(responseJson => console.log(responseJson))
    .catch(err => console.error(err));
# The 'requests' library for Python can be used to make calls to the MoneyMoov API in
# popular python frameworks such as Django and Flask.
import requests
import os

# Remember, the JWT access token must be securely stored ('os' module above allows storage in environment variable)
# ... and when dealing with payment requests, use a MERCHANT token!
jwtToken = os.environ['NOFRIXION_MERCHANT_TOKEN']

baseUrl = "<<SANDBOX_URL>>paymentrequests"
paymentRequestID = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"

headers = {
    "Accept": "application/json",
    "Authorization": f"Bearer {jwtToken}"
}

paymentRequestData = {
    "MerchantID": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
    "Amount": "0.01",
    "Currency": "EUR",
    "CustomerID": "C202202024158",
    "OrderID": "Sample order",
    #The methods below allow the purchaser to choose from those listed - BTC lightning payments coming soon!
    "PaymentMethodTypes": "card,pisp",
    "Description": "Updated payment request",
    #URLs to integrate with merchant's site (required for card payments)
    "OriginUrl": "https://some.origin.url",
    "CallbackUrl": "https://some.callback.url",
    #PISP specific fields
    "PispAccountID": "A120P0JR",
    "PispRecipientReference": "Recipient ref",
    #Card specific fields
    "CardAuthorizeOnly": "true",
    "CardCreateToken": "false",
    "IgnoreAddressVerification": "true",
    "CardIgnoreCVN": "true"
    #Shipping and billing address data can also be included in the payment request
    #=> see https://api-sandbox.nofrixion.com/swagger/index.html for a complete reference.
}

try:
    response = requests.request("PUT", f"{baseUrl}/{paymentRequestID}", headers=headers, data=paymentRequestData)

    if response.ok:
        #  On successful update, the API returns the payment request object
        print(response.json())
    else:
        # If not OK, response contains MoneyMoov problem (https://docs.nofrixion.com/reference/error-messages)
        print(response.json())

except Exception as ex:
    print(ex)

Hosted Payment Page

A payment request can be configured to use the NoFrixion hosted payment page by setting the UseHostedPaymentPage field to true. Doing so removes the need to set the BaseOriginUrl or CallbackUrl, although the CallbackUrl can still be set if desired.

The hosted payment page is a dedicated web page where your customer's can make payments directly to you. The page can be themed with your own logos and styles (at the moment this is a manual process, please contact [email protected]).

Web Hook

An optional HTTP web hook can be sent to your own server when a payment request is marked as fully paid. To receive the web hook the SuccessWebHookUrl field needs to be set to a valid URL.

The URL will be invoked as a GET request, i.e. there will be no request body. Two query parameters will be added to the URL. The first one will be "id" and will hold the payment request ID. The second one will be "orderid" and will hold the payment request OrderID, note the OrderID could be empty if it was not set when the payment request was created.

🚧

The recommended approach when receiving a success web hook is to use the "id" parameter to call the moneymoov get payment request endpoint to retrieve the full details of the payment request and check the status. Web hooks can be easily spoofed and should not be relied upon.