forked from apoloz/alfa-bank-sdk
fix(sign)
This commit is contained in:
@@ -12,37 +12,47 @@ trait SignableData
|
||||
{
|
||||
public function sign(SignerInterface $signer): self
|
||||
{
|
||||
// 1. Create a clone to represent the data-to-be-signed (without existing signatures)
|
||||
$clone = clone $this;
|
||||
// 1. Get raw data as array
|
||||
$data = $this->toArray();
|
||||
|
||||
// We explicitly set digestSignatures to null or empty for the signature calculation
|
||||
// assuming the bank expects the "business payload" only.
|
||||
// If the bank expects the field "digestSignatures": [] to be present in signed string,
|
||||
// we should initialize it as empty collection.
|
||||
// Based on common practices, we exclude it or keep it null.
|
||||
// Let's assume we exclude it (set to null if the property is nullable).
|
||||
$clone->digestSignatures = null;
|
||||
// 2. Remove existing signatures if any
|
||||
unset($data['digestSignatures']);
|
||||
|
||||
// 2. Serialize to JSON
|
||||
// We use JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES to match typical API expectations
|
||||
$jsonToSign = $clone->toJson(JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
|
||||
// 3. Canonicalize (RFC 8785 - simple version: sort keys, remove nulls, no spaces)
|
||||
$canonicalData = $this->canonicalizeArray($data);
|
||||
|
||||
$jsonToSign = json_encode($canonicalData, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
|
||||
|
||||
// 3. Sign
|
||||
// 4. Sign
|
||||
$signature = $signer->sign($jsonToSign);
|
||||
|
||||
// 4. Attach signature to the original object
|
||||
// 5. Attach signature to the original object
|
||||
if ($this->digestSignatures === null) {
|
||||
$this->digestSignatures = new DataCollection(DigestSignatureData::class, []);
|
||||
}
|
||||
|
||||
// We can't push to DataCollection directly if it's not array-access compatible in all versions,
|
||||
// but Spatie DataCollection is usually iterable.
|
||||
// Safest way is to reconstruct it.
|
||||
$current = array_values($this->digestSignatures->toCollection()->all());
|
||||
$current[] = new DigestSignatureData($signature, 'cms');
|
||||
$current[] = new DigestSignatureData($signature, 'rsa');
|
||||
|
||||
$this->digestSignatures = new DataCollection(DigestSignatureData::class, $current);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
private function canonicalizeArray(array $array): array
|
||||
{
|
||||
// Remove nulls and empty strings
|
||||
$array = array_filter($array, fn($v) => $v !== null);
|
||||
|
||||
// Sort keys lexically
|
||||
ksort($array);
|
||||
|
||||
foreach ($array as $key => $value) {
|
||||
if (is_array($value)) {
|
||||
$array[$key] = $this->canonicalizeArray($value);
|
||||
}
|
||||
}
|
||||
|
||||
return $array;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user