Kommo + GoCardless: автоматическое прямое дебетование из воронки продаж
GoCardless — европейская платформа для прямого дебетования: SEPA Direct Debit (EU), BACS (UK), ACH (US). В отличие от Stripe или Mollie, GoCardless специализируется на регулярных платежах через банковские счета — без комиссий за карточные транзакции и с более высоким success rate для подписочных бизнесов. Без интеграции с Kommo менеджер создаёт мандат вручную после Won. С интеграцией Won автоматически инициирует процесс получения мандата — клиент получает ссылку для авторизации списаний прямо в минуту после закрытия сделки.
GoCardless vs Stripe для SaaS-подписок в EU
GoCardless (SEPA DD):
— Фиксированная комиссия: €0.20–0.60 за транзакцию (не % от суммы)
— Нет лимита на % — на крупных подписках значительно дешевле карт
— Мандат даётся один раз -> повторные списания без участия клиента
— Success rate 97–99% (карты: 85–92% из-за истечений, блокировок)
— Идеально для B2B SaaS с ежемесячными/ежеквартальными invoice
Stripe (карточные платежи):
— % от транзакции (2.9% + $0.30 или локальные EU тарифы)
— Карты истекают, блокируются -> involuntary churn
— Мгновенная оплата (vs 2–5 рабочих дней для DD)
Для кастомных интеграций Kommo с европейскими SaaS GoCardless часто предпочтительнее именно из-за структуры комиссий и надёжности.
Что синхронизируется
Kommo -> GoCardless:
— Won -> создать Customer в GoCardless с данными из сделки
— Won -> создать Redirect Flow (ссылка для авторизации мандата клиентом)
— Won -> отправить ссылку на мандат клиенту (через Note или email)
— После получения мандата -> создать Subscription (план, сумма, интервал)
GoCardless -> Kommo:
— payment.paid -> Note: «GoCardless: платёж получен, €{amount}»
— payment.failed -> Note + задача менеджеру: «Платёж не прошёл — связаться с клиентом»
— mandate.cancelled -> Note + задача: «Мандат отозван — переоформить»
— subscription.cancelled -> Note: «Подписка отменена»
GoCardless API: ключевые запросы
Base URL: https://api.gocardless.com.
Аутентификация: Authorization: Bearer {access_token}.
Access Token: GoCardless Dashboard -> Developers -> Create Access Token.
Заголовок версии API: GoCardless-Version: 2015-07-06 (обязателен).
import requests
GC_TOKEN = "your_access_token"
GC_BASE_URL = "https://api.gocardless.com"
GC_HEADERS = {
"Authorization": f"Bearer {GC_TOKEN}",
"GoCardless-Version": "2015-07-06",
"Content-Type": "application/json",
}
def create_customer(name: str, email: str, company_name: str = "") -> dict:
payload = {
"customers": {
"email": email,
"given_name": name.split()[0] if name else "",
"family_name": " ".join(name.split()[1:]) if len(name.split()) > 1 else "",
"company_name": company_name,
}
}
resp = requests.post(f"{GC_BASE_URL}/customers", headers=GC_HEADERS, json=payload)
resp.raise_for_status()
return resp.json()["customers"]
def create_redirect_flow(customer_id: str, description: str,
success_redirect_url: str, session_token: str) -> dict:
# Создаёт ссылку для авторизации мандата клиентом
payload = {
"redirect_flows": {
"description": description,
"session_token": session_token, # уникальная строка для сессии
"success_redirect_url": success_redirect_url,
"prefilled_customer": {"id": customer_id},
}
}
resp = requests.post(f"{GC_BASE_URL}/redirect_flows", headers=GC_HEADERS, json=payload)
resp.raise_for_status()
return resp.json()["redirect_flows"]
def complete_redirect_flow(redirect_flow_id: str, session_token: str) -> dict:
# Завершить redirect flow после возврата клиента, получить mandate_id
payload = {"data": {"session_token": session_token}}
resp = requests.post(
f"{GC_BASE_URL}/redirect_flows/{redirect_flow_id}/actions/complete",
headers=GC_HEADERS,
json=payload,
)
resp.raise_for_status()
return resp.json()["redirect_flows"]
def create_subscription(mandate_id: str, amount_cents: int,
currency: str, interval_unit: str,
name: str) -> dict:
# interval_unit: "monthly" | "weekly" | "yearly"
# amount_cents: сумма в центах/евроцентах (49.00 EUR = 4900)
payload = {
"subscriptions": {
"amount": amount_cents,
"currency": currency,
"interval_unit": interval_unit,
"name": name,
"links": {"mandate": mandate_id},
}
}
resp = requests.post(f"{GC_BASE_URL}/subscriptions", headers=GC_HEADERS, json=payload)
resp.raise_for_status()
return resp.json()["subscriptions"]
def on_deal_won(lead: dict, contact: dict):
import uuid
email = get_contact_email(contact)
name = contact["name"]
company = get_custom_field(lead, COMPANY_FIELD_ID) or ""
amount = lead.get("price", 0)
plan = get_custom_field(lead, PLAN_FIELD_ID) or "Growth"
# Создать Customer
customer = create_customer(name, email, company)
customer_id = customer["id"]
# Создать Redirect Flow - ссылка для клиента
session_token = str(uuid.uuid4())
flow = create_redirect_flow(
customer_id=customer_id,
description=f"Авторизация списаний - {plan} план",
success_redirect_url="https://yourapp.com/payment/confirmed",
session_token=session_token,
)
# Сохранить данные в Kommo
update_kommo_deal(lead["id"], {
"gc_customer_id": customer_id,
"gc_redirect_flow_id": flow["id"],
"gc_session_token": session_token,
})
create_kommo_note(lead["id"],
f"GoCardless: мандат ожидает авторизации\n"
f"Ссылка для клиента: {flow['redirect_url']}")
Webhook после авторизации клиентом (redirect_flow.completed):
@app.route("/webhooks/gocardless/redirect", methods=["GET"])
def gc_redirect_complete():
# Клиент вернулся после авторизации мандата
redirect_flow_id = request.args.get("redirect_flow_id")
deal_id = find_deal_by_field("gc_redirect_flow_id", redirect_flow_id)
if not deal_id:
return "OK", 200
session_token = get_deal_field(deal_id, "gc_session_token")
flow = complete_redirect_flow(redirect_flow_id, session_token)
mandate_id = flow["links"]["mandate"]
amount = get_deal_amount(deal_id)
sub = create_subscription(
mandate_id=mandate_id,
amount_cents=int(amount * 100),
currency="EUR",
interval_unit="monthly",
name=f"Подписка #{deal_id}",
)
update_kommo_deal(deal_id, {"gc_mandate_id": mandate_id,
"gc_subscription_id": sub["id"]})
create_kommo_note(deal_id,
f"GoCardless: мандат получен, подписка создана (ID: {sub['id']})")
return "OK", 200
Обработка GoCardless Webhook (платёжные события):
import hmac, hashlib
GC_WEBHOOK_SECRET = "your_webhook_secret"
@app.route("/webhooks/gocardless", methods=["POST"])
def gc_webhook():
# Верификация подписи
sig = request.headers.get("Webhook-Signature", "")
expected = hmac.new(
GC_WEBHOOK_SECRET.encode(), request.data, hashlib.sha256
).hexdigest()
if not hmac.compare_digest(expected, sig):
return "", 498
payload = request.json
for event in payload.get("events", []):
resource_type = event.get("resource_type") # "payments", "mandates", "subscriptions"
action = event.get("action") # "paid", "failed", "cancelled" etc.
links = event.get("links", {})
if resource_type == "payments":
payment_id = links.get("payment")
mandate_id = links.get("mandate")
deal_id = find_deal_by_field("gc_mandate_id", mandate_id)
if not deal_id:
continue
amount = event.get("details", {}).get("amount", 0) / 100
if action == "paid":
create_kommo_note(deal_id,
f"GoCardless: платёж получен - €{amount:.2f}")
elif action == "failed":
reason = event.get("details", {}).get("description", "unknown")
create_kommo_note(deal_id,
f"GoCardless: платёж не прошёл - {reason}")
create_kommo_task(deal_id,
"GoCardless: связаться с клиентом - проблема с платежом")
elif resource_type == "mandates" and action == "cancelled":
mandate_id = links.get("mandate")
deal_id = find_deal_by_field("gc_mandate_id", mandate_id)
if deal_id:
create_kommo_note(deal_id, "GoCardless: мандат отозван клиентом")
create_kommo_task(deal_id,
"GoCardless: переоформить мандат или выставить счёт альтернативно")
return "", 204
Sandbox для тестирования
GoCardless предоставляет sandbox-среду (https://api-sandbox.gocardless.com) — полная копия production API. Тестовые реквизиты банковского счёта генерирует Dashboard. Webhook можно тестировать через ngrok или GoCardless -> Developers -> Webhook endpoints -> Send test event.
Реальный кейс
EU SaaS-компания (Нидерланды, 40–60 новых клиентов в месяц, Kommo + GoCardless):
- До: после Won менеджер вручную отправлял GoCardless-ссылку через email. Задержка 1–2 часа. 30% клиентов не завершали авторизацию мандата — follow-up вручную.
- После: Won -> GoCardless ссылка в Note за 5 секунд + автоматический email клиенту. Конверсия в завершённый мандат выросла до 89% (было 67%) — ссылка приходит пока клиент ещё в «режиме покупки».
- Дополнительно:
payment.failed-> задача менеджеру в тот же день. Involuntary churn снизился на 31% — команда реагирует до конца billing-периода.
Для кого актуально
- EU SaaS и B2B-компании с ежемесячными/ежеквартальными платежами
- Команды с высоким MRR на клиента ($200+) — фиксированная комиссия GoCardless выгоднее % от Stripe
- Компании в UK/Нидерланды/Германия/Франция — SEPA и BACS нативны
- 20+ активных подписок — при меньшем объёме ручное управление ещё терпимо
Часто задаваемые вопросы
GoCardless vs Stripe для EU SaaS — когда что выбрать?
GoCardless: ежемесячные подписки B2B в EU, высокий средний чек ($200–5000/мес), нет необходимости в мгновенных платежах. Stripe: одноразовые платежи, e-commerce, нужна мгновенная оплата, международный рынок за пределами EU. Можно использовать оба: GoCardless для подписок, Stripe для апгрейдов и одноразовых платежей.
Как работает SEPA Direct Debit — сколько дней до списания?
После авторизации мандата первое списание занимает 2–3 рабочих дня (уведомление клиенту + T+2/T+3). Повторные — стандартно T+2. GoCardless автоматически уведомляет клиента перед каждым списанием (обязательно по SEPA-правилам, обычно за 3+ дня).
Можно ли сделать мандат без перехода клиента по ссылке?
Для SEPA DD — нет, клиент должен авторизовать мандат. Альтернатива: SEPA Instant Credit Transfer (не GoCardless) или использовать GoCardless Instant Bank Pay (Faster Payments, UK только). Для EU самый надёжный способ — redirect flow с брендированной страницей GoCardless.
GoCardless поддерживает несколько валют?
Да: EUR (SEPA), GBP (BACS), USD (ACH), SEK, DKK, AUD, NZD, CAD. Каждая валюта требует отдельного Scheme в аккаунте. Российский рубль и большинство EM-валют не поддерживаются.
Итого
- GoCardless API:
Authorization: Bearer {token}+GoCardless-Version: 2015-07-06 - Поток: create customer -> create redirect flow -> клиент авторизует -> complete flow -> create subscription
- Webhook: HMAC-SHA256 через
Webhook-Signature, события в массивеevents[] - Ключевые события:
payment.paid,payment.failed,mandate.cancelled - Sandbox:
https://api-sandbox.gocardless.com— полная копия production - Преимущество vs карты: фиксированная комиссия + 97–99% success rate для подписок
Если вы используете GoCardless и Kommo и хотите автоматизировать получение мандатов при Won — опишите структуру тарифов и billing-интервалы. Exceltic.dev настроит redirect flow и обработку платёжных событий.