Python短信对接案例:如何高效发送短信验证码(附完整代码)
目录导读
为什么选择Python对接短信验证码
在用户注册、登录验证、密码找回等场景中,短信验证码是最普遍的身份验证方式,Python因其简洁的语法、丰富的第三方库,成为对接短信API的首选语言,根据Stack Overflow 2023年调查,Python在云服务API调用场景中的使用率超过65%。

核心优势:
- 快速开发:使用
requests库即可在10行代码内完成调用 - 生态完善:主流短信服务商(阿里云、腾讯云、七牛云等)均提供Python SDK
- 异步支持:
aiohttp可轻松实现高并发短信发送
实际业务场景:
某电商平台日发送验证码超过50万条,使用Python异步框架后,单机QPS从500提升至3000+,且代码维护成本降低40%。
主流短信服务商与Python SDK选择
| 服务商 | Python SDK包名 | 特点 | 免费额度 |
|---|---|---|---|
| 阿里云 | aliyun-python-sdk-core |
国内覆盖最广,文档完善 | 每月100条 |
| 腾讯云 | tencentcloud-sdk-python |
国际短信支持好,延迟低 | 每月100条 |
| 七牛云 | qiniu |
价格便宜,适合高频验证码 | 新用户送500条 |
| Twilio(国际) | twilio |
全球覆盖,开发者友好 | 提供试用金$15 |
选择建议:
- 目标用户在国内:优先阿里云或腾讯云,节点覆盖好,三网合一到达率99%+
- 需要国际短信:Twilio或腾讯云国际版
- 对成本敏感:七牛云或短信包采购模式
实战案例:阿里云短信验证码对接
1 准备工作
- 注册阿里云账号,开通“短信服务”
- 获取AccessKey ID和Secret(需保存到环境变量,切勿硬编码)
- 申请短信签名和模板(如:“您的验证码为${code},5分钟内有效”)
2 安装依赖
pip install aliyun-python-sdk-core-v3
3 完整代码实现
import json
from aliyunsdkcore.client import AcsClient
from aliyunsdkcore.request import CommonRequest
def send_sms(phone, code):
# 初始化客户端(实际代码中建议从环境变量读取)
client = AcsClient(
'<your-access-key-id>', # 替换为你的AccessKey ID
'<your-access-key-secret>', # 替换为你的AccessKey Secret
'cn-hangzhou' # 地域ID,固定为cn-hangzhou
)
# 构建请求
request = CommonRequest()
request.set_accept_format('json')
request.set_domain('dysmsapi.aliyuncs.com')
request.set_method('POST')
request.set_version('2017-05-25')
request.set_action_name('SendSms')
# 设置业务参数
request.add_query_param('PhoneNumbers', phone)
request.add_query_param('SignName', '你的短信签名') # 替换为已审核签名
request.add_query_param('TemplateCode', 'SMS_123456789') # 替换为模板ID
request.add_query_param('TemplateParam', json.dumps({"code": code}))
# 发送并处理响应
try:
response = client.do_action_with_exception(request)
result = json.loads(response)
if result.get('Code') == 'OK':
print(f"短信发送成功:{phone}")
return True
else:
print(f"发送失败:{result.get('Message')}")
return False
except Exception as e:
print(f"异常错误:{str(e)}")
return False
# 使用示例
if __name__ == '__main__':
send_sms('13800138000', '123456')
4 代码要点说明
- 参数
TemplateParam:必须使用json.dumps序列化,否则会报签名错误 - 状态码判断:
Code为OK代表成功,其他值参考阿里云API错误码文档 - 签名字段:短信签名需在控制台申请审核通过后使用
案例二:腾讯云短信验证码对接
1 准备工作
- 腾讯云控制台开通“短信服务”,创建应用获取AppID
- 在“签名管理”和“模板管理”中创建并审核
2 安装SDK
pip install tencentcloud-sdk-python
3 核心代码
from tencentcloud.common import credential
from tencentcloud.sms.v20210111 import sms_client, models
def send_tencent_sms(phone, code):
# 初始化凭证(建议从环境变量读取)
cred = credential.Credential(
"<your-secret-id>",
"<your-secret-key>"
)
client = sms_client.SmsClient(cred, "ap-guangzhou")
# 构建请求
req = models.SendSmsRequest()
req.SmsSdkAppId = "1256456789" # 你的应用ID
req.SignName = "你的签名"
req.TemplateId = "SMS_123456"
req.TemplateParamSet = [code]
req.PhoneNumberSet = ["+86" + phone] # 需加国际区号
# 发送
response = client.SendSms(req)
if response.SendStatusSet[0].Code == "Ok":
print(f"发送成功:{phone}")
return True
else:
print(f"失败原因:{response.SendStatusSet[0].Message}")
return False
与阿里云的主要差异:
- 腾讯云需在手机号前加国际区号(如
+86) - 参数
TemplateParamSet是列表形式,不用JSON - 响应状态通过
SendStatusSet列表中的Code判断
常见问题与问答Q&A
Q1:短信验证码发送后用户长时间未收到怎么办?
A: 可采取以下排查步骤:
- 检查手机是否拦截(尤其是iOS的“未知发件人”过滤)
- 调用API后立即查询“短信发送记录”确认是否成功
- 模拟环境下可设置重试机制:发送失败后间隔30秒重试一次,最多3次
- 若批量失败,检查短信模板是否过期或被驳回
Q2:如何防止短信接口被恶意调用导致资损?
A: 必须实施以下安全措施:
- 添加图形验证码:发送短信前要求用户输入图片验证码
- 频率限制:同一手机号60秒内只能请求一次
- IP白名单:仅在服务端调用,避免前端直连API
- 签名验证:使用HMAC-SHA256对请求参数进行签名验证(如阿里云的SignName机制)
Q3:Python中如何管理多个短信服务商的切换?
A: 推荐使用工厂模式 + 策略模式:
class SmsFactory:
@staticmethod
def get_sender(provider='aliyun'):
if provider == 'aliyun':
return AliyunSender()
elif provider == 'tencent':
return TencentSender()
else:
raise ValueError("Unsupported provider")
sender = SmsFactory.get_sender('tencent')
sender.send('138xxxx', '123456')
这样可以做到业务代码与具体供应商解耦,切换仅需修改配置。
Q4:短信发送量较大时,Python性能如何优化?
A: 建议采用以下优化方案:
- 使用连接池:
requests.Session()复用TCP连接 - 异步发送:
asyncio+aiohttp实现非阻塞,单机可并发500+请求 - 批量发送:某些服务商支持一次API调用发送多个手机号(如阿里云的
PhoneNumberJson参数) - 消息队列缓冲:将发送任务放入Redis或RabbitMQ,由Worker异步消费,削峰填谷
性能优化与安全建议
1 生产环境必做的5件事
- 密钥管理:使用环境变量(
.env文件)或密钥管理服务(如AWS Secrets Manager),严禁硬编码 - 日志记录:记录每次API调用的请求ID、手机号、状态码、耗时,便于排查
- 超时设置:
requests.post(url, timeout=5)防止服务商响应慢导致应用阻塞 - 熔断机制:当连续5次发送失败时,暂停该服务商调用并切换备用渠道(如腾讯云切阿里云)
- 监控告警:使用Prometheus+Grafana监控短信发送成功率,成功率低于95%触发告警
2 代码级优化示例(异步发送)
import aiohttp
import asyncio
async def send_sms_async(phone, code):
async with aiohttp.ClientSession() as session:
# 构造请求参数(此处以阿里云为例)
async with session.post('https://dysmsapi.aliyuncs.com', data={
'PhoneNumbers': phone,
'SignName': '你的签名',
'TemplateCode': 'SMS_xxx',
'TemplateParam': '{"code":"'+code+'"}'
}) as resp:
result = await resp.json()
return result.get('Code') == 'OK'
# 批量发送
async def batch_send(phone_list, code):
tasks = [send_sms_async(phone, code) for phone in phone_list]
results = await asyncio.gather(*tasks)
return results
全文总结:
通过本文的完整案例解析,您应该已经掌握了使用Python对接主流短信服务商发送验证码的核心技巧,实际开发中,请务必注意安全配置和性能优化,建议先在测试环境充分验证(如使用阿里云“单条发送”接口,日免费额度100条),选择服务商时,除了价格,更要关注到达率和SLA保障,推荐将代码封装为可复用的模块,方便后续维护和切换。