diff --git a/assets/css/admin/facebook-for-woocommerce-whatsapp-utility.css b/assets/css/admin/facebook-for-woocommerce-whatsapp-utility.css
new file mode 100644
index 000000000..76fa2dea5
--- /dev/null
+++ b/assets/css/admin/facebook-for-woocommerce-whatsapp-utility.css
@@ -0,0 +1,249 @@
+.onboarding-card {
+ background-color: #f7f7f7;
+ border: 1px solid #ccc;
+ border-radius: 10px;
+ box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
+ width: 680px;
+ margin: 40px auto 0; /* Top margin 5px, horizontal centering */
+}
+.custom-dashicon-check {
+ position: relative;
+ display: inline-block;
+ width: 26px; /* Set the size of the circle */
+ height: 26px; /* Set the size of the circle */
+ background-color: #1a805b; /* Fill the circle with green */
+ border-radius: 50%; /* Make it a circle */
+ margin-right: 20px;
+ top: 50%;
+ transform: translateY(-50%);
+}
+.custom-dashicon-check::before {
+ content: '\f147'; /* Unicode for dashicons-yes-alt */
+ font-family: 'Dashicons';
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ transform: translate(-55%, -45%) scale(1.2); /* Center and slightly enlarge the checkmark */
+ font-size: 20px; /* Set the size of the checkmark */
+ color: white; /* Make the checkmark white */
+ text-shadow:
+ -4px 0 #1a805b,
+ 4px 0 #1a805b,
+ 0 -2px #1a805b,
+ 0 2px #1a805b; /* Increase shadow offsets to thin the checkmark more */
+}
+
+.custom-dashicon-circle {
+ position: relative;
+ display: inline-block;
+ width: 20px; /* Set the size of the circle */
+ height: 20px; /* Set the size of the circle */
+ border-radius: 50%; /* Make it a circle */
+ margin-right: 20px;
+ border: 3px solid #222121ab;
+ top: 50%;
+ transform: translateY(-50%);
+}
+.custom-dashicon-halfcircle {
+ position: relative;
+ display: inline-block;
+ width: 20px; /* Set the size of the circle */
+ height: 20px; /* Set the size of the circle */
+ border-radius: 50%; /* Make it a circle */
+ margin-right: 20px;
+ border: 3px solid #222121ab;
+ background-image: linear-gradient(to left, #222121ab 50%, transparent 50%);
+ background-clip: padding-box; /* Add this line */
+ top: 50%;
+ transform: translateY(-50%);
+}
+.card-content-icon {
+ display: flex;
+}
+.card-item {
+ padding: 10px 24px;
+ justify-content: space-between;
+ display: flex;
+}
+.divider {
+ border-bottom: 1px solid #ccc;
+}
+.review-payment-content {
+ padding: 20px;
+ margin-bottom: 10px;
+}
+.whatsapp-onboarding-button {
+ margin-left: auto;
+ position: relative;
+ top: 50%;
+ margin: auto 0; /* Ensure button is centered */
+}
+.whatsapp-onboarding-done-button {
+ margin-left: auto;
+ padding: 6px 0;
+}
+.card-content {
+ max-width: 90%;
+}
+.card-content-icon h2 {
+ top: 50%;
+}
+.card-content-icon p {
+ margin-top: -10px; /* Remove margin top */
+}
+.event-config {
+ display: flex;
+ flex-direction: row;
+ padding-top: 10px;
+}
+.event-config-heading-container {
+ display: flex;
+ flex-direction: row;
+}
+.event-config-manage-button {
+ position: relative;
+ margin-left: auto;
+ top: 50%;
+ padding-left: 20px;
+ padding-right: 10px;
+}
+.event-config-status {
+ background-color: #FFFFFF;
+ border: 1px solid #9f9f9f;
+ color: #9f9f9f;
+ padding: 4px 10px;
+ text-align: center;
+ display: inline-block;
+ border-radius: 16px;
+ margin-left: 10px;
+ font-size: small;
+ align-self: center;
+}
+.on-status {
+ background-color: #00A32A;
+ color: #FFFFFF;
+ border:none;
+}
+.manage-event-card-item {
+ padding: 20px;
+ justify-content: space-between;
+}
+.manage-event-selector {
+ min-width: 100%;
+}
+.manage-event-template-block {
+ border: 1px solid #c4c3c3;
+ margin-bottom: 20px;
+}
+.manage-event-template-header {
+ position: relative;
+ display: block;
+ padding: 20px;
+ font-size: medium;
+}
+.manage-event-template-footer {
+ padding: 20px;
+ display: flex;
+ flex-direction: row-reverse;
+ justify-content: flex-start;
+}
+.manage-event-button {
+ margin-left: 20px;
+}
+.fbwa-hidden-element {
+ display: none;
+}
+.error-notice-wrapper {
+ justify-content: left;
+ padding-left: 20px;
+ padding-bottom: 10px;
+ margin-right: 20px; /* Add the right margin */
+}
+.notice-error {
+ background-color: #f7f7f7;
+ border: 1px solid #EF0000; /* Red border */
+ border-radius: 0; /* No curvature */
+ border-left-width: 5px; /* Thicker left border */
+ width: 100%; /* Take up full width */
+}
+.notice-error p {
+ margin: 5px;
+}
+.warning-custom-modal {
+ display: none; /* Hidden by default */
+ position: absolute;
+ left: 0;
+ top: 0;
+ width: 100%;
+ height: 100%;
+ background-color: rgba(0,0,0,0.4); /* Black with opacity */
+}
+/* Modal content */
+.warning-modal-content {
+ background-color: #fefefe;
+ margin: 25% auto;
+ padding: 20px;
+ border: 1px solid #ddd;
+ top: 10%;
+ width: 50%;
+ max-width: 500px;
+ border-radius: 10px;
+ box-shadow: 0 4px 8px rgba(0,0,0,0.1);
+}
+/* Modal body */
+.warning-modal-body {
+ padding: 20px 0;
+}
+/* Modal footer */
+.warning-modal-footer {
+ padding: 10px 0;
+ text-align: right;
+}
+/* Close button */
+.warning-modal-close {
+ color: #aaa;
+ float: right;
+ font-size: 28px;
+ font-weight: bold;
+ cursor: pointer;
+ position: absolute;
+ right: 0;
+ top: 0;
+}
+.warning-modal-close:hover {
+ color: #000;
+}
+.whatsapp-icon {
+ width: 45px;
+ height: 40px;
+ flex-shrink: 0; /* Prevents icon from shrinking */
+}
+.contact-info {
+ padding-left: 10px;
+ display: flex;
+ flex-direction: column;
+}
+.contact-info h3 {
+ margin: 0;
+ font-size: 1.1em;
+}
+.contact-info p {
+ margin: 0;
+ font-size: 1.1em;
+ color: #666;
+}
+.disconnect-footer-left {
+ display: flex;
+ padding: 25px;
+}
+.disconnect-footer-right-separator {
+ margin-right:10px;
+}
+.disconnect-footer-right {
+ padding: 30px;
+ margin-left: auto;
+}
+.disconnect-footer {
+ display: flex;
+ position: relative;
+}
diff --git a/assets/images/whatsapp_icon.png b/assets/images/whatsapp_icon.png
new file mode 100644
index 000000000..7637f5b15
Binary files /dev/null and b/assets/images/whatsapp_icon.png differ
diff --git a/assets/js/admin/whatsapp-billing.js b/assets/js/admin/whatsapp-billing.js
new file mode 100644
index 000000000..3ba8c2bb6
--- /dev/null
+++ b/assets/js/admin/whatsapp-billing.js
@@ -0,0 +1,50 @@
+/**
+ * Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
+ *
+ * This source code is licensed under the license found in the
+ * LICENSE file in the root directory of this source tree.
+ *
+ * @package FacebookCommerce
+ */
+
+jQuery( document ).ready( function( $ ) {
+ var $billingStepInProgress = $('#wc-fb-whatsapp-billing-inprogress');
+ var $billingStepNotStarted = $('#wc-fb-whatsapp-billing-notstarted');
+ var $billingStepSuccess = $('#wc-fb-whatsapp-billing-success');
+ var $billingSubcontent = $('#wc-fb-whatsapp-billing-subcontent');
+ var $billingButtonWrapper = $('#wc-fb-whatsapp-billing-button-wrapper');
+ var $whatsappOnboardingDoneButton = $('#whatsapp-onboarding-done-button');
+ if (facebook_for_woocommerce_whatsapp_billing.consent_collection_enabled) {
+ facebook_for_woocommerce_whatsapp_billing.is_payment_setup ? $billingStepSuccess.show() : $billingStepInProgress.show();
+ $whatsappOnboardingDoneButton.show();
+ $billingStepNotStarted.hide();
+ } else {
+ $billingStepInProgress.hide();
+ $billingStepNotStarted.show();
+ $billingSubcontent.hide();
+ $whatsappOnboardingDoneButton.hide();
+ $billingButtonWrapper.hide()
+ }
+
+ // handle the whatsapp add payment button click should open billing flow in Meta
+ $('#wc-whatsapp-add-payment').click(function(event) {
+
+ $.post( facebook_for_woocommerce_whatsapp_billing.ajax_url, {
+ action: 'wc_facebook_whatsapp_fetch_url_info',
+ nonce: facebook_for_woocommerce_whatsapp_billing.nonce
+ }, function ( response ) {
+ if ( response.success ) {
+ console.log( 'Whatsapp Billing Url Info Fetched Successfully', response );
+ var business_id = response.data.business_id;
+ var asset_id = response.data.waba_id;
+ const BILLING_URL = `https://business.facebook.com/billing_hub/accounts/details/?business_id=${business_id}&asset_id=${asset_id}&account_type=whatsapp-business-account`;
+ window.open( BILLING_URL);
+ } else {
+ console.log( 'Whatsapp Billing Url Info Fetch Failure', response );
+ }
+ } );
+
+
+ });
+
+} );
diff --git a/assets/js/admin/whatsapp-connection.js b/assets/js/admin/whatsapp-connection.js
new file mode 100644
index 000000000..e6674fcf6
--- /dev/null
+++ b/assets/js/admin/whatsapp-connection.js
@@ -0,0 +1,73 @@
+/**
+ * Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
+ *
+ * This source code is licensed under the license found in the
+ * LICENSE file in the root directory of this source tree.
+ *
+ * @package FacebookCommerce
+ */
+
+jQuery( document ).ready( function( $ ) {
+ var $connectSuccess = $('#wc-fb-whatsapp-connect-success');
+ var $connectInProgress = $('#wc-fb-whatsapp-connect-inprogress');
+ var $connectSubcontent = $('#wc-fb-whatsapp-onboarding-subcontent');
+ var $connectButtonWrapper = $('#wc-fb-whatsapp-onboarding-button-wrapper');
+ if (facebook_for_woocommerce_whatsapp_onboarding_progress.whatsapp_onboarding_complete) {
+ $connectSuccess.show();
+ $connectInProgress.hide();
+ $connectSubcontent.hide();
+ $connectButtonWrapper.hide();
+ } else {
+ $connectSuccess.hide();
+ $connectInProgress.show();
+ }
+
+ // handle the whatsapp connect button click should open hosted ES flow
+ $( '#woocommerce-whatsapp-connection' ).click( function( event ) {
+ const APP_ID = '474166926521348'; // WOO_COMMERCE_APP_ID
+ const CONFIG_ID = '1237758981048330'; // WOO_COMMERCE_WHATSAPP_CONFIG_ID
+ const HOSTED_ES_URL = `https://business.facebook.com/messaging/whatsapp/onboard/?app_id=${APP_ID}&config_id=${CONFIG_ID}`;
+ window.open( HOSTED_ES_URL);
+ updateProgress(0,1800000); // retry for 30 minutes
+ });
+
+ function updateProgress(retryCount = 0, pollingTimeout = 1800000) {
+ $.post( facebook_for_woocommerce_whatsapp_onboarding_progress.ajax_url, {
+ action: 'wc_facebook_whatsapp_onboarding_progress_check',
+ nonce: facebook_for_woocommerce_whatsapp_onboarding_progress.nonce
+ }, function ( response ) {
+
+ // check if the response is success (i.e. onboarding is completed)
+ if ( response.success ) {
+ console.log( 'Whatsapp Connection is Complete', response );
+ // update the progress for connect whatsapp step
+ $connectInProgress.remove();
+ $connectSuccess.show();
+ // collapse whatsapp onboarding step subcontect and button on success
+ $connectSubcontent.hide();
+ $connectButtonWrapper.hide();
+ // update the progress for collect consent step and show button and subcontent
+ $('#wc-fb-whatsapp-consent-collection-inprogress').show();
+ $('#wc-fb-whatsapp-consent-collection-notstarted').hide();
+ $('#wc-fb-whatsapp-consent-subcontent').show();
+ $('#wc-fb-whatsapp-consent-button-wrapper').show();
+
+ // update the progress of payment step if payment already setup
+ if(response.data['is_payment_setup'] === true) {
+ $('#wc-fb-whatsapp-billing-inprogress').hide();
+ $('#wc-fb-whatsapp-billing-notstarted').hide();
+ $('#wc-fb-whatsapp-billing-success').show();
+ }
+ } else {
+ console.log('Whatsapp connection is not complete. Checking again in 5 seconds:', response, ', retry attempt:', retryCount, 'pollingTimeout', pollingTimeout);
+ if(retryCount >= pollingTimeout) {
+ console.log('Max retries reached. Aborting.');
+ return;
+ }
+ setTimeout( function() { updateProgress(retryCount + 1, pollingTimeout); }, 5000 );
+ }
+ } );
+
+ }
+
+} );
diff --git a/assets/js/admin/whatsapp-consent-remove.js b/assets/js/admin/whatsapp-consent-remove.js
new file mode 100644
index 000000000..de76d9eaf
--- /dev/null
+++ b/assets/js/admin/whatsapp-consent-remove.js
@@ -0,0 +1,94 @@
+/**
+ * Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
+ *
+ * This source code is licensed under the license found in the
+ * LICENSE file in the root directory of this source tree.
+ *
+ * @package FacebookCommerce
+ */
+
+jQuery( document ).ready( function( $ ) {
+ // Get the modal and related elements
+ var modal = document.getElementById("wc-fb-warning-modal");
+ var cancelButton = document.getElementById("wc-fb-warning-modal-cancel");
+ var confirmButton = document.getElementById("wc-fb-warning-modal-confirm");
+ var $statusElement = $('#wc-whatsapp-collect-consent-status');
+
+ // On click of the remove button, show the warning modal
+ $("#wc-whatsapp-collect-consent-remove").click(function(event) {
+ // Show the modal
+ modal.style.display = "block";
+
+ // Prevent default action
+ event.preventDefault();
+ });
+
+ if (cancelButton) {
+ // Close modal when clicking the Cancel button
+ cancelButton.onclick = function() {
+ modal.style.display = "none";
+ };
+ }
+
+ if (confirmButton) {
+ // Handle confirm action
+ confirmButton.onclick = function() {
+ // Send the AJAX request to disable WhatsApp consent collection
+ $.post(facebook_for_woocommerce_whatsapp_consent_remove.ajax_url, {
+ action: 'wc_facebook_whatsapp_consent_collection_disable',
+ nonce: facebook_for_woocommerce_whatsapp_consent_remove.nonce
+ }, function(response) {
+ if (response.success) {
+ console.log( 'Whatsapp Consent Collection Disabled Successfully', response );
+ // Change the status from "on-status" to "off-status" for the specific element.
+ $statusElement.removeClass('on-status').addClass('off-status');
+ // Update the text to "Off".
+ $statusElement.text('Off');
+
+ // Hide the original "Remove" button
+ $('#wc-whatsapp-collect-consent-remove-container').addClass('fbwa-hidden-element');
+
+ // Show the "Add" button
+ $('#wc-whatsapp-collect-consent-add-container').removeClass('fbwa-hidden-element');
+ } else {
+ console.log( 'Whatsapp Consent Collection Disabling Failed', response );
+ }
+ });
+
+ // Close the modal
+ modal.style.display = "none";
+ };
+ }
+
+ // Add event listener to the "Add" button
+ $('#wc-whatsapp-collect-consent-add').click(function() {
+ // Send the AJAX request to enable WhatsApp consent collection
+ $.post(facebook_for_woocommerce_whatsapp_consent.ajax_url, {
+ action: 'wc_facebook_whatsapp_consent_collection_enable',
+ nonce: facebook_for_woocommerce_whatsapp_consent.nonce
+ }, function(response) {
+ if (response.success) {
+ console.log( 'Whatsapp Consent Collection Enabled Successfully', response );
+ // Change the status from "off-status" to "on-status" for the specific element.
+ $statusElement.removeClass('off-status').addClass('on-status');
+ // Update the text to "On".
+ $statusElement.text('On');
+
+ // Hide the "Add" button
+ $('#wc-whatsapp-collect-consent-add-container').addClass('fbwa-hidden-element');
+
+ // Show the original "Remove" button
+ $('#wc-whatsapp-collect-consent-remove-container').removeClass('fbwa-hidden-element');
+ } else {
+ console.log( 'Whatsapp Consent Collection Enabling Failed', response );
+ }
+ });
+ });
+
+ // Close modal when clicking outside of it
+ window.onclick = function(event) {
+ if (event.target == modal) {
+ modal.style.display = "none";
+ }
+ };
+});
diff --git a/assets/js/admin/whatsapp-consent.js b/assets/js/admin/whatsapp-consent.js
new file mode 100644
index 000000000..ee64c60c2
--- /dev/null
+++ b/assets/js/admin/whatsapp-consent.js
@@ -0,0 +1,83 @@
+/**
+ * Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
+ *
+ * This source code is licensed under the license found in the
+ * LICENSE file in the root directory of this source tree.
+ *
+ * @package FacebookCommerce
+ */
+
+jQuery( document ).ready( function( $ ) {
+ var $consentCollectSuccess = $('#wc-fb-whatsapp-consent-collection-success');
+ var $consentCollectInProgress = $('#wc-fb-whatsapp-consent-collection-inprogress');
+ var $consentCollectNotStarted = $('#wc-fb-whatsapp-consent-collection-notstarted');
+ var $consentSubcontent = $('#wc-fb-whatsapp-consent-subcontent');
+ var $consentButtonWrapper = $('#wc-fb-whatsapp-consent-button-wrapper');
+ if (facebook_for_woocommerce_whatsapp_consent.whatsapp_onboarding_complete) {
+ if (facebook_for_woocommerce_whatsapp_consent.consent_collection_enabled) {
+ showConsentCollectionProgressIcon(true, false, false);
+ $consentSubcontent.hide();
+ $consentButtonWrapper.hide();
+ } else {
+ showConsentCollectionProgressIcon(false, true, false);
+ }
+ } else {
+ showConsentCollectionProgressIcon(false, false, true);
+ $consentSubcontent.hide();
+ $consentButtonWrapper.hide();
+ }
+
+ // handle the whatsapp consent collect button click should save setting to wp_options table
+ $( '#wc-whatsapp-collect-consent' ).click( function( event ) {
+
+ $.post( facebook_for_woocommerce_whatsapp_consent.ajax_url, {
+ action: 'wc_facebook_whatsapp_consent_collection_enable',
+ nonce: facebook_for_woocommerce_whatsapp_consent.nonce
+ }, function ( response ) {
+ if ( response.success ) {
+ console.log( 'Whatsapp Consent Collection is Enabled in Checkout Flow', response );
+ // update the progress for collect consent step and hide the button and subcontent
+ showConsentCollectionProgressIcon(true, false, false);
+ $consentSubcontent.hide();
+ $consentButtonWrapper.hide();
+ // update the progress of billing step and show the button and subcontent
+ if(response.data['is_payment_setup'] === true) {
+ $('#wc-fb-whatsapp-billing-inprogress').hide();
+ $('#wc-fb-whatsapp-billing-notstarted').hide();
+ $('#wc-fb-whatsapp-billing-success').show();
+ } else {
+ $('#wc-fb-whatsapp-billing-inprogress').show();
+ $('#wc-fb-whatsapp-billing-notstarted').hide();
+
+ }
+ $('#wc-fb-whatsapp-billing-subcontent').show();
+ $('#wc-fb-whatsapp-billing-button-wrapper').show();
+ $('#whatsapp-onboarding-done-button').show();
+ } else {
+ console.log( 'Whatsapp Consent Collection Enabling has Failed', response );
+ }
+ } );
+
+ });
+
+ function showConsentCollectionProgressIcon(success, inProgress, notStarted) {
+ if (success) {
+ $consentCollectSuccess.show();
+ } else {
+ $consentCollectSuccess.hide();
+ }
+
+ if (inProgress) {
+ $consentCollectInProgress.show();
+ } else {
+ $consentCollectInProgress.hide();
+ }
+
+ if (notStarted) {
+ $consentCollectNotStarted.show();
+ } else {
+ $consentCollectNotStarted.hide();
+ }
+ }
+
+} );
diff --git a/assets/js/admin/whatsapp-disconnect.js b/assets/js/admin/whatsapp-disconnect.js
new file mode 100644
index 000000000..91cbde3de
--- /dev/null
+++ b/assets/js/admin/whatsapp-disconnect.js
@@ -0,0 +1,75 @@
+/**
+ * Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
+ *
+ * This source code is licensed under the license found in the
+ * LICENSE file in the root directory of this source tree.
+ *
+ * @package FacebookCommerce
+ */
+
+jQuery( document ).ready( function( $ ) {
+ // Get the modal and related elements
+ var modal = document.getElementById("wc-fb-disconnect-warning-modal");
+ var cancelButton = document.getElementById("wc-fb-disconnect-warning-modal-cancel");
+ var confirmButton = document.getElementById("wc-fb-disconnect-warning-modal-confirm");
+
+ // On click of the remove button, show the warning modal
+ $("#wc-whatsapp-disconnect-button").click(function(event) {
+ // Show the modal
+ modal.style.display = "block";
+
+ // Prevent default action
+ event.preventDefault();
+ });
+
+ if (cancelButton) {
+ // Close modal when clicking the Cancel button
+ cancelButton.onclick = function() {
+ modal.style.display = "none";
+ };
+ }
+
+ if (confirmButton) {
+ // Handle confirm action
+ confirmButton.onclick = function() {
+ $.post( facebook_for_woocommerce_whatsapp_disconnect.ajax_url, {
+ action: 'wc_facebook_disconnect_whatsapp',
+ nonce: facebook_for_woocommerce_whatsapp_disconnect.nonce
+ }, function ( response ) {
+ if ( response.success ) {
+ let url = new URL(window.location.href);
+ let params = new URLSearchParams(url.search);
+ params.delete('view');
+ url.search = params.toString();
+ window.location.href = url.toString();
+ console.log( 'Whatsapp Disconnect Success', response );
+ } else {
+ console.log("Whatsapp Disconnect Failure!!!",response);
+ }
+ } );
+
+ // Close the modal
+ modal.style.display = "none";
+ };
+ }
+
+ // handle whatsapp disconnect widget edit link click should open business manager with whatsapp asset selected
+ $( '#wc-whatsapp-disconnect-edit' ).click( function( event ) {
+ $.post( facebook_for_woocommerce_whatsapp_disconnect.ajax_url, {
+ action: 'wc_facebook_whatsapp_fetch_url_info',
+ nonce: facebook_for_woocommerce_whatsapp_disconnect.nonce
+ }, function ( response ) {
+
+ if ( response.success ) {
+ console.log( 'Whatsapp Edit Url Info Fetched Successfully', response );
+ var business_id = response.data.business_id;
+ var asset_id = response.data.waba_id;
+ const WHATSAPP_MANAGER_URL = `https://business.facebook.com/latest/whatsapp_manager/phone_numbers/?asset_id=${asset_id}&business_id=${business_id}`;
+ window.open(WHATSAPP_MANAGER_URL);
+ } else {
+ console.log( 'Whatsapp Edit Url Info Fetch Failure', response );
+ }
+ } );
+ });
+
+} );
diff --git a/assets/js/admin/whatsapp-events.js b/assets/js/admin/whatsapp-events.js
new file mode 100644
index 000000000..bfaed97df
--- /dev/null
+++ b/assets/js/admin/whatsapp-events.js
@@ -0,0 +1,129 @@
+/**
+ * Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
+ *
+ * This source code is licensed under the license found in the
+ * LICENSE file in the root directory of this source tree.
+ *
+ * @package FacebookCommerce
+ */
+
+jQuery( document ).ready( function( $ ) {
+ // Set Event Status for Order Placed
+ var orderPlacedActiveStatus = $('#order-placed-active-status');
+ var orderPlacedInactiveStatus = $('#order-placed-inactive-status');
+ if(facebook_for_woocommerce_whatsapp_events.order_placed_enabled){
+ orderPlacedInactiveStatus.hide();
+ orderPlacedActiveStatus.show();
+ }
+ else {
+ orderPlacedActiveStatus.hide();
+ orderPlacedInactiveStatus.show();
+ }
+
+ // Set Event Status for Order FulFilled
+ var orderFulfilledActiveStatus = $('#order-fulfilled-active-status');
+ var orderFulfilledInactiveStatus = $('#order-fulfilled-inactive-status');
+ if(facebook_for_woocommerce_whatsapp_events.order_fulfilled_enabled){
+ orderFulfilledInactiveStatus.hide();
+ orderFulfilledActiveStatus.show();
+ }
+ else {
+ orderFulfilledActiveStatus.hide();
+ orderFulfilledInactiveStatus.show();
+ }
+
+ // Set Event Status for Order Refunded
+ var orderRefundedActiveStatus = $('#order-refunded-active-status');
+ var orderRefundedInactiveStatus = $('#order-refunded-inactive-status');
+ if(facebook_for_woocommerce_whatsapp_events.order_refunded_enabled){
+ orderRefundedInactiveStatus.hide();
+ orderRefundedActiveStatus.show();
+ }
+ else {
+ orderRefundedActiveStatus.hide();
+ orderRefundedInactiveStatus.show();
+ }
+
+ var eventConfiglanguage = getEventLanguage(facebook_for_woocommerce_whatsapp_events.event);
+ $("#manage-event-language").val(eventConfiglanguage);
+
+ $('#woocommerce-whatsapp-manage-order-placed, #woocommerce-whatsapp-manage-order-fulfilled, #woocommerce-whatsapp-manage-order-refunded').click(function (event) {
+ var clickedButtonId = $(event.target).attr("id");
+ let view=clickedButtonId.replace("woocommerce-whatsapp-", "");
+ view = view.replaceAll("-", "_");
+ let url = new URL(window.location.href);
+ let params = new URLSearchParams(url.search);
+ params.set('view', view);
+ url.search = params.toString();
+ window.location.href = url.toString();
+ });
+
+ // call template library get API to show message template header, body and button text configured for the event.
+ $("#library-template-content").load(facebook_for_woocommerce_whatsapp_events.ajax_url, function () {
+ $.post(facebook_for_woocommerce_whatsapp_events.ajax_url, {
+ action: 'wc_facebook_whatsapp_fetch_library_template_info',
+ nonce: facebook_for_woocommerce_whatsapp_events.nonce,
+ event: facebook_for_woocommerce_whatsapp_events.event,
+ }, function (response) {
+ if (response.success) {
+ const parsedData = JSON.parse(response.data);
+ const apiResponseData = parsedData.data[0];
+ // Parse template strings as HTML and extract text content to sanitize text
+ const header = $.parseHTML(apiResponseData.header)[0].textContent;
+ const body = $.parseHTML(apiResponseData.body)[0].textContent;
+ if (facebook_for_woocommerce_whatsapp_events.event === "ORDER_REFUNDED") {
+ $('#library-template-content').html(`
+
Header
+ ${header}
+ Body
+ ${body}
+ `).show();
+ }
+ else {
+ const button = $.parseHTML(apiResponseData.buttons[0].text)[0].textContent;
+ $('#library-template-content').html(`
+ Header
+ ${header}
+ Body
+ ${body}
+ Call to action
+ ${button}
+ `).show();
+ }
+ }
+ });
+ });
+
+ $('#woocommerce-whatsapp-save-order-confirmation').click(function (event) {
+ var languageValue = $("#manage-event-language").val();
+ var statusValue = $('input[name="template-status"]:checked').val();
+ console.log('Save confirmation clicked: ', languageValue, statusValue);
+ $.post(facebook_for_woocommerce_whatsapp_events.ajax_url, {
+ action: 'wc_facebook_whatsapp_upsert_event_config',
+ nonce: facebook_for_woocommerce_whatsapp_events.nonce,
+ event: facebook_for_woocommerce_whatsapp_events.event,
+ language: languageValue,
+ status: statusValue
+ }, function (response) {
+ //TODO: Add Error Handling
+ let url = new URL(window.location.href);
+ let params = new URLSearchParams(url.search);
+ params.set('view', 'utility_settings');
+ url.search = params.toString();
+ window.location.href = url.toString();
+ });
+ });
+
+ function getEventLanguage(event) {
+ switch (event) {
+ case "ORDER_PLACED":
+ return facebook_for_woocommerce_whatsapp_events.order_placed_language;
+ case "ORDER_FULFILLED":
+ return facebook_for_woocommerce_whatsapp_events.order_fulfilled_language;
+ case "ORDER_REFUNDED":
+ return facebook_for_woocommerce_whatsapp_events.order_refunded_language;
+ default:
+ return null;
+ }
+ }
+});
\ No newline at end of file
diff --git a/assets/js/admin/whatsapp-finish.js b/assets/js/admin/whatsapp-finish.js
new file mode 100644
index 000000000..98d22e8ea
--- /dev/null
+++ b/assets/js/admin/whatsapp-finish.js
@@ -0,0 +1,53 @@
+/**
+ * Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
+ *
+ * This source code is licensed under the license found in the
+ * LICENSE file in the root directory of this source tree.
+ *
+ * @package FacebookCommerce
+ */
+
+jQuery( document ).ready( function( $ ) {
+ // handle the whatsapp finish button click
+ $( '#wc-whatsapp-onboarding-finish' ).click( function( event ) {
+ // call the connect API to create configs and check payment
+ $.post( facebook_for_woocommerce_whatsapp_finish.ajax_url, {
+ action: 'wc_facebook_whatsapp_finish_onboarding',
+ nonce: facebook_for_woocommerce_whatsapp_finish.nonce
+ }, function ( response ) {
+ if ( response.success ) {
+ // If success, redirect to utility settings page
+ let url = new URL(window.location.href);
+ let params = new URLSearchParams(url.search);
+ params.set('view', 'utility_settings');
+ url.search = params.toString();
+ window.location.href = url.toString();
+ console.log( 'Whatsapp Connect Success', response );
+ } else {
+ var message;
+ const error = response.data;
+ console.log( 'Whatsapp Connect Failure', response );
+
+ switch (error) {
+ case "Incorrect payment setup":
+ message = facebook_for_woocommerce_whatsapp_finish.i18n.payment_setup_error;
+ break;
+ case "Onboarding is not complete or has failed.":
+ message = facebook_for_woocommerce_whatsapp_finish.i18n.onboarding_incomplete_error;
+ break;
+ default:
+ message = facebook_for_woocommerce_whatsapp_finish.i18n.generic_error;
+ }
+
+
+ const errorNoticeHtml = `
+
+ `;
+ $( '#payment-method-error-notice' ).html( errorNoticeHtml ).show();
+ }
+ } );
+ });
+
+} );
diff --git a/assets/js/admin/whatsapp-templates.js b/assets/js/admin/whatsapp-templates.js
new file mode 100644
index 000000000..be01ba924
--- /dev/null
+++ b/assets/js/admin/whatsapp-templates.js
@@ -0,0 +1,26 @@
+/**
+ * Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
+ *
+ * This source code is licensed under the license found in the
+ * LICENSE file in the root directory of this source tree.
+ *
+ * @package FacebookCommerce
+ */
+
+jQuery( document ).ready( function( $ ) {
+ // handle whatsapp view insights link click should open template insights in WhatsSpp Manager
+ $( '#woocommerce-whatsapp-manager-insights' ).click( function( event ) {
+ $.post( facebook_for_woocommerce_whatsapp_templates.ajax_url, {
+ action: 'wc_facebook_whatsapp_fetch_url_info',
+ nonce: facebook_for_woocommerce_whatsapp_templates.nonce
+ }, function ( response ) {
+ console.log(response);
+ if ( response.success ) {
+ var business_id = response.data.business_id;
+ var asset_id = response.data.waba_id;
+ const MANAGE_TEMPLATES_URL = `https://business.facebook.com/latest/whatsapp_manager/message_templates?business_id=${business_id}&asset_id=${asset_id}`;
+ window.open(MANAGE_TEMPLATES_URL);
+ }
+ } );
+ });
+} );
diff --git a/class-wc-facebookcommerce.php b/class-wc-facebookcommerce.php
index d1291a640..e45a2ce82 100644
--- a/class-wc-facebookcommerce.php
+++ b/class-wc-facebookcommerce.php
@@ -99,6 +99,9 @@ class WC_Facebookcommerce extends WooCommerce\Facebook\Framework\Plugin {
/** @var WooCommerce\Facebook\Handlers\WebHook webhook handler */
private $webhook_handler;
+ /** @var WooCommerce\Facebook\Handlers\Whatsapp_WebHook whatsapp webhook handler */
+ private $whatsapp_webhook_handler;
+
/** @var WooCommerce\Facebook\Commerce commerce handler */
private $commerce_handler;
@@ -172,6 +175,7 @@ public function init() {
add_action( 'init', array( $this, 'get_integration' ) );
add_action( 'init', array( $this, 'register_custom_taxonomy' ) );
add_action( 'add_meta_boxes_product', array( $this, 'remove_product_fb_product_set_metabox' ), 50 );
+ add_action( 'woocommerce_init', array($this, 'add_whatsapp_consent_checkout_fields'));
add_filter( 'fb_product_set_row_actions', array( $this, 'product_set_links' ) );
add_filter( 'manage_edit-fb_product_set_columns', array( $this, 'manage_fb_product_set_columns' ) );
@@ -195,7 +199,6 @@ public function init() {
$this->heartbeat = new Heartbeat( WC()->queue() );
$this->heartbeat->init();
-
$this->feed_manager = new WooCommerce\Facebook\Feed\FeedManager();
$this->checkout = new WooCommerce\Facebook\Checkout();
$this->product_feed = new WooCommerce\Facebook\Products\Feed();
@@ -225,16 +228,19 @@ public function init() {
$this->background_remove_duplicate_visibility_meta = new Background_Remove_Duplicate_Visibility_Meta();
}
+
new WooCommerce\Facebook\API\Plugin\InitializeRestAPI();
$this->connection_handler = new WooCommerce\Facebook\Handlers\Connection( $this );
new WooCommerce\Facebook\Handlers\MetaExtension();
- $this->webhook_handler = new WooCommerce\Facebook\Handlers\WebHook( $this );
- $this->tracker = new WooCommerce\Facebook\Utilities\Tracker();
- $this->rollout_switches = new WooCommerce\Facebook\RolloutSwitches( $this );
+ $this->webhook_handler = new WooCommerce\Facebook\Handlers\WebHook( $this );
+ $this->whatsapp_webhook_handler = new WooCommerce\Facebook\Handlers\Whatsapp_Webhook( $this );
+ $this->tracker = new WooCommerce\Facebook\Utilities\Tracker();
+ $this->rollout_switches = new WooCommerce\Facebook\RolloutSwitches( $this );
// Init jobs
$this->job_manager = new WooCommerce\Facebook\Jobs\JobManager();
add_action( 'init', [ $this->job_manager, 'init' ] );
+ add_action( 'admin_init', [ $this->rollout_switches, 'init' ] );
// Instantiate the debug tools.
$this->debug_tools = new DebugTools();
@@ -242,15 +248,16 @@ public function init() {
// load admin handlers, before admin_init
if ( is_admin() ) {
if ($this->use_enhanced_onboarding()) {
- $this->admin_enhanced_settings = new WooCommerce\Facebook\Admin\Enhanced_Settings( $this->connection_handler->is_connected() );
+ $this->admin_enhanced_settings = new WooCommerce\Facebook\Admin\Enhanced_Settings( $this );
} else {
- $this->admin_settings = new WooCommerce\Facebook\Admin\Settings( $this->connection_handler->is_connected() );
+ $this->admin_settings = new WooCommerce\Facebook\Admin\Settings( $this );
}
}
}
}
+
/**
* Initializes the admin handling.
*
@@ -266,7 +273,6 @@ function () {
},
0
);
- add_action( 'admin_init', [ $this->rollout_switches, 'init' ] );
}
/**
@@ -876,6 +882,30 @@ protected function get_current_page_id() {
return $current_screen_id;
}
+ /**
+ * Add checkout fields to collect whatsapp consent if consent collection is enabled
+ *
+ * @since 2.3.0
+ *
+ * @param array $fields
+ *
+ * @return array
+ */
+ function add_whatsapp_consent_checkout_fields($fields) {
+ if (get_option('wc_facebook_whatsapp_consent_collection_setting_status', 'disabled') === 'enabled') {
+ woocommerce_register_additional_checkout_field(
+ array(
+ 'id' => 'wc_facebook/whatsapp_consent_checkbox', // id = namespace/field_name
+ 'label' => esc_html('Get order updates on WhatsApp'),
+ 'location' => 'address',
+ 'type' => 'checkbox',
+ 'optionalLabel' => esc_html('Get order updates on WhatsApp')
+ )
+ );
+ }
+ return $fields;
+ }
+
/**
* Determines if the enhanced onboarding (iframe) should be used.
*
diff --git a/facebook-commerce-whatsapp-utility-event.php b/facebook-commerce-whatsapp-utility-event.php
new file mode 100644
index 000000000..9fef14afa
--- /dev/null
+++ b/facebook-commerce-whatsapp-utility-event.php
@@ -0,0 +1,131 @@
+ 'ORDER_PLACED',
+ 'completed' => 'ORDER_FULFILLED',
+ 'refunded' => 'ORDER_REFUNDED',
+ );
+
+ public function __construct() {
+ if ( ! $this->is_whatsapp_utility_enabled() ) {
+ return;
+ }
+ add_action( 'woocommerce_order_status_changed', array( $this, 'process_wc_order_status_changed' ), 10, 3 );
+ }
+
+ /**
+ * Determines if WhatsApp Utility Messages are enabled
+ * TODO: Update this function to check for gating logic for Alpha businesses
+ *
+ * @since 2.3.0
+ *
+ * @return bool
+ */
+ private function is_whatsapp_utility_enabled() {
+ return true;
+ }
+
+
+ /**
+ * Hook to process Order Processing, Order Completed and Order Refunded events for WhatsApp Utility Messages
+ *
+ * @param string $order_id Order id
+ * @param string $old_status Old Order Status
+ * @param string $new_status New Order Status
+ *
+ * @return void
+ * @since 2.3.0
+ */
+ public function process_wc_order_status_changed( $order_id, $old_status, $new_status ) {
+ // WhatsApp Utility Messages are supported only for Processing status
+ $supported_statuses = array_keys( self::ORDER_STATUS_TO_EVENT_MAPPING );
+ if ( ! in_array( $new_status, $supported_statuses, true ) ) {
+ return;
+ }
+
+ wc_get_logger()->info(
+ sprintf(
+ /* translators: %s $order_id */
+ __( 'Processing Order id %1$s to send Whatsapp Utility messages', 'facebook-for-woocommerce' ),
+ $order_id,
+ )
+ );
+ $event = self::ORDER_STATUS_TO_EVENT_MAPPING[ $new_status ];
+
+ // Check WhatsApp Event Config is active
+ $event_config_id_option_name = implode( '_', array( WhatsAppUtilityConnection::WA_UTILITY_OPTION_PREFIX, strtolower( $event ), 'event_config_id' ) );
+ $event_config_language_option_name = implode( '_', array( WhatsAppUtilityConnection::WA_UTILITY_OPTION_PREFIX, strtolower( $event ), 'language' ) );
+ $event_config_id = get_option( $event_config_id_option_name, null );
+ $language_code = get_option( $event_config_language_option_name, null );
+ if ( empty( $event_config_id ) || empty( $language_code ) ) {
+ wc_get_logger()->info(
+ sprintf(
+ /* translators: %s $order_id */
+ __( 'Messages Post API call for Order id %1$s skipped due to no active event config', 'facebook-for-woocommerce' ),
+ $order_id,
+ )
+ );
+ return;
+ }
+
+ $order = wc_get_order( $order_id );
+ // Check WhatsApp Consent Checkbox is selected in shipping and billing
+ $billing_consent_value = $order->get_meta( '_wc_billing/wc_facebook/whatsapp_consent_checkbox' );
+ $shipping_consent_value = $order->get_meta( '_wc_shipping/wc_facebook/whatsapp_consent_checkbox' );
+ $has_whatsapp_consent = $billing_consent_value && $shipping_consent_value;
+ // Get WhatsApp Phone number from entered Billing and Shipping phone number
+ $billing_phone_number = $order->get_billing_phone();
+ $shipping_phone_number = $order->get_shipping_phone();
+ $phone_number = ( isset( $billing_phone_number ) && $billing_consent_value ) ? $billing_phone_number : $shipping_phone_number;
+ // Get Customer first name
+ $first_name = $order->get_billing_first_name();
+ // Get Total Refund Amount for Order Refunded event
+ $total_refund = 0;
+ foreach ( $order->get_refunds() as $refund ) {
+ $total_refund += $refund->get_amount();
+ }
+ $currency = $order->get_currency();
+ $refund_amount = $total_refund * 1000;
+ if ( empty( $phone_number ) || ! $has_whatsapp_consent || empty( $event ) || empty( $first_name ) ) {
+ wc_get_logger()->info(
+ sprintf(
+ /* translators: %s $order_id */
+ __( 'Messages Post API call for Order id %1$s skipped due to missing whatsapp consent or Order info', 'facebook-for-woocommerce' ),
+ $order_id,
+ )
+ );
+ return;
+ }
+
+ // Check Access token and WACS is available
+ $bisu_token = get_option( 'wc_facebook_wa_integration_bisu_access_token', null );
+ $wacs_id = get_option( 'wc_facebook_wa_integration_wacs_id', null );
+ if ( empty( $bisu_token ) || empty( $wacs_id ) ) {
+ wc_get_logger()->info(
+ sprintf(
+ /* translators: %s $order_id */
+ __( 'Messages Post API call for Order id %1$s Failed due to missing access token or wacs info', 'facebook-for-woocommerce' ),
+ $order_id,
+ )
+ );
+ return;
+ }
+ WhatsAppUtilityConnection::post_whatsapp_utility_messages_events_call( $event, $event_config_id, $language_code, $wacs_id, $order_id, $phone_number, $first_name, $refund_amount, $currency, $bisu_token );
+ }
+}
diff --git a/facebook-commerce.php b/facebook-commerce.php
index a823af178..ae1f30497 100644
--- a/facebook-commerce.php
+++ b/facebook-commerce.php
@@ -204,6 +204,9 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
/** @var WC_Facebook_Product_Feed instance. */
private $fbproductfeed;
+ /** @var WC_Facebookcommerce_Whatsapp_Utility_Event instance. */
+ private $wa_utility_event_processor;
+
/**
* Init and hook in the integration.
*
@@ -397,6 +400,9 @@ public function __construct( WC_Facebookcommerce $facebook_for_woocommerce ) {
// Product Set hooks.
add_action( 'fb_wc_product_set_sync', [ $this, 'create_or_update_product_set_item' ], 99, 2 );
add_action( 'fb_wc_product_set_delete', [ $this, 'delete_product_set_item' ], 99 );
+
+ // Init Whatsapp Utility Event Processor
+ $this->wa_utility_event_processor = $this->load_whatsapp_utility_event_processor();
}
/**
@@ -3146,4 +3152,19 @@ public function ajax_display_test_result() {
wp_die();
}
+ /**
+ * Init WhatsApp Utility Event Processor.
+ *
+ * @return void
+ */
+ public function load_whatsapp_utility_event_processor() {
+ // Attempt to load WhatsApp Utility Event Processor
+ include_once 'facebook-commerce-whatsapp-utility-event.php';
+ if ( class_exists( 'WC_Facebookcommerce_Whatsapp_Utility_Event' ) ) {
+ if ( ! isset( $this->wa_utility_event_processor ) ) {
+ $this->wa_utility_event_processor = new WC_Facebookcommerce_Whatsapp_Utility_Event( $this );
+ }
+ }
+ }
+
}
diff --git a/includes/AJAX.php b/includes/AJAX.php
index 405987f5f..09060b4c7 100644
--- a/includes/AJAX.php
+++ b/includes/AJAX.php
@@ -14,6 +14,7 @@
use WooCommerce\Facebook\Admin\Settings_Screens\Product_Sync;
use WooCommerce\Facebook\Admin\Settings_Screens\Shops;
use WooCommerce\Facebook\Framework\Plugin\Exception as PluginException;
+use WooCommerce\Facebook\Handlers\WhatsAppUtilityConnection;
defined( 'ABSPATH' ) || exit;
@@ -51,8 +52,32 @@ public function __construct() {
// get the current sync status
add_action( 'wp_ajax_wc_facebook_get_sync_status', array( $this, 'get_sync_status' ) );
+ // check the status of whatsapp onboarding and update the progress
+ add_action( 'wp_ajax_wc_facebook_whatsapp_onboarding_progress_check', array( $this, 'whatsapp_onboarding_progress_check' ) );
+
+ // update the wp_options with wc_facebook_whatsapp_consent_collection_setting_status to enabled
+ add_action( 'wp_ajax_wc_facebook_whatsapp_consent_collection_enable', array( $this, 'whatsapp_consent_collection_enable' ) );
+
+ // fetch url info - waba id and business id
+ add_action( 'wp_ajax_wc_facebook_whatsapp_fetch_url_info', array( $this, 'wc_facebook_whatsapp_fetch_url_info' ) );
+
+ // action to fetch required info and make api call to meta to finish onboarding
+ add_action( 'wp_ajax_wc_facebook_whatsapp_finish_onboarding', array( $this, 'wc_facebook_whatsapp_finish_onboarding' ) );
+
+ // fetch configured library template info
+ add_action( 'wp_ajax_wc_facebook_whatsapp_fetch_library_template_info', array( $this, 'whatsapp_fetch_library_template_info' ) );
+
+ // action to create or update utility event config info
+ add_action( 'wp_ajax_wc_facebook_whatsapp_upsert_event_config', array( $this, 'whatsapp_upsert_event_config' ) );
+
// search a product's attributes for the given term
add_action( 'wp_ajax_' . self::ACTION_SEARCH_PRODUCT_ATTRIBUTES, array( $this, 'admin_search_product_attributes' ) );
+
+ // update the wp_options with wc_facebook_whatsapp_consent_collection_setting_status to disabled
+ add_action( 'wp_ajax_wc_facebook_whatsapp_consent_collection_disable', array( $this, 'whatsapp_consent_collection_disable' ) );
+
+ // disconnect whatsapp account from woocommcerce app
+ add_action( 'wp_ajax_wc_facebook_disconnect_whatsapp', array( $this, 'wc_facebook_disconnect_whatsapp' ) );
}
@@ -189,6 +214,241 @@ public function get_sync_status() {
wp_send_json_success( $remaining_products );
}
+ /**
+ * Get data for creating the billing or whatsapp manager url for whatsapp account.
+ *
+ * @internal
+ *
+ * @since 1.10.0
+ */
+ public function wc_facebook_whatsapp_fetch_url_info() {
+ wc_get_logger()->info(
+ sprintf(
+ __( 'Fetching url info(WABA ID+BusinessID) for whatsapp pages', 'facebook-for-woocommerce' )
+ )
+ );
+ facebook_for_woocommerce()->log( '' );
+ if ( ! check_ajax_referer( 'facebook-for-wc-whatsapp-billing-nonce', 'nonce', false ) && ! check_ajax_referer( 'facebook-for-wc-whatsapp-templates-nonce', 'nonce', false ) && ! check_ajax_referer( 'facebook-for-wc-whatsapp-disconnect-nonce', 'nonce', false ) ) {
+ wc_get_logger()->info(
+ sprintf(
+ __( 'Nonce Verification Error while Fetching Url Info', 'facebook-for-woocommerce' )
+ )
+ );
+ wp_send_json_error( 'Invalid security token sent.' );
+ }
+
+ $waba_id = get_option( 'wc_facebook_wa_integration_waba_id', null );
+ $business_id = get_option( 'wc_facebook_wa_integration_business_id', null );
+
+ if ( empty( $waba_id ) || empty( $business_id ) ) {
+ wc_get_logger()->info(
+ sprintf(
+ __( 'Missing Waba ID + Business ID during Fetch Url Info. Whatsapp Onboarding is not complete or has failed.', 'facebook-for-woocommerce' )
+ )
+ );
+ wp_send_json_error( 'Whatsapp onboarding is not complete or has failed.' );
+ }
+
+ $response = array(
+ 'waba_id' => $waba_id,
+ 'business_id' => $business_id,
+ );
+
+ wp_send_json_success( $response );
+ }
+
+ /**
+ * Get data for for finish onboarding call and make api call.
+ *
+ * @internal
+ *
+ * @since 1.10.0
+ */
+ public function wc_facebook_whatsapp_finish_onboarding() {
+ wc_get_logger()->info(
+ sprintf(
+ __( 'Getting data for Whatsapp Finish Onboarding Done Button Click', 'facebook-for-woocommerce' )
+ )
+ );
+ if ( ! check_ajax_referer( 'facebook-for-wc-whatsapp-finish-nonce', 'nonce', false ) ) {
+ wc_get_logger()->info(
+ sprintf(
+ __( 'Nonce Verification Error in Finish Onboarding Flow', 'facebook-for-woocommerce' )
+ )
+ );
+ wp_send_json_error( 'Invalid security token sent.' );
+ }
+ $external_business_id = get_option( 'wc_facebook_external_business_id', null );
+ $wacs_id = get_option( 'wc_facebook_wa_integration_wacs_id', null );
+ $waba_id = get_option( 'wc_facebook_wa_integration_waba_id', null );
+ $bisu_token = get_option( 'wc_facebook_wa_integration_bisu_access_token', null );
+ if ( empty( $external_business_id ) || empty( $wacs_id ) || empty( $waba_id ) || empty( $bisu_token ) ) {
+ wc_get_logger()->info(
+ sprintf(
+ __( 'Finish Onboarding - Onboarding is not complete or has failed.', 'facebook-for-woocommerce' ),
+ )
+ );
+ wp_send_json_error( 'Onboarding Flow is not complete or has failed.' );
+ }
+ WhatsAppUtilityConnection::wc_facebook_whatsapp_connect_utility_messages_call( $waba_id, $wacs_id, $external_business_id, $bisu_token );
+ }
+
+
+ /**
+ * Checks if the onboarding for whatsapp is complete once business has initiated onboarding.
+ *
+ * @internal
+ *
+ * @since 1.10.0
+ */
+ public function whatsapp_onboarding_progress_check() {
+ if ( ! check_ajax_referer( 'facebook-for-wc-whatsapp-onboarding-progress-nonce', 'nonce', false ) ) {
+ wp_send_json_error( 'Invalid security token sent.' );
+ }
+ $waba_id = get_option( 'wc_facebook_wa_integration_waba_id', null );
+ $is_payment_setup = (bool) get_option( 'wc_facebook_wa_integration_is_payment_setup', null );
+ if ( ! empty( $waba_id ) ) {
+ wp_send_json_success(
+ array(
+ 'message' => 'WhatsApp onboarding is complete',
+ 'is_payment_setup' => $is_payment_setup,
+ )
+ );
+ }
+ wp_send_json_error( 'WhatsApp onboarding is not complete' );
+ }
+
+ public function whatsapp_consent_collection_enable() {
+ wc_get_logger()->info(
+ sprintf(
+ __( 'Enabling Whatsapp Consent Collection in Checkout Flow', 'facebook-for-woocommerce' )
+ )
+ );
+ if ( ! check_ajax_referer( 'facebook-for-wc-whatsapp-consent-nonce', 'nonce', false ) ) {
+ wc_get_logger()->info(
+ sprintf(
+ __( 'Nonce Verification Error in Whatsapp Consent Collection', 'facebook-for-woocommerce' )
+ )
+ );
+ wp_send_json_error( 'Invalid security token sent.' );
+ }
+ if ( get_option( 'wc_facebook_whatsapp_consent_collection_setting_status' ) !== 'enabled' ) {
+ update_option( 'wc_facebook_whatsapp_consent_collection_setting_status', 'enabled' );
+ }
+ $is_payment_setup = (bool) get_option( 'wc_facebook_wa_integration_is_payment_setup', null );
+ wc_get_logger()->info(
+ sprintf(
+ __( 'Whatsapp Consent Collection Enabled Successfully in Checkout Flow', 'facebook-for-woocommerce' )
+ )
+ );
+ wp_send_json_success(
+ array(
+ 'message' => 'Whatsapp Consent Collection Enabled Successfully in Checkout Flow',
+ 'is_payment_setup' => $is_payment_setup,
+ )
+ );
+ }
+
+ public function whatsapp_consent_collection_disable() {
+ wc_get_logger()->info(
+ sprintf(
+ __( 'Disabling Whatsapp Consent Collection in Utility Settings View', 'facebook-for-woocommerce' )
+ )
+ );
+ if ( ! check_ajax_referer( 'facebook-for-wc-whatsapp-consent-disable-nonce', 'nonce', false ) ) {
+ wp_send_json_error( 'Invalid security token sent.' );
+ }
+ if ( get_option( 'wc_facebook_whatsapp_consent_collection_setting_status' ) !== 'disabled' ) {
+ update_option( 'wc_facebook_whatsapp_consent_collection_setting_status', 'disabled' );
+ }
+ wc_get_logger()->info(
+ sprintf(
+ __( 'Whatsapp Consent Collection Disabled Successfully in Utility Settings View', 'facebook-for-woocommerce' )
+ )
+ );
+ wp_send_json_success();
+ }
+
+ /**
+ * Disconnect Whatsapp from WooCommerce.
+ *
+ * @internal
+ *
+ * @since 1.10.0
+ */
+ public function wc_facebook_disconnect_whatsapp() {
+ wc_get_logger()->info(
+ sprintf(
+ __( 'Diconnecting Whatsapp From Woocommerce', 'facebook-for-woocommerce' )
+ )
+ );
+ if ( ! check_ajax_referer( 'facebook-for-wc-whatsapp-disconnect-nonce', 'nonce', false ) ) {
+ wc_get_logger()->info(
+ sprintf(
+ __( 'Nonce Verification Failed while Diconnecting Whatsapp From Woocommerce', 'facebook-for-woocommerce' )
+ )
+ );
+ wp_send_json_error( 'Invalid security token sent.' );
+ }
+
+ $integration_config_id = get_option( 'wc_facebook_wa_integration_config_id', null );
+ $bisu_token = get_option( 'wc_facebook_wa_integration_bisu_access_token', null );
+ $waba_id = get_option( 'wc_facebook_wa_integration_waba_id', null );
+ if ( empty( $integration_config_id ) || empty( $bisu_token ) || empty( $waba_id ) ) {
+ wc_get_logger()->info(
+ sprintf(
+ __( 'Missing Integration Config ID, BISU token, WABA ID while Diconnecting Whatsapp From Woocommerce', 'facebook-for-woocommerce' )
+ )
+ );
+ wp_send_json_error( 'Missing integration_config_id or bisu_token or waba_id for Disconnect API call' );
+ }
+ WhatsAppUtilityConnection::wc_facebook_disconnect_whatsapp( $waba_id, $integration_config_id, $bisu_token );
+ }
+
+ public function whatsapp_fetch_library_template_info() {
+ facebook_for_woocommerce()->log( 'Fetching library template data for whatsapp utility event' );
+ if ( ! check_ajax_referer( 'facebook-for-wc-whatsapp-events-nonce', 'nonce', false ) ) {
+ wp_send_json_error( 'Invalid security token sent.' );
+ }
+ $bisu_token = get_option( 'wc_facebook_wa_integration_bisu_access_token', null );
+ if ( empty( $bisu_token ) ) {
+ wp_send_json_error( 'Missing access token for Library template API call' );
+ }
+ // Get POST parameters from the request
+ $event = isset( $_POST['event'] ) ? wc_clean( wp_unslash( $_POST['event'] ) ) : '';
+ WhatsAppUtilityConnection::get_template_library_content( $event, $bisu_token );
+ }
+ /**
+ * Creates or Updates WhatsApp Utility Event Configs
+ *
+ * @internal
+ *
+ * @since 1.10.0
+ */
+ public function whatsapp_upsert_event_config() {
+ facebook_for_woocommerce()->log( 'Calling POST API to upsert whatsapp utility event' );
+ if ( ! check_ajax_referer( 'facebook-for-wc-whatsapp-events-nonce', 'nonce', false ) ) {
+ wp_send_json_error( 'Invalid security token sent.' );
+ }
+ // Get BISU token
+ $bisu_token = get_option( 'wc_facebook_wa_integration_bisu_access_token', null );
+ if ( empty( $bisu_token ) ) {
+ wp_send_json_error( 'Missing access token for Event Configs POST API call' );
+ }
+ // Get Integration Config id
+ $integration_config_id = get_option( 'wc_facebook_wa_integration_config_id', null );
+ if ( empty( $integration_config_id ) ) {
+ wp_send_json_error( 'Missing Integration Config for Event Configs POST API call' );
+ }
+ // Get POST parameters from the request
+ $event = isset( $_POST['event'] ) ? wc_clean( wp_unslash( $_POST['event'] ) ) : '';
+ $language = isset( $_POST['language'] ) ? wc_clean( wp_unslash( $_POST['language'] ) ) : '';
+ $status = isset( $_POST['status'] ) ? wc_clean( wp_unslash( $_POST['status'] ) ) : '';
+ if ( empty( $event ) || empty( $language ) || empty( $status ) ) {
+ wp_send_json_error( 'Missing request parameters for Event Configs POST API call' );
+ }
+ WhatsAppUtilityConnection::post_whatsapp_utility_messages_event_configs_call( $event, $integration_config_id, $language, $status, $bisu_token );
+ }
/**
* Maybe triggers a modal warning when the merchant toggles sync enabled status in bulk.
diff --git a/includes/Admin/Enhanced_Settings.php b/includes/Admin/Enhanced_Settings.php
index 1f7009746..d1f0297f4 100644
--- a/includes/Admin/Enhanced_Settings.php
+++ b/includes/Admin/Enhanced_Settings.php
@@ -15,6 +15,8 @@
use WooCommerce\Facebook\Admin\Settings_Screens\Shops;
use WooCommerce\Facebook\Framework\Helper;
use WooCommerce\Facebook\Framework\Plugin\Exception as PluginException;
+use WooCommerce\Facebook\Admin\Settings_Screens\Whatsapp_Utility;
+use WooCommerce\Facebook\RolloutSwitches;
defined( 'ABSPATH' ) || exit;
@@ -38,16 +40,24 @@ class Enhanced_Settings {
*/
const SUBMENU_PAGE_ID = 'edit-tags.php?taxonomy=fb_product_set&post_type=product';
+ /** @var \WC_Facebookcommerce */
+ private $plugin;
+
+
/**
* Enhanced settings constructor.
*
* @since 3.5.0
*
- * @param bool $is_connected
+ * @param \WC_Facebookcommerce $plugin is the plugin instance of WC_Facebookcommerce
*/
- public function __construct( bool $is_connected ) {
- $this->screens = $this->build_menu_item_array( $is_connected );
+ public function __construct( \WC_Facebookcommerce $plugin ) {
+ $this->plugin = $plugin;
+ $this->screens = $this->build_menu_item_array();
+
+ add_action( 'admin_menu', array( $this, 'build_menu_item_array' ) );
+ add_action( 'admin_init', array( $this, 'add_extra_screens' ) );
add_action( 'admin_menu', array( $this, 'add_menu_item' ) );
add_action( 'wp_loaded', array( $this, 'save' ) );
@@ -61,21 +71,39 @@ public function __construct( bool $is_connected ) {
*
* @since 3.5.0
*
- * @param bool $is_connected is Facebook connected
* @return array
*/
- private function build_menu_item_array( bool $is_connected ): array {
+ public function build_menu_item_array(): array {
+ $is_connected = $this->plugin->get_connection_handler()->is_connected();
+
if ( $is_connected ) {
- // TODO: Add Utility messaging tab
// TODO: Remove Product sync and Product sets tab once catalog changes are complete
- return array(
+ $screens = array(
Settings_Screens\Shops::ID => new Settings_Screens\Shops(),
Settings_Screens\Product_Sync::ID => new Settings_Screens\Product_Sync(),
Settings_Screens\Product_Sets::ID => new Settings_Screens\Product_Sets(),
);
} else {
- // TODO: Add Utility messaging tab
- return [ Settings_Screens\Shops::ID => new Settings_Screens\Shops() ];
+ $screens = [ Settings_Screens\Shops::ID => new Settings_Screens\Shops() ];
+ }
+
+ return $screens;
+ }
+
+ /**
+ * Add extra screens to $this->screens - basic settings_screens
+ *
+ * @since 3.5.0
+ *
+ * @return void
+ */
+ public function add_extra_screens(): void {
+ $rollout_switches = $this->plugin->get_rollout_switches();
+ $is_connected = $this->plugin->get_connection_handler()->is_connected();
+ $is_whatsapp_utility_messaging_enabled = $rollout_switches->is_switch_enabled( RolloutSwitches::WHATSAPP_UTILITY_MESSAGING );
+
+ if ( true === $is_connected && true === $is_whatsapp_utility_messaging_enabled ) {
+ $this->screens[ Settings_Screens\Whatsapp_Utility::ID ] = new Settings_Screens\Whatsapp_Utility();
}
}
@@ -186,7 +214,18 @@ public function render_tabs( $current_tab ) {
?>
plugin = $plugin;
- $this->screens = $this->build_menu_item_array( $is_connected );
+ $this->screens = $this->build_menu_item_array();
+ add_action( 'admin_menu', array( $this, 'build_menu_item_array' ) );
+ add_action( 'admin_init', array( $this, 'add_extra_screens' ) );
add_action( 'admin_menu', array( $this, 'add_menu_item' ) );
add_action( 'wp_loaded', array( $this, 'save' ) );
add_filter( 'parent_file', array( $this, 'set_parent_and_submenu_file' ) );
@@ -58,15 +67,15 @@ public function __construct( bool $is_connected ) {
/**
* Arranges the tabs. If the plugin is connected to FB, Advertise tab will be first, otherwise the Connection tab will be the first tab.
*
- * @param bool $is_connected is Facebook connected
* @since 3.0.7
*/
- private function build_menu_item_array( bool $is_connected ): array {
+ public function build_menu_item_array(): array {
$advertise = [ Settings_Screens\Advertise::ID => new Settings_Screens\Advertise() ];
$connection = [ Settings_Screens\Connection::ID => new Settings_Screens\Connection() ];
- $first = ( $is_connected ) ? $advertise : $connection;
- $last = ( $is_connected ) ? $connection : $advertise;
+ $is_connected = $this->plugin->get_connection_handler()->is_connected();
+ $first = ( $is_connected ) ? $advertise : $connection;
+ $last = ( $is_connected ) ? $connection : $advertise;
$screens = array(
Settings_Screens\Product_Sync::ID => new Settings_Screens\Product_Sync(),
@@ -76,6 +85,15 @@ private function build_menu_item_array( bool $is_connected ): array {
return array_merge( array_merge( $first, $screens ), $last );
}
+ public function add_extra_screens(): void {
+ $rollout_switches = $this->plugin->get_rollout_switches();
+ $is_connected = $this->plugin->get_connection_handler()->is_connected();
+ $is_whatsapp_utility_messaging_enabled = $rollout_switches->is_switch_enabled( RolloutSwitches::WHATSAPP_UTILITY_MESSAGING );
+ if ( true === $is_connected && true === $is_whatsapp_utility_messaging_enabled ) {
+ $this->screens[ Settings_Screens\Whatsapp_Utility::ID ] = new Settings_Screens\Whatsapp_Utility();
+ }
+ }
+
/**
* Adds the Facebook menu item.
*
@@ -219,7 +237,18 @@ public function render_tabs( $current_tab ) {
?>
initHook();
+
+ add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_assets' ) );
+ }
+
+ /**
+ * Initializes this whatsapp utility settings page's properties.
+ */
+ public function initHook(): void {
+ $this->id = self::ID;
+ $this->label = __( 'Utility messages', 'facebook-for-woocommerce' );
+ $this->title = __( 'Utility messages', 'facebook-for-woocommerce' );
+ }
+
+ /**
+ * Enqueue the assets.
+ *
+ * @internal
+ *
+ * @since 2.0.0
+ */
+ public function enqueue_assets() {
+
+ if ( ! $this->is_current_screen_page() ) {
+ return;
+ }
+
+ wp_enqueue_style( 'wc-facebook-admin-whatsapp-settings', facebook_for_woocommerce()->get_plugin_url() . '/assets/css/admin/facebook-for-woocommerce-whatsapp-utility.css', array(), \WC_Facebookcommerce::VERSION );
+ wp_enqueue_script(
+ 'facebook-for-woocommerce-connect-whatsapp',
+ facebook_for_woocommerce()->get_asset_build_dir_url() . '/admin/whatsapp-connection.js',
+ array( 'jquery', 'jquery-blockui', 'jquery-tiptip', 'wc-enhanced-select' ),
+ \WC_Facebookcommerce::PLUGIN_VERSION
+ );
+ $waba_id = get_option( 'wc_facebook_wa_integration_waba_id', '' );
+ $whatsapp_connected = ! empty( $waba_id );
+ wp_localize_script(
+ 'facebook-for-woocommerce-connect-whatsapp',
+ 'facebook_for_woocommerce_whatsapp_onboarding_progress',
+ array(
+ 'ajax_url' => admin_url( 'admin-ajax.php' ),
+ 'nonce' => wp_create_nonce( 'facebook-for-wc-whatsapp-onboarding-progress-nonce' ),
+ 'whatsapp_onboarding_complete' => $whatsapp_connected,
+ 'i18n' => array(
+ 'result' => true,
+ ),
+ )
+ );
+ wp_enqueue_script(
+ 'facebook-for-woocommerce-whatsapp-consent',
+ facebook_for_woocommerce()->get_asset_build_dir_url() . '/admin/whatsapp-consent.js',
+ array( 'jquery', 'jquery-blockui', 'jquery-tiptip', 'wc-enhanced-select' ),
+ \WC_Facebookcommerce::PLUGIN_VERSION
+ );
+ $consent_collection_enabled = get_option( 'wc_facebook_whatsapp_consent_collection_setting_status', null ) === 'enabled';
+ wp_localize_script(
+ 'facebook-for-woocommerce-whatsapp-consent',
+ 'facebook_for_woocommerce_whatsapp_consent',
+ array(
+ 'ajax_url' => admin_url( 'admin-ajax.php' ),
+ 'nonce' => wp_create_nonce( 'facebook-for-wc-whatsapp-consent-nonce' ),
+ 'whatsapp_onboarding_complete' => $whatsapp_connected,
+ 'consent_collection_enabled' => $consent_collection_enabled,
+ 'i18n' => array(
+ 'result' => true,
+ ),
+ )
+ );
+ $is_payment_setup = (bool) get_option( 'wc_facebook_wa_integration_is_payment_setup', null );
+ wp_enqueue_script(
+ 'facebook-for-woocommerce-whatsapp-billing',
+ facebook_for_woocommerce()->get_asset_build_dir_url() . '/admin/whatsapp-billing.js',
+ array( 'jquery', 'jquery-blockui', 'jquery-tiptip', 'wc-enhanced-select' ),
+ \WC_Facebookcommerce::PLUGIN_VERSION
+ );
+ wp_localize_script(
+ 'facebook-for-woocommerce-whatsapp-billing',
+ 'facebook_for_woocommerce_whatsapp_billing',
+ array(
+ 'ajax_url' => admin_url( 'admin-ajax.php' ),
+ 'nonce' => wp_create_nonce( 'facebook-for-wc-whatsapp-billing-nonce' ),
+ 'consent_collection_enabled' => $consent_collection_enabled,
+ 'is_payment_setup' => $is_payment_setup,
+ 'i18n' => array(
+ 'result' => true,
+ ),
+ )
+ );
+ $order_placed_event_config_id = get_option( 'wc_facebook_wa_order_placed_event_config_id', null );
+ $order_placed_language = get_option( 'wc_facebook_wa_order_placed_language', 'en' );
+ $order_fulfilled_event_config_id = get_option( 'wc_facebook_wa_order_fulfilled_event_config_id', null );
+ $order_fulfilled_language = get_option( 'wc_facebook_wa_order_fulfilled_language', 'en' );
+ $order_refunded_event_config_id = get_option( 'wc_facebook_wa_order_refunded_event_config_id', null );
+ $order_refunded_language = get_option( 'wc_facebook_wa_order_refunded_language', 'en' );
+ wp_enqueue_script(
+ 'facebook-for-woocommerce-whatsapp-events',
+ facebook_for_woocommerce()->get_asset_build_dir_url() . '/admin/whatsapp-events.js',
+ array( 'jquery', 'jquery-blockui', 'jquery-tiptip', 'wc-enhanced-select' ),
+ \WC_Facebookcommerce::PLUGIN_VERSION
+ );
+ wp_localize_script(
+ 'facebook-for-woocommerce-whatsapp-events',
+ 'facebook_for_woocommerce_whatsapp_events',
+ array(
+ 'ajax_url' => admin_url( 'admin-ajax.php' ),
+ 'nonce' => wp_create_nonce( 'facebook-for-wc-whatsapp-events-nonce' ),
+ 'event' => $this->get_current_event(),
+ 'order_placed_enabled' => ! empty( $order_placed_event_config_id ),
+ 'order_placed_language' => $order_placed_language,
+ 'order_fulfilled_enabled' => ! empty( $order_fulfilled_event_config_id ),
+ 'order_fulfilled_language' => $order_fulfilled_language,
+ 'order_refunded_enabled' => ! empty( $order_refunded_event_config_id ),
+ 'order_refunded_language' => $order_refunded_language,
+ 'i18n' => array(
+ 'result' => true,
+ ),
+ )
+ );
+ wp_enqueue_script(
+ 'facebook-for-woocommerce-whatsapp-finish',
+ facebook_for_woocommerce()->get_asset_build_dir_url() . '/admin/whatsapp-finish.js',
+ array( 'jquery', 'jquery-blockui', 'jquery-tiptip', 'wc-enhanced-select' ),
+ \WC_Facebookcommerce::PLUGIN_VERSION
+ );
+ wp_localize_script(
+ 'facebook-for-woocommerce-whatsapp-finish',
+ 'facebook_for_woocommerce_whatsapp_finish',
+ array(
+ 'ajax_url' => admin_url( 'admin-ajax.php' ),
+ 'nonce' => wp_create_nonce( 'facebook-for-wc-whatsapp-finish-nonce' ),
+ 'i18n' => array( // will generate i18 pot translation
+ 'payment_setup_error' => __( 'To proceed, add a payment method to make future purchases on your accounts.', 'facebook-for-woocommerce' ),
+ 'onboarding_incomplete_error' => __( 'Whatsapp Business Account Onboarding is not complete or has failed.', 'facebook-for-woocommerce' ),
+ 'generic_error' => __( 'Something went wrong. Please try again.', 'facebook-for-woocommerce' ),
+ ),
+ )
+ );
+ wp_enqueue_script(
+ 'facebook-for-woocommerce-whatsapp-consent-remove',
+ facebook_for_woocommerce()->get_asset_build_dir_url() . '/admin/whatsapp-consent-remove.js',
+ array( 'jquery', 'jquery-blockui', 'jquery-tiptip', 'wc-enhanced-select' ),
+ \WC_Facebookcommerce::PLUGIN_VERSION
+ );
+ wp_localize_script(
+ 'facebook-for-woocommerce-whatsapp-consent-remove',
+ 'facebook_for_woocommerce_whatsapp_consent_remove',
+ array(
+ 'ajax_url' => admin_url( 'admin-ajax.php' ),
+ 'nonce' => wp_create_nonce( 'facebook-for-wc-whatsapp-consent-disable-nonce' ),
+ 'i18n' => array(
+ 'result' => true,
+ ),
+ )
+ );
+ wp_enqueue_script(
+ 'facebook-for-woocommerce-whatsapp-templates',
+ facebook_for_woocommerce()->get_asset_build_dir_url() . '/admin/whatsapp-templates.js',
+ array( 'jquery', 'jquery-blockui', 'jquery-tiptip', 'wc-enhanced-select' ),
+ \WC_Facebookcommerce::PLUGIN_VERSION
+ );
+ wp_localize_script(
+ 'facebook-for-woocommerce-whatsapp-templates',
+ 'facebook_for_woocommerce_whatsapp_templates',
+ array(
+ 'ajax_url' => admin_url( 'admin-ajax.php' ),
+ 'nonce' => wp_create_nonce( 'facebook-for-wc-whatsapp-templates-nonce' ),
+ 'i18n' => array(
+ 'result' => true,
+ ),
+ )
+ );
+ wp_enqueue_script(
+ 'facebook-for-woocommerce-whatsapp-disconnect',
+ facebook_for_woocommerce()->get_asset_build_dir_url() . '/admin/whatsapp-disconnect.js',
+ array( 'jquery', 'jquery-blockui', 'jquery-tiptip', 'wc-enhanced-select' ),
+ \WC_Facebookcommerce::PLUGIN_VERSION
+ );
+ wp_localize_script(
+ 'facebook-for-woocommerce-whatsapp-disconnect',
+ 'facebook_for_woocommerce_whatsapp_disconnect',
+ array(
+ 'ajax_url' => admin_url( 'admin-ajax.php' ),
+ 'nonce' => wp_create_nonce( 'facebook-for-wc-whatsapp-disconnect-nonce' ),
+ 'i18n' => array(
+ 'result' => true,
+ ),
+ )
+ );
+ }
+
+
+ /**
+ * Renders the screen.
+ *
+ * @since 2.0.0
+ */
+ public function render() {
+ $view = $this->get_current_view();
+ if ( 'utility_settings' === $view ) {
+ $this->render_utility_message_overview();
+ } elseif ( in_array( $view, self::MANAGE_EVENT_VIEWS, true ) ) {
+ $this->render_manage_events_view();
+ } else {
+ $this->render_utility_message_onboarding();
+ }
+ parent::render();
+ }
+
+ /**
+ * Renders the WhatsApp Utility Onboarding screen.
+ */
+ public function render_utility_message_onboarding() {
+
+ ?>
+
+
+
+
+
+
+ get_current_event();
+ ?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 'order_management_4',
+ 'ORDER_FULFILLED' => 'shipment_confirmation_4',
+ 'ORDER_REFUNDED' => 'refund_confirmation_1',
+ );
+
+ /** @var string Default language for Library Template */
+ const DEFAULT_LANGUAGE = 'en';
+
+ /**
+ * Makes an API call to Template Library API
+ *
+ * @param string $event Order Management Event
+ * @param string $bisu_token the BISU token received in the webhook
+ */
+ public static function get_template_library_content( $event, $bisu_token ) {
+ wc_get_logger()->info(
+ sprintf(
+ __( 'In Template Library Get API call ', 'facebook-for-woocommerce' ),
+ )
+ );
+ $base_url = array( self::GRAPH_API_BASE_URL, self::API_VERSION, 'message_template_library' );
+ $base_url = esc_url( implode( '/', $base_url ) );
+ $library_name = self::EVENT_TO_LIBRARY_TEMPLATE_MAPPING[ $event ];
+
+ $params = array(
+ 'name' => $library_name,
+ 'language' => self::DEFAULT_LANGUAGE,
+ 'access_token' => $bisu_token,
+ );
+ $url = add_query_arg( $params, $base_url );
+ $options = array(
+ 'headers' => array(
+ 'Authorization' => $bisu_token,
+ ),
+ 'body' => array(),
+ );
+
+ $response = wp_remote_request( $url, $options );
+ $status_code = wp_remote_retrieve_response_code( $response );
+ $data = wp_remote_retrieve_body( $response );
+ if ( is_wp_error( $response ) || 200 !== $status_code ) {
+ wc_get_logger()->info(
+ sprintf(
+ /* translators: %s $error_message */
+ __( 'Template Library GET API call Failed %1$s ', 'facebook-for-woocommerce' ),
+ $data,
+ )
+ );
+ wp_send_json_error( $response, 'Template Library GET API call Failed' );
+ } else {
+ wc_get_logger()->info(
+ sprintf(
+ __( 'Template Library GET API call Succeeded', 'facebook-for-woocommerce' )
+ )
+ );
+ wp_send_json_success( $data, 'Finish Template Library API Call' );
+ }
+ }
+
+ /**
+ * Makes an API call to Whatsapp Utility Message Connect API
+ *
+ * @param string $waba_id WABA ID
+ * @param string $wacs_id WACS ID
+ * @param string $external_business_id external business ID
+ * @param string $bisu_token BISU token
+ */
+ public static function wc_facebook_whatsapp_connect_utility_messages_call( $waba_id, $wacs_id, $external_business_id, $bisu_token ) {
+ $base_url = array( self::GRAPH_API_BASE_URL, self::API_VERSION, $waba_id, 'connect_utility_messages' );
+ $base_url = esc_url( implode( '/', $base_url ) );
+ $query_params = array(
+ 'external_integration_id' => $external_business_id,
+ 'wacs_id' => $wacs_id,
+ 'access_token' => $bisu_token,
+ );
+ $base_url = add_query_arg( $query_params, $base_url );
+ $options = array(
+ 'headers' => array(
+ 'Authorization' => $bisu_token,
+ ),
+ 'body' => array(),
+ );
+ $response = wp_remote_post( $base_url, $options );
+ wc_get_logger()->info(
+ sprintf(
+ /* translators: %s $response */
+ __( 'Connect Whatsapp Utility Message API Response: %1$s ', 'facebook-for-woocommerce' ),
+ json_encode( $response ),
+ )
+ );
+ $response_body = explode( "\n", wp_remote_retrieve_body( $response ) );
+ $response_data = json_decode( $response_body[0] );
+ if ( is_wp_error( $response ) || 200 !== wp_remote_retrieve_response_code( $response ) ) {
+ $error_message = $response_data->error->error_user_title ?? $response_data->error->message ?? 'Something went wrong. Please try again later!';
+
+ wc_get_logger()->info(
+ sprintf(
+ /* translators: %s $error_message */
+ __( 'Connect Whatsapp Utility Message API Call Failure %1$s ', 'facebook-for-woocommerce' ),
+ $error_message,
+ )
+ );
+ wp_send_json_error( $error_message, 'Finish Onboarding Failure' );
+ } else {
+ $integration_config_id = $response_data->id;
+ wc_get_logger()->info(
+ sprintf(
+ /* translators: %s $integration_config_id */
+ __( 'Connect Whatsapp Utility Message API Call Success!!! Integration ID: %1$s!!!', 'facebook-for-woocommerce' ),
+ $integration_config_id,
+ )
+ );
+ update_option( 'wc_facebook_wa_integration_config_id', $integration_config_id );
+ wp_send_json_success( $response, 'Finish Onboarding Success' );
+ }
+ }
+
+ /**
+ * Makes an API call to Whatsapp Utility Message Disconnect API and delete the options in DB
+ *
+ * @param string $waba_id WABA ID
+ * @param string $integration_config_id whatsapp integration config ID
+ * @param string $bisu_token BISU token
+ */
+ public static function wc_facebook_disconnect_whatsapp( $waba_id, $integration_config_id, $bisu_token ) {
+ $base_url = array( self::GRAPH_API_BASE_URL, self::API_VERSION, $waba_id, 'disconnect_utility_messages' );
+ $base_url = esc_url( implode( '/', $base_url ) );
+ $query_params = array(
+ 'integration_config_id' => $integration_config_id,
+ 'access_token' => $bisu_token,
+ );
+ $base_url = add_query_arg( $query_params, $base_url );
+ $options = array(
+ 'headers' => array(
+ 'Authorization' => $bisu_token,
+ ),
+ 'body' => array(),
+ );
+ $response = wp_remote_post( $base_url, $options );
+ wc_get_logger()->info(
+ sprintf(
+ /* translators: %s $error_message */
+ __( 'Disconnect Whatsapp Utility Message API Call Response: %1$s ', 'facebook-for-woocommerce' ),
+ json_encode( $response ),
+ )
+ );
+ if ( is_wp_error( $response ) || 200 !== wp_remote_retrieve_response_code( $response ) ) {
+ $error_data = explode( "\n", wp_remote_retrieve_body( $response ) );
+ $error_object = json_decode( $error_data[0] );
+ $error_message = $error_object->error->error_user_title ?? $error_object->error->message ?? 'Something went wrong. Please try again later!';
+
+ wc_get_logger()->info(
+ sprintf(
+ /* translators: %s $error_message */
+ __( 'Disconnect Whatsapp Utility Message API Call Error: %1$s ', 'facebook-for-woocommerce' ),
+ $error_message,
+ )
+ );
+ wp_send_json_error( $error_message, 'Disconnect Whatsapp Failure' );
+ } else {
+ wc_get_logger()->info(
+ sprintf(
+ __( 'Disconnect Whatsapp Utility Message API Call Success!!!', 'facebook-for-woocommerce' )
+ )
+ );
+
+ // delete all the whatsapp setting options in DB
+ $wa_settings = array(
+ 'wc_facebook_wa_integration_waba_id',
+ 'wc_facebook_wa_integration_bisu_access_token',
+ 'wc_facebook_wa_integration_business_id',
+ 'wc_facebook_wa_integration_wacs_phone_number',
+ 'wc_facebook_wa_integration_is_payment_setup',
+ 'wc_facebook_wa_integration_wacs_id',
+ 'wc_facebook_wa_integration_waba_profile_picture_url',
+ 'wc_facebook_wa_integration_waba_display_name',
+ 'wc_facebook_whatsapp_consent_collection_setting_status',
+ 'wc_facebook_wa_integration_config_id',
+ 'wc_facebook_wa_order_placed_event_config_id',
+ 'wc_facebook_wa_order_placed_language',
+ 'wc_facebook_wa_order_fulfilled_event_config_id',
+ 'wc_facebook_wa_order_fulfilled_language',
+ 'wc_facebook_wa_order_refunded_event_config_id',
+ 'wc_facebook_wa_order_refunded_language',
+ );
+
+ self::wc_facebook_whatsapp_settings_delete( $wa_settings );
+
+ wc_get_logger()->info(
+ sprintf(
+ __( 'Disconnect Whatsapp Utility Message - Whatsapp Settings Deletion Success!!!', 'facebook-for-woocommerce' )
+ )
+ );
+
+ wp_send_json_success( $response, 'Disconnect Whatsapp Success' );
+ }
+ }
+
+ public static function wc_facebook_whatsapp_settings_delete( $wa_settings ) {
+ foreach ( $wa_settings as $setting ) {
+ delete_option( $setting ); // this only deletes if option exists, no error on failure
+ }
+ }
+
+ /**
+ * Makes an API call to Whatsapp Utility Event Configs Post API to create or update Event Configs
+ *
+ * @param string $event Order Management Event
+ * @param string $integration_config_id Integration Config Id
+ * @param string $language Language Code
+ * @param string $status ACTIVE or INACTIVE
+ * @param string $bisu_token the BISU token received in the webhook
+ */
+ public static function post_whatsapp_utility_messages_event_configs_call( $event, $integration_config_id, $language, $status, $bisu_token ) {
+ $base_url = array( self::GRAPH_API_BASE_URL, self::API_VERSION, $integration_config_id, 'event_configs' );
+ $base_url = esc_url( implode( '/', $base_url ) );
+ $account_url = get_permalink( get_option( 'woocommerce_myaccount_page_id' ) );
+ $view_orders_endpoint = get_option( 'woocommerce_myaccount_view_order_endpoint' );
+ $view_orders_base_url = esc_url( $account_url . $view_orders_endpoint );
+ // Order Refunded template has no CTA
+ $library_template_button_inputs = 'ORDER_REFUNDED' === $event ? array() : array(
+ array(
+ 'type' => 'URL',
+ 'url' => array(
+ // View Url is dynamic and has order_id as suffix
+ 'base_url' => "$view_orders_base_url/{{1}}",
+ // Example view orders url with order id: 1234
+ 'url_suffix_example' => "$view_orders_base_url/1234",
+ ),
+ ),
+ );
+ $query_params = array(
+ 'event' => $event,
+ 'language' => $language,
+ 'status' => $status,
+ 'library_template_name' => self::EVENT_TO_LIBRARY_TEMPLATE_MAPPING[ $event ],
+ 'library_template_button_inputs' => $library_template_button_inputs,
+ 'access_token' => $bisu_token,
+ );
+ $base_url = add_query_arg( $query_params, $base_url );
+ $options = array(
+ 'headers' => array(
+ 'Authorization' => $bisu_token,
+ ),
+ 'body' => array(),
+ 'timeout' => 300, // 5 minutes
+ );
+ $response = wp_remote_post( $base_url, $options );
+ $status_code = wp_remote_retrieve_response_code( $response );
+ $data = explode( "\n", wp_remote_retrieve_body( $response ) );
+ $response_object = json_decode( $data[0] );
+ $is_error = is_wp_error( $response );
+ if ( is_wp_error( $response ) || 200 !== $status_code ) {
+ $error_message = $response_object->error->error_user_title ?? $response_object->error->message ?? 'Something went wrong. Please try again later!';
+ wc_get_logger()->info(
+ sprintf(
+ /* translators: %s $error_message %s status code %s is_wp_error value*/
+ __( 'Event Configs Post API call Failed with Error: %1$s, Status code: %2$d, Is Wp Error: %3$s', 'facebook-for-woocommerce' ),
+ $error_message,
+ $status_code,
+ (string) $is_error,
+ )
+ );
+ wp_send_json_error( $response, 'Event Configs Post API call Failed' );
+ } else {
+ $event_config_id_option_name = implode( '_', array( self::WA_UTILITY_OPTION_PREFIX, strtolower( $event ), 'event_config_id' ) );
+ $event_config_language_option_name = implode( '_', array( self::WA_UTILITY_OPTION_PREFIX, strtolower( $event ), 'language' ) );
+ $event_config_id = $response_object->id;
+ $event_status = $response_object->status;
+ $language = $response_object->language;
+ wc_get_logger()->info(
+ sprintf(
+ /* translators: %s $option_name %s $event_config_id %s $event_status */
+ __( 'Event Configs Post API call Succeeded. API Response Event Config id: %1$s, Event Status: %2$s, Language: %3$s', 'facebook-for-woocommerce' ),
+ $event_config_id,
+ $event_status,
+ $language,
+ )
+ );
+ if ( 'ACTIVE' === $event_status ) {
+ update_option( $event_config_id_option_name, $event_config_id );
+ update_option( $event_config_language_option_name, $language );
+ } else {
+ $settings = array(
+ $event_config_id_option_name,
+ $event_config_language_option_name,
+ );
+ self::wc_facebook_whatsapp_settings_delete(
+ $settings
+ );
+ }
+ wp_send_json_success( 'Event Configs Post API call Completed' );
+ }
+ }
+
+
+ /**
+ * Makes an API call to Event Processor: Message Events Post API to send whatsapp utility messages
+ * TODO: Update API Endpoint from Messages to Message Events
+ *
+ * @param string $event Order Managerment event
+ * @param string $event_config_id Event Config Id
+ * @param string $language_code Language code
+ * @param string $wacs_id Whatsapp Phone Number id
+ * @param string $order_id Order id
+ * @param string $phone_number Customer phone number
+ * @param string $first_name Customer first name
+ * @param int $refund_value Amount refunded to the Customer
+ * @param string $currency Currency code
+ * @param string $bisu_token the BISU token received in the webhook
+ */
+ public static function post_whatsapp_utility_messages_events_call( $event, $event_config_id, $language_code, $wacs_id, $order_id, $phone_number, $first_name, $refund_value, $currency, $bisu_token ) {
+ $base_url = array( self::GRAPH_API_BASE_URL, self::API_VERSION, $wacs_id, "messages?access_token=$bisu_token" );
+ $base_url = esc_url( implode( '/', $base_url ) );
+ $name = self::EVENT_TO_LIBRARY_TEMPLATE_MAPPING[ $event ];
+ $components = self::get_components_for_event( $event, $order_id, $first_name, $refund_value, $currency );
+ $options = array(
+ 'body' => array(
+ 'messaging_product' => 'whatsapp',
+ 'to' => $phone_number,
+ 'template' => array(
+ 'name' => $name,
+ 'language' => array(
+ 'code' => $language_code,
+ ),
+ 'components' => $components,
+ ),
+ 'type' => 'template',
+ ),
+ );
+ $response = wp_remote_post( $base_url, $options );
+ $status_code = wp_remote_retrieve_response_code( $response );
+ $data = explode( "\n", wp_remote_retrieve_body( $response ) );
+ $response_object = json_decode( $data[0] );
+ if ( is_wp_error( $response ) || 200 !== $status_code ) {
+ $error_message = $response_object->error->error_user_title ?? $response_object->error->message ?? 'Something went wrong. Please try again later!';
+ wc_get_logger()->info(
+ sprintf(
+ /* translators: %s $order_id %s $error_message */
+ __( 'Messages Post API call for Order id %1$s Failed %2$s ', 'facebook-for-woocommerce' ),
+ $order_id,
+ $error_message,
+ )
+ );
+ } else {
+ wc_get_logger()->info(
+ sprintf(
+ /* translators: %s $order_id */
+ __( 'Messages Post API call for Order id %1$s Succeeded.', 'facebook-for-woocommerce' ),
+ $order_id
+ )
+ );
+ }
+ }
+
+
+ /**
+ * Gets Component Objects for Order Management Events
+ *
+ * @param string $event Order Management event
+ * @param string $order_id Order id
+ * @param string $first_name Customer first name
+ * @param string $refund_value Amount refunded to the Customer
+ * @param string $currency Currency code
+ */
+ public static function get_components_for_event( $event, $order_id, $first_name, $refund_value, $currency ) {
+ if ( 'ORDER_REFUNDED' === $event ) {
+ return array(
+ array(
+ 'type' => 'HEADER',
+ 'parameters' => array(
+ array(
+ 'type' => 'currency',
+ 'currency' => array(
+ 'fallback_value' => 'VALUE',
+ 'code' => $currency,
+ 'amount_1000' => $refund_value,
+ ),
+ ),
+ ),
+ ),
+ array(
+ 'type' => 'BODY',
+ 'parameters' => array(
+ array(
+ 'type' => 'text',
+ 'text' => $first_name,
+ ),
+ array(
+ 'type' => 'currency',
+ 'currency' => array(
+ 'fallback_value' => 'VALUE',
+ 'code' => $currency,
+ 'amount_1000' => $refund_value,
+ ),
+ ),
+ array(
+ 'type' => 'text',
+ 'text' => "#$order_id",
+ ),
+ ),
+ ),
+ );
+ } else {
+ return array(
+ array(
+ 'type' => 'BODY',
+ 'parameters' => array(
+ array(
+ 'type' => 'text',
+ 'text' => $first_name,
+ ),
+ array(
+ 'type' => 'text',
+ 'text' => "#$order_id",
+ ),
+ ),
+ ),
+ array(
+ 'type' => 'BUTTON',
+ 'sub_type' => 'url',
+ 'index' => 0,
+ 'parameters' => array(
+ array(
+ 'type' => 'text',
+ 'text' => "$order_id",
+ ),
+ ),
+ ),
+ );
+ }
+ }
+}
diff --git a/includes/Handlers/Whatsapp_Webhook.php b/includes/Handlers/Whatsapp_Webhook.php
new file mode 100644
index 000000000..12d9605ef
--- /dev/null
+++ b/includes/Handlers/Whatsapp_Webhook.php
@@ -0,0 +1,209 @@
+ array( 'POST' ),
+ 'callback' => array( $this, 'whatsapp_webhook_callback' ),
+ 'permission_callback' => '__return_true',
+ ),
+ )
+ );
+ }
+
+ /**
+ * Updates Facebook settings options.
+ *
+ * @param array $settings Array of settings to update.
+ *
+ * @return bool
+ * @internal
+ */
+ private static function update_settings( $settings ) {
+ $updated = array();
+ foreach ( $settings as $key => $value ) {
+ if ( ! empty( $key ) ) {
+ $updated[ $key ] = update_option( $key, $value );
+ }
+ }
+ // if any of setting updates failed, return false
+ return ! in_array( false, $updated, true );
+ }
+
+ /**
+ * Authenticates Whatsapp Webhook using the SHA1 of the external business ID and BISU token
+ *
+ * @param string $auth_key the auth key received in the webhook
+ * @param string $bisu_token the BISU token received in the webhook
+ *
+ * @return bool
+ * @internal
+ */
+ private static function authenticate_request( $auth_key, $bisu_token ) {
+ $external_business_id = get_option( 'wc_facebook_external_business_id' );
+
+ $expected_auth_key = 'sha1=' . (string) hash_hmac( 'sha1', $bisu_token, $external_business_id );
+
+ return hash_equals( $expected_auth_key, $auth_key );
+ }
+
+
+
+ /**
+ * Whatsapp Webhook Listener
+ *
+ * @since 2.3.0
+ * @see Connection
+ *
+ * @param \WP_REST_Request $request The request.
+ * @return \WP_REST_Response
+ */
+ public function whatsapp_webhook_callback( \WP_REST_Request $request ) {
+ try {
+ $request_params = $request->get_params();
+ $waba_id = sanitize_text_field( $request_params['wabaId'] );
+ $wacs_id = sanitize_text_field( $request_params['wacsId'] );
+ $is_waba_payment_setup = sanitize_text_field( $request_params['isWabaPaymentSetup'] );
+ $waba_profile_picture_url = sanitize_text_field( $request_params['wabaProfilePictureUrl'] );
+ $bisu_token = sanitize_text_field( $request_params['clientBisuToken'] );
+ $business_id = sanitize_text_field( $request_params['clientBusinessId'] );
+ $wacs_phone_number = sanitize_text_field( $request_params['wacsPhoneNumber'] );
+ $waba_display_name = sanitize_text_field( $request_params['wabaDisplayName'] );
+ $auth_key = sanitize_text_field( $request_params['authKey'] );
+
+ // authentication is done via auth_key using sha_1 hash mac of BISU token and external business ID stored in woo DB
+ $authentication_result = self::authenticate_request( $auth_key, $bisu_token );
+
+ if ( false === $authentication_result ) {
+ wc_get_logger()->info(
+ sprintf(
+ __( 'Authentication Failure on received Whatsapp Webhook', 'facebook-for-woocommerce' ),
+ )
+ );
+ return new \WP_REST_Response(
+ [
+ 'success' => false,
+ 'message' => 'Authentication Failure on received Whatsapp Webhook',
+ ],
+ 400
+ );
+ }
+
+ if ( empty( $waba_id ) || empty( $bisu_token ) || empty( $business_id ) || empty( $wacs_phone_number ) || empty( $wacs_id ) ) {
+ wc_get_logger()->info(
+ sprintf(
+ __( 'All required onboarding info not received in Whatsapp Webhook', 'facebook-for-woocommerce' ),
+ )
+ );
+ return new \WP_REST_Response(
+ [
+ 'success' => false,
+ 'message' => 'All required onboarding info not received in Whatsapp Webhook',
+ ],
+ 400
+ );
+ }
+
+ wc_get_logger()->info(
+ sprintf(
+ /* translators: %s waba ID %s business ID */
+ __( 'Whatsapp Account WebHook Event received. WABA ID: %1$s, Business ID: %2$s ', 'facebook-for-woocommerce' ),
+ $waba_id,
+ $business_id
+ )
+ );
+
+ $options_setting_fields = array(
+ 'wc_facebook_wa_integration_waba_id' => $waba_id,
+ 'wc_facebook_wa_integration_bisu_access_token' => $bisu_token,
+ 'wc_facebook_wa_integration_business_id' => $business_id,
+ 'wc_facebook_wa_integration_wacs_phone_number' => $wacs_phone_number,
+ 'wc_facebook_wa_integration_is_payment_setup' => $is_waba_payment_setup,
+ 'wc_facebook_wa_integration_wacs_id' => $wacs_id,
+ 'wc_facebook_wa_integration_waba_profile_picture_url' => $waba_profile_picture_url,
+ 'wc_facebook_wa_integration_waba_display_name' => $waba_display_name,
+
+ );
+
+ $result = self::update_settings( $options_setting_fields );
+
+ if ( false === $result ) {
+ wc_get_logger()->info(
+ sprintf(
+ /* translators: %d $waba_id, %d $business_id. */
+ __( 'Whatsapp Integration Setting Fields Update Failure waba_id: %1$s, business_id: %2$s', 'facebook-for-woocommerce' ),
+ $waba_id,
+ $business_id,
+ )
+ );
+
+ return new \WP_REST_Response(
+ [
+ 'success' => false,
+ 'message' => 'Whatsapp Integration Setting Fields Update Failure',
+ ],
+ 400
+ );
+
+ }
+
+ wc_get_logger()->info(
+ sprintf(
+ /* translators: %d $waba_id, %d $business_id. */
+ __( 'Whatsapp Integration Setting Fields stored successfully in wp_options. wc_facebook_wa_integration_waba_id: %1$s, wc_facebook_wa_integration_business_id: %2$s ', 'facebook-for-woocommerce' ),
+ $waba_id,
+ $business_id,
+ )
+ );
+
+ return new \WP_REST_Response( [ 'success' => true ], 200 );
+ } catch ( \Exception $e ) {
+ return $this->error_response(
+ [
+ 'success' => false,
+ 'message' => $e->getMessage(),
+ ],
+ 500
+ );
+ }
+ }
+}
diff --git a/includes/RolloutSwitches.php b/includes/RolloutSwitches.php
index e9beb84dc..1c925c269 100644
--- a/includes/RolloutSwitches.php
+++ b/includes/RolloutSwitches.php
@@ -23,10 +23,12 @@ class RolloutSwitches {
/** @var \WC_Facebookcommerce commerce handler */
private \WC_Facebookcommerce $plugin;
- public const SWITCH_ROLLOUT_FEATURES = 'rollout_enabled';
+ public const SWITCH_ROLLOUT_FEATURES = 'rollout_enabled';
+ public const WHATSAPP_UTILITY_MESSAGING = 'whatsapp_utility_messages_enabled';
private const ACTIVE_SWITCHES = array(
self::SWITCH_ROLLOUT_FEATURES,
+ self::WHATSAPP_UTILITY_MESSAGING,
);
/**
* Stores the rollout switches and their enabled/disabled states.
@@ -88,7 +90,7 @@ public function is_switch_enabled( string $switch_name ) {
return false;
}
- return $this->rollout_switches[ $switch_name ] ?? true;
+ return isset( $this->rollout_switches[ $switch_name ] ) ? $this->rollout_switches[ $switch_name ] : true;
}
public function is_switch_active( string $switch_name ): bool {
diff --git a/webpack.config.js b/webpack.config.js
index ad207bcf0..ab10dc326 100644
--- a/webpack.config.js
+++ b/webpack.config.js
@@ -13,23 +13,31 @@ const jQueryUIAdminFileNames = [
'settings-commerce',
'settings-sync',
'enhanced-settings-sync',
+ 'whatsapp-billing',
+ 'whatsapp-connection',
+ 'whatsapp-consent',
+ 'whatsapp-templates',
+ 'whatsapp-finish',
+ 'whatsapp-consent-remove',
+ 'whatsapp-disconnect',
+ 'whatsapp-events',
];
const jQueryUIAdminFileEntries = {};
jQueryUIAdminFileNames.forEach( ( name ) => {
- jQueryUIAdminFileEntries[ `admin/${ name }` ] = `./assets/js/admin/${ name }.js`;
+ jQueryUIAdminFileEntries[ `admin/${ name }` ] = `./assets/js/admin/${ name }.js`;
} );
module.exports = {
- ...defaultConfig,
- entry: {
- // Use admin/index.js for any new React-powered UI
- 'admin/index': './assets/js/admin/index.js',
- ...jQueryUIAdminFileEntries,
- },
- output: {
- filename: '[name].js',
- path: __dirname + '/assets/build',
- },
+ ...defaultConfig,
+ entry: {
+ // Use admin/index.js for any new React-powered UI
+ 'admin/index': './assets/js/admin/index.js',
+ ...jQueryUIAdminFileEntries,
+ },
+ output: {
+ filename: '[name].js',
+ path: __dirname + '/assets/build',
+ },
};