PSE Reference Fields Encryption (JWE)
What is it and what is it for?
When processing transactions through PSE, you can send the fields reference-one, reference-two, and reference-three as part of the payment-method object. These fields may contain sensitive information depending on your merchant's economic activity (for example, IP addresses, document numbers, or financial product opening dates).
To protect this information, Wompi offers you the option to encrypt these fields using JWE (JSON Web Encryption). This is completely optional: if your business does not require encryption, you can continue sending values in plain text as usual. Wompi automatically detects whether a field is encrypted or not and processes it transparently.
When should you use encryption?
Consider encrypting the reference fields if:
- Your business belongs to the Financial Services category and you send sensitive user data in these fields.
- You want to add an extra layer of security to the information traveling in the transaction.
- Your internal security policy requires sensitive data to be transmitted encrypted.
If none of these cases apply to you, you can continue sending the fields in plain text without any issues.
How does it work?
The process is straightforward:
- Download the public key from this Wompi documentation page.
- Encrypt the fields
reference-one,reference-two, and/orreference-threeusing that public key. - Send the encrypted values in your transaction, whether through the Widget, Web Checkout, or directly via API.
- Wompi detects that the fields are encrypted, decrypts them internally, and processes the transaction normally.
You can encrypt all reference fields, just some, or none at all. Each field is evaluated independently, so it is perfectly valid to send reference-one in plain text and reference-two encrypted in the same transaction.
Step 1: Get the public key
The RSA public key you need for encryption is available directly on this page. Copy it or download it using the button:
LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUlJQ0lqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FnOEFNSUlDQ2dLQ0FnRUFwWVVEMW9wclRteUFyWVJ6d3k3SgpzM1EyRXhPN1ZEY0ViT256RVpBTzBtZlA5YWY3OU9ObEpzQ1JzWkl1bjhuZW5kenR0UHlEWE1Qak0zWTAxMzhtCmUyb3Erb05UY1pkY1pLaGFGYTBiVjdTOC9TaWlpS2VsczFnTG5nQUszbWx0bmJKTGFKMGwrOFA2THc5bHZXbVYKQ1NBUUk5WFJNaWdtdkxLa2JJT1lSY0tOdkpIekJMQkNxNzh1L01KZCsxZWJ1bGx5ZzN2VmZuZ1RBZUJRcVFkawp3aGxQY2Z4Z2dteWlKbTdmajRXcUFGTzdQalMrTUd0RDZRNklBRUZYa28zS0N0OVhxWkJnRER4ZERxL01qNklYCmhxNUd6MFJYU2tKVStYcTFiS2hGOTErM0x2VUwrZmVwS2R3aDd6cnFPa2I3d2ZwODVHcVo4dkRVU2ZOMlR4THUKZXFlVm5JOWJjT3BsUXlsTTlxckY4TDBleTZxR24wMERQb0NCRGNiL1NJNnF3blhtdjNoUW9NWWlOR0pTejAvbApIUmx0UGpJWFplMUZTNWVwbndmcVVMaC92SEhmWllrVDVaazVzUG9QNlVSTzJrZGtjVmpaMWNUUHRvRTNqemN5Ck9KWnQ5eDNUWVcrbXNhMGFndjlyUXNPazlkRFFTNTFaUVZtLzM4UmV3Ly9Sc0x3YVk4RVV3WE1NR2lBc2ZZb0wKOEJjR1I1bXB0ZVJFcGEwZTJvZGNyYVh5dGo3UndwZTZPWFRMTlA3VWN1RENwOHBUM202ODMxWFlxUXk0LzdhSAp4WTJaNUNncklOT00zeUQ0VkdNQzhKVVc3L3BqTnI2bHJjNytYRldrODhyYlBzMWhucVhkZk5HNUdiOHg3WHBjCjBEYWpwa3RDdlRFU3JBTGtZOHJzaVMwQ0F3RUFBUT09Ci0tLS0tRU5EIFBVQkxJQyBLRVktLS0tLQo=
We recommend storing this key in an environment variable or in your application's configuration, and refreshing it periodically in case Wompi rotates the keys.
Step 2: Encrypt the reference fields
The encryption uses the JWE (JSON Web Encryption) standard in compact serialization format. The algorithms you should use are:
| Parameter | Value | Description |
|---|---|---|
alg (Key Management) | RSA-OAEP | Algorithm for wrapping the ephemeral symmetric key using the RSA public key |
enc (Content Encryption) | A256GCM | Content encryption algorithm (AES-256-GCM) |
The encryption result is a string with 5 segments separated by dots:
BASE64URL(Header).BASE64URL(EncryptedKey).BASE64URL(IV).BASE64URL(Ciphertext).BASE64URL(AuthTag)
Example with jose v2 (Node.js)
If your project uses jose version 2:
npm install jose@^2.0.7
const { JWE, JWK } = require('jose');
// 1. Load the public key you downloaded from the Wompi documentation
const publicKey = JWK.asKey(PUBLIC_KEY_PEM);
// 2. Encrypt the reference field value
const encryptedReferenceOne = JWE.encrypt(
'192.168.1.1', // The value you want to encrypt
publicKey,
{ alg: 'RSA-OAEP', enc: 'A256GCM' }
);
// encryptedReferenceOne is now a JWE string ready to send
console.log(encryptedReferenceOne);
// eyJhbGciOiJSU0EtT0FFUCIsImVuYyI6IkEyNTZHQ00ifQ.abc123...
Example with jose v4+ / v5 (Node.js)
If your project uses jose version 4 or higher:
npm install jose@^5.0.0
const { importSPKI, CompactEncrypt } = require('jose');
async function encryptReference(value, publicKeyPem) {
// 1. Import the public key
const publicKey = await importSPKI(publicKeyPem, 'RSA-OAEP');
// 2. Encrypt the value
const encoder = new TextEncoder();
const jwe = await new CompactEncrypt(encoder.encode(value))
.setProtectedHeader({ alg: 'RSA-OAEP', enc: 'A256GCM' })
.encrypt(publicKey);
return jwe;
}
// Usage
const encryptedReferenceOne = await encryptReference('192.168.1.1', PUBLIC_KEY_PEM);
Step 3: Send the encrypted fields in your transaction
Once the fields are encrypted, send them exactly as you would send plain text values. Wompi automatically detects the JWE format and decrypts them before processing the transaction. You don't need to indicate in any way that the fields are encrypted: the system identifies it on its own.
In the Widget or Web Checkout
Use the reference-one, reference-two, and reference-three fields within the payment-method object as you normally would. The only difference is that the value will be the encrypted JWE string instead of plain text:
<form>
<script
src="https://checkout.wompi.co/widget.js"
data-render="button"
data-public-key="pub_test_X0zDA9xoKdePzhd8a0x9HAez7HgGO2fH"
data-currency="COP"
data-amount-in-cents="4950000"
data-reference="MY-UNIQUE-REFERENCE"
data-signature:integrity="YOUR_INTEGRITY_SIGNATURE"
data-payment-method:reference-one="eyJhbGciOiJSU0EtT0FFUCIsImVuYyI6IkEyNTZHQ00ifQ..."
data-payment-method:reference-two="eyJhbGciOiJSU0EtT0FFUCIsImVuYyI6IkEyNTZHQ00ifQ..."
data-payment-method:reference-three="eyJhbGciOiJSU0EtT0FFUCIsImVuYyI6IkEyNTZHQ00ifQ..."
></script>
</form>
The data-payment-method:reference-* attributes accept both plain text and JWE encrypted values. You can migrate gradually without changing your integration structure.
Via API
If you integrate directly with the Wompi API, send the encrypted values in the request body within the payment_method object. The field accepts the full JWE string:
{
"payment_method": {
"type": "PSE",
"reference_one": "eyJhbGciOiJSU0EtT0FFUCIsImVuYyI6IkEyNTZHQ00ifQ...",
"reference_two": "eyJhbGciOiJSU0EtT0FFUCIsImVuYyI6IkEyNTZHQ00ifQ...",
"reference_three": "eyJhbGciOiJSU0EtT0FFUCIsImVuYyI6IkEyNTZHQ00ifQ..."
}
}
You can mix encrypted and plain text fields in the same transaction. For example, sending reference_one encrypted and reference_two in plain text is perfectly valid.
## Full example
This example shows how to get the public key, encrypt all three reference fields, and send the transaction:
```javascript
const { importSPKI, CompactEncrypt } = require('jose');
async function createEncryptedTransaction() {
// 1. Use the public key you downloaded from the Wompi documentation
const publicKeyPem = process.env.WOMPI_PUBLIC_KEY; // Store it in an environment variable
// 2. Import the public key
const publicKey = await importSPKI(publicKeyPem, 'RSA-OAEP');
const encoder = new TextEncoder();
// 3. Helper function to encrypt a field
const encrypt = async (value) => {
return new CompactEncrypt(encoder.encode(value))
.setProtectedHeader({ alg: 'RSA-OAEP', enc: 'A256GCM' })
.encrypt(publicKey);
};
// 4. Encrypt the reference fields
const referenceOne = await encrypt('192.168.1.1');
const referenceTwo = await encrypt('20230115');
const referenceThree = await encrypt('123456789');
// 5. Send the transaction with the encrypted fields
// Encrypted fields are used just like plain text ones,
// Wompi detects and decrypts them automatically.
}
Important things to know
- It's optional. Encryption is an additional security layer. If you don't need it, keep sending the fields in plain text.
- You can mix. It is valid to send some fields encrypted and others in plain text in the same transaction. Each field is evaluated independently.
- Error-tolerant. If decryption fails for any reason (wrong key, corrupted token, etc.), the field is passed as-is to processing. Wompi will not reject the transaction due to a decryption error.
- Always use Wompi's public key. Do not generate your own key pair. The public key you need is available for download on this page.
- Refresh periodically. We recommend fetching the public key regularly to make sure you are using the most recent one, in case Wompi rotates it.
- PSE only. This encryption is available exclusively for the reference fields of the PSE payment method in Colombia.