Assume that your integration is an online marketplace, and that a customer just placed an order on your site. A few days after the customer initiated their payment, your application receives this webhook.
The topic
field of an event holds a description of the event, which is similar the subject of an e-mail message. The webhook
itself contains _links
to the resource impacted by the event that can be used to retrieve more information about the webhook you have received.
{
"id": "cac95329-9fa5-42f1-a4fc-c08af7b868fb",
"resourceId": "cdb5f11f-62df-e611-80ee-0aa34a9b2388",
"topic": "customer_transfer_created",
"timestamp": "2017-01-20T22:45:12.790Z",
"_links": {
"self": {
"href": "https://api-sandbox.dwolla.com/events/cac95329-9fa5-42f1-a4fc-c08af7b868fb"
},
"account": {
"href": "https://api-sandbox.dwolla.com/accounts/ad5f2162-404a-4c4c-994e-6ab6c3a13254"
},
"resource": {
"href": "https://api-sandbox.dwolla.com/transfers/cdb5f11f-62df-e611-80ee-0aa34a9b2388"
},
"customer": {
"href": "https://api-sandbox.dwolla.com/customers/e358a488-6699-4d79-bbfb-c5bf58100ea4"
}
},
"created": "2017-01-20T22:45:12.790Z"
}
Before we process any data from the webhook we’ll want to validate that the request really came from Dwolla and not someone pretending to be Dwolla. Dwolla signs each webhook request with the secret
you passed in when you created the webhook subscription. The signature is contained in the X-Request-Signature-SHA-256
header and is a SHA256 HMAC hash of the request body with the key being your webhook secret.
You can validate the webhook by generating the same SHA256 HMAC hash and comparing it to the signature sent with the payload.
var crypto = require("crypto");
var bufferFrom = require("buffer").Buffer.from;
function verifyGatewaySignature(
proposed_signature,
webhook_secret,
payload_body
) {
var hash = crypto
.createHmac("sha256", webhook_secret)
.update(payload_body)
.digest("hex");
return crypto.timingSafeEqual(
bufferFrom(proposed_signature),
bufferFrom(hash)
);
}
It is important to consider that duplicate webhooks may be fired for the same Event
. To avoid doing any business logic twice, you would need to build idempotent webhook event processing in your app by checking if you have already successfully processed a webhook for a particular event. Event IDs are unique, so if you receive a webhook with an event ID that you have already received and acknowledged, then you can ignore that webhook.
To do this, keep a queue of events in a database and check to see if an Event
has the same self
resource location in _links
as another event. If not, process the logic for that event. To illustrate, this is how a developer would implement this using Ruby and the ActiveRecord ORM.
check_db = ActiveRecord::Base.connection.execute("SELECT * FROM EVENTS WHERE SELF = #{event[:_links][:self].to_s}")
# check_db will be an array of rows returned
unless check_db.length() == 0
# do something
end
Use sandbox environment to test API requests.
Dwolla, Inc. is the operator of a software platform that communicates user instructions for funds transfers to our financial institution partners.
Dwolla is an agent of Veridian Credit Union. All ACH and Wire transfers are performed by Veridian Credit Union. Your Dwolla Balance, if any, is held in one or more pooled holding accounts held by Veridian Credit Union. These funds may not be eligible for share insurance by the National Credit Union Share Insurance Fund.
Sponsorship and Settlement of Push-to-Debit payment services provided by MetaBank®, N.A.
Push-to-Debit payments are typically available within 30 minutes.
Real-Time Payments are performed by Cross River Bank, which holds funds on behalf of the Receiver of such transactions in one or more pooled custodial accounts. These funds are not subject to FDIC pass-through deposit insurance.