Learn the basic functionality of the Weebly PHP Webhook Client. Click the "Start" button below to see how Viewsaurus works.
Start TutorialThe tutorial's navigation controls are located above this text. Use <i class="fa fa-fw fa-play"></i> to move to the next step of the tutorial. Use <i class="fa fa-fw fa-play fa-rotate-180"></i> to move to the previous step of the tutorial (if there is one). Use <i class="fa fa-fw fa-list"></i> to see an overview of all the steps in the tutorial.
To obtain valid API Keys, you must first register your weebly app.
Please name this new app uniquely by using the following app naming convention (you will use this later in the tutorial as well): {{PREFIX}}-evt-sub
To ensure a unique naming patter, I recommend setting {{PREFIX}} to the initial of your first name + first three characters of your last name.
For example, if your name is "James Gunn", your {{PREFIX}} would be: jgun
.
Set the 'category' of your new app to Services
.
Please use the instructions in the README file to setup this app for live operation and to see it in action.
This app uses Composer for dependency management, and is expected to run on Heroku within a Docker container.
You can run this project locally, but that is outside the scope of this tutorial (since you'll need secure tunneling using a tool such as ngrok.
Instead, it is expected you will follow the directions in the README file to deploy this container to Heroku.
Here, the code is checking if you are running locally or in production, and loads the environment variables appropriately.
Once dependencies are loaded from Composer autoload, the app checks to make certain your Weebly API Keys are available as environment Variables, because they will be used in subsequent request handlers.
If these checks all return satisfactory results, the app is started.
It handles all incoming HTTP requests to /oauth
(where '/' is the webroot of the app).
Please read the App Authorization and Installation Flow to understand each phase of the OAuth2 Authorization Flow that Weebly apps encounter during installation.
First, the code will accept HTTP GET requests going to /oauth/phase-one
, and immediately defines the clientId
and secretKey
variables which were made available from the Weebly Middleware.
As a developer, you must KNOW with great confidence the inbound requests your web applications can trust.
In this section of code you can see how to invalidate requests to ensure that requests sent to this particular route can be trusted as coming from Weebly. Here, a comparison object is created and converted into a string (verification HMAC) using identical values to the Weebly generated HMAC. then you use these two pieces of data to invalidate the HMAC query parameter received in requests to this route, are actually requests you can trust were sent from Weebly servers.
You can read the details about this here, but to provide you the 'gist' of what happens:
manifest.json
) that your app is requestingSince the request is trusted, you first generate the second phase URL, callback parameters, and version (if included in the original request).
Then your app redirects to the appropriate Weebly URL to obtain an authorization_code
.
If the redirect is successfully formed/accepted, Weebly will respond to your redirect by sending a new HTTP request to containing an authorization_code
correlating to the Weebly User and Site.
Here, the code designates it will accept HTTP GET requests going to /oauth/phase-two
, and immediately defines the clientId
and secretKey
variables.
NOTE: It is of CRITICAL IMPORTANCE you take every measure possible to secure and mitigate attackers from obtaining your Weebly API Keys (including your app manifest.json
file).
There are a few things happening here to exchange the authorization_code
for a valid access_token
:
authorization_code
, client_id
, client_secret
redirect_url
parameter is used as the destination for the subsequent code-token exchange request/app-center/oauth/access_token
access_token
will be received upon a successful request, and should be stored securely by your app for future Weebly API requestsMany developers get confused about when their app is actually "installed" and "connected" to a Weebly site.
Logging new access_tokens to '/messages/messages.txt' file is not very useful or productive. What this section of code represents is the correct point-in-time during the App Authorization and Installation Flow when your app/service has an opportunity to ensure the most optimal User Experience by performing any:
These types of service initializations should occur prior to your app redirecting to the final destination, which you can see in the next step of the tutorial.
To reach this point in the code, your app must have:
manifest.json
callback_url propertyauthorization_code
from the phase-two portion of the OAuth2 Authorization Flowauthorization_code
for a valid API access_token
This final redirect indicates to Weebly that your app has completed all necessary setup and configuration operations, and the app should be considered "installed" and "connected".
If your app does not perform this final redirect, your app will be in a disconnected state.
Your app needs to handle all incoming HTTP POST requests beginning with /webhooks
.
The URL where events will be sent is defined in webhooks.callback_url
property of your manifest.json
.
Please read the Receiving Webhooks to understand the data Weebly will POST to your app when events occur to which your app has subscribed.
Weebly apps can subscribe to events. There are several different types of events available for your app to be notified about when they occur upon a site where your app is installed:
You define the types of Weebly Events your app will receive in the webhooks.events property in your manifest.json
.
The default events
this app subscribes to are: app.uninstall
, user.update
, site.publish
, site.delete
. These are all crucial events for any Weebly App and are highly recommended for subscription.
The code here indicates this app will only HTTP POST requests sent to:
{{YOUR_APP_ROOT_URL}}/webhooks/callback
will be accepted, but you still need to peform request invalidation to be certain Weebly sent the request.
To prevent malicious attackers from spoofing or forging requests to your webhook.callback_url
you need to invalidate the request.
All Webhook Event POST Request Body will contain:
client_id
: Your app's Client ID from the Weebly Developer Admin Portalclient_version
: The version of your app which generated the event (helpful in cases of managing multiple versions)event
: The event name (according to the Weebly Webhook docs)timestamp
: Unix epoch timestamp when the event occurred according to Weebly serversdata
: Event-specific data, see the respective Webhook Event Type docshmac
: client_id,
client_version,
event,
timestamp, and
data` sent in the request to be used to invalidate incoming event requestsSimilar to verifying the HMAC hash received on app installation, here we prepare a comparison object/string and then re-generate the HMAC to be certain the request was actually created and sent by Weebly.
Here, the code is merely logging the event headers and requests to console, but this is an opportunity for your app to become event-driven!
In production apps, this is the point-in-time to handle events allowing your app to behave proactively, addressing concerns such as:
app.uninstall
or site.delete
events)When your app has received a valid and verified Weebly Event Request, it is expected that your server will respond with an HTTP 200 Status Code before the request times out.
If you respond with anything other than an HTTP 200 to a valid Weebly Webhook Event Request, Weebly will continue to retry sending the Webhook event to your server up to 12 times over a 48 hour period.
A natural next step is for you to develop custom event handlers that interoperate with your business systems.
This app is already subscribed to: app.uninstall
, site.publish
, site.delete
, and user.update
events.
How would you implement custom handlers for each of these types of events?
You'll want to have a persistent data store to handle:
app.uninstall
or site.delete
eventsTo help us improve this tutorial, and the code we open source, we need your feedback: