经营一个企业需要处理付款。无论你是一个自由职业者还是一个大公司,有时客户会忘记支付他们的欠款。如果你有一个庞大的客户名单,每天翻阅记录并向他们发送催款通知是一种乏味的经历。为了解决这个问题,你可以将整个催款工作流程自动化。
在本教程中,你将学习使用 Twilio的WhatsApp API与Notion API和Python,定期向你的客户发送付款提醒信息。你将使用Notion来存储数据,Twilio来发送WhatsApp信息,Python来实现业务逻辑。我们将创建三个提醒,分别在付款到期前7天、前3天、前1天和后1天发送。
前提条件
要学习本教程,你需要以下项目。
- Python 3.6或更新版本。如果你的操作系统没有提供Python解释器,你可以去python.org下载一个安装程序。
- 一个Twilio账户。如果你是Twilio的新用户,请点击这里创建一个免费账户。
- 一个Notion账户。如果你还没有,请 点击这里创建一个免费账户。
- 一个有活跃WhatsApp账户的智能手机,以测试该项目。
这个数据库的全部代码可以在这个 GitHub仓库中找到。
创建一个Notion数据库
你需要做的第一件事是创建一个Notion数据库。
要做到这一点,打开你的Notion账户,点击添加页面,在数据库下选择表。
一旦表被创建,选择数据源为新数据库,并给你的数据库起一个名字,如 "客户"。
Notion的每个数据库表都有一组字段,你可以在其中存储你的数据。在 "名称"字段后添加以下三个字段到你的表中。
- Pending Amount (Number)- 用于指定客户要支付的金额。
- Due Date (Date)- 用于指定付款的截止日期。
- Phone No. (电话)- 客户的电话号码。
创建完数据库后,你需要在其中添加一些测试客户。就本教程而言,你可以添加你的家庭成员的详细资料,并添加你可以访问的电话号码。确保按照Twilio推荐的E.164格式添加电话号码,否则你在发送信息时可能会出现一些错误。
你的Notion数据库现在已经设置好了。接下来,你需要在你的Python应用程序中使用Notion API查询Notion中的数据。
获取Notion API令牌
要使用Notion API,你需要创建一个Notion集成并获得一个API访问令牌。
要做到这一点,请访问 www.notion.so/my-integrat…,并创建一个新的集成。给它取个名字 "*Payment Reminder",*如果你想的话,还可以上传一个标志。
接下来,把它的内容能力设置为只读内容,评论能力设置为无,用户能力设置为无用户信息,然后点击提交。
一旦集成被创建,你将看到一个秘密的API令牌。复制并妥善保管它,因为你以后在编写Python应用程序时将会用到它。
默认情况下,集成不能访问Notion的页面或数据库。所以,你需要与你的集成分享你想用Notion API查询的特定页面或数据库。
要做到这一点,在Notion中打开你的数据库。点击分享按钮,使用选择器按名称找到你的集成,然后点击邀请。
这样,你就可以在你的Python应用程序中使用Notion API访问你的Notion数据库了。
设置Python项目
首先,打开你的终端,导航到你选择的路径,创建一个名为 "payment-reminders "的项目目录,并通过在终端运行以下命令建立一个虚拟环境。
mkdir payment-reminders && cd payment-reminders
python3 -m venv venv
source venv/bin/activate
对于这个项目,你需要安装以下PIP依赖项。
- twilio- Twilio的Python SDK客户端,用于Twilio API。
- requests- 用来进行HTTP请求。
- python-dotenv- 用于从
.env文件中读取环境变量。
接下来,通过在终端运行以下命令来安装上述列出的PIP依赖项。
pip install twilio requests python-dotenv
连接到Notion API并检查服务状态
现在是写一些代码的时候了。首先,你要连接到Notion API并在你的数据库中获取条目。一旦你有了这些条目,你就可以通过发送GET请求来循环检查它们的状态。
要做到这一点,首先在项目的根目录下创建一个src 目录。在src 目录中,创建一个main.py 文件,并在其中添加以下代码。
import os
from datetime import datetime
import requests
from dotenv import load_dotenv
load_dotenv()
TWILIO_ACCOUNT_SID = os.getenv('TWILIO_ACCOUNT_SID')
TWILIO_AUTH_TOKEN = os.getenv('TWILIO_AUTH_TOKEN')
NOTION_API_BASE_URL = 'https://api.notion.com/v1'
NOTION_API_TOKEN = os.getenv('NOTION_API_TOKEN')
NOTION_DATABASE_ID = os.getenv('NOTION_DATABASE_ID')
# 1
def get_client_details() -> list:
"""
This function calls the Notion API to get a list of clients that we need to monitor.
"""
headers: dict = {
'Authorization': f'Bearer {NOTION_API_TOKEN}',
'Content-Type': 'application/json',
'Notion-Version': '2021-08-16',
}
# uses <https://developers.notion.com/reference/post-database-query>
response: Response = requests.post(
f'{NOTION_API_BASE_URL}/databases/{NOTION_DATABASE_ID}/query', headers=headers)
if response.status_code == 200:
json_response: dict = response.json()['results']
else:
print("Something went wrong")
return
# 2
clients: list = []
for item in json_response:
client: dict = {
'id': item['id'],
'name': item['properties']['Name']['title'][0]['plain_text'],
'pending_amount': item['properties']['Pending Amount']['number'],
'due_date': item['properties']['Due Date']['date']['start'],
'phone_number': item['properties']['Phone No.']['phone_number'],
}
clients.append(client)
return clients
# 3
def is_due(due_date: str) -> bool:
"""
This function checks if the date is due or not.
"""
today = datetime.today()
delta = datetime.strptime(due_date, "%Y-%m-%d") - today
return delta.days == 7 or delta.days == 3 or delta.days == 1 or delta.days < 0
# 4
def main():
clients: list = get_client_details()
for client in clients:
if is_due(client['due_date']):
print(client)
send_reminder(client)
if __name__ == '__main__':
main()
在上述代码中。
- 在
get_client_details函数中,你连接到Notion API并查询你的Notion数据库,以获得存储在其中的数据。对api.notion.com/v1/database…

- 由于响应相当大,而且你不需要所有的数据,你通过创建一个新的客户端列表来减少响应,该列表的结构如下。
{
'id': item['id'],
'name': item['properties']['Name']['title'][0]['plain_text'],
'pending_amount': item['properties']['Pending Amount']['number'],
'due_date': item['properties']['Due Date']['date']['start'],
'phone_number': item['properties']['Phone No.']['phone_number'],
}
- 在
is_due函数中,你检查due_date是否到期。因为在本教程中,目标是在七天前、三天前、到期日前一天以及到期日后的每一天发送提醒,所以这个函数检查的内容相同。 - 在主函数中,你调用
get_client_details函数,对于有到期日的客户,你调用send_reminder function,你将在下一节中编写这个函数。
接下来,在项目的根目录下创建一个.env 文件,并向其添加以下两个环境变量。
NOTION_API_TOKEN=<YOUR-INTERNAL-INTEGRATION-TOKEN>
NOTION_DATABASE_ID=<YOUR-DATABASE-ID>
为了得到你的数据库ID,查看Notion页面的URL结构-- www.notion.so/{workspace_…。URL中与{database_id}相对应的部分是你的数据库的ID。它是一个36个字符的长字符串。
如果你的Notion数据库不在一个工作区里,或者它根本不符合上面显示的URL,它可能看起来像这样:www.notion.so/{database_i…。
发送WhatsApp通知
发送提醒信息是本教程的主要目的。对于发送提醒,你可以使用 Twilio WhatsApp API来执行这项任务。
要做到这一点,首先,登录到你的Twilio账户,并访问 Twilio控制台。在控制台中,注意账户信息部分,并获得账户SID和Auth Token。
接下来,激活你的Twilio沙盒来发送和接收WhatsApp信息。
接下来,将账户SID和Auth Token作为环境变量添加到你的*.env*文件中。
TWILIO_ACCOUNT_SID=<YOUR-ACCOUNT-SID>
TWILIO_AUTH_TOKEN=<YOUR-AUTH-TOKEN>
接下来,更新main.py ,在文件的顶部添加twilio 库,并在main 函数之前添加send_reminder 函数。
from twilio.rest import Client
TWILIO_ACCOUNT_SID = os.getenv('TWILIO_ACCOUNT_SID')
TWILIO_AUTH_TOKEN = os.getenv('TWILIO_AUTH_TOKEN')
# 1
def send_reminder(client: dict):
"""
This function sends a WhatsApp notification using the Twilio WhatsApp Business API.
"""
twilio_client = Client(TWILIO_ACCOUNT_SID, TWILIO_AUTH_TOKEN)
# This is the Twilio Sandbox number. Don't change it.
from_whatsapp_number = 'whatsapp:+14155238886',
to_whatsapp_number = f"whatsapp:{client['phone_number']}"
body: str = f"Hi {client['name']}. Your payment of USD{client['pending_amount']} is due since {client['due_date']}."
try:
twilio_client.messages.create(body=body,
from_=from_whatsapp_number,
to=to_whatsapp_number)
except:
print('There was an error sending the message')
在上面的代码中,你定义了send_reminder 函数,它以client 为输入。它使用Twilio Python SDK(客户端)从Twilio Sandbox的电话号码发送一条WhatsApp信息到客户端的电话号码to_whatsapp_number 。消息的主体包含客户的姓名、待付金额和到期日期。
最后,通过在终端运行以下命令来执行Python应用程序。
python src/main.py
如果你的Notion数据库中有任何空行或字段,应用程序可能会抛出一个索引错误。否则,如果有任何客户有到期日期,那么应用程序将发送一些WhatsApp通知。

自动发送提醒
最后一步是将定期运行Python代码的过程自动化,以不断检查新的到期日期。有很多方法可以使脚本执行自动化,例如--在Heroku上托管你的脚本并使用Heroku Scheduler,在自我托管的机器上使用Crontab,或者使用Github Actions。在本教程中,你将使用Github Actions。
要做到这一点,首先,在你的项目的根目录下创建一个目录路径.github/workflows 。在.github/workflows ,添加一个main.yml 文件,并在其中添加以下代码。
name: Monitoring
on:
schedule:
- cron: "0 0 * * *"
workflow_dispatch:
jobs:
monitor:
runs-on: ubuntu-latest
env:
NOTION_API_TOKEN: ${{ secrets.NOTION_API_TOKEN }}
NOTION_DATABASE_ID: ${{ secrets.NOTION_DATABASE_ID }}
TWILIO_ACCOUNT_SID: ${{ secrets.TWILIO_ACCOUNT_SID }}
TWILIO_AUTH_TOKEN: ${{ secrets.TWILIO_AUTH_TOKEN }}
steps:
- name: Setup Repository
uses: actions/checkout@v2
with:
ref: main
- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: 3.x
- name: Install PIP Dependencies
run: |-
python -m pip install --upgrade pip
pip install -r requirements.txt
- name: Send Reminders
run: |-
python src/main.py
上面的Github动作被安排在每天00:00 UTC运行,由行cron: "0 0 * * *" 指定。根据你的要求,你可以改变代码的运行频率。通过工作流调度,你可以随时手动运行该动作。
编写CRON表达式的一个好工具是crontab.guru/。
接下来,通过在终端运行以下命令,创建一个requirements.txt 文件,列出你的Python应用程序使用的所有依赖项。
pip freeze > requirements.txt
接下来,创建一个 新的Github资源库。转到设置>秘密>行动。

接下来,添加以下秘密和它们各自的值作为仓库的秘密。
接下来,通过在终端运行以下命令,在你的本地项目中初始化一个Git仓库。
git init
接下来,在项目的根目录下创建一个.gitignore 文件,并在其中添加以下文件和目录,以防止它们被推送到上游仓库。
venv
.env
最后,通过在终端运行以下命令,提交并推送更改到你的上游仓库。
git add .
git commit -m "initial commit"
git push origin main
测试
为了验证你到目前为止的所有工作,请访问行动选项卡并手动运行工作流。
等待工作流程完成,并检查WhatsApp上是否有任何通知。

就这样,你已经成功地实现了对客户的付款提醒。
结语
祝贺您!在本教程中,您学会了如何向您的客户发出付款提醒。在本教程中,你学会了使用Twilio、Notion和Python来发送付款提醒信息。你用Notion来存储客户的数据,Python用于逻辑,Twilio用于WhatsApp通知,GitHub Actions用于自动化。
如果这个项目对你有帮助,请告诉我,或者通过电子邮件与我联系,向我问好!这个资源库的全部代码可在这个 GitHub资源库中找到。
Ravgeet是一个在印度的远程全职全栈开发者和技术内容作家。他从事React、Vue、Flutter、Strapi、Python和自动化方面的工作和写作。可以通过电子邮件 ravgeetdhillon[at]gmail.com联系他。 LinkedIn**, 和 Github**.