Request-Flow
App\Services\Grenke\RequestFlowService
Der Orchestrator-Service. Verkettet bis zu 8 Actions zu einem Geschäfts-Workflow:
Create → optional Patch → Poll bis ReadyToSign → E-Signature ODER Paper-Contract → optional Vertrag holen
Endpunkt
POST /api/v1/grenke/grenke/request-flow
Eine Validation-Klasse: App\Http\Requests\GrenkeRequestFlowRequest (die größte FormRequest-Klasse im Projekt).
Flow-Diagramm
Zwei Modi
| Modus | Trigger | Zweck |
|---|---|---|
e_signature | cancel_e_signature: false | Standard-Flow mit Online-Unterschrift |
cancel_e_signature | cancel_e_signature: true | E-Signature wird abgebrochen, Wechsel zu Papiervertrag |
Vollständiges Request-Beispiel
curl -X POST https://api.bluesafety.dev/api/v1/grenke/grenke/request-flow \
-H 'Authorization: Bearer 1|...' \
-H 'Content-Type: application/json' \
-d '{
"request_payload": {
"FinancingAmount": 33877.56,
"Period": 84,
"PaymentFrequency": "Monthly",
"PaymentMethod": "DirectDebit",
"Currency": "EUR",
"ResidualValue": 0,
"ProductType": "ClassicLease",
"HasRepurchase": true,
"Lessee": {
"CompanyName": "Dr. Bettina Brem & Katrin Schimmelpfennig",
"ExternalId": "K562983",
"Email": "info@example.com",
"LegalFormId": 0,
"Addresses": [
{ "Line1": "Truderinger Str. 330", "PostCode": "81825", "City": "München", "Country": "DE", "Type": "main" }
],
"Telephones": [
{ "Number": "+49 89 890566800", "Type": "Phone" },
{ "Number": "+49 89 890566808", "Type": "Fax" }
]
},
"FinancingObjects": [
{ "Quantity": 2, "ObjectTypeId": 13, "Name": "Human Medical Equipment",
"Manufacturer": "BLUE SAFETY", "Details": "SAFEWATER 4.2", "NetPricePerObject": 16938.78 }
]
},
"e_signature_payload": {
"SignerName": "Bettina Brem",
"SignerEmail": "bettina.brem@example.com"
},
"patch_request_payload": { "PaymentMethod": "Invoice" },
"cancel_e_signature": false,
"fetch_contract_document_base64": true,
"fetch_contract_document_download_link": false,
"max_attempts": 10,
"sleep_milliseconds": 1000
}'
Response-Shape (Modus e_signature)
{
"success": true,
"data": {
"success": true,
"mode": "e_signature",
"financingId": "F-1234567",
"request": { ... RequestResponseData::toArray() ... },
"patchedRequest": null,
"patchedLessee": null,
"readyRequest": { ... RequestResponseData::toArray() ... },
"configuration": { ... ESignatureConfigurationData::toArray() ... },
"eSignature": { ... },
"contractDocumentBase64": { "Content": "JVBERi0..." },
"contractDocumentDownloadLink": null
}
}
Programmatisch nutzen
Der Service ist auch direkt aus eigenen Services / Jobs heraus aufrufbar:
- E-Signature-Flow
- Paper-Contract-Flow
- Mit Patch & polling
use App\Services\Grenke\RequestFlowService;
$result = $this->grenkeRequestFlowService->execute(
requestPayload: RequestPayloadData::fromArray($payload),
eSignaturePayload: ESignaturePayloadData::fromArray([
'SignerName' => 'Bettina Brem',
'SignerEmail' => 'bettina.brem@example.com',
]),
fetchContractDocumentBase64: true,
maxAttempts: 15,
sleepMilliseconds: 1500,
);
$result = $this->grenkeRequestFlowService->execute(
requestPayload: RequestPayloadData::fromArray($payload),
cancelESignature: true,
);
// returns mode = 'cancel_e_signature'
$result = $this->grenkeRequestFlowService->execute(
requestPayload: RequestPayloadData::fromArray($payload),
eSignaturePayload: ESignaturePayloadData::fromArray($esign),
patchRequestPayload: PatchRequestPayloadData::fromArray(['PaymentMethod' => 'Invoice']),
patchLesseePayload: PatchLesseePayloadData::fromArray(['CompanyName' => 'XYZ GmbH']),
maxAttempts: 20,
sleepMilliseconds: 2000,
);
Polling — maxAttempts & sleepMilliseconds
Wenn der State nach dem Create nicht direkt ReadyToSign ist, pollt WaitForGrenkeReadyToSignAction bis zu maxAttempts Mal mit sleepMilliseconds Pause dazwischen.
| Parameter | Default | Empfehlung Production |
|---|---|---|
max_attempts | 10 | 15–20 |
sleep_milliseconds | 1000 | 1500–2000 |
Achtung: in einem HTTP-Request kann der Endpoint also bis zu
max_attempts × sleepblockieren. Konfiguriere die PHPmax_execution_timeund Web-Server-Timeouts entsprechend (oder packe den Flow in einen Job).
State-Branching während des Pollings
Wenn der State während des Pollings auf …
ReadyToSign→ return → Flow geht weiter zu E-SignatureMissingInfo→ triggert MissingInfo-Mailflow → ExceptionCancelled/Declined→ Exception (abortsProcess())RunningContract/ContractPrinted→ Exception (Flow ist schon vorbei)
Error-Handling im Controller
try {
$result = $this->grenkeRequestFlowService->execute(/* ... */);
return response()->json(['success' => true, 'data' => $result]);
} catch (Throwable $e) {
\Log::error('GrenkeRequestFlowController store failed', ['message' => $e->getMessage()]);
return response()->json(['success' => false, 'message' => $e->getMessage()], 500);
}