Wix Integration
Use the examples below to add Flik to your Wix site.
We'll be following the step-by-step Wix guide: Payment Provider Service Plugin Tutorial
Step 1
Make sure Developer Mode is enabled in your Wix site before proceeding. You can turn it on by following Wix's Quick Start guide: Enable Coding.
Step 2
In Edit Site view
→ select {}
(Backend & Public) →
Service Plugins → click the +
icon and choose Payment to add a new
Payment Provider plugin.

Step 3
When prompted, enter
flik
as the plugin name and click
Add & Edit Code to generate the plugin
files.

Step 4
Inside the newly created folder
flik
(under
Service Plugins → Payment), locate the two
files flik-config.js
and flik.js
.
Replace their contents with the sample code below.

flik-config.js
Paste this configuration to define how Flik appears in Wix.
export function getConfig() {
return {
title: 'Flik Payment Gateway',
paymentMethods: [{
hostedPage: {
title: 'Flik - Secure Bank Transfer (No fees)',
logos: {
white: {
svg: 'https://flik.co.nz/img/flik_logo_small.svg',
png: 'https://flik.co.nz/img/small_logo_black.png'
},
colored: {
svg: 'https://flik.co.nz/img/flik_logo_small.svg',
png: 'https://flik.co.nz/img/small_logo_black.png'
}
}
}
}],
credentialsFields: [{
simpleField: {
name: 'clientId',
label: 'API id'
}
},
{
simpleField: {
name: 'clientSecret',
label: 'API secret'
}
}]
}
}
flik.js
Paste this code to define how Flik appears in Wix.
const FLIK_OAUTH_TOKEN_ENDPOINT = "https://app.flik.co.nz/api/token";
const FLIK_TRANSACTION_ENDPOINT = "https://app.flik.co.nz/api/transaction";
const FLIK_CONNECT_ENDPOINT = "https://app.flik.co.nz/api/connect/account"
// --- Internal State for Access Token Caching ---
let accessToken = null;
let tokenExpiresAt = 0; // Unix timestamp in milliseconds
/**
* @typedef {object} FlikTokenResponse
* @property {string} accessToken
* @property {number} expiresIn
*/
/**
* @typedef {object} FlikCreateTransactionResponse
* @property {string} redirectUrl
*/
/**
* @typedef {object} FlikConnectAccountResponse
* @property {string} userId
* @property {string} email
*/
/**
* Retrieves a valid OAuth 2.0 access token from the Flik authentication server.
* Caches the token and refreshes it if expired.
*
* This function performs a POST request to Flik's OAuth token endpoint
* using the client credentials flow.
*
* @returns {Promise<string>} A promise that resolves with the access token.
* @throws {Error} If the access token cannot be obtained due to network issues
* or invalid credentials.
*/
async function getAccessToken(clientId, clientSecret) {
// Check if the current token is still valid (not null and not expired)
if (accessToken && Date.now() < tokenExpiresAt) {
console.log("Using cached Flik access token.");
return accessToken;
}
console.log("Obtaining new Flik access token...");
// Prepare the request body as x-www-form-urlencoded
const body = new URLSearchParams({
clientId: clientId,
clientSecret: clientSecret,
}).toString();
try {
const response = await fetch(FLIK_OAUTH_TOKEN_ENDPOINT, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: body,
});
if (!response.ok) {
// Attempt to parse error details from the response body
const errorData = await response.json().catch(() => ({ message: "Unknown error" }));
console.error(`Failed to get Flik access token: ${response.status} - ${JSON.stringify(errorData)}`);
return null;
}
const data = /** @type {FlikTokenResponse} */ (await response.json());
// Store the obtained token and calculate its expiry time
accessToken = data.accessToken;
// expires_in is in seconds, convert to milliseconds for Date.now() comparison
tokenExpiresAt = Date.now() + (data.expiresIn * 1000);
console.log("Successfully obtained new Flik access token.");
return accessToken;
} catch (error) {
console.error("Error during Flik access token retrieval:", error);
// Re-throw the error to be handled by the calling function
throw new Error(`Could not obtain Flik access token: ${error.message}`);
}
}
/**
* Called by Wix when the merchant connects the payment provider in their dashboard.
* This function attempts to verify the provided Flik credentials by obtaining an access token.
*
* @param {object} options - Options provided by Wix (currently not explicitly used for Flik connection setup).
* @returns {Promise<object>} A promise that resolves with connection details upon success.
* @throws {Error} If the connection fails (e.g., due to invalid Flik credentials).
*/
export async function connectAccount(options) {
try {
const { clientId, clientSecret } = options.credentials || {};
const token = await getAccessToken(clientId, clientSecret)
const response = await fetch(FLIK_CONNECT_ENDPOINT, {
method: 'GET',
headers: {
'Authorization': `Bearer ${token}`,
},
});
const data = /** @type {FlikConnectAccountResponse} */ (await response.json());
console.log(data)
if (token) {
return {
credentials: {
client_id: clientId,
client_secret: clientSecret,
},
accountId: data.userId,
accountName: data.email,
};
} else {
return {
reason: "Invalid Credentials"
}
}
} catch (error) {
console.error("Failed to connect Flik account:", error);
// Propagate the error to Wix, indicating that the connection failed.
throw new Error(`Failed to connect Flik account: ${error.message}`);
}
}
/**
* Creates a new transaction with the Flik Payment Gateway.
* This function is invoked by Wix when a customer proceeds to pay with Flik
* during the checkout process.
* @param {object} options - Additional options from Wix. Crucially includes
* `redirectUrl`, which is the URL on the merchant's
* Wix site where the user should be redirected after
* completing payment on Flik's side.
* @returns {Promise<object>} A promise that resolves with an object containing
* the `redirectUrl` to the Flik payment page.
* @throws {Error} If the transaction creation fails due to API errors,
* missing data, or network issues.
*/
export async function createTransaction(options) {
const { order, merchantCredentials, wixTransactionId } = options;
const currency = order.description.currency;
const totalAmount = order.description.totalAmount;
const successfulRedirect = order.returnUrls.successUrl;
const failedUrl = order.returnUrls.failedUrl;
console.log("Order currency:", JSON.stringify(options)); // Should be 'NZD' if store is set correctly
if (currency !== 'NZD') {
throw new Error(`Unsupported currency: ${currency}. Only NZD is supported.`);
}
try {
// Ensure a valid access token is available. It will be fetched if expired or not present.
const token = await getAccessToken(merchantCredentials.client_id, merchantCredentials.client_secret);
const requestBody = {
type: "single",
redirectUrl: successfulRedirect,
failedUrl,
amount: {
currency: currency, // Use the currency from the Wix order.
total: parseFloat(totalAmount / 100), // Ensure the total amount is a float number.
},
creditorReference: {
// Use Wix order ID as a unique reference for the transaction.
reference: order.description.shippingAddress.lastName,
particulars: order.description.shippingAddress.firstName,
code: "Flik", // A concise code, possibly derived from order ID.
},
// TODO change
webhookUrl: 'https://dev-sitex1951496687.wix-dev-center-test.org/_functions/updateTransaction',
foreignTransactionId: wixTransactionId
};
const response = await fetch(FLIK_TRANSACTION_ENDPOINT, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${token}`, // Include the obtained access token.
},
body: JSON.stringify(requestBody), // Send the request body as a JSON string.
});
if (!response.ok) {
// Handle HTTP errors (e.g., 400 Bad Request, 401 Unauthorized)
const errorData = await response.json().catch(() => ({ message: "Unknown error" }));
console.error(`Failed to create Flik transaction: ${response.status} - ${JSON.stringify(errorData)}`);
}
const data = /** @type {FlikCreateTransactionResponse} */ (await response.json());
// Flik API should return a 'redirectUrl' for the user to complete payment.
if (!data.redirectUrl) {
console.error("Flik transaction response missing redirectUrl:", data);
throw new Error("Flik transaction response did not provide a redirect URL.");
}
console.log("Flik transaction created successfully. Redirecting user to:", data.redirectUrl);
const parts = data.redirectUrl.split('/');
const transactionId = parts[parts.length - 1];
// Wix expects the 'redirectUrl' in the returned object to redirect the customer.
return { pluginTransactionId: transactionId, redirectUrl: data.redirectUrl };
} catch (error) {
console.error("Error during Flik transaction creation:", error);
// Propagate the error to Wix's payment flow.
throw new Error(`Could not create Flik transaction: ${error.message}`);
}
}
export async function refundTransaction(transactionId, amount, currency) {
console.warn(`Flik refundTransaction function called for transaction ${transactionId}.
API details for refund are not provided in the specification.
This function is currently a placeholder.`);
// As per the current documentation, there's no refund endpoint specified.
// Therefore, we throw an error indicating that this functionality is not available.
throw new Error("Flik refund functionality not yet implemented: API details missing.");
/*
// Example of what a real refund implementation might look like, assuming Flik provides such an endpoint:
try {
const token = await getAccessToken();
const response = await fetch("https://app.flik.co.nz/api/refund", { // Hypothetical refund endpoint
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${token}`,
},
body: JSON.stringify({
transactionId: transactionId,
amount: amount,
currency: currency,
// ... any other parameters required by Flik's refund API
}),
});
if (!response.ok) {
const errorData = await response.json().catch(() => ({ message: "Unknown error" }));
console.error(`Failed to refund Flik transaction: ${response.status} - ${JSON.stringify(errorData)}`);
throw new Error(`Flik refund failed: ${response.statusText || errorData.message}`);
}
const data = await response.json();
return {
refundStatus: data.status, // e.g., "completed", "pending", "failed"
refundId: data.refundId, // The ID of the refund transaction if provided
};
} catch (error) {
console.error("Error during Flik refund:", error);
throw new Error(`Could not refund Flik transaction: ${error.message}`);
}
*/
}
Step 5
Update the webhookUrl value in flik.js on line 183 so it points to your own Wix site. Replace the placeholder domain with your live domain. For example, if your store is https://www.nzflowers.co.nz then your webhook becomes https://www.nzflowers.co.nz/_functions/updateTransaction.

webhookUrl
to match your site's domain.Step 6
In the {}
panel under Backend, create a new file named
http-functions.js
. Paste the sample code below—this defines an
endpoint (post_updateTransaction
) that Flik will call to notify
your store when a payment status changes.

http-functions.js
in the Backend section.http-functions.js
/**
* @file http-functions.js
* @description This file contains backend HTTP functions for your Wix site.
* It's used to create custom API endpoints accessible via HTTP requests.
*
* This specific function handles the redirect from the Flik Payment Gateway
* after a customer completes (or cancels) a payment.
*/
// Import necessary modules
import {ok, badRequest} from 'wix-http-functions'
import wixPaymentProviderBackend from "wix-payment-provider-backend";
const FLIK_TRANSACTION_STATUS_ENDPOINT = (transactionId) => `https://app.flik.co.nz/api/transaction/${transactionId}`;
// Define the path for your callback URL.
// https://dev-sitex1951496687.wix-dev-center-test.org/_functions/updateTransaction
export async function post_updateTransaction(request) {
const transactionRequestBody = await request.body.json();
if (!transactionRequestBody.transactionId || !transactionRequestBody.foreignTransactionId) {
console.error("Flik callback missing required parameters.");
return badRequest()
}
try {
// 1. Get the transaction state from Flik using your SPI function
const flikTransactionState = await getTransactionState(transactionRequestBody.transactionId);
console.log("Flik transaction state retrieved:", flikTransactionState);
const flikStatus = flikTransactionState.status;
if (flikStatus === 'Completed') {
await wixPaymentProviderBackend.submitEvent({
event: {transaction: {
wixTransactionId: transactionRequestBody.foreignTransactionId,
pluginTransactionId: transactionRequestBody.transactionId,
}}
})
} else {
await wixPaymentProviderBackend.submitEvent({
event: {
transaction: {
wixTransactionId: transactionRequestBody.foreignTransactionId,
pluginTransactionId: transactionRequestBody.transactionId,
reasonCode: 5005,
}
}
})
}
return ok()
} catch (error) {
return badRequest()
}
}
/**
* @typedef {object} FlikGetTransactionResponse
* @property {string} state
*/
async function getTransactionState(transactionId) {
console.log(`Getting state for Flik transaction ID: ${transactionId}`);
try {
const response = await fetch(FLIK_TRANSACTION_STATUS_ENDPOINT(transactionId), {
method: 'GET',
});
if (!response.ok) {
// Handle HTTP errors
const errorData = await response.json().catch(() => ({ message: "Unknown error" }));
console.error(`Failed to get Flik transaction state: ${JSON.stringify(errorData)}`);
}
const data = /** @type {FlikGetTransactionResponse} */ (await response.json());
// Return the key details needed by Wix to update the order status.
// The 'status' can be "Completed" or "Cancelled" as per Flik's documentation.
return {
status: data.state,
};
} catch (error) {
console.error("Error during Flik transaction state retrieval:", error);
throw new Error(`Could not retrieve Flik transaction state: ${error.message}`);
}
}
Step 7
Return to your Wix Dashboard, open Settings → Accept Payments, then click Manage next to the new Flik – Secure Bank Transfer method to review or activate it.



Step 8
On the Manage Flik Payment Gateway screen, enter your Flik client Id
into the API id field and your Flik client secret
into API secret. Click Connect to link your account. The status should switch to Connected.

Step 9
To test the integration, create a new order in your Wix store and select Flik – Secure Bank Transfer as the payment method. You should be redirected to the Flik payment page, where you can complete the payment. Once the payment is complete, you should be redirected back to your Wix store and the order status should be updated to Paid.
