Python——云通讯短信接口对接python3使用

本文介绍了在Python3环境下重写云通讯官方SDK的过程,主要涉及字符集编码、MD5加密语法差异以及请求库的更新。提供了已修正的Python3适用SDK代码片段,强调了可优化的空间,并分享了发送短信的关键方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言:

    云通讯不做介绍,官网的python的sdk还是2.7版本,貌似是从13年到现在没人更新过,现在很多程序跑在python3版本上,好了问题来了,预研版本升级时候对接到第三方接口的sdk是版本2写到,3就是对接不上短信验证码就是发不出来。然后看了下官方的sdk,犹豫后还是重写了官方到sdk,回顾其中主要变动点有三个,一个是2和3到字符集编码格式变化,二是2和3的md5加密上语法有些差异有点小坑,三是官方使用的urllib2请求的,3中已经合并到request中了,甚至个人觉得还不如用request直接来的亲切;

具体内容:

      不做过多废话,下面直接上已经修正python3适用的sdk,当然因为时间仓促来不及进一步优化只是能让程序先用,所以重写后还是有很多优化的地方的;(有相关问题,欢迎加QQ1277207158进行指正)

具体申请应用参考官网哈,主要的就是以下几个参数:

accountSid = 'xxxxxx;                  #账号id           首页就可以看到

accountToken = 'xxxxxx';            #账号token     首页就可以看到

appId = 'xxxxxx;                          #appid   新开户需要创建一个

serverIP = 'app.cloopen.com';      #云通讯生产环境地址,不用变

serverPort = '8883';                                #端口号

softVersion = '2013-12-26';                     #版本号

首先调用函数改写如下:

# coding=utf-8
from CCPRestSDK import REST
#import ConfigParser         #官网sdk带的,没有使用
import logging

# 账号id
accountSid = 'xxxxxx'
# 账号Token
accountToken = 'xxxxxx'
# 应用Id
appId = 'xxxxxx'            #token请自行去官网申请
# 服务地址
serverIP = 'app.cloopen.com'
# 服务端口
serverPort = '8883'
# REST版本
softVersion = '2013-12-26'

# def sendTemplateSMS(to,datas,tempId):
#
#
#     #REST SDK
#     rest = REST(serverIP,serverPort,softVersion)
#     rest.setAccount(accountSid,accountToken)
#     rest.setAppId(appId)
#
#     result = rest.sendTemplateSMS(to,datas,tempId)
#     for k,v in result.iteritems():
#
#         if k=='templateSMS' :
#                 for k,s in v.iteritems():
#                     print '%s:%s' % (k, s)
#         else:
#             print '%s:%s' % (k, v)


class CCP(object):

    def __init__(self):
        self.rest = REST(serverIP, serverPort, softVersion)
        self.rest.setAccount(accountSid, accountToken)
        self.rest.setAppId(appId)

    @staticmethod
    def instance():
        if not hasattr(CCP, "_instance"):
            CCP._instance = CCP()
        return CCP._instance

    def sendTemplateSMS(self, to, datas, tempId):
        try:
            result = self.rest.sendTemplateSMS(to, datas, tempId)
        except Exception as e:
            logging.error(e)
            raise e
        # print result
        # for k, v in result.iteritems():
        #     if k == 'templateSMS':
        #         for k, s in v.iteritems():
        #             print '%s:%s' % (k, s)
        #     else:
        #         print '%s:%s' % (k, v)
        success = "<statusCode>000000</statusCode>"
        if success in result:
            return True
        else:
            return False
ccp = CCP.instance()
if __name__ == "__main__":
    ccp = CCP.instance()
    res = ccp.sendTemplateSMS("185xxxxxxxx", ["1234", 5], 1)
    print(res)

鉴于提示说需要20分钟阅读完,时间宝贵,只拿发送短信部分单独上边说一下,下边是代码可以复制直接使用:

关键就用发送短信方法了:

 # 发送模板短信
    # @param to  必选参数     短信接收彿手机号码集合,用英文逗号分开
    # @param datas 可选参数    内容数据
    # @param tempId 必选参数    模板Id
    def sendTemplateSMS(self, to, datas, tempId):

        self.accAuth()
        nowdate = datetime.datetime.now()
        self.Batch = nowdate.strftime("%Y%m%d%H%M%S")
        # 生成sig
        signature = self.AccountSid + self.AccountToken + self.Batch
        sig = md5(signature.encode()).hexdigest().upper()
        # 拼接URL
        url = "https://" + self.ServerIP + ":" + self.ServerPort + "/" + self.SoftVersion + "/Accounts/" + self.AccountSid + "/SMS/TemplateSMS?sig=" + sig
        # 生成auth
        src = self.AccountSid + ":" + self.Batch
        auth = base64.encodestring(src.encode()).strip().decode()
        req = urllib.request.Request(url)
        self.setHttpHeader(req)
        req.add_header("Authorization", auth)
        #print(req.headers)      #组装请求头
        # 创建包体
        b = ''
        for a in datas:
            b += '<data>%s</data>' % (a)

        body = '<?xml version="1.0" encoding="utf-8"?><SubAccount><datas>' + b + '</datas><to>%s</to><templateId>%s</templateId><appId>%s</appId>\
            </SubAccount>\
            ' % (to, tempId, self.AppId)
        if self.BodyType == 'json':
            # if this model is Json ..then do next code
            b = '['
            for a in datas:
                b += '"%s",' % (a)
            b += ']'
            body = '''{"to": "%s", "datas": %s, "templateId": "%s", "appId": "%s"}''' % (to, b, tempId, self.AppId)
        req.data = body
        #print(req.data)    #组装请求体
        #确认请求体和请求头
        req_headers = req.headers
        req_data = req.data
        # print(req_headers,req_data)
        # print("_______"*20)
        data = ''
        try:
            # res = urllib.request.urlopen(req)
            res = requests.post(url, headers=req_headers, data=req_data)
            # print(res.status_code,res.content,res.text,)
            data = res.text
            # data = res.read()
            # res.close()
            # if self.BodyType == 'json':
            #     # json格式
            #     locations = json.loads(data)
            # else:
            #     # xml格式
            #     xtj = xmltojson()
            #     locations = xtj.main(data)
            if self.Iflog:
                self.log(url, body, data)
            return data
        except Exception as error:
            if self.Iflog:
                self.log(url, body, data)
            return {'172001': '网络错误'}

不难看出方法重复内容非常多,更别说什么工厂模式了,所以其实可改进地方非常多,时间有限,凑合先用,后期会在github上上传一个优化版本;

调用官网接口的SDK的全部代码:

# -*- coding: UTF-8 -*-
#  Copyright (c) 2014 The CCP project authors. All Rights Reserved.
#
#  Use of this source code is governed by a Beijing Speedtong Information Technology Co.,Ltd license
#  that can be found in the LICENSE file in the root of the web site.
#
#   http://www.yuntongxun.com
#
#  An additional intellectual property rights grant can be found
#  in the file PATENTS.  All contributing project authors may
#  be found in the AUTHORS file in the root of the source tree.

from hashlib import md5
import base64
import datetime
import urllib.request
import requests
import json
from xmltojson import xmltojson
from xml.dom import minidom


class REST:
    AccountSid = ''
    AccountToken = ''
    AppId = ''
    SubAccountSid = ''
    SubAccountToken = ''
    ServerIP = ''
    ServerPort = ''
    SoftVersion = ''
    Iflog = True  # 是否打印日志
    Batch = ''  # 时间戳
    BodyType = 'xml'  # 包体格式,可填值:json 、xml

    # 初始化
    # @param serverIP       必选参数    服务器地址
    # @param serverPort     必选参数    服务器端口
    # @param softVersion    必选参数    REST版本号
    def __init__(self, ServerIP, ServerPort, SoftVersion):

        self.ServerIP = ServerIP
        self.ServerPort = ServerPort
        self.SoftVersion = SoftVersion

    # 设置主帐号
    # @param AccountSid  必选参数    主帐号
    # @param AccountToken  必选参数    主帐号Token

    def setAccount(self, AccountSid, AccountToken):
        self.AccountSid = AccountSid
        self.AccountToken = AccountToken

        # 设置子帐号

    #
    # @param SubAccountSid  必选参数    子帐号
    # @param SubAccountToken  必选参数    子帐号Token

    def setSubAccount(self, SubAccountSid, SubAccountToken):
        self.SubAccountSid = SubAccountSid
        self.SubAccountToken = SubAccountToken

        # 设置应用ID

    #
    # @param AppId  必选参数    应用ID

    def setAppId(self, AppId):
        self.AppId = AppId

    def log(self, url, body, data):
        print('这是请求的URL:')
        print(url)
        print('这
### 使用Python Requests库进行HTTPS请求 当利用Python的`requests`库执行HTTPS请求时,可以保持与HTTP请求相似的操作方式,但需要注意一些特定于HTTPS的安全配置选项。默认情况下,`requests`库会对HTTPS连接自动验证服务器SSL证书以保障通信安全[^4]。 对于发起一个简单的GET类型的HTTPS请求而言: ```python import requests response = requests.get(&#39;https://example.com&#39;) print(response.status_code) ``` 如果目标网站拥有有效的公共信任链中的CA签发的SSL证书,则上述代码通常能正常工作而无需额外配置。然而,在某些特殊场景下——比如对接自签名证书的服务端口时,可能需要显式指定路径到本地存储的信任根证书文件来完成认证过程;或者出于开发调试目的暂时忽略证书校验(不推荐用于生产环境),可以通过调整`verify`参数的行为达成需求: ```python # 明确提供可信CA bundle的位置 response_with_custom_ca = requests.get(&#39;https://self-signed.example.org&#39;, verify=&#39;/path/to/cabundle.pem&#39;) # 或者禁用SSL验证 (注意:这存在安全隐患!) unsafe_response = requests.get(&#39;https://some-site-with-invalid-cert/&#39;, verify=False) if unsafe_response.ok: print(unsafe_response.text) else: print(f"Request failed with status code {unsafe_response.status_code}") ``` 针对POST方法下的HTTPS调用同样适用类似的逻辑框架,并且可以根据实际业务需求构建更复杂的payload结构体作为请求主体的一部分传递给服务端解析处理[^3]。 #### 关键点总结: - 默认启用SSL/TLS加密传输层保护机制; - 支持通过`verify`参数定制化控制SSL证书验证策略; - 可选地附加客户机身份凭证材料如client-side certificates以便双向TLS握手建立受信通道。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值