أتمتة ملخص Stripe Payouts إلى Slack بدون فتح Dashboard
هتكسب من المقال ده ملخص أسبوعي واضح لمدفوعات Stripe في Slack، بدل ما تفتح Dashboard وتراجع نفس الأرقام يدويًا كل مرة.
مستوى القارئ: متوسط
المشكلة باختصار
لو عندك متجر صغير أو SaaS بيستقبل مدفوعات يومية، غالبًا حد في الفريق بيفتح Stripe Dashboard كل أسبوع ويراجع الـ payouts: إيه اللي اتحول، إيه اللي فشل، وإيه المتوقع يوصل البنك. الطريقة دي بتفشل لما الشخص المسؤول يسافر، أو لما عدد الحسابات يزيد، أو لما payout فاشل يعدي يومين من غير ما حد يشوفه.
الافتراض إن عندك حساب Stripe واحد، وقناة Slack داخلية للمالية أو العمليات، ومحتاج قراءة فقط من Stripe API. الأوتوميشن هنا لا ينشئ payout، ولا يلغي payout، ولا ينفذ أي حركة مالية. هو يقرأ آخر النتائج ويرسل ملخص.
الفكرة العملية بمثال بسيط
ركز في المثال ده: عندك 30 payout في الأسبوع. المراجعة اليدوية بتاخد 45 دقيقة بين فتح Stripe، فلترة الحالات، نسخ الأرقام، وبعت رسالة للفريق. السكربت التالي يطلب آخر payouts من Stripe، يلخص الإجمالي حسب الحالة، ويبعته إلى Slack خلال 6 دقائق إعداد وتشغيل أسبوعي شبه صفر.
Stripe API يدعم endpoint لعرض payouts بترتيب الأحدث أولًا، مع معاملات مثل limit وstatus. Slack Incoming Webhooks تستقبل طلب POST JSON فيه نص الرسالة. بالظبط ده اللي هنستخدمه.
import os
import requests
from collections import defaultdict
STRIPE_KEY = os.environ["STRIPE_SECRET_KEY"]
SLACK_WEBHOOK_URL = os.environ["SLACK_WEBHOOK_URL"]
def fetch_payouts(limit=25):
response = requests.get(
"https://api.stripe.com/v1/payouts",
auth=(STRIPE_KEY, ""),
params={"limit": limit},
timeout=15,
)
response.raise_for_status()
return response.json()["data"]
def build_summary(payouts):
totals = defaultdict(int)
counts = defaultdict(int)
failed = []
for payout in payouts:
status = payout["status"]
currency = payout["currency"].upper()
amount = payout["amount"] / 100
key = f"{status}_{currency}"
totals[key] += amount
counts[key] += 1
if status == "failed":
failed.append(f"{payout['id']} - {amount:.2f} {currency}")
lines = ["*Stripe payouts weekly summary*"]
for key in sorted(totals):
lines.append(f"- {key}: {counts[key]} payouts / {totals[key]:.2f}")
if failed:
lines.append("*Failed payouts need review:*")
lines.extend(f"- {item}" for item in failed[:5])
else:
lines.append("No failed payouts in the latest batch.")
return "\n".join(lines)
def post_to_slack(text):
response = requests.post(
SLACK_WEBHOOK_URL,
json={"text": text},
timeout=10,
)
response.raise_for_status()
if __name__ == "__main__":
payouts = fetch_payouts(limit=25)
post_to_slack(build_summary(payouts))