This guide simplifies the process of adding the Payment Form to your website. It covers the preparation of the backend, SDK installation, API instance creation, and merchant data setup. Furthermore, it outlines the initialization of the form using various JavaScript frameworks and how to customize its appearance through parameters and styles.
Backend setup
Begin by setting up your backend, a crucial step for successful implementation. Use the Solidgate SDK to integrate the Payment Form seamlessly into your platforms. This SDK offers intuitive features for transactions and payment form customization. To initiate a charge, supply transaction-specific information through paymentIntent object fields.
Description
Order amount in minor units. For example, 1020 means 10 USD and 20 cents. Can be 0 for zero-amount authorization.
Example
1020
Description
Identifier of the predefined product in UUID v4 format.
Example
faf3b86a-1fe6-4ae5-84d4-ab0651d75db2
Description
Customer ID in the merchant’s system.
Example
4dad42f878
Description
ID of the coupon corresponding to a specific product discount, in UUID v4 format. Activates only when a product_id is supplied in the subscription workflow.
Example
eb4c6e93-4c53-447a-b215-5d5786af9844
Description
Price ID of the predefined product. Use get product prices to obtain it.
Example
faf3b86a-1fe6-4ae5-84d4-ab0651d75db2
Description
Customer ID in the merchant’s system.
Example
4dad42f878
Description
Number of payment retries.
Example
1
Description
ID of the coupon corresponding to a specific product discount, in UUID v4 format. Activates only when a product_id is supplied in the subscription workflow.
Example
eb4c6e93-4c53-447a-b215-5d5786af9844
Description
Order ID, which must be unique, is specified in the merchant system.
Example
123456
Description
Currency in three-letter code per the ISO-4217 Wiki standard.
Example
USD
Description
Order description in your system and for bank processing.
Highly recommended to keep the description brief to improve the clarity of payment processing, ideally not exceeding 100 characters. It is used in the email receipt sent to the customer.Example
Premium package
Description
Order items in UTF-8 code.
Example
item1, item2
Description
Date of order creation following the ^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$ pattern.
Example
2025-12-21 11:21:30
Description
Number of payments by the customer.
Example
1
Description
Delay before settlement in hours:
- Visa customer-initiated payments: 240 hours = 10 days
- Visa merchant-initiated payments: 120 hours = 5 days
- All other card brands: 168 hours = 7 days
Example
48
Description
Authorization type that defines the transaction flow and capabilities.
- final - standard authorization, no increments allowed Default value.
- estimated - initial authorization with possible amount changes
Unavailable if estimated is provided
- Auto-settle flow with settle_interval
- Zero-amount authorization with amount 0
- One-time product and subscription payment flow
Example
final
Description
Routing payments flag for 3DS flow.
Example
true
Description
Customer birthdate following the date format that matches the ^\d{4}-\d{2}-\d{2} pattern.
Example
2000-11-21
Description
Customer email.
If not provided, it is collected on the payment form.
Example
customer_first_name string 100Description
Customer’s first name.
Example
John
Description
Customer’s last name.
Example
Snow
Description
Customer’s phone number.
Should be provided in international format E.164 Wiki , starting with the plus + sign.
Recommended format ^\+[1-9]\d{1,14}$
Example
+14155552671
Description
Industry-specific payment data used to identify the classification of the transaction.
Learn more about industry data processing. type string RequiredDescription
Type of entity used to identify the classification of the data being provided.
Allowed values:
car_rental
Example
car_rental
Description
Car rental-related details.
agreement_number string <=9 RequiredDescription
Rental agreement number for the car rental.
Example
RA1029384
Description
Name of the person renting the car.
Example
Alex Johnson
Description
The UTC date and time in ISO 8601 Wiki format.
Example
2026-03-01T11:00:00Z
Description
The UTC date and time in ISO 8601 Wiki format.
Example
2026-03-05T16:30:00Z
Description
Indicates whether the booking is refundable, partially refundable, or non-refundable.
Allowed values:
refundablenon_refundablepartially_refundable
Example
partially_refundable
Description
Daily rental rate in minor units.
Example
10000
Description
Specifies whether the provided rate is daily or weekly.
- D - daily
- W - weekly
Example
D
Description
Number of days for which the car is rented.
Example
4
Description
Customer service phone number of the car rental company.
Example
8005550123
Description
Classification of the rental car.
Example
SUV1
Description
Indicates whether goods or services were tax-exempt.
- Y - tax-exempt
- N - not tax-exempt
Example
N
Description
Fuel charges associated with the rental, in minor units.
Example
2500
Description
Insurance charges associated with the rental, in minor units.
Example
3500
Description
Indicates whether the customer did not pick up the rental car.
- Y - no show
- N - car was picked up
Example
N
Description
Charge for returning a car to a location different from pick-up, in minor units.
Example
4500
Description
Agency code, phone number, or address abbreviation of the return location.
Example
NYC0001234
Description
Address where the car is picked up.
street_line_1 string <=100Description
Street line 1 where the car is picked up.
Example
1 Rental Rd
Description
State or province where the car is picked up in ISO 3166-2 Wiki .
Example
MA
Description
City where the car is picked up.
Example
Boston
Description
ISO-3166 Wiki country code where the car is picked up.
Example
USA
Description
Postcode associated with the picked up location.
Example
02128
Description
Address where the car is dropped off.
street_line_1 string <=100Description
Street line 1 where the car is dropped off.
Example
10 Transit St
Description
State or province where the car is dropped off in ISO 3166-2 Wiki .
Example
NY
Description
City where the car is dropped off.
Example
New York
Description
ISO-3166 Wiki country code where the car is dropped off.
Example
USA
Description
Postcode associated with the dropped-off location.
Example
10001
Description
Maximum allowed distance and cost for exceeding it.
limit integer >=0 RequiredDescription
Maximum distance allowed.
Example
500
Description
Unit of distance.
Allowed values:
mileskm
Example
miles
Description
An additional cost is applied when the distance limit is exceeded.
amount integer >=0 RequiredDescription
Cost amounts to the smallest currency unit.
Example
150
Description
Three-letter ISO-4217 Wiki currency code.
Example
USD
Description
Public IP address of the customer. Both IPv4 and IPv6 are supported.
Private IPs (10.0.0.0-10.255.255.255, 172.16.0.0-172.31.255.255, 192.168.0.0-192.168.255.255) result in an ‘Invalid IP’ error.Example
8.8.8.8
Description
Identifies the marketing or acquisition channel that brought the customer to the transaction.
Example
facebook
Description
Identifies the internal system or flow that triggered the transaction.
Example
main_menu
Description
Country where the goods are purchased or where the seller is based is identified using the ISO-3166 Wiki alpha-3 country code.
Required if you are registered with international payment systems as a marketplace. Being registered as a marketplace, in the context of international payment systems, typically implies that you operate a platform where numerous sellers can offer their goods or services.Example
CHN
Description
Customer country subject to ISO-3166 Wiki alpha-3.
If is not provided, it is automatically inferred.Example
GBR
Description
Customer city.
Example
New Castle
Description
Billing address details.
address string 100Description
First and second line of the billing address.
Example
221B Baker Street
Description
ISO-3166 Wiki country code of the billing address.
Example
USA
Description
ISO 3166-2 Wiki address state code of the billing address.
Example
NY
Description
City name associated with the billing address.
Example
Brooklyn
Description
Address zip/postal code.
If the field is provided, manual entry is not required for it.Example
11201
Description
Customer language settings for the translation of Payment Form fields and the language of email receipts sent for successful payments.
Example
en
Description
Website from which the transaction took place.
Example
device string 50Description
Device of the customer.
Example
iPhone 8 iOS 12.0
Description
Device sessions containing the unique session ID from a PSP fraud SDK and the associated third-party provider.
id string 255Description
Unique session or fingerprint identifier returned by a PSP fraud SDK.
Parameter for tracking customer sessions in payments and for risk analytics. Ensure that you handle this field in compliance with regional data privacy regulations (for example, GDPR Reference in the EU).
Example
dsid_3a20_f9c1_4cd8_89d3_1c5
Description
Specifies the third-party provider associated with the device session.
Identifies the PSP:
- checkout
- airwallex
Example
checkout
Description
Customer platform at the moment of payment.
- WEB - desktop
- MOB - mobile version
- APP - application
If this parameter is not provided, it is automatically inferred from the header.
Example
WEB
Description
User-agent of the customer.
Example
Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (HTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36
Description
Metadata is useful for storing additional, structured information about an object, consisting of up to 10 key-value pairs with a validation limit of 380 characters per field.
The callback notification returns an order_metadata from the order in each state.
Example
{"coupon_code": "NY2025", "partner_id": "123989"}
Description
Provide this URL if you want to redirect a customer to your own Success Screen.
If you do not provide the URL, Solidgate directs customers to the Solidgate Success Screen.Solidgate notification screen is not customizable, but you can define your own success page during initialization.
Example
https://merchant.example/success
Description
Provide this URL if you want to redirect a customer to your own Fail Screen.
If you do not provide the URL, Solidgate directs customers to the Solidgate Fail Screen.Solidgate notification screen is not customizable, but you can define your own fail page during initialization.
Example
https://merchant.example/fail
Description
A customer was detected on the merchant end to be a suspicious one.
⚠️ This field is deprecated and should not be used in new implementations.Example
true
{
"order_id": "123456",
"amount": 50500,
"currency": "USD",
"order_description": "Premium package",
"order_items": "item1, item2",
"order_date": "2025-12-21 11:21:30",
"order_number": 1,
"settle_interval": 48,
"authorization_type": "final",
"retry_attempt": 1,
"force3ds": true,
"customer_date_of_birth": "2000-11-21",
"customer_email": "test@solidgate.com",
"customer_first_name": "John",
"customer_last_name": "Snow",
"customer_phone": "+14155552671",
"industry_data": {
"type": "car_rental",
"car_rental": {
"agreement_number": "RA1029384",
"renter_name": "John Snow",
"pick_up_date": "2026-03-01T11:00:00Z",
"drop_off_date": "2026-03-05T16:30:00Z",
"refundability": "partially_refundable",
"rate": 10000,
"rate_indicator": "D",
"days_rented": "4",
"customer_service_toll_free_number": "8005550123",
"rental_class_id": "SUV1",
"tax_exempt_indicator": "N",
"fuel_charges": 2500,
"insurance_charges": 3500,
"no_show_indicator": "N",
"one_way_drop_off_charges": 4500,
"return_location_id": "NYC0001234",
"pick_up_location": {
"street_line_1": "1 Rental Rd",
"state": "MA",
"city": "Boston",
"country": "USA",
"postal": "02128"
},
"drop_off_location": {
"street_line_1": "10 Transit St",
"state": "NY",
"city": "New York",
"country": "USA",
"postal": "10001"
},
"distance_limit": {
"limit": 500,
"unit": "miles",
"additional_distance_cost": {
"amount": 150,
"currency": "USD"
}
}
}
},
"ip_address": "8.8.8.8",
"traffic_source": "facebook",
"transaction_source": "main_menu",
"purchase_country": "USA",
"geo_country": "USA",
"geo_city": "New Castle",
"billing_address": {
"address": "Street 3D, Apartment 343",
"country": "USA",
"state": "DE",
"city": "New Castle",
"zip_code": "19720"
},
"language": "en",
"website": "https://google.com",
"device": "iPhone 8 iOS 12.0",
"device_sessions": [
{
"id": "dsid_3a20_f9c1_4cd8_89d3_1c5",
"provider": "checkout"
},
{
"id": "a0d24c8a-2b67-4b4b-bd39-d2efbe92a7f0",
"provider": "airwallex"
}
],
"platform": "WEB",
"user_agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (HTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36",
"order_metadata": {
"coupon_code": "NY2025",
"partner_id": "123989"
},
"success_url": "https://merchant.example/success",
"fail_url": "https://merchant.example/fail"
}
Product-based payment
{
"order_id": "123456",
"product_id": "47f95c95-3647-4c5b-ae6d-40fd8d3ac742",
"coupon_id": "eb4c6e93-4c53-447a-b215-5d5786af9844",
"customer_account_id": "4dad42f808",
"currency": "USD",
"order_description": "Premium package",
"order_items": "item1, item2",
"order_date": "2025-12-21 11:21:30",
"order_number": 1,
"settle_interval": 48,
"authorization_type": "final",
"retry_attempt": 1,
"force3ds": true,
"customer_date_of_birth": "2000-11-21",
"customer_email": "test@solidgate.com",
"customer_first_name": "John",
"customer_last_name": "Snow",
"customer_phone": "+14155552671",
"ip_address": "8.8.8.8",
"traffic_source": "facebook",
"transaction_source": "main_menu",
"purchase_country": "CHN",
"geo_country": "GBR",
"geo_city": "New Castle",
"billing_address": {
"address": "Street 3D, Apartment 343",
"country": "USA",
"state": "DE",
"city": "New Castle",
"zip_code": "19720"
},
"language": "en",
"website": "https://google.com",
"device": "iPhone 8 iOS 12.0",
"device_sessions": [
{
"id": "dsid_3a20_f9c1_4cd8_89d3_1c5",
"provider": "checkout"
},
{
"id": "a0d24c8a-2b67-4b4b-bd39-d2efbe92a7f0",
"provider": "airwallex"
}
],
"platform": "WEB",
"user_agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (HTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36",
"order_metadata": {
"coupon_code": "NY2025",
"partner_id": "123989"
},
"success_url": "https://merchant.example/success",
"fail_url": "https://merchant.example/fail"
}
Subscription payment
{
"order_id": "123456",
"product_price_id": "faf3b86a-1fe6-4ae5-84d4-ab0651d75db2",
"coupon_id": "eb4c6e93-4c53-447a-b215-5d5786af9844",
"customer_account_id": "4dad42f808",
"currency": "USD",
"order_description": "Premium package",
"order_items": "item1, item2",
"order_date": "2025-12-21 11:21:30",
"order_number": 1,
"settle_interval": 48,
"authorization_type": "final",
"retry_attempt": 1,
"force3ds": true,
"customer_date_of_birth": "2000-11-21",
"customer_email": "test@solidgate.com",
"customer_first_name": "John",
"customer_last_name": "Snow",
"customer_phone": "+14155552671",
"ip_address": "8.8.8.8",
"traffic_source": "facebook",
"transaction_source": "main_menu",
"purchase_country": "CHN",
"geo_country": "GBR",
"geo_city": "New Castle",
"billing_address": {
"address": "Street 3D, Apartment 343",
"country": "USA",
"state": "DE",
"city": "New Castle",
"zip_code": "19720"
},
"language": "en",
"website": "https://google.com",
"device": "iPhone 8 iOS 12.0",
"device_sessions": [
{
"id": "dsid_3a20_f9c1_4cd8_89d3_1c5",
"provider": "checkout"
},
{
"id": "a0d24c8a-2b67-4b4b-bd39-d2efbe92a7f0",
"provider": "airwallex"
}
],
"platform": "WEB",
"user_agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (HTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36",
"order_metadata": {
"coupon_code": "NY2025",
"partner_id": "123989"
},
"success_url": "https://merchant.example/success",
"fail_url": "https://merchant.example/fail"
}
With SDK
Step 1. Install SDK
Install the Solidgate SDK in your environment:
PHPcomposer require solidgate/php-sdk
Node.js
npm install @solidgate/node-sdk
Go
go get github.com/solidgate-tech/go-sdk
Python
pip3 install solidgate-card-sdk
Step 2. Create SDK instance
To interact with the Solidgate API, create an API instance by calling the API constructor function, passing your Public public_key and Secret secret_key keys as arguments.
<?php
use SolidGate\API\Api;
$api = new Api('public_key', 'secret_key');
Node.js
const solidGate = require('@solidgate/node-sdk');
let api = new solidGate.Api("public_key", "private_key");
Go
solidgateSdk := solidgate.NewSolidGateApi("public_key", "secret_key")
Kotlin
val api = Api(HttpClient(), Credentials("public_key", "secret_key"))
Python
from solidgate import ApiClient
client = ApiClient("public_key", "secret_key")
Step 3. Form intent data
To create a charge, you must provide transaction-related information. This information is contained in a FormInitDTO object, which is created by invoking the formMerchantData function on your API instance. In the example code, this function is called with the paymentIntent object fields.
<?php
use SolidGate\API\Api;
$api = new Api('public_key', 'secret_key');
$response = $api->formMerchantData(['JSON payment intent // fill as described in documentation']);
Node.js
const solidGate = require('@solidgate/node-sdk');
let api = new solidGate.Api("public_key", "private_key");
let paymentIntentData = {
/// fill it as described in documentation
}
let merchantData = api.formMerchantData(paymentIntentData);
const dataToFront = merchantData.toObject()
Go
package main
import (
"encoding/json"
"fmt"
solidgate "github.com/solidgate-tech/go-sdk"
)
func main() {
solidgateSdk := solidgate.NewSolidGateApi("public_key", "secret_key")
paymentIntent := solidgate.PaymentIntent{} // fill as described in documentation
paymentIntentBytes, err := json.Marshal(paymentIntent)
if err != nil {
fmt.Print(err)
}
formInitDto, err := solidgateSdk.FormMerchantData(paymentIntentBytes)
if err != nil {
fmt.Print(err)
}
// ...
}
Kotlin
val api = Api(HttpClient(), Credentials("public_key", "secret_key"))
val attributes = Attributes(mapOf(
"amount" to 123,
"currency" to "USD",
"customer_email" to "test@example.com",
"ip_address" to "8.8.8.8",
"order_description" to "Test subscription",
"order_id" to "order12345",
"platform" to "WEB"
))
val response = api.formMerchantData(attributes)
Python
from solidgate import ApiClient
client = ApiClient("public_key", "secret_key")
payment_intent_dict = {} # fill as described in documentation
responseDTO = client.form_merchant_data(payment_intent_dict)
Step 4. Pass generated data to frontend
After you have set up the FormInitDTO and turned it into a simple object, you can effortlessly integrate it into your frontend code by transmitting the paymentIntent encrypted String (during form initialization).
Without SDK
An alternative option for integrating the payment form exists without using the Solidgate SDK.
- Prepare server-side code in your preferred programming language and libraries to communicate with the Solidgate API.
- Create and encrypt a JSON object with the required fields for a payment transaction.
- Once the
paymentIntentis encrypted, pass it to the frontend for further processing, such as form initialization. - Integrate the
signature
parameter process with the encryption steps for initializing the form, the flow for
paymentIntent encrypted String- The customer starts the transaction by providing the necessary payment data.
- A secure random IV is created with the required size for encryption.
- The system extracts the required size from the secret key and formats it for encryption.
- A cipher object is set up with the selected encryption algorithm, mode, and padding, and initialized with the key and IV for encryption.
- The input data is converted into bytes and encrypted using the initialized cipher.
- The IV and encrypted data become combined into a single byte array for secure transmission, ensuring compatibility and security, such as using the pycryptodome Reference library in Python 3 environments.
- The combined IV and encrypted data become encoded into a Base64 string for safe transmission over the network.
<?php
class PaymentIntentGenerator
{
private string $secretKey;
public function __construct(string $secretKey)
{
$this->secretKey = $secretKey;
}
private function generateEncryptedFormData(array $attributes): string
{
$attributes = json_encode($attributes);
$secretKey = substr($this->secretKey, 0, 32);
$ivLen = openssl_cipher_iv_length('aes-256-cbc');
$iv = openssl_random_pseudo_bytes($ivLen);
$encrypt = openssl_encrypt($attributes, 'aes-256-cbc', $secretKey, OPENSSL_RAW_DATA, $iv);
return $this->base64UrlEncode($iv . $encrypt);
}
private function base64UrlEncode($data): string
{
return str_replace(['+', '/'], ['-', '_'], base64_encode($data));
}
public function testGenerateEncryptedFormData(): void
{
$attributes = [
"order_id" => "order_id",
"amount" => 1100,
"currency" => "USD",
"order_description" => "description",
"customer_email" => "test@yourdomain.com",
"ip_address" => "8.8.8.8",
"platform" => "WEB",
];
$encryptedFormData = $this->generateEncryptedFormData($attributes);
echo "Encrypted Form Data: " . $encryptedFormData . PHP_EOL;
}
}
$yourClassInstance = new PaymentIntentGenerator("api_sk_xxxxaxxxxbdf47a2aea17eb3xxxxxxxx");
$yourClassInstance->testGenerateEncryptedFormData();
Node.js
const crypto = require('crypto');
class PaymentIntentGenerator {
constructor() {
this.secretKey = "api_sk_xxxxaxxxxbdf47a2aea17eb3xxxxxxxx";
}
generateIntent() {
const intent = '{"order_id":"order_id","amount":1100,"currency":"USD","order_description":"description","customer_email":"test@solidgate.com","ip_address":"8.8.8.8","platform":"WEB"}';
const paymentIntent = this.encryptPaymentIntent(intent, this.secretKey);
console.log("Generated Payment Intent:");
console.log(paymentIntent);
}
encryptPaymentIntent(value, secretKey) {
const iv = crypto.randomBytes(16);
const aesKey = Buffer.from(secretKey.substring(0, 32), 'utf-8');
const cipher = crypto.createCipheriv("aes-256-cbc", aesKey, iv);
let encryptedBytes = cipher.update(value, 'utf-8', 'base64');
encryptedBytes += cipher.final('base64');
const encryptedWithIV = Buffer.concat([iv, Buffer.from(encryptedBytes, 'base64')]);
const base64Encoded = encryptedWithIV.toString('base64')
.replace(/\+/g, '-')
.replace(/\//g, '_');
return base64Encoded;
}
}
const generator = new PaymentIntentGenerator();
generator.generateIntent();
Java
import java.nio.charset.StandardCharsets;
import java.security.SecureRandom;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;
public class PaymentIntentGenerator {
private final String secretKey = "api_sk_xxxxaxxxxbdf47a2aea17eb3xxxxxxxx";
public void generateIntent() throws Exception {
String intent = "{\"order_id\":\"order_id\",\"amount\":1100,\"currency\":\"USD\",\"order_description\":\"description\",\"customer_email\":\"test@solidgate.com\",\"ip_address\":\"8.8.8.8\",\"platform\":\"WEB\"}";
String paymentIntent = encryptPaymentIntent(intent, secretKey);
System.out.println("Generated Payment Intent:");
System.out.println(paymentIntent);
}
public String encryptPaymentIntent(String value, String secretKey) throws Exception {
byte[] iv = new byte[16];
new SecureRandom().nextBytes(iv);
SecretKeySpec aesKey = new SecretKeySpec(secretKey.substring(0, 32).getBytes(StandardCharsets.UTF_8), "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, aesKey, new IvParameterSpec(iv));
byte[] encryptedBytes = cipher.doFinal(value.getBytes(StandardCharsets.UTF_8));
byte[] encryptedWithIV = new byte[iv.length + encryptedBytes.length];
System.arraycopy(iv, 0, encryptedWithIV, 0, iv.length);
System.arraycopy(encryptedBytes, 0, encryptedWithIV, iv.length, encryptedBytes.length);
return Base64.getEncoder().encodeToString(encryptedWithIV)
.replace("+", "-")
.replace("/", "_");
}
public static void main(String[] args) throws Exception {
PaymentIntentGenerator generator = new PaymentIntentGenerator();
generator.generateIntent();
}
}
C#
using System;
using System.Security.Cryptography;
using System.Text;
class PaymentIntentGenerator
{
private string secretKey = "api_sk_xxxxaxxxxbdf47a2aea17eb3xxxxxxxx";
public void GenerateIntent()
{
string intent = "{\"order_id\":\"order_id\",\"amount\":1100,\"currency\":\"USD\",\"order_description\":\"description\",\"customer_email\":\"test@solidgate.com\",\"ip_address\":\"8.8.8.8\",\"platform\":\"WEB\"}";
string paymentIntent = EncryptPaymentIntent(intent, secretKey);
Console.WriteLine("Generated Payment Intent:");
Console.WriteLine(paymentIntent);
}
public static string EncryptPaymentIntent(string value, string secretKey)
{
byte[] iv = new byte[16];
new Random().NextBytes(iv);
using (RijndaelManaged aesAlg = new RijndaelManaged())
{
aesAlg.Key = Encoding.UTF8.GetBytes(secretKey.Substring(0, 32));
aesAlg.Mode = CipherMode.CBC;
aesAlg.Padding = PaddingMode.PKCS7;
using (ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, iv))
{
byte[] valueBytes = Encoding.UTF8.GetBytes(value);
byte[] encryptedBytes = encryptor.TransformFinalBlock(valueBytes, 0, valueBytes.Length);
byte[] encryptedWithIV = new byte[iv.Length + encryptedBytes.Length];
Array.Copy(iv, 0, encryptedWithIV, 0, iv.Length);
Array.Copy(encryptedBytes, 0, encryptedWithIV, iv.Length, encryptedBytes.Length);
string base64Encoded = Convert.ToBase64String(encryptedWithIV).Replace("+", "-").Replace("/", "_");
return base64Encoded;
}
}
}
static void Main()
{
PaymentIntentGenerator generator = new PaymentIntentGenerator();
generator.GenerateIntent();
}
}
Go
package main
import (
"bytes"
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"encoding/base64"
"encoding/json"
"fmt"
"io"
)
type PaymentIntentGenerator struct {
key []byte
}
func NewPaymentIntentGenerator(secretKey string) *PaymentIntentGenerator {
return &PaymentIntentGenerator{
key: []byte(secretKey)[:32],
}
}
func (p *PaymentIntentGenerator) GenerateIntent() (string, error) {
intent := map[string]interface{}{
"order_id": "order_id",
"amount": 1100,
"currency": "USD",
"order_description": "description",
"customer_email": "test@solidgate.com",
"ip_address": "8.8.8.8",
"platform": "WEB",
}
intentBytes, err := json.Marshal(intent)
if err != nil {
return "", fmt.Errorf("marshal: %w", err)
}
paymentIntent, err := p.encrypt(intentBytes)
if err != nil {
return "", fmt.Errorf("encrypt: %w", err)
}
return base64.URLEncoding.EncodeToString(paymentIntent), nil
}
func (p *PaymentIntentGenerator) encrypt(raw []byte) ([]byte, error) {
data := p.pad(raw)
block, err := aes.NewCipher(p.key)
if err != nil {
return []byte(nil), fmt.Errorf("new cipher: %w", err)
}
cipherText := make([]byte, aes.BlockSize+len(data))
iv := cipherText[:aes.BlockSize]
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
return nil, fmt.Errorf("io read: %w", err)
}
mode := cipher.NewCBCEncrypter(block, iv)
mode.CryptBlocks(cipherText[aes.BlockSize:], data)
return cipherText, nil
}
func (p *PaymentIntentGenerator) pad(data []byte) []byte {
n := aes.BlockSize - (len(data) % aes.BlockSize)
pb := make([]byte, len(data)+n)
copy(pb, data)
copy(pb[len(data):], bytes.Repeat([]byte{byte(n)}, n))
return pb
}
func main() {
generator := NewPaymentIntentGenerator("api_sk_xxxxaxxxxbdf47a2aea17eb3xxxxxxxx")
intent, err := generator.GenerateIntent()
if err != nil {
fmt.Println(err)
} else {
fmt.Printf("Generated Payment Intent: %s", intent)
}
}
Kotlin
import java.security.SecureRandom
import javax.crypto.Cipher
import javax.crypto.spec.IvParameterSpec
import javax.crypto.spec.SecretKeySpec
import java.util.Base64
class PaymentIntentGenerator {
private val secretKey = "api_sk_xxxxaxxxxbdf47a2aea17eb3xxxxxxxx"
fun generateIntent() {
val intent = "{\"order_id\":\"order_id\",\"amount\":1100,\"currency\":\"USD\",\"order_description\":\"description\",\"customer_email\":\"test@solidgate.com\",\"ip_address\":\"8.8.8.8\",\"platform\":\"WEB\"}"
val paymentIntent = encryptPaymentIntent(intent, secretKey)
println("Generated Payment Intent:")
println(paymentIntent)
}
fun encryptPaymentIntent(value: String, secretKey: String): String {
val iv = ByteArray(16)
SecureRandom().nextBytes(iv)
val aesKey = SecretKeySpec(secretKey.substring(0, 32).toByteArray(charset("UTF-8")), "AES")
val cipher = Cipher.getInstance("AES/CBC/PKCS5Padding")
cipher.init(Cipher.ENCRYPT_MODE, aesKey, IvParameterSpec(iv))
val encryptedBytes = cipher.doFinal(value.toByteArray(charset("UTF-8")))
val encryptedWithIV = ByteArray(iv.size + encryptedBytes.size)
System.arraycopy(iv, 0, encryptedWithIV, 0, iv.size)
System.arraycopy(encryptedBytes, 0, encryptedWithIV, iv.size, encryptedBytes.size)
val base64Encoded = Base64.getEncoder().encodeToString(encryptedWithIV)
.replace("+", "-")
.replace("/", "_")
return base64Encoded
}
}
fun main() {
val generator = PaymentIntentGenerator()
generator.generateIntent()
}
Python
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad
from Crypto.Random import get_random_bytes
import base64
import json
class PaymentIntentGenerator:
def __init__(self):
self.__key = b'api_sk_xxxxaxxxxbdf47a2aea17eb3xxxxxxxx'[:32]
self.__block_size = 16
def generate_intent(self):
intent = {
"order_id": "order_id",
"amount": 1100,
"currency": "USD",
"order_description": "description",
"customer_email": "test@solidgate.com",
"ip_address": "8.8.8.8",
"platform": "WEB"
}
intent_str = json.dumps(intent)
payment_intent = self.encrypt(intent_str)
print("Generated Payment Intent:")
print(payment_intent)
def encrypt(self, raw):
raw = pad(raw.encode(), self.__block_size, style='pkcs7')
iv = get_random_bytes(self.__block_size)
cipher = AES.new(self.__key, AES.MODE_CBC, iv)
return base64.urlsafe_b64encode(iv + cipher.encrypt(raw)).decode('utf-8')
if __name__ == "__main__":
generator = PaymentIntentGenerator()
generator.generate_intent()
Ruby
require 'openssl'
require 'base64'
require 'json'
class PaymentIntentGenerator
IV_LENGTH = 16
KEY_LENGTH = 32
def initialize
@secret_key = 'api_sk_xxxxaxxxxbdf47a2aea17eb3xxxxxxxx'[0, KEY_LENGTH]
end
def generate_intent
intent = {
order_id: 'order_id',
amount: 1100,
currency: 'USD',
order_description: 'description',
customer_email: 'test@solidgate.com',
ip_address: '8.8.8.8',
platform: 'WEB'
}
intent_str = intent.to_json
payment_intent = encrypt_payload(intent_str)
puts 'Generated Payment Intent:'
puts payment_intent
end
private
def encrypt_payload(attributes)
key = @secret_key
iv = OpenSSL::Random.random_bytes(IV_LENGTH)
cipher = OpenSSL::Cipher.new('aes-256-cbc')
cipher.encrypt
cipher.key = key
cipher.iv = iv
encrypted = cipher.update(attributes) + cipher.final
base64_encoded = Base64.urlsafe_encode64(iv + encrypted)
base64_encoded.gsub('+', '-').gsub('/', '_')
end
end
generator = PaymentIntentGenerator.new
generator.generate_intent
Frontend SDK setup
The Solidgate SDK provides a pre-built interface component for payments. It assists in tokenizing customer data, ensuring that card information never interacts with the merchant’s website.
When starting with the Payment Form, you can use Solidgate official payment form SDK wrapper for different JavaScript frameworks:
These integrations automatically load solid-form.js and offer a convenient interface for form operation. Furthermore, you can use manual installation.
Alternatively, manually add the payment form SDK to your checkout page by inserting the script tag at the end of the HTML file’s <body> tag. Use the Solidgate CDN-hosted form for easy integration, ensuring the latest version and preventing potential issues from script modification.
<script src="https://cdn.solidgate.com/js/solid-form.js"></script>
Check the console for a warning that
Solidgate PaymentFormSdk
is already initialized. If this warning appears,
solid-form.js
has most likely been loaded and run twice. Remove the unnecessary connection.
Next, create a container for the payment form on your page and assign it a custom ID, as demonstrated below. Avoid setting height or display properties for elements inside the container, including the container itself, to prevent form appearance issues due to CSS conflicts.
The following example specifies a container with the default id of Solidgate SDK.
<div id="solid-payment-form-container"></div>
Alternatively, use your own container, passing its id to iframeParams as shown in the example below.
const data = {
iframeParams: {
containerId: 'your-custom-container-id'
}
}
Form initialization
After completing all the steps and modifying the required parameters, initiate the Solidgate SDK
Reactimport React, { FC } from 'react'
import ReactDOM from 'react-dom';
import Payment, { InitConfig } from "@solidgate/react-sdk"
export const MyPayment: FC<{
merchantData: InitConfig['merchantData']
styles?: InitConfig['styles']
formParams?: InitConfig['formParams']
width?: string
}> = (props) => {
return (<Payment
merchantData={props.merchantData}
styles={props.styles}
formParams={props.formParams}
width={props.width}
/>)
}
Vanilla JS
const form = PaymentFormSdk.init(data);
Vue
<template>
<Payment
:merchant-data="merchantData"
:form-params="formParams"
width="100%"
/>
</template>
<script lang="ts" setup>
import { defineAsyncComponent } from 'vue'
import { InitConfig } from '@solidgate/vue-sdk'
const Payment = defineAsyncComponent(() => import('@solidgate/vue-sdk'))
const merchantData: InitConfig['merchantData'] = {
merchant: '<<--YOUR MERCHANT ID-->>',
signature: '<<--YOUR SIGNATURE OF THE REQUEST-->>',
paymentIntent: '<<--YOUR PAYMENT INTENT-->>'
}
const formParams: InitConfig['formParams'] = {}
</script>
Angular
/// in app.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { SolidPaymentModule } from '@solidgate/angular-sdk';
import { AppComponent } from './app.component';
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
SolidPaymentModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
/// in app.component.ts
import {Component} from '@angular/core';
import {FormType, InitConfig} from "@solidgate/angular-sdk";
@Component({
selector: 'app-root',
template: `
<ngx-solid-payment
[formParams]="formParams"
[merchantData]="merchantData"
width="100%"
></ngx-solid-payment>
`
})
export class AppComponent {
merchantData: InitConfig['merchantData'] = {
merchant: '<<--YOUR MERCHANT ID-->>',
signature: '<<--YOUR SIGNATURE OF THE REQUEST-->>',
paymentIntent: '<<--YOUR PAYMENT INTENT-->>'
}
formParams: InitConfig['formParams'] = {
formTypeClass: FormType.Default
}
}
Object data (or InitConfig interface in case of frameworks usage) should contain the:
Description
Main object required to init the form.
Contains all the information for creating payment on the Solidgate side.
merchant string RequiredDescription
Unique merchant identification.
Shall be shared at the moment of registration.
Example
api_pk_7b197...ba108f842
Description
Signature of request.
It allows verifying whether the request from the merchant is genuine on the payment gateway server.
Example
MjNiYjVj…ZhYmMxMzNiZDY=
Description
Encrypted aes-cbc-256 string of JSON request data with random IV (16 bytes) and secret key is the first 32 bytes of the merchant secret key.
Example
E5FKjxw5vRjjIZ….vmG2YFjg5xcvuedQ==
Description
Control non-mandatory parameters of the form (like Cardholder name and templates).
buttonType stringDescription
Type of payment button: with continue text or default one with pay text.
Example
continue
Default
pay
Description
Override the default text of the submit button.
Example
Pay Now
Default
not set isCardHolderVisible booleanDescription
Defines should cardholder field be always visible.
Otherwise, it could be shown simultaneously during additional fields request.
Default
false
Example
true
Description
Mask cvv number as *** during input.
Default
false
Example
true
Description
Text on the header of the payment form.
Default
not setExample
Enter your payment data
Description
Text on the title of the payment form.
Default
not setExample
Card info
Description
Template of Payment Form.
defaultcardinlineflat
Default
default
Example
card
Description
Visibility of the Powered by Solidgate logo.
Default
false
Example
true
Description
An array with a list of card brands that could be displayed on the payment form.
american-expressaurabajajbancontactbc-cardcartes-bancairesdankortdiners-clubdiscoverelogpn-cardhipercardinteracjcbmaestromadamastercardpaypalrupaythai-payment-networktroyunionpayvervevisa
Default
[]
Example
['american-express','diners-club','discover','maestro', 'mastercard', 'paypal','visa']
Description
An array with a list of card brands that could be displayed on the payment form.
Default
[]
Example
['visa-secure', 'mcc-id-check', 'ssl', 'pci-dss', 'norton', 'mc-affee']
Description
Link to Google Font.
Please, avoid using large font sets to keep form loading fast.
Default
not setExample
//fonts.googleapis.com/css2?family=Roboto:wght@400;500&display=swap
Description
Card form visibility.
Set false to hide the card form and show only the status page.
Default
true
Example
false
Description
Controls whether customers can submit the card form by pressing Enter or clicking the Submit button.
Usefully for implementing custom submit flow.
Default
true
Example
false
Description
Setting to disable form autofocus.
Default
true
Example
false
Description
Manage the styles of your payment form.
input_groupThis class targets all input fields within the form, enabling you to apply consistent styling.
To view changes, directly modify the input_group class in your CSS. Activation occurs automatically as the form renders.
Defines the style for the payment form’s header.
Adjustments to the header class become visible upon a form load and are particularly useful for aligning with your brand identity.
Responsible for the overall container of the form, allowing for adjustments in font, color, or spacing.
The form_body becomes visible when the form is initialized and can be tailored to fit seamlessly within your site’s design.
Customize the subtitle of your payment form, enhancing readability and focus.
Changes are immediately visible, providing a quick way to align form instructions with customer expectations.
submit_buttonControls the styling of the form’s submit button.
To hide the button, set the display property to none in your styles. This class becomes crucial when you prefer a custom button or need to follow the specific design systems.
Wraps fields like CVV and Expiry Date in the default form template, enabling a two-column layout for a compact and organized look.
Alterations to this class are seen as soon as the form is rendered.
card_viewEdit the card template, such as changing the background color with a property like card_view: { 'background': '#3D4251'}.
This class is particularly impactful for branding purposes and customer engagement.
card_brandsModifies the display of card brand logos, ensuring they fit well within your form’s design.
The size and position can be adjusted to meet visual design standards.
card_numberSpecific to the card number input field, this class can be styled to indicate valid input or errors, with immediate feedback enhancing the customer’s experience. card_cvv
Targets the CVV field, allowing for distinct styles during error states or focus, providing immediate visual cues to the customer. expiry_date
Controls the appearance of the expiry date field.
Customizing this field can ensure consistency with other form elements and can trigger when the field is in focus or an error state.
card_holderDescription
Defines the style for the cardholder’s name field, which is a crucial element for transactions.
A string parameter ranging from 2 to 50 characters. The pattern ^\w.{0,48}\w$ is used to validate the format.
The field specifies the name as it appears on the card, essential for transaction processing. It requires at least one space between the first and last names to ensure accuracy and enhance transaction conversions. For some PSPs, if the merchant does not provide this value, it is filled with the default John Snow. additional_fieldManages the styling of any additional fields that may be required for specific transactions. This ensures that these fields are visible and styled according to the form’s design when they become relevant. zip_code
Styling for the ZIP code field is important in address forms, and any updates to this class appear as soon as the field is rendered. body_errors
Customize the error messages associated with the card and flat templates, ensuring that any validation errors are communicated effectively and clearly.
The errors customization forcard and flat template.
secure_info
Edits the appearance of security-related branding, such as SSL certificates or payment compliance logos, reinforcing trust and security on the payment form. iframeParams object
Description
Customize form container placement and sizes.
width stringDescription
Parameter allows the overriding of the form width. You can set the value in either percentage, such as 100%, or pixels, like 320px.
Default
not setDepending on the form template:
default: 300pxcard: 352pxinline: 300pxflat: 320px
Example
100%
Description
Custom containerId to place form.
If not set, it is displayed in the element with id solid-payment-form-container
Default
not setExample
your-custom-container-id
const data = {
merchantData: {
merchant: 'api_pk_7b197...ba108f842',
signature: 'MjliMzU4ODE3ZDVlM2E1YWZmYzI1NmU4MzU3YjhlODRkMTJmZTk1NjIxOWNiYzFmNDk0N2NkNjk5YTA5Y2Q4NzIzOWIwMTgxZTQwOGExZjFmYWQ1NzQyYjc3ZGRjMzE0MTczYTQ2OGEyMTlmNGI4YzA5ZmNhMTczZDI0ZDBkZmM=',
paymentIntent: 'E5FKjxw5vRjjIZBKtH_Q9oN1Wmn5icMn720prO4nPB3cYpzC9wLAHwq9IwstmD-YFLFPsdq2Rk9YzRJhxdPEq2KI19fFt1QotX-smH5_xWxGfYcv9rf2Y4v4KWgbjzJylHTDM6eCXVvbdZyVU54vD3sxntN3gFiyuhEzMn8mKoDV0UdIqLN_VsTAdehBUrqk7aPNzXCfSqpy9pCBlpdFNCfgOyHoDXGGS_Z9fK3gCw7usF2v0IU96mQGzdtyEUs1Z2MJYwle7sjEkWNEb9SkpW1zUXEZCFMF8Cu-dn6fWe4cVE2Ok1MDeTE43dySgw9e8GzMxgPmG2YFjg5xcvuedQ=='
},
formParams: {
buttonType: 'default',
submitButtonText: 'Pay',
isCardHolderVisible: true,
hideCvvNumbers: true,
headerText: 'Enter your debit or credit card details (from merchant)',
titleText: 'Card info (from merchant)',
formTypeClass: 'default',
googleFontLink: '//fonts.googleapis.com/css2?family=DM+Sans:ital@1&display=swap',
autoFocus: false
},
styles: {
submit_button: {
'background-color': 'red',
'font-size': '16px',
'font-weight': 'bold',
':hover': {
'background-color': 'green'
},
form_body: {
'font-family': 'DM Sans'
}
}
}
}
Form cleanup
You can use form.destroy() to clean up the form instance fully. This method ensures that all associated resources are properly destroyed, including cleaning up the DOM tree and removing any residual event listeners or states that may persist.
this.form.destroy()
Handle initialization errors
There might be errors when setting up the Payment Form, and if you encounter them:
- Verify that
paymentIntentcontains the required parameters. - Confirm that the
ip_addressadded is not private. - Verify that the
ip_addressadded matches the selected region if using a VPN. - Ensure that the form styles do not have the
opacityproperty set to 0 . - Inspect form styles for any elements that could be covering the form area.
- Ensure that you generate a new
order_idfor each transaction attempt.
You can test payments to make sure everything works as expected. If the outlined steps do not resolve the issue, please contact us for further assistance. When contacting, share the details of the issue and the steps you have taken to resolve it.
To change transaction parameters after the form is initialized, see Update payment form .