How to parse Uniform webhook response?

I’m trying to use Uniform to allow site visitors to sign up to my clients newsletter. The newsletter is managed through Hubspot and I managed to send data to the provided Webhook.

It actually works but does never ever returns the error response from Hubspot. FOr example if a user (an email) already exists in the system…

Tried to output non-success quite verbose for debugging

// site/snippet/newsletter-form.php
...
<?php if ($form->success()): ?>
            Thank you for your message. We will get back to you soon!
        <?php else: ?>
            No-success:
            <?php snippet('uniform/errors', ['form' => $form]) ?>
        <?php endif; ?>

        <?php if ($form->error()): ?>
                Error Errors:
                <?php foreach($form->error() as $err): ?>
                    <?= $err ?>
                <?php endforeach ?>
        <?php endif; ?>

Do I need to manually parse the response to their API and return it to the frontend. If so – how?

This is what my controller looks like:

// site/controllers/default.php
use Uniform\Form;

return function ($kirby)
{
    $form = new Form([
        'email' => [
            'rules' => ['required', 'email'],
            'message' => 'Please enter a valid email address',
        ],
    ]);

    if ($kirby->request()->is('POST')) {
        // hubspot want data to be in properties array inside data -> do that to the data
        $properties = $form->data('', '', true);
       $form
        ->webhookAction([
            'url' => 'https://api.hubapi.com/crm/v3/objects/contacts',
            'json' => true,
            'params' => [
                'method' => 'POST',
                'data' => [
                    'properties' => $properties
                ],
                'headers' => ["Authorization: Bearer $access_token"],
            ],
        ]);
    }

    return compact('form');
};

Thank you! :slight_smile:

As far as I can see from a quick look into the source code, this Webhook action never returns anything, unless the remote request itself fails. So if the request is successful and the error only in the response, nothing will ever be returned.

Thanks for the quick reply!

You’re right. For now I duplicated the code into a Custom Action (see Actions - Kirby Uniform) and raising an error on HTTP request codes above 201 (which is “Created”).

This is the code I added:

if ($response->code() > 201) {
  $errorMsg = json_decode($response->content())->message;
  $this->fail('An error occurred: ' . $errorMsg);
}

As my Hubspot endpoint requires data (fields) to be present in a dedicated properties key I make use of the Action’s transform function.

public function transformData(array $data)
{
    return ['properties' => $data];
}

Full code below.

Thanks again, Danke und Tschüss! :wave:

<?php
//site/plugins/uniform-custom-actions/HubspotAction.php
namespace Uniform\Actions;

use Exception;
use Kirby\Toolkit\A;
use Kirby\Http\Remote;
use Kirby\Toolkit\I18n;

class HubspotAction extends Action
{
    public function perform()
    {
        $url = $this->requireOption('url');
        $only = $this->option('only');
        $except = $this->option('except');
        $escape = $this->option('escapeHtml', true);

        if (is_array($only)) {
            $data = [];
            foreach ($only as $key) {
                $data[$key] = $this->form->data($key, '', $escape);
            }
        } else {
            $data = $this->form->data('', '', $escape);
        }

        if (is_array($except)) {
            foreach ($except as $key) {
                unset($data[$key]);
            }
        }

        $params = $this->option('params', []);
        // merge the optional 'static' data from the action array with the form data
        $data = array_merge(A::get($params, 'data', []), $data);
        $params['data'] = $this->transformData($data);

        if ($this->option('json') === true) {
            $headers = ['Content-Type: application/json'];
            $params['data'] = json_encode($params['data'], JSON_UNESCAPED_SLASHES);
        } else {
            $headers = ['Content-Type: application/x-www-form-urlencoded'];
        }

        $params['headers'] = array_merge(A::get($params, 'headers', []), $headers);

        try {
            $response = Remote::request($url, $params);
            
            if ($response->code() > 201) {
                $errorMsg = json_decode($response->content())->message;
                $this->fail('An error occurred: ' . $errorMsg);
            }
        } catch (Exception $e) {
            $this->fail(I18n::translate('uniform-webhook-error').$e->getMessage());
        }
    }

    public function transformData(array $data)
    {
        return ['properties' => $data];
    }
}