更新时间:2024-06-21 GMT+08:00
Python
样例 |
|
---|---|
环境要求 |
基于Python 3.7.0版本,要求Python 3.7及以上版本。 |
引用库 |
requests 2.18.1(仅示例1引用)
|
- 发送短信为单模板群发短信示例,发送分批短信为多模板群发短信示例。
- 本文档所述Demo在提供服务的过程中,可能会涉及个人数据的使用,建议您遵从国家的相关法律采取足够的措施,以确保用户的个人数据受到充分的保护。
- 本文档所述Demo仅用于功能演示,不允许客户直接进行商业使用。
- 本文档信息仅供参考,不构成任何要约或承诺。
发送短信(示例1)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
import time import uuid import hashlib import base64 import requests #需要先使用pip install requests命令安装依赖 # 必填,请参考"开发准备"获取如下数据,替换为实际值 url = 'https://smsapi.ap-southeast-1.myhuaweicloud.com:443/sms/batchSendSms/v1' #APP接入地址+接口访问URI // 认证用的appKey和appSecret硬编码到代码中或者明文存储都有很大的安全风险,建议在配置文件或者环境变量中密文存放,使用时解密,确保安全; APP_KEY = "c8RWg3ggEcyd4D3p94bf3Y7x1Ile" #Application Key APP_SECRET = "q4Ii87Bh************80SfD7Al" #Application Secret sender = "csms12345678" #中国大陆短信签名通道号或全球短信通道号 TEMPLATE_ID = "8ff55eac1d0b478ab3c06c3c6a492300" #模板ID #条件必填,中国大陆短信关注,当templateId指定的模板类型为通用模板时生效且必填,必须是已审核通过的,与模板类型一致的签名名称 #全球短信不用关注该参数 signature = "华为云短信测试" #签名名称 # 必填,全局号码格式(包含国家码),示例:+8615123456789,多个号码之间用英文逗号分隔 receiver = "+8615123456789,+8615234567890" #短信接收人号码 # 选填,短信状态报告接收地址,推荐使用域名,为空或者不填表示不接收状态报告 statusCallBack = "" ''' 选填,使用无变量模板时请赋空值 TEMPLATE_PARAM = ''; 单变量模板示例:模板内容为"您的验证码是${NUM_6}"时,TEMPLATE_PARAM可填写为'["369751"]' 双变量模板示例:模板内容为"您有${NUM_2}件快递请到${TXT_20}领取"时,TEMPLATE_PARAM可填写为'["3","人民公园正门"]' 查看更多模板和变量规范 ''' TEMPLATE_PARAM = '["369751"]' #模板变量,此处以单变量验证码短信为例,请客户自行生成6位验证码,并定义为字符串类型,以杜绝首位0丢失的问题(例如:002569变成了2569)。 ''' 构造X-WSSE参数值 @param appKey: string @param appSecret: string @return: string ''' def buildWSSEHeader(appKey, appSecret): now = time.strftime('%Y-%m-%dT%H:%M:%SZ') #Created nonce = str(uuid.uuid4()).replace('-', '') #Nonce digest = hashlib.sha256((nonce + now + appSecret).encode()).hexdigest() digestBase64 = base64.b64encode(digest.encode()).decode() #PasswordDigest return 'UsernameToken Username="{}",PasswordDigest="{}",Nonce="{}",Created="{}"'.format(appKey, digestBase64, nonce, now) def main(): # 请求Headers header = {'Authorization': 'WSSE realm="SDP",profile="UsernameToken",type="Appkey"', 'X-WSSE': buildWSSEHeader(APP_KEY, APP_SECRET)} # 请求Body formData = {'from': sender, 'to': receiver, 'templateId': TEMPLATE_ID, 'templateParas': TEMPLATE_PARAM, 'statusCallback': statusCallBack, # 'signature': signature #使用中国大陆短信通用模板时,必须填写签名名称 } print(header) # 为防止因HTTPS证书认证失败造成API调用失败,需要先忽略证书信任问题 r = requests.post(url, data=formData, headers=header, verify=False) print(r.text) #打印响应信息 if __name__ == '__main__': main() |
发送短信(示例2)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 |
import time import uuid import hashlib import base64 import ssl import urllib.parse import urllib.request # 必填,请参考"开发准备"获取如下数据,替换为实际值 url = 'https://smsapi.ap-southeast-1.myhuaweicloud.com:443/sms/batchSendSms/v1' #APP接入地址+接口访问URI APP_KEY = "c8RWg3ggEcyd4D3p94bf3Y7x1Ile" #Application Key // 认证用的appKey和appSecret硬编码到代码中或者明文存储都有很大的安全风险,建议在配置文件或者环境变量中密文存放,使用时解密,确保安全; APP_SECRET = "q4Ii87Bh************80SfD7Al" #Application Secret sender = "csms12345678" #中国大陆短信签名通道号或全球短信通道号 TEMPLATE_ID = "8ff55eac1d0b478ab3c06c3c6a492300" #模板ID #条件必填,中国大陆短信关注,当templateId指定的模板类型为通用模板时生效且必填,必须是已审核通过的,与模板类型一致的签名名称 #全球短信不用关注该参数 signature = "华为云短信测试" #签名名称 # 必填,全局号码格式(包含国家码),示例:+8615123456789,多个号码之间用英文逗号分隔 receiver = "+8615123456789,+8615234567890" #短信接收人号码 # 选填,短信状态报告接收地址,推荐使用域名,为空或者不填表示不接收状态报告 statusCallBack = "" ''' 选填,使用无变量模板时请赋空值 TEMPLATE_PARAM = ''; 单变量模板示例:模板内容为"您的验证码是${NUM_6}"时,TEMPLATE_PARAM可填写为'["369751"]' 双变量模板示例:模板内容为"您有${NUM_2}件快递请到${TXT_20}领取"时,TEMPLATE_PARAM可填写为'["3","人民公园正门"]' 查看更多模板和变量规范 ''' TEMPLATE_PARAM = '["369751"]' #模板变量,此处以单变量验证码短信为例,请客户自行生成6位验证码,并定义为字符串类型,以杜绝首位0丢失的问题(例如:002569变成了2569)。 ''' 构造X-WSSE参数值 @param appKey: string @param appSecret: string @return: string ''' def buildWSSEHeader(appKey, appSecret): now = time.strftime('%Y-%m-%dT%H:%M:%SZ') #Created nonce = str(uuid.uuid4()).replace('-', '') #Nonce digest = hashlib.sha256((nonce + now + appSecret).encode()).hexdigest() digestBase64 = base64.b64encode(digest.encode()).decode() #PasswordDigest return 'UsernameToken Username="{}",PasswordDigest="{}",Nonce="{}",Created="{}"'.format(appKey, digestBase64, nonce, now) def main(): # 请求Body formData = urllib.parse.urlencode({ 'from': sender, 'to': receiver, 'templateId': TEMPLATE_ID, 'templateParas': TEMPLATE_PARAM, 'statusCallback': statusCallBack, # 'signature': signature #使用中国大陆短信通用模板时,必须填写签名名称 }).encode('ascii') req = urllib.request.Request(url=url, data=formData, method='POST') #请求方法为POST # 请求Headers参数 req.add_header('Authorization', 'WSSE realm="SDP",profile="UsernameToken",type="Appkey"') req.add_header('X-WSSE', buildWSSEHeader(APP_KEY, APP_SECRET)) req.add_header('Content-Type', 'application/x-www-form-urlencoded') # 为防止因HTTPS证书认证失败造成API调用失败,需要先忽略证书信任问题 ssl._create_default_https_context = ssl._create_unverified_context try: r = urllib.request.urlopen(req) #发送请求 print(r.read().decode('utf-8')) #打印响应信息 except urllib.error.HTTPError as e: print(e.code) print(e.read().decode('utf-8')) except urllib.error.URLError as e: print(e.reason) if __name__ == '__main__': main() |
发送分批短信(示例1)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 |
import time import uuid import hashlib import base64 import requests #需要先使用pip install requests命令安装依赖 # 必填,请参考"开发准备"获取如下数据,替换为实际值 url = 'https://smsapi.ap-southeast-1.myhuaweicloud.com:443/sms/batchSendDiffSms/v1' #APP接入地址+接口访问URI // 认证用的appKey和appSecret硬编码到代码中或者明文存储都有很大的安全风险,建议在配置文件或者环境变量中密文存放,使用时解密,确保安全; APP_KEY = "c8RWg3ggEcyd4D3p94bf3Y7x1Ile" #Application Key APP_SECRET = "q4Ii87Bh************80SfD7Al" #Application Secret sender = "csms12345678" #中国大陆短信签名通道号或全球短信通道号 TEMPLATE_ID_1 = "8ff55eac1d0b478ab3c06c3c6a492300" #模板ID1 TEMPLATE_ID_2 = "8ff55eac1d0b478ab3c06c3c6a492300" #模板ID2 #条件必填,中国大陆短信关注,当templateId指定的模板类型为通用模板时生效且必填,必须是已审核通过的,与模板类型一致的签名名称 #全球短信不用关注该参数 signature_1 = "华为云短信测试" #签名名称1 signature_2 = "华为云短信测试" #签名名称2 # 必填,全局号码格式(包含国家码),示例:+8615123456789,多个号码之间用英文逗号分隔 receiver_1 = ["+8615123456789", "+8615234567890"] #模板1的接收号码 receiver_2 = ["+8615123456789", "+8615234567890"] #模板2的接收号码 # 选填,短信状态报告接收地址,推荐使用域名,为空或者不填表示不接收状态报告 statusCallBack = "" ''' 选填,使用无变量模板时请赋空值 TEMPLATE_PARAM = []; 单变量模板示例:模板内容为"您的验证码是${NUM_6}"时,TEMPLATE_PARAM可填写为["369751"] 双变量模板示例:模板内容为"您有${NUM_2}件快递请到${TXT_20}领取"时,TEMPLATE_PARAM可填写为["3","人民公园正门"] 查看更多模板和变量规范 ''' TEMPLATE_PARAM_1 = ["123456"] #模板1变量,此处以单变量验证码短信为例,请客户自行生成6位验证码,并定义为字符串类型,以杜绝首位0丢失的问题(例如:002569变成了2569)。 TEMPLATE_PARAM_2 = ["234567"] #模板2变量,此处以单变量验证码短信为例,请客户自行生成6位验证码,并定义为字符串类型,以杜绝首位0丢失的问题(例如:002569变成了2569)。 ''' 构造X-WSSE参数值 @param appKey: string @param appSecret: string @return: string ''' def buildWSSEHeader(appKey, appSecret): now = time.strftime('%Y-%m-%dT%H:%M:%SZ') #Created nonce = str(uuid.uuid4()).replace('-', '') #Nonce digest = hashlib.sha256((nonce + now + appSecret).encode()).hexdigest() digestBase64 = base64.b64encode(digest.encode()).decode() #PasswordDigest return 'UsernameToken Username="{}",PasswordDigest="{}",Nonce="{}",Created="{}"'.format(appKey, digestBase64, nonce, now) def main(): # 请求Headers header = {'Authorization':'WSSE realm="SDP",profile="UsernameToken",type="Appkey"', 'X-WSSE': buildWSSEHeader(APP_KEY, APP_SECRET)} # 请求Body jsonData = {'from': sender, 'statusCallback': statusCallBack, 'smsContent':[ {'to':receiver_1, 'templateId':TEMPLATE_ID_1, 'templateParas':TEMPLATE_PARAM_1, # 'signature':signature_1 #使用中国大陆短信通用模板时,必须填写签名名称 }, {'to':receiver_2, 'templateId':TEMPLATE_ID_2, 'templateParas':TEMPLATE_PARAM_2, # 'signature':signature_2 #使用中国大陆短信通用模板时,必须填写签名名称 }] } print(header) # 为防止因HTTPS证书认证失败造成API调用失败,需要先忽略证书信任问题 r = requests.post(url, json=jsonData, headers=header, verify=False) print(r.text) #打印响应信息 if __name__ == '__main__': main() |
发送分批短信(示例2)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 |
import time import uuid import hashlib import base64 import json import ssl import urllib.request # 必填,请参考"开发准备"获取如下数据,替换为实际值 url = 'https://smsapi.ap-southeast-1.myhuaweicloud.com:443/sms/batchSendDiffSms/v1' #APP接入地址+接口访问URI // 认证用的appKey和appSecret硬编码到代码中或者明文存储都有很大的安全风险,建议在配置文件或者环境变量中密文存放,使用时解密,确保安全; APP_KEY = "c8RWg3ggEcyd4D3p94bf3Y7x1Ile" #Application Key APP_SECRET = "q4Ii87Bh************80SfD7Al" #Application Secret sender = "csms12345678" #中国大陆短信签名通道号或全球短信通道号 TEMPLATE_ID_1 = "8ff55eac1d0b478ab3c06c3c6a492300" #模板ID1 TEMPLATE_ID_2 = "8ff55eac1d0b478ab3c06c3c6a492300" #模板ID2 #条件必填,中国大陆短信关注,当templateId指定的模板类型为通用模板时生效且必填,必须是已审核通过的,与模板类型一致的签名名称 #全球短信不用关注该参数 signature_1 = "华为云短信测试" #签名名称1 signature_2 = "华为云短信测试" #签名名称2 # 必填,全局号码格式(包含国家码),示例:+8615123456789,多个号码之间用英文逗号分隔 receiver_1 = ["+8615123456789", "+8615234567890"] #模板1的接收号码 receiver_2 = ["+8615123456789", "+8615234567890"] #模板2的接收号码 # 选填,短信状态报告接收地址,推荐使用域名,为空或者不填表示不接收状态报告 statusCallBack = "" ''' 选填,使用无变量模板时请赋空值 TEMPLATE_PARAM = []; 单变量模板示例:模板内容为"您的验证码是${NUM_6}"时,TEMPLATE_PARAM可填写为["369751"] 双变量模板示例:模板内容为"您有${NUM_2}件快递请到${TXT_20}领取"时,TEMPLATE_PARAM可填写为["3","人民公园正门"] 查看更多模板和变量规范 ''' TEMPLATE_PARAM_1 = ["123456"] #模板1变量,此处以单变量验证码短信为例,请客户自行生成6位验证码,并定义为字符串类型,以杜绝首位0丢失的问题(例如:002569变成了2569)。 TEMPLATE_PARAM_2 = ["234567"] #模板2变量,此处以单变量验证码短信为例,请客户自行生成6位验证码,并定义为字符串类型,以杜绝首位0丢失的问题(例如:002569变成了2569)。 ''' 构造X-WSSE参数值 @param appKey: string @param appSecret: string @return: string ''' def buildWSSEHeader(appKey, appSecret): now = time.strftime('%Y-%m-%dT%H:%M:%SZ') #Created nonce = str(uuid.uuid4()).replace('-', '') #Nonce digest = hashlib.sha256((nonce + now + appSecret).encode()).hexdigest() digestBase64 = base64.b64encode(digest.encode()).decode() #PasswordDigest return 'UsernameToken Username="{}",PasswordDigest="{}",Nonce="{}",Created="{}"'.format(appKey, digestBase64, nonce, now) def main(): # 请求Body jsonData = json.dumps({'from': sender, 'statusCallback': statusCallBack, 'smsContent':[ {'to':receiver_1, 'templateId':TEMPLATE_ID_1, 'templateParas':TEMPLATE_PARAM_1, # 'signature':signature_1 #使用中国大陆短信通用模板时,必须填写签名名称 }, {'to':receiver_2, 'templateId':TEMPLATE_ID_2, 'templateParas':TEMPLATE_PARAM_2, # 'signature':signature_2 #使用中国大陆短信通用模板时,必须填写签名名称 }] }).encode('ascii') req = urllib.request.Request(url=url, data=jsonData, method='POST') #请求方法为POST # 请求Headers参数 req.add_header('Authorization', 'WSSE realm="SDP",profile="UsernameToken",type="Appkey"') req.add_header('X-WSSE', buildWSSEHeader(APP_KEY, APP_SECRET)) req.add_header('Content-Type', 'application/json') # 为防止因HTTPS证书认证失败造成API调用失败,需要先忽略证书信任问题 ssl._create_default_https_context = ssl._create_unverified_context try: r = urllib.request.urlopen(req) #发送请求 print(r.read().decode('utf-8')) #打印响应信息 except urllib.error.HTTPError as e: print(e.code) print(e.read().decode('utf-8')) except urllib.error.URLError as e: print(e.reason) if __name__ == '__main__': main() |
接收状态报告
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
import urllib.parse # 短信平台上报状态报告数据样例(urlencode) #success_body = "sequence=1&total=1&updateTime=2018-10-31T08%3A43%3A41Z&source=2&smsMsgId=2ea20735-f856-4376-afbf-570bd70a46ee_11840135&status=DELIVRD"; failed_body = "orgCode=E200027&sequence=1&total=1&updateTime=2018-10-31T08%3A43%3A41Z&source=2&smsMsgId=2ea20735-f856-4376-afbf-570bd70a46ee_11840135&status=RTE_ERR"; ''' 解析状态报告数据 @param data: 短信平台上报的状态报告数据 @return: ''' def onSmsStatusReport(data): keyValues = urllib.parse.parse_qs(data); #解析状态报告数据 ''' Example: 此处已解析status为例,请按需解析所需参数并自行实现相关处理 'smsMsgId': 短信唯一标识 'total': 长短信拆分条数 'sequence': 拆分后短信序号 'source': 状态报告来源 'updateTime': 资源更新时间 'status': 状态报告枚举值 'orgCode': 状态码 ''' status = keyValues.get('status'); #状态报告枚举值 # 通过status判断短信是否发送成功 if 'DELIVRD' == str.upper(status[0]): print('Send sms success. smsMsgId: ', keyValues.get('smsMsgId')[0]); else: # 发送失败,打印status和orgCode print('Send sms failed. smsMsgId: ', keyValues.get('smsMsgId')[0]); print('Failed status: ', status[0]); print('Failed orgCode: ', keyValues.get('orgCode')[0]); if __name__ == '__main__': # onSmsStatusReport(success_body) onSmsStatusReport(failed_body) |
父主题: X-WSSE认证