React to webhooks with EXT:reactions
since TYPO3 12.1
There is a new addition to the TYPO3 family: TYPO3 12.1 introduces the new system extension reactions. This will make it possible in future to create and edit data records in TYPO3 via webhooks, but also to initiate other tasks such as an import or to retrieve certain status information from TYPO3.
Webhooks are requests (web requests) to a system in order to complete predefined tasks. You may already know webhooks from Github, because you can also set up webhooks there so that, for example, the new version is automatically updated in Packagist after a deployment or a fresh version of your extension documentation is rendered.
Currently (02.12.2022) TYPO3 is only delivered with a predefined reaction type. This type can be used to create certain data records such as pages, categories, content elements or file collections. The new system already comes with its own registration for reactions, so it is only a matter of time before TYPO3 itself will offer further reaction types or that the TYPO3 community will extend this system with further reaction types by means of extensions.
Create new Reaction data record
EXT:reactions comes with a new backend module that you can use to create and edit reactions. Click on "Create new Reaction" at the top of the Reactions module. There you can now select the reaction type that the reaction should take care of. As already mentioned, only the type"Create database record" is currently available. For the name and description, you can describe the reaction in more detail in your own words, such as "Create category from Shopware". The identifier is automatically filled in by TYPO3 and cannot be changed. The reaction can be uniquely identified via this identifier and is a mandatory part of the subsequent request. In the Secret field, click on the small Generate icon to create a new authorization token for this reaction. Attention: Copy the authorization token somewhere, because it will only be displayed once! After saving it, you will no longer have access to it and the database will only contain an argon2id hash that you cannot use for the request. If you have lost the token, please generate a new token using the Generate icon and save the data record.
Further down, select the table in which the new data record is to be created. Use Storage-PID to specify in which system folder (PID) new data records are to be stored and select a user in the Impersonate User field in whose name the new data records are to be created. Make sure that the user has all rights or is assigned to a corresponding group that is allowed to create the new data records. You may want to test this manually beforehand to be sure.
Depending on which table you have selected, a different number of additional fields will now appear, which you can fill with default values. If you don't always want to create the same data record with the same title and description with the reaction, you can use placeholders that can be dynamically filled with data from the request (the payload). More on this later.
After saving, your new reaction appears in the list view of the Reactions module.
Calling the Reaction
In the list view of the Reaction module, you can see the URL that you should use for the call for each Reaction data record. Example:
https://typo3git.ddev.site/typo3/reaction/baf6b616-e1ea-48d6-ab45-f8562e8028a7
For a complete example of a cURL request, click on Example:
curl -X 'POST' \
'https://typo3git.ddev.site/typo3/reaction/baf6b616-e1ea-48d6-ab45-f8562e8028a7' \
-d '{"my-payload":"my-value","field-b":"my-input"}' \
-H 'accept: application/json' \
-H 'x-api-key: ***your-secret***'
You must replace the ***your-secret*** section with the authorization token that you created using the generate icon. If you now execute this shell command in a terminal window, the execution should be acknowledged with {"success":true} and you will find a newly created data set in your system folder defined above.
Dynamic values using payload
Instead of using fixed default values for the fields, you have the option of accessing data from the payload. There is this syntax for this: ${path}
Let's take another look at a cURL command:
curl -X 'POST' \
'https://typo3git.ddev.site/typo3/reaction/baf6b616-e1ea-48d6-ab45-f8562e8028a7' \
-d '{"category":{"title": "Cars", "desc": "wromm wromm"}}' \
-H 'accept: application/json' \
-H 'x-api-key: 25356c33f500f092daf65d0091eb90af6e9c3a78'
With the option "-d" you can add additional data to this POST request. This data must be specified in JSON format and is converted internally into an array. This can also be a multiple nested array, as shown above.
TYPO3 already provides a corresponding path syntax to extract a specific value even in large, multi-nested arrays. To get to the title of the category in the request from above, you must use the following placeholder: ${category.title}. It is up to you to link this value with another predefined value: Shopware category: ${category.title}
Create your own reaction types
According to Services.yaml of the reactions extension, you only need to create a new PHP class that implements the interface \TYPO3\CMS\Reactions\Reaction\ReactionInterface. As a result, this class is automatically provided with the reactions.reaction tag via dependency injection and is made available in the ReactionRegistry, thus extending the selection of reaction types in the selection menu of the reaction data set.
Among other things, the interface "forces" you to create a method react. The complete request, the prepared payload (the data as an array) and the reaction data set as a ReactionInstruction object are made available to you as arguments. Values that cannot be retrieved as a getter method in the ReactionInstruction object must be retrieved using the toArray() method: toArray()['my_special_value'] ?? ''