Webhook debugging and documentation questions


(Eric Mayefsky) #1

Hey Dwollans,

I am adding webhooks to my service and am having difficulty getting the webhooks to actually fire. A few questions related to this:

–Is there any external way to see if a webhook is working, other than knowing that my endpoint is not being hit? That would be a nice debugging feature, I would think, for a lot of folks, to just be able to click a button in your app dashboard that triggers an attempted post to a webhook.

–The documentation says “Although Notifications are asynchronous, the information sent with the request will always follow the corresponding information on Dwolla.com and, where exposed, the information available via the Dwolla API. For example, if you subscribe an application to transaction status Notifications, the status value sent via the Notification contains the same status you’d see on Dwolla.com or in a response from Dwolla’s transactions API for the given transaction.” How asynchronous are we talking? Are there any SLAs at all on when the webhook arrives?

https://developers.dwolla.com/dev/pages/webhooks describes four webhooks, but a fifth one, TransactionCreated, is available in the Add/Remove Application Features page. Any reason this is undocumented?

–Does TransactionStatus fire when a transaction is first created, or only TransactionCreated? For transactions that involve existing Dwolla balances, and so are processed immediately, do TransactionCreated and TransactionStatus both fire?


(Gordon Zheng) #2

Hey @Eric_Mayefsky,

A common cause for failed webhooks is a webhook URL with a port number. Dwolla will ignore port numbers and default to port 80 for http and 443 for https. For example, if you set the webhook URL to:

http://mywebsite.com:3000/webhook

Dwolla will actually send webhooks to:

http://mywebsite.com:80/webhook

Let’s answer those questions…

  1. I usually set the Webhook “All URL” in application settings to a requestb.in when testing webhooks. This will confirm that webhooks are actually being fired for whatever action you’re expecting to trigger the webhook. It’s definitely on our wish-list to build a webhook request/log inspector like Twilio’s.
  2. There is no service-level agreement which guarantees the timing of webhooks. We can say for sure, though, that webhooks are always sent immediately after the event which triggers it occurs. For example, a TransactionStatus webhook will be sent, 1 second after a transaction is created via the Send endpoint, rather than, say, 1 minute.
  3. Good catch. TransactionCreated is a deprecated webhook type. It is no longer fired, which is why it’s no longer documented. Thanks for pointing this out. We will remove the field from the Application Features page.
  4. When a transaction is created, a TransactionStatus webhook is fired immediately. Any changes to its status afterwards, say, if it becomes failed or processed or reclaimed, will also trigger another TransactionStatus webhook immediately following the change.

Hope that helps!


(Eric Mayefsky) #3

Thanks @gordon! This was super helpful and I was able to figure out the issues I was having.

Just to be 1000% clear: for a Dwolla balance-funded transaction, the TransactionStatus comes into existence as processed, right? So (at least for a properly functioning transaction) we should see exactly one TransactionStatus webhook in the lifetime of the transaction.


(Gordon Zheng) #4

Yes, a balance funded transaction will only fire a TransactionStatus webhook with a status of “processed”.

That’s because balance funded transactions clear instantly.


#5

Hello all,

I can get webhooks to fire (I think). The website is set to https://www.(mywebsite).com/(mycode) because my endpoint would 301 redirect any other format

My issue is with responding to the webhook. I am using nodejs/express. There seems to be two ways of getting webhook info.

  1. Something like this: app.post(’/(mycode)’, handleWebhookFunction).
  2. Something like this: dwollaAppToken.get(${dwollaWHSubscriptionLocation}/webhooks).then(webhooksCB, webhooksErrCB);

The first function has a a signature like this handleWebhookFunction(req, res). I can respond with an HTTP status.
In the second function I get a list of webhooks. I can’t respond to this (at least I can’t do res.sendStatus(200)), but I can get the detailed webhook info.

If I respond in the first case, the second call will no longer display the corresponding webhook (that is my understanding), and there is no way to relate the two responses. There is no common ID format, for example.

Below are samples of the data I get from each call. I want to respond to the first and process the second, but it’s not clear to me how I can do this. Btw, these are from two separate events.

Thanks.

  1. req.body under handleWebhookFunction(req, res).
    { Id: ‘2337695’,
    Type: ‘Transaction’,
    Subtype: ‘Status’,
    Created: ‘2017-07-11T05:34:54.000Z’,
    Triggered: ‘2017-07-11T05:34:50.635Z’,
    Value: ‘processed’,
    Transaction:
    { Type: ‘money_sent’,
    Notes: ‘’,
    Fees: [],
    Id: 2337695,
    Source: [Object],
    Destination: [Object],
    Amount: 10,
    SentDate: ‘2017-07-11T05:34:54.000Z’,
    ClearingDate: ‘’,
    Status: ‘processed’ },
    Metadata: null },

^^^^^This is all the relevant info from the post request^^^^^^^

  1. res.body._embedded.webhooks[i] upon dwollaAppToken.get(${dwollaWHSubscriptionLocation}/webhooks).then(webhooksCB, webhooksErrCB)

{
"_links": {
“self”: {
“href”: “https://api-sandbox.dwolla.com/webhooks/b1ec06f5-7c4b-4ca9-bdbe-409908be98aa”,
“type”: “application/vnd.dwolla.v1.hal+json”,
“resource-type”: “webhook”
},
“subscription”: {
“href”: “https://api-sandbox.dwolla.com/webhook-subscriptions/c78d4844-6dd8-4558-b461-2b8fa85e33e4”,
“type”: “application/vnd.dwolla.v1.hal+json”,
“resource-type”: “webhook-subscription”
},
“retry”: {
“href”: “https://api-sandbox.dwolla.com/webhooks/b1ec06f5-7c4b-4ca9-bdbe-409908be98aa/retries”,
“type”: “application/vnd.dwolla.v1.hal+json”,
“resource-type”: “retry”
},
“event”: {
“href”: “https://api-sandbox.dwolla.com/events/79fc9948-aaac-4ec6-a4da-6a19afb5a472”,
“type”: “application/vnd.dwolla.v1.hal+json”,
“resource-type”: “event”
}
},
“id”: “b1ec06f5-7c4b-4ca9-bdbe-409908be98aa”,
“topic”: “transfer_created”,
“accountId”: “c9bed799-0810-4049-9977-5435b612548c”,
“eventId”: “79fc9948-aaac-4ec6-a4da-6a19afb5a472”,
“subscriptionId”: “c78d4844-6dd8-4558-b461-2b8fa85e33e4”,
“attempts”: [
{
“id”: “bda3e91f-f7ba-4893-80bb-0135ae317bf7”,
“request”: {
“timestamp”: “2017-07-02T07:21:59.463Z”,
“url”: “https://mywebsite.com/mycode”,
“headers”: [
{
“name”: “X-Dwolla-Topic”,
“value”: “transfer_created”
},
{
“name”: “X-Request-Signature-SHA-256”,
“value”: “db58a45726b419d7ef66a54b94e2b066592238ddd732452e7ceaac1f40597404”
}
],
“body”: “{“id”:“79fc9948-aaac-4ec6-a4da-6a19afb5a472”,“resourceId”:“9121cf22-f75e-e711-80f3-0aa34a9b2388”,“topic”:“transfer_created”,“timestamp”:“2017-07-02T07:21:59.220Z”,”_links":{“self”:{“href”:"https://api-sandbox.dwolla.com/events/79fc9948-aaac-4ec6-a4da-6a19afb5a472"},“account”:{“href”:“https://api-sandbox.dwolla.com/accounts/c9bed799-0810-4049-9977-5435b612548c”},“resource”:{“href”:“https://api-sandbox.dwolla.com/transfers/9121cf22-f75e-e711-80f3-0aa34a9b2388”}},“created”:“2017-07-02T07:21:59.220Z”}"
},
“response”: {
“timestamp”: “2017-07-02T07:21:59.465Z”,
“headers”: [
{
“name”: “Date”,
“value”: “Sun, 02 Jul 2017 07:21:59 GMT”
},
{
“name”: “Location”,
“value”: “https://www.mywebsite.com/mycode
},
{
“name”: “Server”,
“value”: “nginx/1.10.2”
},
{
“name”: “X-Powered-By”,
“value”: “Express”
},
{
“name”: “Content-Length”,
“value”: “0”
},
{
“name”: “Connection”,
“value”: “keep-alive”
}
],
“statusCode”: 301,
“body”: “”
}
}


#6

Scratch that:
" The website is set to https://www.(mywebsite).com/(mycode) because my endpoint would 301 redirect any other format"

I made sure to keep this format in the app features on the dwolla website, but when I created the webhook subscription in my app source code, I had this form —https://(mywebsite).com/(mycode)— [no “www”], so the webhooks were getting redirected.

Now the request object in app.post(’/(mycode)’, handleWebhookFunction). has all the relevant fields, as if from dwollaAppToken.get(${dwollaWHSubscriptionLocation}/webhooks).then(webhooksCB, webhooksErrCB);

So maybe I don’t even need to do the latter in my app, unless I want to retry a webhook.

Thanks to all.