Signature computing

Widget URL

To authenticate your marketplace with the Pleenk Widget, all url requests must be signed. Add a query param named signature with the value of the calculated signature. This ensures secure and authorized communication between your marketplace and Pleenk.

Widget Signature Calculation

To secure the data fields sent with the widget, follow these steps:

  1. Sort Fields Alphabetically:
    • Arrange all fields that start with pw_ in alphabetical order by their names.
  2. Encode Fields in UTF-8:
    • Ensure that all field values are encoded in UTF-8 format.
  3. Concatenate Field Values:
    • Concatenate the values of these fields into a single string, separating each value with the “+” character.
  4. Convert to ByteArray:
    • Convert the resulting concatenated string into an 8-bit ByteArray.
  5. Sign the ByteArray:
    • Use the ECDSA key with SHA-512 to sign this ByteArray.
  6. Encode the Signature:
    • Convert the resulting signature into a URLBase64 string.
  7. Add to Signature Field:
    • Save this URLBase64 string in the signature field of your widget.
public static String sign(Map<String, String> params, PrivateKey privateKey) throws Exception {
  var data = params.entrySet().stream()
    .sorted(Map.Entry.comparingByKey())
    .map(Map.Entry::getValue)
    .collect(Collectors.joining("+"));

  var signature = Signature.getInstance("SHA512withECDSA");
  signature.initSign(privateKey);
  signature.update(data.getBytes(StandardCharsets.UTF_8));
  return Base64.getUrlEncoder().withoutPadding().encodeToString(signature.sign());
}
function sign($params, $privateKeyPem) {
    ksort($params);
    $data = implode('+', array_values($params));

    $privateKey = openssl_pkey_get_private($privateKeyPem);
    openssl_sign($data, $signature, $privateKey, OPENSSL_ALGO_SHA512);

    return rtrim(strtr(base64_encode($signature), '+/', '-_'), '=');
}
def sign(params, private_key_pem):
    sorted_params = sorted(params.items())
    data = '+'.join(value for key, value in sorted_params)

    private_key = ecdsa.SigningKey.from_pem(private_key_pem)
    signature = private_key.sign(data.encode('utf-8'), hashfunc=hashlib.sha512, sigencode=ecdsa.util.sigencode_der)

    return base64.urlsafe_b64encode(signature).decode('utf-8').rstrip('=')
import  { createSign } from 'crypto';

const privateKeyPem = `-----BEGIN PRIVATE KEY-----
....................................................................
....................................................................
-----END PRIVATE KEY-----`


const sign = (params, privateKey) => {
  const sortedParams = Object.keys(params).sort().map(key => params[key]).join('+');

  const sign = createSign("SHA512");
  sign.update(sortedParams);
  sign.end();
  return Buffer.from((sign.sign(privateKey)).toString('base64url'));
}

function run() {
    const confidentialityWalletId = "XXXXXXXX"

    const params = {
      pw_confidentiality_wallet: confidentialityWalletId,
      pw_description: "Product 123",
      pw_transaction_ref: "INTERNAL-ID",
      pw_beneficiary_0: `${confidentialityWalletId}|42`,
    }

    const signature = sign(params, privateKeyPem)

    const httpParams = Object.entries({...params, ...{signature: signature}})
      .map(([key, value]) =>
        `${encodeURIComponent(key)}=${encodeURIComponent(value)}`
      )
      .join('&');

		return 'https://app.sandbox.pleenk.com/payment?' + httpParams
}

By following these steps, you ensure that the data being transmitted is secure and verifiable, maintaining the integrity of your transactions with Pleenk.

API

To authenticate your marketplace with the Pleenk API, all HTTP requests must be signed. Add a custom HTTP header named pleenk-signature with the value of the calculated signature. This ensures secure and authorized communication between your marketplace and Pleenk.

Signature computing for GET

To secure the URL of your GET request, follow these steps:

  1. Convert the URL(Path + Query Param) to an 8-bit ByteArray:
    • Ensure that the entire URL string is converted to a ByteArray. Ex: /path?param1=value&param2=value2
  2. Sign the ByteArray:
    • Use the ECDSA key with SHA-512 to sign the ByteArray.
  3. Encode the Signature:
    • Convert the resulting signature into a URLBase64 string.
  4. Add to Header:
    • Save this URLBase64 string in the pleenk-signature header of your HTTP request.
public static String sign(String url, PrivateKey privateKey) throws Exception {
  var signature = Signature.getInstance("SHA512withECDSA");
  signature.initSign(privateKey);
  signature.update(url.getBytes(StandardCharsets.UTF_8));
  return Base64.getUrlEncoder().withoutPadding().encodeToString(signature.sign());
}
function sign($url, $privateKeyPem) {
    $privateKey = openssl_pkey_get_private($privateKeyPem);
    openssl_sign($url, $signature, $privateKey, OPENSSL_ALGO_SHA512);

    return rtrim(strtr(base64_encode($signature), '+/', '-_'), '=');
}
def sign(url, private_key_pem):
    private_key = ecdsa.SigningKey.from_pem(private_key_pem)
    signature = private_key.sign(url.encode('utf-8'), hashfunc=hashlib.sha512, sigencode=ecdsa.util.sigencode_der)

    return base64.urlsafe_b64encode(signature).decode('utf-8').rstrip('=')
import  { createSign } from 'crypto';

const privateKeyPem = `-----BEGIN PRIVATE KEY-----
....................................................................
....................................................................
-----END PRIVATE KEY-----`

const sign = (params, privateKey) => {
  const sortedParams = Object.keys(params)
    .sort()
    .map((key) => params[key])
    .join("+");

  const sign = createSign("SHA512");
  sign.update(sortedParams);
  sign.end();
  return Buffer.from(sign.sign(privateKey).toString("base64url"));
};

function run() {
  const confidentialityWalletId = "XXXXXXXX";

  const params = {
    pw_confidentiality_wallet: confidentialityWalletId,
    pw_description: "Product 123",
    pw_transaction_ref: "INTERNAL-ID",
    pw_beneficiary_0: `${confidentialityWalletId}|42`,
  };

  const signature = sign(params, privateKeyPem);

  const httpParams = Object.entries({ ...params, ...{ signature: signature } })
    .map(
      ([key, value]) =>
        `${encodeURIComponent(key)}=${encodeURIComponent(value)}`,
    )
    .join("&");

  return "https://app.sandbox.pleenk.com/payment?" + httpParams;
}

Signature computing for POST

To secure the URL of your POST request, follow these steps:

  1. Convert the body payload to an 8-bit ByteArray:
    • Ensure that the request payload is converted to a ByteArray.
  2. Sign the ByteArray:
    • Use the ECDSA key with SHA-512 to sign the ByteArray.
  3. Encode the Signature:
    • Convert the resulting signature into a URLBase64 string.
  4. Add to Header:
    • Save this URLBase64 string in the pleenk-signature header of your HTTP request.
public static String sign(String payload, PrivateKey privateKey) throws Exception {
  var signature = Signature.getInstance("SHA512withECDSA");
  signature.initSign(privateKey);
  signature.update(payload.getBytes(StandardCharsets.UTF_8));
  return Base64.getUrlEncoder().withoutPadding().encodeToString(signature.sign());
}
function sign($payload, $privateKeyPem) {
    $privateKey = openssl_pkey_get_private($privateKeyPem);
    openssl_sign($payload, $signature, $privateKey, OPENSSL_ALGO_SHA512);

    return rtrim(strtr(base64_encode($signature), '+/', '-_'), '=');
}
def sign(payload, private_key_pem):
    private_key = ecdsa.SigningKey.from_pem(private_key_pem)
    signature = private_key.sign(payload.encode('utf-8'), hashfunc=hashlib.sha512, sigencode=ecdsa.util.sigencode_der)

    return base64.urlsafe_b64encode(signature).decode('utf-8').rstrip('=')
function sign(payload, privateKeyPem) {
    const sign = crypto.createSign('SHA512');
    sign.update(payload);
    const signature = sign.sign(privateKeyPem);
    return signature.toString('base64').replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
}