Skip to content
Kayana

Building an advanced Kayana integration in PHP

Last updated Jan 9, 2026

Build an advanced Kayana integration in PHP form to securely collect card details and accept payments using Kayana's Payment API, powered by RYFT, for your e-commerce store.

Overview

The Kayana Payment API enables you to accept payments from customers without needing to build your own checkout process. This guide walks you through integrating the payment flow in sandbox mode, where you can safely test without processing real transactions.

What you'll build:

  • Create a payment instance on your server
  • Retrieve the PSP public key for frontend initialisation
  • Display a secure payment form using the RYFT SDK
  • Process the payment securely

Before you begin

You'll need:

  • A Kayana property ID
  • Access to the sandbox environment
  • Basic knowledge of server-side development (PHP examples provided)

Sandbox vs Production:

  • Sandbox: Test environment with fake transactions – no authentication required
  • Production: Live environment – requires an authorisation token from Kayana

How it works

The payment flow consists of three steps:

  1. Server-side: Create a payment instance and receive a client_secret
  2. Server-side: Fetch the PSP public key for frontend initialisation
  3. Client-side: Render the payment form using the RYFT SDK and complete the transaction

Set up the server

Base URL

Sandbox:

https://integration.dev.kayana.co.uk

Production:

https://integration.kayana.co.uk

Authentication

All production API requests require an Authorisation header with your API token.

x-api-key: YOUR_API_KEY

Note: In sandbox mode, authentication is optional but can be included for testing production-compatible requests.

Step 1: Create a payment

Create a payment instance by calling the /admin/payment endpoint. This returns a client_secret that you'll use to complete the payment on the frontend.

Endpoint

POST /web/payment

Headers

HeaderValueRequired
Content-Typeapplication/jsonYes
x-api-keyYOUR_API_KEYYes

Request Parameters

ParameterTypeDescription
property_idstringFormat Prop_*
psp_codestringRYFT
pre_authorisebooleanIndicates whether the payment should be pre-authorised instead of captured immediately
currency_codestringGBP, EUR, USD
amountnumberDecimal amount (example: 12.0)
customer_emailstringCustomer email

Example request

<?php $curl = curl_init(); curl_setopt_array($curl, array( CURLOPT_URL => 'https://integration.dev.kayana.co.uk/web/payment', CURLOPT_RETURNTRANSFER => true, CURLOPT_CUSTOMREQUEST => 'POST', CURLOPT_POSTFIELDS => json_encode([ "property_id" => "Prop_abc123example", 'psp_code' => $config['stripe']['psp_code'], "currency" => "GBP", "amount" => 12.0, "customer_email" => "customer@example.com" ]), CURLOPT_HTTPHEADER => array( 'Content-Type: application/json', 'x-api-key: YOUR_API_KEY' ), )); $response = curl_exec($curl); curl_close($curl); $data = json_decode($response, true); echo $response; ?>

Response

{ "status": true, "data": { "instance_id": "Payment_xyz789example", "client_secret": "ps_secret123example", "next_step": { "action": "FORM", "proceed": true }, "transaction_id": "Tx_txn456example" } }

Response parameters

ParameterDescription
instance_idUnique identifier for this payment instance
client_secretSecret key used to complete the payment on the frontend (keep this secure)
next_step.actionIndicates the next action required (typically FORM for card payments)
next_step.proceedBoolean indicating whether to proceed with the payment flow
transaction_idUnique identifier for tracking this transaction

Important: The client_secret is a sensitive piece of information and should be kept secure. Only pass it to your frontend when needed to complete the payment.

Step 2: Retrieve the PSP public key

Fetch the public key required to initialise the RYFT payment SDK on your frontend. This key is specific to your PSP (RYFT) and the currency associated with it.

Endpoint

GET /web/payment/public-key

Headers

HeaderValueRequired
x-api-keyYOUR_API_KEYYes
x-psp-codeRYFTYes
x-currency-codeGBP (or your currency)Yes

Example request

<?php $curl = curl_init(); curl_setopt_array($curl, array( CURLOPT_URL => 'https://integration.dev.kayana.co.uk/web/payment/public-key', CURLOPT_RETURNTRANSFER => true, CURLOPT_CUSTOMREQUEST => 'GET', CURLOPT_HTTPHEADER => array( 'x-api-key: YOUR_API_KEY', 'x-psp-code: RYFT', 'x-currency-code: GBP' ), )); $response = curl_exec($curl); curl_close($curl); $data = json_decode($response, true); echo $response; ?>

Response

{ "status": true, "data": { "public_key": "pk_sandbox_abc123examplekey" } }

Response parameters

ParameterDescription
public_keyPSP public key for initialising the RYFT SDK on your frontend

Step 3: Complete the payment on the frontend

Use the public key to initialise the RYFT SDK and the client secret to confirm the payment.

Integration overview

  1. Include the RYFT SDK in your frontend
  2. Initialise RYFT with your public_key
  3. Create a payment form using RYFT's UI components
  4. Confirm the payment using the client_secret

Note: The exact frontend implementation depends on the RYFT JavaScript SDK. Refer to RYFT's documentation for detailed frontend integration steps.

Basic frontend flow

// Initialize RYFT with the public key const ryft = Ryft('pk_sandbox_abc123examplekey'); // Create a payment form const elements = ryft.elements(); const cardElement = elements.create('card'); cardElement.mount('#card-element'); // Handle form submission const form = document.getElementById('payment-form'); form.addEventListener('submit', async (event) => { event.preventDefault(); // Confirm payment with client_secret const {error, paymentIntent} = await ryft.confirmCardPayment( 'ps_secret123example', // client_secret from Step 1 { payment_method: { card: cardElement } } ); if (error) { console.error(error.message); } else { console.log('Payment successful!', paymentIntent); } });

Testing in sandbox

Use these test card numbers to simulate different payment scenarios in the sandbox environment. These cards do not process real transactions.

Test card numbers

Card NumberBrandScenario
4242 4242 4242 4242VisaSuccessful payment
4000 0025 0000 3155VisaRequires authentication (3D Secure)
4000 0000 0000 9995VisaPayment declined (insufficient funds)

Additional test card details:

  • Expiry date: Any future date (e.g., 12/34)
  • CVC: Any 3 digits (e.g., 123)
  • Postal code: Any valid format (e.g., SW1A 1AA)

Warning: Sandbox test cards must never be used in production. Real card details should only be entered in the production environment.

Additional endpoints for orders

Suggested flow: Create Order → Authorise Payment


├── Capture → Success
├── Cancel → Void payment
└── Refund → After capture

Authentication

All API requests must include the following headers:

HeaderTypeRequiredDescription
x-api-keyStringYesYour API key
typeStringYesMust be set to business
Content-TypeStringYesMust be application/json

1. Capture Authorised Payment

Endpoint

POST /web/payment/capture-authorised-payment

Request Parameters

FieldTypeRequiredDescription
order_idStringYesOrder ID
amountNumberYesAmount to capture

cURL Example

curl --location 'https://integration.dev.kayana.co.uk/web/payment/capture-authorised-payment' \ --header 'Content-Type: application/json' \ --header 'type: business' \ --header 'x-api-key: <YOUR_API_KEY>' \ --data '{ "order_id": "Order_xxx", "amount": 5 }'

Sample Response

{ "status": "success", "message": "Payment captured successfully", "data": { "order_id": "Order_xxx", "captured_amount": 5 } }

2. Cancel Authorised Payment

Endpoint

POST /web/payment/cancel-authorised-payment

Request Parameters

FieldTypeRequiredDescription
order_idStringYesOrder ID

cURL Example

curl --location 'https://integration.dev.kayana.co.uk/web/payment/cancel-authorised-payment?order_id=Order_xxx' \ --header 'Content-Type: application/json' \ --header 'type: business' \ --header 'x-api-key: <YOUR_API_KEY>'

Sample Response

{ "status": "success", "message": "Payment cancelled successfully" }

3. Refund Payment

Endpoint

POST /web/payment/refund

Request Parameters

FieldTypeRequiredDescription
order_idStringYesOrder ID
amountNumberYesRefund amount

cURL Example

curl --location --request POST 'https://integration.dev.kayana.co.uk/web/payment/refund?order_id=Order_xxx&amount=0.4' \ --header 'Content-Type: application/json' \ --header 'type: business' \ --header 'x-api-key: <YOUR_API_KEY>'

Sample Response

{ "status": "success", "message": "Refund processed", "data": { "order_id": "Order_xxx", "refunded_amount": 0.4 } }

4. Fetch Order Details

Endpoint

GET /web/order/fetch-order-details-by-order-id

Request Parameters

FieldTypeRequiredDescription
order_idStringYesOrder ID

cURL Example

curl --location 'https://integration.dev.kayana.co.uk/web/order/fetch-order-details-by-order-id?order_id=Order_xxx' \ --header 'type: business' \ --header 'x-api-key: <YOUR_API_KEY>'

Sample Response

{ "status": "success", "data": { "order_id": "Order_xxx", "status": "captured", "amount": 5 } }

Error handling

All API responses include a status field indicating success or failure.

Error response format

{ "status": false, "message": "Description of what went wrong" }

Common errors

ErrorCauseSolution
Invalid authorization tokenToken is missing, expired, or incorrectVerify your authorisation token with Kayana support
Missing required headersRequired header (e.g., x-psp-code) not providedCheck that all the necessary headers are included in your request
Invalid property IDProperty ID format is incorrect or doesn't existVerify your property ID matches the format Prop_*
Unsupported currencyCurrency code is not supported for this propertyCheck supported currencies with Kayana support
PSP configuration missingRYFT is not configured for this propertyContact Kayana to enable RYFT for your account

Going live

Before moving to production:

  1. Get production credentials: Contact Kayana Technical Support for your production authorisation token
  2. Update your base URL: Switch from the sandbox URL to the production URL
  3. Add authentication: Include your authorisation token in all requests
  4. Update frontend keys: Replace sandbox public keys with production keys
  5. Remove test cards: Ensure only real payment methods are accepted

Necessary: Never use sandbox keys or test cards in a production environment. Production keys must be kept secure and never exposed in client-side code.

Support

Need help?

  • Technical issues: Contact Kayana Technical Support
  • Production credentials: Request from your Kayana account manager
  • PSP configuration: Reach out to Kayana Technical Support
  • Explore webhook integration for payment notifications
  • Learn about refunds and dispute handling
  • Set up recurring payments for subscriptions

Next steps: If you prefer Stripe as your payment service provider, refer to our guide on building an advanced Kayana integration for RYFT in PHP.

Still need a hand?Contact support← All help