Webhooks
Webhooks call a certain website that you register within Áskell when certain events happen. Events that can be registered before:
State identifier |
Description |
|---|---|
|
All events that are connected to subscriptions |
|
Subscription created |
|
Subscription changed |
|
Subscription renewed |
|
Allir atburðir sem tengjast samningsáskriftum |
|
Samningsáskrift stofnuð |
|
Samningsáskrift breytt |
|
Samningsáskrift endurnýjuð |
|
Allir atburðir sem tengjast keyrslum reikningagerðar |
|
Keyrsla reikningagerðar stofnuð |
|
Keyrsla reikningagerðar breytt |
|
Keyrsla reikningagerðar tókst |
|
Keyrsla reikningagerðar mistókst endanlega |
|
Fyrirhugað að reyna aftur keyrslu reikningagerðar |
|
All events that are connected to customers |
|
Customer created |
|
Customer changed |
|
All events that are connected to individual payments |
|
Individual payment created |
|
Individual payment changed (f.ex. transaction is successful or non successful) |
|
Retry pending for an individual payment |
|
All events that are connected to checkouts |
|
Checkout created |
|
Checkout changed |
Identification
Við mælum með því að allir vefkrókar séu auðkenndir. Við undirritum hvert kall með haus (e. header) sem heitir Hook-HMAC. Gildið er HMAC hakkaður strengur byggður á innihaldi vefkallsins og svo leynilegu gildi sem er aðeins þekkt af okkur og þér. Þú færð þetta leynilega gildi í hendurnar þegar þú stofnar nýjan vefkrók. Tegund atburðar kemur einnig fram í hausnum Hook-Event. Útgáfa API gagna kemur fram í hausnum Hook-API-Version. Eldri plan/áskriftar vefkrókar senda v1, en nýja samningsáskriftarkerfið sendir v2.
Here is a Python example. The process is very similar to what Shopify uses and you can find more code examples in their documentation here.
import base64
import hmac
import hashlib
WEBHOOK_SECRET = "Your webhook secret".encode()
WEBHOOK_DIGEST_TYPE = 'sha512'
def verify(hmac_header, digest_method, secret, message):
digestmod = getattr(hashlib, digest_method)
signed = base64.b64encode(
hmac.new(secret, message, digestmod).digest(),
).strip()
return hmac.compare_digest(signed, hmac_header)
# your view function
def handle_webhook(request):
# The signature
digest = request.META.get('HTTP_HOOK_HMAC').encode()
# The name of the webhook event
event = request.META.get('HTTP_HOOK_EVENT').encode()
body = request.body
if verify(digest, WEBHOOK_DIGEST_TYPE, WEBHOOK_SECRET, body):
payload = json.loads(body)
# ... the rest of your code here```
require 'rubygems'
require 'base64'
require 'openssl'
require 'sinatra'
WEBHOOK_SECRET = 'Your webhook secret'
WEBHOOK_DIGEST_TYPE = 'sha512'
helpers do
def verify_webhook(secret, data, hmac_header)
digested = ::OpenSSL::HMAC.digest(WEBHOOK_DIGEST_TYPE, secret, data)
calculated_hmac = Base64.encode64(digested).strip
return calculated_hmac == hmac_header
end
end
post '/' do
request.body.rewind
data = request.body.read
if verify_webhook(WEBHOOK_SECRET, env["HTTP_HOOK_HMAC"])
# deserialize data' using json and process webhook
end
end
<?php
define('WEBHOOK_SECRET', 'Your webhook secret')
define('WEBHOOK_DIGEST_TYPE', 'sha512')
function verify_webhook($data, $hmac_header)
{
$calculated_hmac = base64_encode(hash_hmac(WEBHOOK_DIGEST_TYPE, $data,
WEBHOOK_SECRET, true));
return ($hmac_header == $calculated_hmac);
}
$hmac_header = $_SERVER['HTTP_HOOK_HMAC'];
$data = file_get_contents('php://input');
$verified = verify_webhook($data, $hmac_header);
?>
Data in webhooks
Subscriptions (subscription.*)
When a subscription is created, updated or renewed the following events are sent. Here is an example of data that comes with a subscription event:
{
"id": 12345,
"plan": {
"id": 12345,
"name": "Titill",
"alternative_name": "Annar titill",
"reference": "",
"interval": "month",
"interval_count": 1,
"amount": "1.0000",
"currency": "ISK",
"trial_period_days": 5,
"enabled": true,
"private": false,
"electronic_only": true,
"description": "Some description"
},
"customer": 12345,
"customer_reference": "customer-12345",
"trial_end": "2024-01-01T00:00:00Z",
"start_date": "2024-01-01T00:00:00Z",
"ended_at": null,
"reference": "reference-12345",
"active": true,
"meta": "{}",
"description": "Some subscription description",
"active_until": "2024-02-01T00:00:00Z",
"is_on_trial": false,
"token": "md5sumtokenwith32chars",
"is_failing": false,
"last_billing_log": {
"id": 12345,
"billing_log_type": "renewal",
"billing_date": "2024-01-01T00:00:00Z",
"plan_billed_up_to": "2024-02-01T00:00:00Z",
"total": null,
"transaction": {
"external_reference": null,
"data": {},
"state": "settled",
"uuid": "some-guid-with-numbers-and-letters",
"fail_code": null,
"refund_code": null,
"cancel_code": null,
"amount": "1.00",
"currency": "ISK",
"payment_method": null,
"created_at": "2024-01-01T00:00:00Z"
}
},
"delivery_address": null,
"amount": "1.0000"
}
Samningsáskriftir (subscription_contract.*)
Þegar samningsáskrift er búin til, uppfærist eða endurnýjast eru sendir viðeigandi atburðir. Hér er dæmi um gögn sem koma með atburði um samningsáskrift:
{
"id": 12345,
"customer": 33482,
"state": "active",
"billing_anchor_at": "2024-01-01T00:00:00Z",
"next_billing_at": "2024-02-01T00:00:00Z",
"cancel_at": null,
"cancel_at_period_end": false,
"canceled_at": null,
"ended_at": null,
"currency": "ISK",
"recurring": true,
"legacy_subscription": null,
"created_at": "2024-01-01T00:00:00Z",
"updated_at": "2024-01-01T00:00:00Z"
}
Keyrslur reikningagerðar (billing_run.*)
Þegar keyrsla reikningagerðar er stofnuð, breytist, tekst, mistekst eða er sett í endurtekningu eru sendir viðeigandi atburðir. Hér er dæmi um gögn sem koma með atburði um keyrslu reikningagerðar:
{
"id": 12345,
"contract": 12345,
"period_start_at": "2024-01-01T00:00:00Z",
"period_end_at": "2024-02-01T00:00:00Z",
"state": "succeeded",
"currency": "ISK",
"subtotal_amount": "1000.0000",
"tax_amount": "0.0000",
"total_amount": "1000.0000",
"attempt_count": 1,
"max_attempts": 4,
"next_retry_at": null,
"last_attempt_at": "2024-01-01T00:00:00Z",
"transaction": 54321,
"created_at": "2024-01-01T00:00:00Z",
"updated_at": "2024-01-01T00:00:00Z"
}
Customer (customer.*)
When a customer is created or updated the following events are sent. Here is an example of data that comes with a customer event:
{
"id": 33482,
"first_name": "",
"last_name": "",
"delivery_name": "",
"address_1": "",
"address_2": "",
"address_3": "",
"zip_code": "",
"city": "",
"country": "",
"email": null,
"customer_reference": "0208912039",
"payment_method": [],
"address": null
}
Individual payment (payment.*)
When an individual payment is created, changed or retired the following events are sent. Here is an example of data that comes with a individual payment event:
{
"uuid": "some-guid-with-numbers-and-letters",
"amount": "1.0000",
"currency": "ISK",
"description": "Description here",
"reference": "some-reference",
"state": "settled",
"created_at": "2024-01-01T00:00:00Z",
"updated_at": "2024-01-01T00:00:00Z",
"transactions": [
{
"external_reference": "410009982476",
"data": {
"id": "4100000000",
"receipt": {}, // receipt contains vendor specific fields, not listed here
"status": "settled"
},
"state": "settled",
"uuid": "some-guid-with-numbers-and-letters",
"fail_code": null,
"refund_code": null,
"cancel_code": null,
"amount": "1.00",
"currency": "ISK",
"payment_method": {
"verified": true,
"canceled": false,
"valid_until": "2025-03-01T00:00:00Z",
"display_info": "XXXX-XXXX-XXXX-4324 (Visa)",
"credit_card": true
},
"created_at": "2024-01-01T00:00:00Z"
}
]
}
Checkout (checkout.*)
When a checkout is created or changed:
{
"token": "3a44383eb19dc9183be4df5ad655094c88159af4",
"checkout_url": "http://askell.is/checkout/3a44383eb19dc9183be4df5ad655094c88159af4/",
"status": "tokencreated"
}