Signatures
When using Fondy Gateway to create payments, each request and response must include a signature for validation. This ensures data integrity and prevents unauthorised modification of transaction details. The signature is generated using SHA1 encryption and a specific set of parameters.
Make sure you have your Payment Key ready from the Fondy portal. This key is required for signature generation.
When to Use Signatures
Signatures are used in two primary cases:
- Request Signatures: When sending a request to Fondy, the signature ensures the data is correct and authentic. For example, in a payment request, you must include a signature to verify that your information hasn't been tampered with.
- Response Validation: Fondy returns a response with a signature after processing your request. You can validate this signature to confirm that the response data has not been altered in transit.
Fondy SDKs automatically handle signature generation and response validation. If you are using an SDK, you do not need to manually create signatures or validate responses - the SDKs handle these tasks for you.
Creating a Signature
Let's walk through creating a signature with a practical example:
Step 1: Prepare Payment Parameters
First, define the parameters for your payment request. These parameters contain essential information about the transaction:
order_id
: A unique identifier for the paymentorder_desc
: A description of what is being purchasedcurrency
: The currency code for the transaction (e.g. GBP, USD, EUR)amount
: The payment amount in the smallest currency unit (e.g. cents/pence)merchant_id
: Your unique merchant identifier from Fondysender_email
: The customer's email address
{
"order_id": "test12345612122121221",
"order_desc": "test12121order",
"currency": "GBP",
"amount": 125,
"merchant_id": 1396424,
"sender_email": "email@email.com"
}
You can find your Payment Key in the Fondy portal under Merchant Settings.
Step 2: Create the Signature String
To create the signature string:
- Take all your payment parameters and sort their names alphabetically
- Get the value for each parameter in this sorted order
- Join all values with the | (pipe) symbol
- Add your Payment Key at the beginning, followed by another | symbol
For example, if your parameters are order_id
, amount
, and currency
, you would:
- Sort them:
amount
,currency
,order_id
- Get their values in that order
- Join with |:
value1|value2|value3
- Add Payment Key:
PaymentKey|value1|value2|value3
The final format will be:
Payment Key|amount|currency|merchant_id|order_desc|order_id|sender_email
Replacing with actual values:
PnguSqqcdmFH5p5UlLxXi5zm2SOdm6zW|125|GBP|1396424|test12121order|test12345612122121221|email@email.com
Step 3: Generate the SHA1 Hash
Using a SHA1 function on the signature string generates the final signature:
caf43947bfa47356214925099304a6b6f7afcc24
Complete Implementation
Here's a Python implementation that handles the entire process:
import hashlib
def generate_signature(data: dict, secret_key: str) -> str:
# Remove empty values and 'signature' parameter
clean_data = {k: str(v) for k, v in data.items()
if v is not None and v != "" and k != "signature"}
# Sort parameters alphabetically
sorted_keys = sorted(clean_data.keys())
# Get values in sorted order
values = [clean_data[k] for k in sorted_keys]
# Create signature string with Payment Key
signature_string = secret_key + "|" + "|".join(values)
# Generate SHA1 hash (lowercase)
return hashlib.sha1(signature_string.encode('utf-8')).hexdigest().lower()
# Example usage
payment_data = {
"order_id": "test12345612122121221",
"order_desc": "test12121order",
"currency": "GBP",
"amount": 125,
"merchant_id": 1396424,
"sender_email": "email@email.com"
}
# Generate signature using your Payment Key
signature = generate_signature(payment_data, "PnguSqqcdmFH5p5UlLxXi5zm2SOdm6zW")
Using the Signature
After generating the signature, include it in your API request to the Accept Purchase (Fondy Checkout) endpoint:
{
"request": {
"order_id": "test12345612122121221",
"order_desc": "test12121order",
"currency": "GBP",
"amount": 125,
"signature": "caf43947bfa47356214925099304a6b6f7afcc24",
"merchant_id": 1396424,
"sender_email": "email@email.com"
}
}
Validating Signatures in Fondy Responses
Fondy responses include a signature
parameter that ensures the integrity of the data. When validating a response, you must recreate the signature using the response parameters and compare it with the provided signature
.
Step-by-Step Validation Guide
-
Remove Excluded Parameters Remove these parameters from the response before generating the signature:
signature
response_signature_string
(only appears in test mode)
-
Create Validation String
- Sort remaining parameters alphabetically
- Combine values with the
|
separator - Ensure:
- Empty parameters are excluded
- No
|
is added for empty values - UTF-8 encoding is used for non-Latin characters
-
Generate and Compare Signatures
def validate_response(response_data: dict, secret_key: str) -> bool:
# Get the signature from response
received_signature = response_data.pop('signature', '')
# Remove response_signature_string if present (test mode)
response_data.pop('response_signature_string', '')
# Generate signature from remaining data
calculated_signature = generate_signature(response_data, secret_key)
# Compare signatures
return received_signature == calculated_signature
Example Response Validation
# Example response data
response_data = {
"order_id": "test12345612122121221",
"payment_id": "125",
"status": "approved",
"signature": "6bd069be8a6e2f2bbe176df00ba63cc681ca38aa"
}
# Validate the response
is_valid = validate_response(response_data, "PnguSqqcdmFH5p5UlLxXi5zm2SOdm6zW")
if is_valid:
print("Response signature is valid")
else:
print("Invalid signature - possible data tampering")
Common Issues and Troubleshooting
Invalid Signature Error in API Response
If you receive an invalid signature error, check these common issues:
-
Payment Key Verification
# Ensure you're using the correct Payment Key from your Merchant Portal
secret_key = "YOUR_ACTUAL_PAYMENT_KEY" # Get this from Merchant Settings -
UTF-8 Encoding
# Ensure proper encoding for non-Latin characters
signature_string = signature_string.encode('utf-8') -
Zero Values
# Ensure zero values are treated correctly
clean_data = {k: str(v) for k, v in data.items()
if v is not None and v != "" and k != "signature"} -
Debug Signature String
# Log the signature string for debugging
print(f"Signature String: {signature_string}")
# Compare with response_signature_string in test mode
Mismatched Signature in Server Callbacks
When handling server callbacks, verify:
-
Parameter Exclusion
# Remove signature and response_signature_string
callback_data = response_data.copy()
callback_data.pop('signature', None)
callback_data.pop('response_signature_string', None) -
Parameter Order
# Ensure correct parameter order
sorted_keys = sorted(callback_data.keys())
ordered_values = [callback_data[k] for k in sorted_keys]
Best Practices
-
Case Sensitivity
# Always use lowercase for SHA1 output
signature = hashlib.sha1(signature_string).hexdigest().lower()Correct:
6bd069be8a6e2f2bbe176df00ba63cc681ca38aa
Incorrect:6BD069BE8A6E2F2BBE176DF00BA63CC681CA38AA
-
Endpoint-Specific Parameters
- Include only the necessary parameters for your specific endpoint
- Different endpoints may require different parameters:
/api/recurring
has different requirements than/api/redirect
- Check the endpoint documentation for required parameters
When in test mode, use the response_signature_string
parameter to debug signature generation. This parameter shows the exact string used to generate the signature.
Following these guidelines and troubleshooting steps, you can effectively implement signature validation and handle any signature-related issues in your integration with Fondy Gateway.