Skip to content

Register the integration webhook in Sequra#104

Closed
tamaralogeecom wants to merge 17 commits intomasterfrom
feature/LIS-90
Closed

Register the integration webhook in Sequra#104
tamaralogeecom wants to merge 17 commits intomasterfrom
feature/LIS-90

Conversation

@tamaralogeecom
Copy link
Copy Markdown
Collaborator

@tamaralogeecom tamaralogeecom commented Dec 29, 2025

What is the goal?

  • Register the integration webhook in Sequra and enable webhook re-registration on the Connection page

References

How is it being implemented?

  • Implemented RegexProvider
  • Added encodeURIComponent to replace values in the URL path
  • Updated CORE version for integration registration logic
  • Updated CORE UI version to render the button and handle webhook re-registration
  • Added a migration to register webhooks for existing users

How is it tested?

  • Run the command to check the PHP syntax
  • Manual tests
    • New installation
      • Install and enable the SeQura module in the Magento 2 system.
      • Test the onboarding flow.
      • Test webhook re-registration on the Connection Settings page.
    • Existing installation
      • Update the SeQura module in the Magento 2 system.
      • Test module behavior
      • Test webhook re-registration on the Connection Settings page.

@tamaralogeecom
Copy link
Copy Markdown
Collaborator Author

We have noticed that an “Advanced” section has been added in the latest CORE UI version. Should these changes be included in the current onboarding implementation for the Magento 2 integration? They would require implementing a new endpoint and backend business logic. If this is something that should be included at this point, then the exact requirements for what the endpoint should return need to be clearly defined.

@tamaralogeecom
Copy link
Copy Markdown
Collaborator Author

We also observed that encodeURIComponent was replaced with a direct string replacement for {storeId} in the API calls. This approach does not work for the Magento 2 integration because Magento generates the backend URL and automatically encodes URI components when {storeId} or any other value is added to the path. That encoded value must then be replaced. For now, the JS controllers in the Magento integration are overridden so that encodeURIComponent is still used, ensuring the plugin behaves as expected.

@tamaralogeecom
Copy link
Copy Markdown
Collaborator Author

Please provide us with the translations for the button on the Connection Settings page, which allows merchants to re-register their store integration for the corresponding deployment target:

Button label:

  • Re-register webhooks

Success message:

  • Webhooks were re-registered successfully.

Error message:

  • Webhooks were not re-registered successfully.

@mescalantea
Copy link
Copy Markdown
Contributor

We also observed that encodeURIComponent was replaced with a direct string replacement for {storeId} in the API calls. This approach does not work for the Magento 2 integration because Magento generates the backend URL and automatically encodes URI components when {storeId} or any other value is added to the path. That encoded value must then be replaced. For now, the JS controllers in the Magento integration are overridden so that encodeURIComponent is still used, ensuring the plugin behaves as expected.

Thanks @tamaralogeecom for pointing this out. I've submitted a solution via this PR. Please have a look at it

@mescalantea
Copy link
Copy Markdown
Contributor

We have noticed that an “Advanced” section has been added in the latest CORE UI version. Should these changes be included in the current onboarding implementation for the Magento 2 integration? They would require implementing a new endpoint and backend business logic. If this is something that should be included at this point, then the exact requirements for what the endpoint should return need to be clearly defined.

This new section is not part of the Onboarding flow. It is accesible once the onboarding is completed. I would implement it in a new PR due you will need to do several changes to support it. There's a working implementation in the woocommerce repository you can use as a guide.

@mescalantea
Copy link
Copy Markdown
Contributor

mescalantea commented Dec 30, 2025

Please provide us with the translations for the button on the Connection Settings page, which allows merchants to re-register their store integration for the corresponding deployment target:

Button label:

  • Re-register webhooks
    🇪🇸 Volver a registrar webhooks
    🇫🇷 Re-enregistrer les webhooks
    🇮🇹 Registrare nuovamente i webhook
    🇵🇹 Registrar novamente os webhooks

Success message:

  • Webhooks were re-registered successfully.
    🇪🇸 Los webhooks se registraron nuevamente con éxito.
    🇫🇷 Les webhooks ont été réenregistrés avec succès.
    🇮🇹 I webhook sono stati registrati nuovamente con successo.
    🇵🇹 Os webhooks foram registrados novamente com sucesso.

Error message:

  • Webhooks were not re-registered successfully.
    🇪🇸 No se pudieron volver a registrar los webhooks.
    🇫🇷 Les webhooks n’ont pas pu être réenregistrés avec succès.
    🇮🇹 Non è stato possibile registrare nuovamente i webhook.
    🇵🇹 Não foi possível registrar novamente os webhooks.

@tamaralogeecom

@m1k3lm m1k3lm marked this pull request as ready for review January 8, 2026 16:49
Copilot AI review requested due to automatic review settings January 8, 2026 16:49
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This pull request implements webhook registration functionality in Sequra for a Magento 2 integration. The changes include adding a webhook re-registration button on the Connection Settings page, implementing a RegexProvider for validation, updating the CORE and CORE UI library versions, and adding an Advanced section with debug logging capabilities.

Key Changes:

  • Added webhook re-registration functionality with UI button and backend endpoint
  • Implemented regex validation system with ValidationService updates
  • Added Advanced/Debug section for log management
  • Updated CORE UI library to enable new features
  • Fixed URL parameter encoding (changed from encodeURIComponent wrapping to inline usage)
  • Added comprehensive translation updates for 5 languages (EN, ES, FR, IT, PT)

Reviewed changes

Copilot reviewed 36 out of 41 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
StateController.js (override) Adds Advanced state/pages, fixes URL encoding, adds data store clearing
SettingsController.js (override) Updates to use new encoding pattern and adds SequraFE.customHeader
PaymentController.js (override) Adds support link, updates encoding, handles payment method icons
ConnectionSettingsForm.js Implements webhook re-registration button and handler
AdvancedController.js New controller for debug logs management page
ValidationService.js Adds regex provider requirement check and new validation methods
UtilityService.js Adds getMenuItems helper for navigation
ResponseService.js Adds successHandler for success messages
ElementGenerator.js Adds createActionsBar and createSupportLink helpers
GeneralSettingsForm.js Adds service-related fields and validation
Translation files Comprehensive updates for webhook, debug, and service features
sequra-core.css Major styling updates with proper scoping and new components
index.phtml Adds regex configuration and ValidationService loading
sequra_configuration_index.xml Updates script loading order
package.json Updates CORE UI version to feature branch

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread view/adminhtml/web/js/AdvancedController.js Outdated
Comment thread view/adminhtml/web/js/GeneralSettingsForm.js Outdated
Comment thread view/adminhtml/web/js/GeneralSettingsForm.js Outdated
Comment thread view/adminhtml/web/js/ElementGenerator.js Outdated
Comment thread view/adminhtml/web/js/override/StateController.js Outdated
Tamara Vukovic added 2 commits January 13, 2026 17:43
ISSUE: LIS-90
ISSUE: LIS-90
@m1k3lm m1k3lm requested a review from Copilot March 3, 2026 08:23
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 36 out of 41 changed files in this pull request and generated 17 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +281 to +284

if (!dataStore.deploymentsSettings?.some(deployment => deployment.active === true)) {
page = SequraFE.appPages.DEPLOYMENTS;
}
Copy link

Copilot AI Mar 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (blocking): Invalid appPages reference breaks onboarding navigation
SequraFE.appPages.DEPLOYMENTS doesn’t exist (DEPLOYMENTS is nested under appPages.ONBOARDING). This will set page to undefined and can route users to the wrong onboarding step. Use SequraFE.appPages.ONBOARDING.DEPLOYMENTS here (and in the other occurrences in this switch).

Copilot uses AI. Check for mistakes.
Comment on lines +99 to +103
currentVersion: version.current,
newVersion: {
versionLabel: version.new,
versionUrl: version.downloadNewVersionUrl
},
Copy link

Copilot AI Mar 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (blocking): newVersion is always rendered, even when no update is available
PageHeader shows a download link whenever newVersion is truthy and versionLabel !== currentVersion. Passing { versionLabel: null, versionUrl: null } will still be truthy and can render a broken link. Pass null unless both version.new and version.downloadNewVersionUrl are present.

Copilot uses AI. Check for mistakes.
Comment on lines +71 to +74
Promise.all([
sellingCountries ? [] : api.get(configuration.getSellingCountriesUrl, null, SequraFE.customHeader),
paymentMethods ? [] : api.get(configuration.getPaymentMethodsUrl.replace(encodeURIComponent('{merchantId}'), countryConfiguration[0].merchantId)),
]).then(([sellingCountriesRes, paymentMethodsRes]) => {
Copy link

Copilot AI Mar 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (blocking): Missing custom header when loading payment methods
This get() call omits SequraFE.customHeader (3rd param), so it may fail in environments where the backend requires the custom header. Use api.get(url, null, SequraFE.customHeader) (and keep the encoded {merchantId} replacement).

Copilot uses AI. Check for mistakes.
Comment on lines +463 to +469
const valid = validator.validateDateOrDuration(changedGeneralSettings.defaultServicesEndDate);
validator.validateField(
document.querySelector('.sq-default-services-end-date'),
!valid,
'validation.invalidTimeDuration'
);

Copy link

Copilot AI Mar 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (blocking): isValidTimeDuration() can crash when the field isn’t rendered
document.querySelector('.sq-default-services-end-date') can be null when service-selling fields aren’t added, but validateField() assumes a non-null element and will throw. Guard on SequraFE.flags.isServiceSellingAllowed and/or the element existing before validating.

Suggested change
const valid = validator.validateDateOrDuration(changedGeneralSettings.defaultServicesEndDate);
validator.validateField(
document.querySelector('.sq-default-services-end-date'),
!valid,
'validation.invalidTimeDuration'
);
// If service selling is not allowed, skip validating the related field.
if (SequraFE.flags && SequraFE.flags.isServiceSellingAllowed === false) {
return true;
}
const fieldElement = document.querySelector('.sq-default-services-end-date');
const valid = validator.validateDateOrDuration(changedGeneralSettings.defaultServicesEndDate);
// Only attempt to validate the field if the element exists in the DOM.
if (fieldElement) {
validator.validateField(
fieldElement,
!valid,
'validation.invalidTimeDuration'
);
}

Copilot uses AI. Check for mistakes.
Comment on lines +134 to +135
$jsonEncoded = json_encode($regex);
return $jsonEncoded === false ? '' : $jsonEncoded;
Copy link

Copilot AI Mar 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (blocking): Returning an empty string can generate invalid JS
If json_encode() fails, this returns '', and the template outputs SequraFE.regex = ; which is a syntax error. Return '{}' (or throw) on failure; consider JSON_THROW_ON_ERROR to surface encoding problems.

Suggested change
$jsonEncoded = json_encode($regex);
return $jsonEncoded === false ? '' : $jsonEncoded;
try {
$jsonEncoded = json_encode($regex, JSON_THROW_ON_ERROR);
} catch (\JsonException $e) {
// Fallback to an empty JSON object to avoid generating invalid JavaScript
return '{}';
}
return $jsonEncoded;

Copilot uses AI. Check for mistakes.
Comment on lines +98 to +101
promises = Promise.all([
SequraFE.state.getData('paymentMethods') ?? api.get(configuration.getPaymentMethodsUrl.replace(encodeURIComponent('{merchantId}'), countrySettings[0].merchantId)),
SequraFE.state.getData('allAvailablePaymentMethods') ?? api.get(configuration.getAllAvailablePaymentMethodsUrl, null, SequraFE.customHeader),
])
Copy link

Copilot AI Mar 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (blocking): Missing auth header + wrong get() signature when fetching payment methods
ajaxService.get(url, errorCallback, customHeader) treats the 2nd argument as the error callback. This call passes no customHeader, so requests can fail if the backend requires it. Pass null (or a callback) as the 2nd arg and SequraFE.customHeader as the 3rd.

Copilot uses AI. Check for mistakes.
Comment on lines +206 to +216
const handleCountryChange = (value) => {
utilities.showLoader();
api.get(configuration.getPaymentMethodsUrl.replace(encodeURIComponent('{merchantId}'), value))
.then((methods) => {
paymentMethods = [...methods];
document.querySelector('.sq-table-container').remove();
document.querySelector('.sq-content-inner')?.append(
components.DataTable.create(getTableHeaders(), getTableRows())
)
})
.finally(utilities.hideLoader);
Copy link

Copilot AI Mar 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (blocking): Missing custom header when changing country
This request omits SequraFE.customHeader (and passes the URL as the only argument, so the 2nd arg is treated as errorCallback). Use api.get(url, null, SequraFE.customHeader) to keep the request consistent with other authenticated calls.

Copilot uses AI. Check for mistakes.
size: 'medium',
className: '',
onClick: handleReRegister,
label: 'Re-register webhooks'
Copy link

Copilot AI Mar 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue: Button label isn’t translatable
createButton() treats label as a translation key. Using a literal string here prevents localization (and bypasses the existing connection.webhookReRegistration.title key). Use a translation key for the button label.

Suggested change
label: 'Re-register webhooks'
label: 'connection.webhookReRegistration.title'

Copilot uses AI. Check for mistakes.
Comment on lines +603 to +604
SequraFE.responseService.errorHandler(
{errorMessage: error}
Copy link

Copilot AI Mar 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue: Error handling passes a non-string into errorHandler
In the catch block, { errorMessage: error } passes an Error/object, which will typically render as [object Object] and won’t translate. Pass a translation key (or error.message) or just forward the backend error shape returned by ajaxService (often contains errorCode/errorMessage).

Suggested change
SequraFE.responseService.errorHandler(
{errorMessage: error}
const errorMessage =
error && typeof error === 'object'
? (error.errorMessage || error.message || 'connection.webhookReRegistration.errorMessage')
: (error || 'connection.webhookReRegistration.errorMessage');
SequraFE.responseService.errorHandler(
{errorMessage: errorMessage}

Copilot uses AI. Check for mistakes.
Comment thread composer.json
"prefer-stable": true,
"require": {
"php": ">=7.4 <8.5",
"sequra/integration-core": "dev-feature/LIS-90",
Copy link

Copilot AI Mar 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue: Composer dependency points to a dev branch
Depending on sequra/integration-core: dev-feature/LIS-90 makes builds non-reproducible and can unexpectedly change as the branch moves. Prefer a tagged release (or a fixed commit reference) before merging to reduce deployment risk.

Suggested change
"sequra/integration-core": "dev-feature/LIS-90",
"sequra/integration-core": "dev-feature/LIS-90#abcdef1234567890abcdef1234567890abcdef12",

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants