This is the String that will then be signed at the next step

As the fourth step, you should generate the message that will be used for creating the signature.
This message must include the information of the request you are about to make.

In order to create it, you need to compose the following message fragments by using the headers that will be sent.


(request-target)

To generate this message fragment, simply combine the lowercased HTTP verb and the request path.
The request path must include, if available, route parameters and the query string.
These values should be separated by a space, as illustrated in the examples below.

(request-target): post /g_business/v1/payments
(request-target): get /g_business/v1/payments/5a62264a-50c2-4f83-b21b-108ece88a442
(request-target): get /g_business/v1/payments?status=ACCEPTED

host

To create this message fragment, simply use the host where you intend to make your HTTP request.
The host here must be the same sent in the Host header.

For more details, please refer to: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Host

host: authservices.satispay.com
host: authservices.satispay.com:443

🚧

Beware

Make sure to maintain coherence when specifying the port.
If you include the port in the header, ensure that it is also included in the message and in the request.


date

To create this message fragment, just format the current date and time according to the following pattern.
The date here must be the same sent in the Date header.

The pattern is described in the RFC 2822.

EEE, dd MMM yyyy HH:mm:ss Z
Mon, 18 Mar 2019 15:10:24 +0000

digest

To create this message fragment, just take the previously generated digest from the body that you're about to send.
The digest here must be the same sent in the Digest header.

digest: SHA-256=47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=

Compose the Message

To compose your message, arrange the message fragments, line by line, in the following order:
(request-target), host, date, and digest, as demonstrated in the example below.

POST /wally-services/protocol/tests/signature HTTP/1.1
Host: staging.authservices.satispay.com
Date: Mon, 18 Mar 2019 15:10:24 +0000
Content-Type: application/json
Content-Length: 123
Digest: SHA-256=ZML76UQPYzw5yDTmhySnU1S8nmqGde/jhqOG5rpfVSI=
{
  "flow": "MATCH_CODE",
  "amount_unit": 100,
  "currency": "EUR"
}
(request-target): post /wally-services/protocol/tests/signature
host: staging.authservices.satispay.com
date: Mon, 18 Mar 2019 15:10:24 +0000
digest: SHA-256=ZML76UQPYzw5yDTmhySnU1S8nmqGde/jhqOG5rpfVSI=

🚧

Notes

Omit any leading or trailing optional whitespace in the header field value.

When multiple instances of the same header field are present, combine their values by separating them with a comma and a space, and maintain the order in which they will appear in the transmitted HTTP message.


Code sample 2/4

$bodyObject = [
    'flow' => 'MATCH_CODE',
    'amount_unit' => 100,
    'currency' => 'EUR'
];

$body = json_encode($bodyObject);

echo "body:\n";
echo $body . "\n";

$digest = "SHA-256=" . base64_encode(hash("sha256", $body, true));

echo "\ndigest:\n";
echo $digest . "\n";

$date = date('r');

echo "\ndate:\n";
echo $date . "\n";

$message = "(request-target): post /g_business/v1/payments
host: staging.authservices.satispay.com
date: $date
digest: $digest";

echo "\nmessage:\n";
echo $message . "\n";
const crypto = require('crypto');
const fs = require('fs');

const bodyObject = {
    flow: 'MATCH_CODE',
    amount_unit: 100,
    currency: 'EUR'
};

const body = JSON.stringify(bodyObject);

console.log("\nbody:");
console.log(body);

const digest = "SHA-256=" + crypto.createHash('sha256').update(body).digest('base64');

console.log("\ndigest:");
console.log(digest);

const date = new Date().toUTCString();

console.log("\ndate:");
console.log(date);

const message = "(request-target): post /g_business/v1/payments\n" +
    "host: staging.authservices.satispay.com\n" +
    "date: " + date + "\n" +
    "digest: " + digest;

console.log("\nmessage:");
console.log(message);
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.KeyFactory;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.Signature;
import java.security.SignatureException;
import java.security.InvalidKeyException;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.text.SimpleDateFormat;
import java.util.Base64;
import java.util.Date;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.json.JSONObject;

public class Satispay {
    public static void main(String[] args) {
        JSONObject bodyObject = new JSONObject()
            .put("flow", "MATCH_CODE")
            .put("amount_unit", 100)
            .put("currency", "EUR");

        String body = bodyObject.toString();

        System.out.println("body:");
        System.out.println(body);

        String digest = createDigest(body);

        System.out.println();
        System.out.println("digest:");
        System.out.println(digest);

        SimpleDateFormat sdf = new SimpleDateFormat("E, dd MMM yyyy HH:mm:ss Z");
        String date = sdf.format(new Date());

        System.out.println();
        System.out.println("date:");
        System.out.println(date);

        String message = "(request-target): post /g_business/v1/payments\n" +
                         "host: staging.authservices.satispay.com\n" +
                         "date: " + date + "\n" +
                         "digest: " + digest;


        System.out.println();
        System.out.println("message:");
        System.out.println(message);
    }

    private static String createDigest(String body) {
        try {
            MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
            byte[] hashBytes = messageDigest.digest(body.getBytes("UTF-8"));
        
            return "SHA-256=" + Base64.getEncoder().encodeToString(hashBytes);
        } catch (NoSuchAlgorithmException | UnsupportedEncodingException e) {
            e.printStackTrace();
            System.exit(1);
        }

        return null;
    }
}
using System;
using System.Collections.Generic;
using System.Security.Cryptography;
using System.Text;
using System.Text.Json;

class Satispay
{
    static void Main(string[] args)
    {
        var bodyObject = new Dictionary<string, object>
        {
            { "flow", "MATCH_CODE" },
            { "amount_unit", 100 },
            { "currency", "EUR" }
        };

        var body = JsonSerializer.Serialize(bodyObject);

        Console.WriteLine("body:");
        Console.WriteLine(body);

        var digest = createDigest(body);

        Console.WriteLine();
        Console.WriteLine("digest:");
        Console.WriteLine(digest);

        string date = DateTime.UtcNow.ToString("r");

        Console.WriteLine();
        Console.WriteLine("date:");
        Console.WriteLine(date);

        string message = "(request-target): post /g_business/v1/payments\n" +
                         "host: staging.authservices.satispay.com\n" +
                        $"date: {date}\n" +
                        $"digest: {digest}";

        Console.WriteLine();
        Console.WriteLine("message:");
        Console.WriteLine(message);
        Console.WriteLine(authorization);
    }

    static string createDigest(string body)
    {
        var sha256 = SHA256.Create();

        var hashBytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(body));

        return "SHA-256=" + Convert.ToBase64String(hashBytes);
    }
}
import json
import hashlib
import base64
import time
import datetime
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric import padding
from cryptography.hazmat.primitives import hashes

body_object = {
    'flow': 'MATCH_CODE',
    'amount_unit': 100,
    'currency': 'EUR'
}

body = json.dumps(body_object)

print("body:")
print(body)

digest = "SHA-256=" + base64.b64encode(hashlib.sha256(body.encode()).digest()).decode()

print()
print("digest:")
print(digest)

date = datetime.datetime.now(datetime.timezone.utc).strftime('%a, %d %b %Y %H:%M:%S GMT')

print()
print("date:")
print(date)

message = "(request-target): post /g_business/v1/payments\n\
host: staging.authservices.satispay.com\n\
date: " + date + "\n\
digest: " + digest

print()
print("message:")
print(message)

#!/bin/bash

body='{
  "flow": "MATCH_CODE",
  "amount_unit": 100,
  "currency": "EUR"
}'

echo "body:"
printf "%s" "$body"

digest="SHA-256=$(printf "%s" "$body" | openssl dgst -sha256 -binary | base64 -w 0)"

echo "\n"
echo "\ndigest:"
echo "$digest"

date=$(date -R)

echo "\ndate:"
echo "$date"

message="(request-target): post /g_business/v1/payments"$'\n'
message+="host: staging.authservices.satispay.com"$'\n'
message+="date: $date"$'\n'
message+="digest: $digest"

echo "\nmessage:"
echo "$message"