月度归档: 2021 年 4 月

java服务器开发

java服务器开发基础篇-从零开始
这里记录了*初期的基本开发步骤。
推荐一个免费视频课程:http://study.163.com/course/courseMain.htm?courseId=1005265066,讲的非常详细。

1、创建一个基础工程
见:https://www.cnblogs.com/sweeeper/p/5488215.html
创建的工程中目录结构:

src: 源代码目录,在这个目录下写代码
JRE System Library: java系统库目录,一般不用管
Java EE * Libraries: javaweb库目录,一般不用管
WebRoot: 发布后服务器根目录。当项目部署时这个文件夹会以工程名称命名的文件夹形式出现在服务器中。并且src中的代码会编译为二进制文件保存在这个目录下的WEB-INF/classes中。而在开发过程中需要的资源文件也会以工程中的目录结构存在于这个目录下。
2、创建servlet
直接创建servlet,xml文件会自动配置

3、要点记录
get请求下。可从request中获取,URL,URI,get请求的参数,获取当前web应用名称。
2.
4、通过花生壳连接外网
注册花生壳并8RMB开通账号,登录路由器打开花生壳映射(不能和花生壳客户端同时使用,会导致冲突),花生壳客户端管理页面建立新映射。

WEB服务器、应用程序服务器、HTTP服务器区别

WEB服务器、应用程序服务器、HTTP服务器有何区别?IIS、Apache、Tomcat、Weblogic、WebSphere都各属于哪种服务器,这些问题困惑了很久,今天终于梳理清楚了:

Web服务器的基本功能就是提供Web信息浏览服务。它只需支持HTTP协议、HTML文档格式及URL。与客户端的网络浏览器配合。因为Web服务器主要支持的协议就是HTTP,所以通常情况下HTTP服务器和WEB服务器是相等的(有没有支持除HTTP之外的协议的web服务器,作者没有考证过),说的是一回事。

应用程序服务器(简称应用服务器),我们先看一下微软对它的定义:”我们把应用程序服务器定义为“作为服务器执行共享业务应用程序的底层的系统软件”。 就像文件服务器为很多用户提供文件一样,应用程序服务器让多个用户可以同时使用应用程序(通常是客户创建的应用程序)”

通俗的讲,Web服务器传送(serves)页面使浏览器可以浏览,然而应用程序服务器提供的是客户端应用程序可以调用(call)的方法(methods)。确切一点,你可以说:Web服务器专门处理HTTP请求(request),但是应用程序服务器是通过很多协议来为应用程序提供(serves)商业逻辑 (business logic)。

以Java EE为例,Web服务器主要是处理静态页面处理和作为 Servlet容器,解释和执行servlet/JSP,而应用服务器是运行业务逻辑的,主要是EJB、 JNDI和JMX API等J2EE API方面的,还包含事务处理、数据库连接等功能,所以在企业级应用中,应用服务器提供的功能比WEB服务器强大的多。

以这样的定义,IIS、Apache、Tomcat都可以属于Web服务器,Weblogic、WebSphere都属于应用服务器。

Apache:在Web服务器中,Apache是纯粹的Web服务器,经常与Tomcat配对使用。它对HTML页面具有强大的解释能力,但是不能解释嵌入页面内的服务器端脚本代码(JSP/Servlet)。

Tomcat:早期的Tomcat是一个嵌入Apache内的JSP/Servlet解释引擎Apache+Tomcat就相当于IIS+ASP。后来的Tomcat已不再嵌入Apache内,Tomcat进程独立于Apache进程运行。 而且,Tomcat已经是一个独立的Servlet和JSP容器,业务逻辑层代码和界面交互层代码可以分离了。因此,有人把Tomcat叫做轻量级应用服务器。

IIS:微软早期的IIS,就是一个纯粹的Web服务器。后来,它嵌入了ASP引擎,可以解释VBScript和JScript服务器端代码了,这时,它就可以兼作应用服务器。当然,它与J2EE应用服务器根本无法相比,但是,从功能上说,从原理上说,它勉强可以称之为应用服务器。确切地说,它是兼有一点应用服务器功能的Web服务器。

综上:Apache是纯粹的web服务器,而Tomcat和IIS因为具有了解释执行服务器端代码的能力,可以称作为轻量级应用服务器或带有服务器功能的Web服务器。Weblogic、WebSphere因为能提供强大的J2EE功能,毫无疑问是*对的应用服务器。对于处于中间位置的Tomcat,它可以配合纯Web服务器Apache一起使用,也可以作为应用服务器的辅助与应用服务器一起部署:

一、Tomcat与应用服务器

到目前为止,Tomcat一直被认为是Servlet/JSP API的执行器,也就所谓的Servlet容器。然而,Tomcat并不仅仅如此,它还提供了JNDI和JMX API的实现机制。尽管如此,Tomcat仍然还不能算是应用服务器,因为它不提供大多数J2EE API的支持。

很有意思的是,目前许多的应用服务器通常把Tomcat作为它们Servlet和JSP API的容器。由于Tomcat允许开发者只需通过加入一行致谢,就可以把Tomcat嵌入到它们的应用中。遗憾的是,许多商业应用服务器并没有遵守此规则。

对于开发者来说,如果是为了寻找利用Servlet、JSP、JNDI和JMX技术来生成Java Web应用的话,选择Tomcat是一个优秀的解决方案;但是为了寻找支持其他的J2EE API,那么寻找一个应用服务器或者把Tomcat作为应用服务器的辅助,将是一个不错的解决方案;第三种方式是找到独立的J2EE API实现,然后把它们跟Tomcat结合起来使用。虽然整合会带来相关的问题,但是这种方式是*为有效的。。

二、Tomcat与Web服务器

Tomcat是提供一个支持Servlet和JSP运行的容器。Servlet和JSP能根据实时需要,产生动态网页内容。而对于Web服务器来说, Apache仅仅支持静态网页,对于支持动态网页就会显得无能为力;Tomcat则既能为动态网页服务,同时也能为静态网页提供支持。尽管它没有通常的Web服务器快、功能也不如Web服务器丰富,但是Tomcat逐渐为支持静态内容不断扩充。大多数的Web服务器都是用底层语言编写如C,利用了相应平台的特征,因此用纯Java编写的Tomcat执行速度不可能与它们相提并论。

一般来说,大的站点都是将Tomcat与Apache的结合,Apache负责接受所有来自客户端的HTTP请求,然后将Servlets和JSP的请求转发给Tomcat来处理。Tomcat完成处理后,将响应传回给Apache,*后Apache将响应返回给客户端。

而且为了提高性能,可以一台apache连接多台tomcat实现负载平衡。

关于WEB服务器、应用程序服务器的更详细区别可以参考下面这篇文章:

通俗的讲,Web服务器传送(serves)页面使浏览器可以浏览,然而应用程序服务器提供的是客户端应用程序可以调用(call)的方法(methods)。确切一点,你可以说:Web服务器专门处理HTTP请求(request),但是应用程序服务器是通过很多协议来为应用程序提供(serves)商业逻辑 (business logic)。

下面让我们来细细道来:

Web服务器(Web Server)

Web服务器可以解析(handles)HTTP协议。当Web服务器接收到一个HTTP请求(request),会返回一个HTTP响应 (response),例如送回一个HTML页面。为了处理一个请求(request),Web服务器可以响应(response)一个静态页面或图片,进行页面跳转(redirect),或者把动态响应(dynamic response)的产生委托(delegate)给一些其它的程序例如CGI脚本,JSP(JavaServer Pages)脚本,servlets,ASP(Active Server Pages)脚本,服务器端(server-side)JavaScript,或者一些其它的服务器端(server-side)技术。无论它们(译者注:脚本)的目的如何,这些服务器端(server-side)的程序通常产生一个HTML的响应(response)来让浏览器可以浏览。

要知道,Web服务器的代理模型(delegation model)非常简单。当一个请求(request)被送到Web服务器里来时,它只单纯的把请求(request)传递给可以很好的处理请求 (request)的程序(译者注:服务器端脚本)。Web服务器仅仅提供一个可以执行服务器端(server-side)程序和返回(程序所产生的)响应(response)的环境,而不会超出职能范围。服务器端(server-side)程序通常具有事务处理(transaction processing),数据库连接(database connectivity)和消息(messaging)等功能。

虽然Web服务器不支持事务处理或数据库连接池,但它可以配置(employ)各种策略(strategies)来实现容错性(fault tolerance)和可扩展性(scalability),例如负载平衡(load balancing),缓冲(caching)。集群特征(clustering—features)经常被误认为仅仅是应用程序服务器专有的特征。

应用程序服务器(The Application Server)

根据我们的定义,作为应用程序服务器,它通过各种协议,可以包括HTTP,把商业逻辑暴露给(expose)客户端应用程序。Web服务器主要是处理向浏览器发送HTML以供浏览,而应用程序服务器提供访问商业逻辑的途径以供客户端应用程序使用。应用程序使用此商业逻辑就象你调用对象的一个方法 (或过程语言中的一个函数)一样。

应用程序服务器的客户端(包含有图形用户界面(GUI)的)可能会运行在一台PC、一个Web服务器或者甚至是其它的应用程序服务器上。在应用程序服务器与其客户端之间来回穿梭(traveling)的信息不仅仅局限于简单的显示标记。相反,这种信息就是程序逻辑(program logic)。正是由于这种逻辑取得了(takes)数据和方法调用(calls)的形式而不是静态HTML,所以客户端才可以随心所欲的使用这种被暴露的商业逻辑。

在大多数情形下,应用程序服务器是通过组件 (component) 的应用程序接口(API)把商业逻辑暴露(expose)(给客户端应用程序)的,例如基于J2EE(Java 2 Platform, Enterprise Edition)应用程序服务器的EJB(Enterprise JavaBean)组件模型。此外,应用程序服务器可以管理自己的资源,例如看大门的工作(gate-keeping duties)包括安全(security),事务处理(transaction processing),资源池(resource pooling),和消息(messaging)。就象Web服务器一样,应用程序服务器配置了多种可扩展(scalability)和容错(fault tolerance)技术。

一个例子

例如,设想一个在线商店(网站)提供实时定价(real-time pricing)和有效性(availability)信息。这个站点(site)很可能会提供一个表单(form)让你来选择产品。当你提交查询 (query)后,网站会进行查找(lookup)并把结果内嵌在HTML页面中返回。网站可以有很多种方式来实现这种功能。我要介绍一个不使用应用程序服务器 的情景和一个使用应用程序服务器的情景。观察一下这两中情景的不同会有助于你了解应用程序服务器的功能。

情景1:不带应用程序服务器的Web服务器

在此种情景下,一个Web服务器独立提供在线商店的功能。Web服务器获得你的请求(request),然后发送给服务器端(server- side)可以处理请求(request)的程序。此程序从数据库或文本文件(flat file,译者注:flat file是指没有特殊格式的非二进制的文件,如properties和XML文件等)中查找定价信息。一旦找到,服务器端(server-side)程序把结果信息表示成(formulate)HTML形式,*后Web服务器把会它发送到你的Web浏览器。

简而言之,Web服务器只是简单的通过响应(response)HTML页面来处理HTTP请求(request)。

情景2:带应用程序服务器的Web服务器

情景2和情景1相同的是Web服务器还是把响应(response)的产生委托(delegates)给脚本(译者注:服务器端 (server-side)程序)。然而,你可以把查找定价的商业逻辑(business logic)放到应用程序服务器上。由于这种变化,此脚本只是简单的调用应用程序服务器的查找服务(lookup service),而不是已经知道如何查找数据然后表示为(formulate)一个响应(response)。这时当该脚本程序产生HTML响应(response)时就可以使用该服务的返回结果了。

在此情景中,应用程序服务器提供(serves)了用于查询产品的定价信息的商业逻辑。(服务器的)这种功能(functionality)没有指出有关显示和客户端如何使用此信息的细节,相反客户端和应用程序服务器只是来回传送数据。当有客户端调用应用程序服务器的查找服务(lookup service)时,此服务只是简单的查找并返回结果给客户端。

通过从响应产生(response-generating)HTML的代码中分离出来,在应用程序之中该定价(查找)逻辑的可重用性更强了。其他的客户端,例如收款机,也可以调用同样的服务(service)来作为一个店员给客户结帐。相反,在情景1中的定价查找服务是不可重用的因为信息内嵌在 HTML页中了。

总而言之,在情景2的模型中,在Web服务器通过回应HTML页面来处理HTTP请求(request),而应用程序服务器则是通过处理定价和有效性(availability)请求(request)来提供应用程序逻辑的。

警告(Caveats)

现在,XML Web Services已经使应用程序服务器和Web服务器的界线混淆了。通过传送一个XML有效载荷(payload)给服务器,Web服务器现在可以处理数据和响应(response)的能力与以前的应用程序服务器同样多了。

另外,现在大多数应用程序服务器也包含了Web服务器,这就意味着可以把Web服务器当作是应用程序服务器的一个子集(subset)。虽然应用程序服务器包含了Web服务器的功能,但是开发者很少把应用程序服务器部署(deploy)成这种功能(capacity)(译者注:这种功能是指既有应用程序服务器的功能又有Web服务器的功能)。相反,如果需要,他们通常会把Web服务器独立配置,和应用程序服务器一前一后。这种功能的分离有助于提高性能(简单的Web请求(request)就不会影响应用程序服务器了),分开配置(专门的Web服务器,集群(clustering)等等),而且给*佳产品的选取留有余地。

Android 查看app包名

一,有apk安装包

二,没有apk,但已安装到Android设备中

 

一,有apk安装包
1.1,使用aapt的dump badging命令查看app包名

a,使用cmd命令行中cd 切换到aapt所在的目录,如果已经为aapt配置了环境变量,可以跳过!

b,输入 aapt dump badging C:\Users\Administrator\Desktop\adbc.apk命令运行,OK;

其中C:\Users\Administrator\Desktop\adbc.apk是app所在的路径

还可以这样输入:

aapt dump badging C:\Users\Administrator\Desktop\adbc.apk | findstr “package” >E:\package.txt

其中:| findstr “package” 过滤出带有package信息

>E:\package.txt 输出到指定的文件,没有这个文件会自动创建;

1.2,使用aapt的 dump xmltree命令查看包名

a,和1.1中的a步骤一样

b,命令行中输入 aapt dump xmltree C:\Users\Administrator\Desktop\adbc.apk AndroidManifest.xml | findstr “package” 命令运行,OK;也可以不要 | findstr “package” 加上他只是起到过滤的作用,把我们想要的包名过滤出来;

其中C:\Users\Administrator\Desktop\adbc.apk是app所在的路径

二,没有apk,但已安装到Android设备中
2.1,通过adb

a,PC连接Android设备

b,Android设备中点开app,app的任何界面都可以;

c,cmd命令行中输入:adb shell dumpsys window w |findstr \/ |findstr name= 或者 adb shell dumpsys window | findstr mCurrentFocus查看包名

2.2,也是通过adb

a,PC连接Android设备

b,cmd 进入命令行,输入: adb shell pm list package  列出所有的应用的包名 (-s:列出系统应用  -3:列出第三方应用 -f:列出应用包名及对应的apk名及存放位置  -i:列出应用包名及其安装来源)

常用的java应用服务器大概介绍

何为应用服务器呢?它主要为应用程序提供运行环境,为组件提供服务。想进一步了解,可以查看我的博客:何为容器?

Java 的应用服务器很多,从功能上分为两类:WEB 应用服务器和 Java EE 应用服务器。相对来说 Java EE 服务器的功能更加强大。

WEB 服务器

Tomcat 、Bejy Tiger 、Geronimo 、 Jetty 、Jonas 、Jrun 、Orion 、Resin。

Java EE 服务器

TongWeb 、BES Application Server 、 Apusic Application Server 、 IBM Websphere 、Sun Application Server 、Oracle 的 Oracle9i/AS 、Sun Java System Application Server 、Bea Weblogic 、JBoss、开源GlassFish。

下面简单介绍几个应用服务器。

Apache Tomcat
Tomcat是Apache 软件基金会(Apache Software Foundation)的Jakarta 项目中的一个核心项目,由Apache、Sun 和其他一些公司及个人共同开发而成。由于有了Sun 的参与和支持,*新的Servlet 和JSP 规范总是能在Tomcat 中得到体现。因为Tomcat 技术先进、性能稳定,而且免费,因而深受Java 爱好者的喜爱并得到了部分软件开发商的认可,成为目前比较流行的Web 应用服务器。

优点:
1、免费的开源代码
2、轻量级应用服务器,在中小型 系统 和并发访问用户不是很多的场合下被普遍使用
3、占用的系统资源小,启动快
4、扩展性好,支持负载平衡与邮件服务等开发应用系统常用的功能

目前*新版本是8.0。

Jetty
Jetty 是一个开源的WEB容器,它为基于Java的web内容,例如JSP和servlet提供运行环境。Jetty是使用Java语言编写的,它的API以一组JAR包的形式发布。开发人员可以将Jetty容器实例化成一个对象,可以迅速为一些独立运行的Java应用提供网络和web连接。

优点:
1、免费的开源代码
2、轻量级,运行速度快。
3、易用
默认配置可以满足大部分的需求;将 Jetty 嵌入到应用程序当中只需要非常少的代码;
4、可扩展
Jetty 设计了非常良好的接口,用户可以非常方便地对 Jetty 的某些实现进行修改,使得 Jetty 适用于特殊的应用程序的需求。
5、易嵌入
Jetty 设计之初就是作为一个优秀的组件来设计的,这也就意味着 Jetty 可以非常容易的嵌入到应用程序当中。从某种程度上,你也可以把 Jetty 理解为一个嵌入式的Web服务器。

目前*新版本是:9.1.4

JBoss
JBoss是全世界开发者共同努力的成果,一个基于J2EE的开放源代码的应用服务器。因为JBoss代码遵循LGPL许可,可以在任何商业应用中免费使用它,而不用支付费用。2006年,Jboss公司被Redhat公司收购。JBoss 是一个管理EJB的容器和服务器,支持EJB 1.1、EJB 2.0和EJB3.0的规范。但JBoss核心服务不包括支持servlet/JSP的WEB容器,一般与Tomcat或Jetty绑定使用。
另外,JBoss在J2EE应用服务器领域已成为发展*为迅速的应用服务器.在市场占有率和服务满意度上取得了巨大的成功,丝毫不逊色于其它的非开源竞争对手,如WebSPhere、WebLogic、Application Server.

优点:

1、标准的开源J2EE容器
2、性能好,执行效率高
3、支持集群,理论上无*大访问量限制一说。
4、可伸缩性强
可伸缩性应该是架构选择的主要标准,所谓可伸缩性,只在小型系统、一台服务器情况下,我的系统也可以良好运转,多台服务器扩展后,我的系统只需通过增加硬件就可以实现性能扩展,无需修改太多软件。
5、支持热部署

目前JBOSS的*新版本号为7.1。

BEA WebLogic (收费)
WebLogic是Oracle的主要产品之一,是商业市场上主要的Java(J2EE)应用服务器软件(application server)之一,是世界上*个成功商业化的J2EE应用服务器。它是一套基于JAVA功能强大的电子商务套件,提供了许多功能强大的中间件以方便 编程 人员编写的JSP、SERVLET 等电子商务应用,可以为企业提供一个完整的商务应用解决方案。

优点:
1、标准
对业内多种标准的全面支持,使Web应用系统的实施更为简单。
2、可扩展性
WebLogic Server以其高扩展的架构体系闻名于业内,包括客户机连接的共享、资源pooling以及动态网页和EJB组件群集。
3、快速开发
凭借对EJB和JSP的支持,以及BEA WebLogic Server 的Servlet组件架 构体系,可加速投放市场速度。
4、更趋灵活
BEA WebLogic Server的特点是与* 数据库 、操作系统和Web服务器紧密集成。
5、可靠性
其容错、系统管理和安全性能已经在全球数以千记的关键任务环境中得以验证。

目前WEBLOGIC*新版本号为:12c

IBM WebSphere (收费)
WebSphere Application Server 是一种功能完善、开放的Web应用程序服务器,是IBM电子商务计划的核心部分。WebSphere 是随需应变的电子商务时代的*主要的软件平台。使用它,你可以开发、部署和整合新一代的电子商务应用,如B2B电子商务,并支持从简单的网页内容发布到企业级事务处理的商业应用。

目前WEBSPHERE*新版本号为:8.5.5

BEA公司的Weblogic服务器和IBM的Websphere在J2EE应用服务器市场中占据*对主导地位,都是商用产品。而JBoss和Tomcat算是开源的应用服务器界的两大明星。个人愚见,如果开发的是大型的、开放的、需要安全级别较高的系统,*好选用WebLogic 或Websphere等商用应用服务器,如果你开发的系统是分布式的,而且仅仅在公司内部使用,那么你可以选择JBoss。当然,大家都知道Tomcat是一个web 应用服务器,如果你开发的系统较小型,不涉及分布式等,那Tomcat将是你不错的选择。

通过阿里云域名动态解析 IP 地址

这两天在家里用树莓派折腾了一个家用服务器,主要用来做 mac 的 Time Machine ,还有就是当做下载机和 nas ,想着平时上班时间家里没人用网络,空着也是空着,就可以利用空闲带宽下个美剧啥的。所以在服务器上装了个远程迅雷和 transmission ,这些网上教程一大把,跟着教程做很快就能搞好。

但是我遇到的问题就是,家用的宽带不是固定 IP 的,如果路由器断个网重新连接就会被分配到不同的 ip ,一旦 ip 换了那就没办法通过外网连接到服务器上了。之前也尝试过在路由器上绑定花生壳,但是实际使用效果不是很好,不是很清楚花生壳的动态更新机制,好几次家里网络已经更新了 ip 但是花生壳那边没有及时更新。

花生壳的方案不行,那就只有找别的方法了。同时我顺便了解了下花生壳能够动态解析域名的原因,原来使用的是 DDNS 服务,关于 DDNS ,网上的解释是:

DDNS ( Dynamic Domain Name Server )是动态域名服务的缩写。
DDNS 是将用户的动态 IP 地址映射到一个固定的域名解析服务上,用户每次连接网络的时候客户端程序就会通过信息传递把该主机的动态 IP 地址传送给位于服务商主机上的服务器程序,服务器程序负责提供 DNS 服务并实现动态域名解析。 –百度百科

这不正是我需要的功能么,正好我自己也有域名,我的域名是在阿里云上注册的,所以我就去阿里云上看有没有提供动态域名解析服务,果不其然在网站上找到了修改解析记录的 api 文档。

由于我比较擅长的是 java(其实也是唯一擅长的),所以我下了他们的 JAVA SDK ,申请好Access Key 很快就接入成功了,但是感觉在 Linux 服务器上用 Java 来执行更新好像是件很 Low 的事,正常的使用方式应该用脚本才对啊。正好*近我在自学 Phthon ,所以顺便边学边做用 python 脚本来实现吧。

好啦,以上的都是废话,下面的才是正题。

1.首先你得有个阿里云的域名

2.到阿里云管理控制台申请Access Key

3.下载Python sdk,SDK 主要帮我们封装好了一些数据格式转换和对接的方法,能够方便我们快速接入,当然如果你足够牛逼的话,你也完全可以全部自己写。

4.进行接入操作。我的主要思路是运行该脚本的时候先去阿里云获取域名绑定的 ip 地址,再跟
当前服务器 ip 地址做对比,如果 ip 相同则说明没改变,不需要操作。如果 ip 不同则修改域名绑定的 ip 地址。

5.服务器部署。在服务器上通过 corntab 设置一项定时计划,让服务器定期执行该脚本。 linux 设置定时计划命令:

crontab -e

几个注意点:

1.请记得保管好你的 Access Key ,所以我没有在我的代码里直接写 Access Key Id 和 Access Key Secret ,我把他们单独放在一个 key.json 文件中,同时将这个文件排除出 git ,保证只有我自己知道,因为一旦这两个值泄露了那别人就可以直接修改你的域名了。

2.阿里云通过 RecordId 来区分每条域名解析记录,但是他们之前文档上对于这个参数的描述只写了“解析记录的 ID ”,没有写如何获取这条解析记录 ID ,我去我的阿里云控制台上找了好久都没找到,到后来我突然想到 sdk 上有获取域名信息的 api ,我试着用这个果然返回的信息里有这个字段,后来联系了他们客服,他们也说在控制台上没办法找到,也只有通过 api 获取域名信息才能找到,后来他们也在文档中注明了这个字段的获取方式。

3.更新域名解析主要用到的是阿里云 sdk 包里 aliyun/api/rest/Dns20150109UpdateDomainRecordRequest.py 方法,我为了偷懒直接在这个方法里写死了一些需要固定传入的参数,如果你要对自己的域名做解析的话记得去修改这些参数值。

4.我已经把这个项目发到 github 上,欢迎有需要的使用,同时也欢迎一起交流

abelyao 2016-01-10 16:29:22 +08:00 ❤️ 3
话说… 楼主… 如果只是为了 DDNS 可以用 Dnspod 有 API 可以直接操作…
并且通过 cron 定时任务,一行脚本的事…

*/15 * * * * curl -k -X POST https://dnsapi.cn/Record.Ddns -d ‘login_email=登录邮箱&login_password=登录密码&format=json&domain_id=域名编号&record_id=记录编号&record_line=默认&sub_domain=子域名’

每 15 分钟更新一次
abelyao 2
abelyao 2016-01-10 16:30:18 +08:00
当然… 我赞同所有以学习为目的的折腾,上面的回复仅仅针对 DDNS 的多种实现方式…
abcbit 3
abcbit 2016-01-10 16:30:22 +08:00
何必這麼麻煩,而且 DDNS 的可靠性太差,更新也慢

1 、租個 vps ,裝上 nginx+php 或 python
2 、树莓派定期執行 wget 或 curl 到 vps 的網址,*好加上驗證比如 a.com/get?key=1234
3 、訪問 vps 上的網頁,得到*新的 remote_addr
yexm0 4
yexm0 2016-01-10 16:39:56 +08:00 via Android
ddns 更新应该不慢吧。我用路由器挂 he 的 ipv6 隧道就要用到它们给的 ddns 功能,我见每次重拨后域名对应的 ip 都有及时更新啊。
bdbai 5
bdbai 2016-01-10 16:46:54 +08:00 via iPhone
@abelyao 原来 DNSPod 还有这一手…蠢蠢的我还去解析手机版页面登录提交?
abelyao 6
abelyao 2016-01-10 16:49:19 +08:00 ❤️ 2
@bdbai Dnspod 的 api 功能还挺丰富的~ 而且任何帐号都可以使用,不需要申请啥的
miaol 7
miaol 2016-01-10 16:52:53 +08:00 ❤️ 1
@abelyao
1.你这个果然好简单,一行代码能搞定,我之前真的不知道还有这个,又学到了一个新技能,非常感谢?
2.我的域名是放在阿里云上的,如果要用 dnspod 的话得把我的域名转过去才行,我对阿里云的服务还是比较满意的,暂时不想换
3.好吧被你说中了,其实我真的只是自己闲着没事干想吓折腾下而已==!
bdbai 8
bdbai 2016-01-10 16:59:37 +08:00 via iPhone
@abelyao 多谢指点。下面给一个 API 文档供其他同学参考:
https://www.dnspod.cn/docs/records.html#dns
abelyao 9
abelyao 2016-01-10 18:40:32 +08:00 ❤️ 1
@miaol @bdbai 两位客气啦 🙂
虽然都是折腾,可能目的也不一样,所以一起学习嘛。
我当初是为了直接刷了 OpenWrt 的路由器能直接动态解析域名,又不想在路由器上装过于复杂的插件,所以找到了这个方法,路由器是 24 小时开机的,这样就算每天电信给我换 IP 我也不需要第二台设备就可以随时 DDNS 啦。
bdbai 10
bdbai 2016-01-10 18:47:22 +08:00 via iPhone
@abelyao 没有别人指点的折腾,走了弯路自己都不知道?

Slienc7 11
Slienc7 2016-01-10 19:02:28 +08:00
花生壳更新不及时是路由器的问题,不是花生壳的问题。

花生壳也有 API 。
miaol 12
miaol 2016-01-10 19:34:52 +08:00
@xgowex 我觉得应该也是,但是路由器只能填花生壳账号信息,没办法对更新频率做设置。好吧,是我误会花生壳了,他是个好同志==!
wuhanpizi 13
wuhanpizi 2016-01-10 21:40:17 +08:00
@miaol 不需要转到 dnspod~~直接使用他们的解析就 ok ~~解析服务器改成他们的即可
miaol 14
miaol 2016-01-10 23:18:50 +08:00
@wuhanpizi 果然是这样啊,只能怪我之前了解的太少了,但是我这个都已经弄好了懒得再换了,不过又学到了一种新的实现方法也挺好的,非常感谢!
maskerTUI 15
maskerTUI 2016-01-10 23:27:37 +08:00 via Android
看到前面我就想起 tunnel 了
clanned 16
clanned 2016-01-11 00:15:11 +08:00 via Android
Dnspod 或者 cloudxns 可以参考我这里的脚本 https://github.com/xdtianyu/scripts/tree/master/ddns ,我在 ddwrt 和 openwrt 上用了很久了。 https://www.xdty.org/?s=Ddns
lesliejiang 17
lesliejiang 2016-12-26 23:08:13 +08:00
@abcbit 好想知道具体怎样做的。被动态 IP 搞死~
Terenc3 18
Terenc3 2017-02-08 13:52:49 +08:00
我的动态域名也放在阿里云,其他域名都在 DNSPOD ,主要是阿里云年付 40 块就可以买到 TTL 1 秒的付费服务!!!!

1 秒,什么概念! 不过我一般用 30 秒,因为 1 秒太夸张了,基本上每次访问都要去获取 DNS 。另外阿里云 DNS 同步速度挺快的,家里用 PPPoE ,然后使用 python 写了个脚本调用 API ,再使用 crontab 设一个任务每分钟获取。

用了半年,非常平稳。

请原谅我再一次地推销我的文章:
通过 python 将阿里云 DNS 解析作为 DDNS 使用 >> 文章短链接 >> https://c4.hk/2l
Alliot 19
Alliot 2017-04-10 11:33:43 +08:00
呼,过了几个路由,感觉还是得用内网穿透了
ferock 20
ferock 2017-05-31 14:24:37 +08:00
@abelyao 已测,可用
jethroso 21
jethroso 2017-11-16 12:51:51 +08:00
@abelyao 请教“ domain_id=域名编号&record_id=记录编号”怎么填写?谢谢!
snowice123 22
snowice123 2018-04-19 22:16:53 +08:00
@abelyao 你好,可以回复一下我吗,大哥,我现在急需弄一个阿里云动态 DNS,用做厂里的 * 连接,你这招是怎么弄的啊,谢谢,你能留一下 QQ 吗,
snowice123 23
snowice123 2018-04-19 22:19:19 +08:00
@miaol 大哥,我现在急需一个你这样的阿里云 DNS ——因为现在用的是花生壳的 DDNS,不稳定,能教一下吗。1.2 步可以看懂,到第三步我就看不懂了,我没编程基础,能教下小白吗,谢谢

全局获取Context技巧

前言:

Android提供了一个Application类,每当应用程序启动的时候,系统就会自动将这个类进行初始化,而我们可以定制一个自己的Application类,以便管理程序内的一些全局状态信息,比如说全局Context。

在android开发中,很多地方都要用到Context上下文这个类对象,比如:弹出 Toast

的时候需要、启动活动的时候需要、发送广播的时候需要、操作数据库的时候需要、使用通

知的时候需要等。

如果是在Activity中,那么获取这个context对象很容易,因为Activity本身就继承Context,直接受用this就可以了。

但是对于比较复杂的逻辑,这些代码没有放在Activity中,那么,获取Context就显得不是那么容易了。

这里告诉大家一个技巧:

Android 提供了一个 Application 类,每当应用程序启动的时候,系统就会自动将这个类

进行初始化。 而我们可以定制一个自己的 Application 类, 以便于管理程序内一些全局的状态信息,比如说全局 Context。

1,新建一个类MyApplication继承Application.

代码如下:

package com.example.networktest;
public class MyApplication extends Application {
private static Context context;
@Override
public void onCreate() {
context = getApplicationContext();
}
public static Context getContext() {
return context;
}
}

2,在 AndroidManifest.xml 文件的<application>标签下进行指定就可以了,代码如下所示:

<manifest xmlns:android=”http://schemas.android.com/apk/res/android”
package=”com.example.networktest”
android:versionCode=”1″
android:versionName=”1.0″ >
……
<application
android:name=”com.example.networktest.MyApplication”
…… >
……
</application>
</manifest>

注意:指定 MyApplication 的时候一定要加上完整的包名,不然系统将无法找到这

个类。

这样我们就已经实现了一种全局获取 Context的机制,之后不管你想在项目的任何地方

使用 Context,只需要调用一下 MyApplication.getContext()就可以了。

实现步骤:
1.自定义一个类继承Applicatioon类
public class MyApplication extends Application {

private static Context mContext;

@Override
public void onCreate() {
super.onCreate();
//获取context
mContext = getApplicationContext();
}
//创建一个静态的方法,以便获取context对象
public static Context getContext(){
return mContext;
}
}

2.在Manifest添加一句语句:原因上面说过了
<application
//注意是完整的路劲,我这个是因为前面有一句:package=”com.example.getcontexttest”
android:name=”.util.MyApplication”
…………
</application>

3.自定义一个类,创建一个静态方法,用于验证:
public class GetContext {

public static void toastNews(){

Context context = MyApplication.getContext();
Toast.makeText(context, “hello world”, Toast.LENGTH_SHORT).show();

}
}

*后调用这个方法:
public class MainActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

GetContext.toastNews();
}
}

高防服务器哪里好

大品牌商例如阿里云神马的太坑爹了就不考虑了

试过镇江,宿迁,台州的机器,单线电信

试过群英的,试过安徽的,佛山的也试过几个段子,福州 27 的段子也试过

绍兴的部分也试过,嘉兴的部分也试过。

网络质量都不太行啊,能双线三线*好。

来几位 IDC 大神推荐些高防的服务器,主要是做网站用。

配置无所谓,防御能秒解就行

价格 1500 以下

IDC 大神快来吧,小生天天测试服务器已经身心疲惫了。

abel163 1
abel163 2017-03-14 16:00:19 +08:00
福州双线的还行吧
lsido 2
lsido 2017-03-14 19:45:35 +08:00 via Android
@abel163 哪里有卖呢
stevenkang 3
stevenkang 2017-03-15 13:45:34 +08:00
安利一个 ssf.cc
集群 500G 单 100G ,¥ 150/月,八核 /2G/10M/120G
lsido 4
lsido 2017-03-16 07:56:44 +08:00 via Android
@stevenkang 四五互联?这家机器试过了,都是虚的
wtf8888 5
wtf8888 2017-03-19 00:18:45 +08:00
@lsido 一定要国内的?
lsido 6
lsido 2017-03-19 10:50:36 +08:00 via Android
@wtf8888 国外网络更差了
wangzhangwei 7
wangzhangwei 2017-03-19 22:45:25 +08:00
1500 以下租不到合适的哦,我记得以前在广东找灾备机房,光租台机器也得 1500 元 /月,防几十个 G 的双线机房 4 , 5000 左右 /月。建议你就用个阿里云、腾讯云之类的,再找个外地的 IDC 朋友提前说好,一旦有攻击就转移到外地去,等风头过了再转到云上,按天也交不了几个钱的。纯属个人建议。
lsido 8
lsido 2017-03-23 05:49:44 +08:00
@wangzhangwei 好吧…以前可能是一直用云库把网站访问忽略了,转移到机器上,网站访问快多了
duola 9
duola 2017-03-25 20:59:02 +08:00
@ 不知道你试过这个没有,他们号称打不挂, www.kk30.com
lsido 10
lsido 2017-03-27 02:31:40 +08:00 via Android
@duola 快快网络,他自家的还行就是太贵,其他机房都是代售的辣鸡

cuqk 11
cuqk 2018-12-01 21:39:56 +08:00 via Android
请问楼主后来用了哪家服务?
zoenreo 12
zoenreo 2018-12-20 23:23:12 +08:00
徐州高防,妥妥的,联系我就行,可以先测试,QQ:872283896

安卓手机里出现无法删除的 0B 文件怎么办?

如图:

9 条回复    2021-02-09 17:16:10 +08:00

tiny1994095
    2

tiny1994095   57 天前 via Android

使用不同的文件管理器删除,例如谷歌文件*客,我也出现过。
learningman
    3

learningman   57 天前

试试 chattr -i ?
calloc
    4

calloc   57 天前

下个终端模拟器执行 rm 命令删除
Dox
    5

Dox   57 天前 via iPad

@calloc 请问是手机还是电脑的终端模拟器?具体要怎么操作呢?
calloc
    6

calloc   57 天前   ❤️ 1

@Dox 安装手机版终端模拟器并打开,执行`find /sdcard -name ‘APKPure_ v3.17.16_apkpure.com.apk’`找到该文件所在的目录,在终端模拟器中 cd 到该目录,执行`rm APKPure_ v3.17.16_apkpure.com.apk`
liqingcan
    7

liqingcan   57 天前

这种情况放以前,由于强迫症和洁癖,我会想尽一些办法把这个文件删掉,甚至于回复出厂设置和刷机。
现在:又不占地方,随他去吧,反正又看不到。
Lemeng
    8

Lemeng   57 天前

我的处理方式是删不掉,就懒得管他了
gablic
    9

gablic   56 天前

建议双清

LSI 的 raid 卡都不支持 Non-RAID 吗?

之前一直用 Dell 的服务器,Dell 的 13 代服务器的 raid 卡都支持 Non-RAID,就是可以单独把一些硬盘设置成 Non-RAID,操作系统就可以直接识别到硬盘。
今天跟另外一个服务器提供商聊了一下,他们的 RAID 卡都是用的 LSI 的,说是 LSI 的卡全都不支持,感觉很诧异。不知道有没有使用了解的朋友
第 1 条附言  ·  2017-08-22 12:45:22 +08:00

原来 Dell 的 raid 卡在非 Dell 的服务器上也可以用,这样就好办了,RAID 卡直接用买 Dell h730P
mhycy 2017-08-21 20:14:10 +08:00
老卡都是 IR,IT 模式分开的,只有新卡 LSI 93XX 系列开始才支持混合阵列,记忆中是这样
lydasia 2
lydasia 2017-08-21 20:14:19 +08:00
9201-16i 路过,在 FreeNAS 中服役。。刷 it 固件就行。
lydasia 3
lydasia 2017-08-21 20:16:18 +08:00
单独的话老卡应该都不支持,一楼可能说得对的。不过我已经彻底放弃硬件 RAID 了。
hncqp 4
hncqp 2017-08-21 21:01:34 +08:00
jbod 也是可以的,要么就刷 it 模式了
ovear 5
ovear 2017-08-21 21:01:49 +08:00
有直通卡
一个硬盘你直接打 raid0 呗。。
yanest 6
yanest 2017-08-22 07:02:48 +08:00 via iPhone
@lydasia 直通卡我知道,只是用了直通卡系统盘就没法做 raid1 了,总有些担心。
yanest 7
yanest 2017-08-22 07:04:40 +08:00 via iPhone
@ovear raid0 貌似没办法获取到硬盘的信息,和故障后直接替换
yanest 8
yanest 2017-08-22 07:36:29 +08:00 via iPhone
@mhycy 混合模式在 lsi 的卡上怎么称呼,我只知道 Dell 叫 nonraid,查了 lsi 的 pdf 貌似没有这个说法
yanest 9
yanest 2017-08-22 07:38:10 +08:00 via iPhone
@hncqp jbod 是混合的吗?既有 raid 又有直通?
lydasia 10
lydasia 2017-08-22 08:04:15 +08:00
@yanest 我系统盘是 zfs mirror 的。

lydasia 11
lydasia 2017-08-22 08:09:42 +08:00
http://www.xasun.com/article/e1/2105.html
http://we.poppur.com/thread-2138497-1-1.html

好像是叫 IT/IR 混合?
wxlg1117 12
wxlg1117 2017-08-22 08:57:24 +08:00 via Android
低端是 HBA 卡,有 ir 模式支持不需要 xor 的 raid 模式比如 0-1-10…之类,高端硬 RAID 卡,必须组 raid 吧
mhycy 13
mhycy 2017-08-22 09:01:17 +08:00
@yanest 我还没用过 LSI 原版 93XX 系列的卡。。抱歉了
mhycy 14
mhycy 2017-08-22 09:01:39 +08:00
@wxlg1117 楼主问的不是这个事
fcka 15
fcka 2017-08-22 09:21:43 +08:00 via Android
十二楼正解。便宜的支持,贵的不支持。
hncqp 16
hncqp 2017-08-22 10:37:44 +08:00
@yanest jobd 即直通与 raid 互不干扰(可以选择将 hdd 设置为 jobd 模式或者 raid 模式),当然不是所有卡都有 jobd 模式
yanest 17
yanest 2017-08-22 11:58:48 +08:00 via iPhone
@hncqp 我发现 lsi 原厂卡真是无语,9361 带缓存和 bbu 却不支持 jbod,9341 支持 jbod 不支持缓存。
Dell 同是 3108 主控芯片的 h730 都支持
hncqp 18
hncqp 2017-08-22 16:34:43 +08:00
@yanest 估计刷固件可以解决,没刷过 93 系列的,还在用 92 的

Python 发送短信

Python 发送短信
短信发送平台
在发送短信前需要添加两个配置文件,将下面两个文件复制下来即可
xmltojson.py

“`# -*- coding: utf-8 -*-
# python xml.etree.ElementTree

import xml.etree.ElementTree as ET

# from xml.dom import minidom

class xmltojson:
# global var
# show log
SHOW_LOG = True
# XML file
XML_PATH = None
a = {}
m = []

def get_root(self, path):
”’parse the XML file,and get the tree of the XML file
finally,return the root element of the tree.
if the XML file dose not exist,then print the information”’
# if os.path.exists(path):
# if SHOW_LOG:
# print(‘start to parse the file : [{}]’.format(path))
tree = ET.fromstring(path)
return tree
# else:
# print(‘the path [{}] dose not exist!’.format(path))

def get_element_tag(self, element):
”’return the element tag if the element is not None.”’
if element is not None:

return element.tag
else:
print(‘the element is None!’)

def get_element_attrib(self, element):
”’return the element attrib if the element is not None.”’
if element is not None:

return element.attrib
else:
print(‘the element is None!’)

def get_element_text(self, element):
”’return the text of the element.”’
if element is not None:
return element.text
else:
print(‘the element is None!’)

def get_element_children(self, element):
”’return the element children if the element is not None.”’
if element is not None:

return [c for c in element]
else:
print(‘the element is None!’)

def get_elements_tag(self, elements):
”’return the list of tags of element’s tag”’
if elements is not None:
tags = []
for e in elements:
tags.append(e.tag)
return tags
else:
print(‘the elements is None!’)

def get_elements_attrib(self, elements):
”’return the list of attribs of element’s attrib”’
if elements is not None:
attribs = []
for a in elements:
attribs.append(a.attrib)
return attribs
else:
print(‘the elements is None!’)

def get_elements_text(self, elements):
”’return the dict of element”’
if elements is not None:
text = []
for t in elements:
text.append(t.text)
return dict(zip(self.get_elements_tag(elements), text))
else:
print(‘the elements is None!’)

def main(self, xml):
# root
root = self.get_root(xml)

# children
children = self.get_element_children(root)

children_tags = self.get_elements_tag(children)

children_attribs = self.get_elements_attrib(children)

i = 0

# 获取二级元素的每一个子节点的名称和值
for c in children:
p = 0
c_children = self.get_element_children(c)
dict_text = self.get_elements_text(c_children)
if dict_text:
# print (children_tags[i])
if children_tags[i] == ‘TemplateSMS’:
self.a[‘templateSMS’] = dict_text
else:
if children_tags[i] == ‘SubAccount’:
k = 0

for x in children:
if children_tags[k] == ‘totalCount’:
self.m.append(dict_text)
self.a[‘SubAccount’] = self.m
p = 1
k = k + 1
if p == 0:
self.a[children_tags[i]] = dict_text
else:
self.a[children_tags[i]] = dict_text

else:
self.a[children_tags[i]] = c.text
i = i + 1
return self.a

def main2(self, xml):
# root
root = self.get_root(xml)

# children
children = self.get_element_children(root)

children_tags = self.get_elements_tag(children)

children_attribs = self.get_elements_attrib(children)

i = 0

# 获取二级元素的每一个子节点的名称和值
for c in children:
p = 0
c_children = self.get_element_children(c)
dict_text = self.get_elements_text(c_children)
if dict_text:
if children_tags[i] == ‘TemplateSMS’:
k = 0

for x in children:
if children_tags[k] == ‘totalCount’:
self.m.append(dict_text)
self.a[‘TemplateSMS’] = self.m
p = 1
k = k + 1
if p == 0:
self.a[children_tags[i]] = dict_text
else:
self.a[children_tags[i]] = dict_text

else:
self.a[children_tags[i]] = c.text
i = i + 1
return self.a

CCPRestSDK.py

# -*- 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.

import base64
import datetime
import json
from hashlib import md5
from urllib import request as urllib2

from .xmltojson import xmltojson

class REST:
AccountSid = ”
AccountToken = ”
AppId = ”
SubAccountSid = ”
SubAccountToken = ”
ServerIP = ”
ServerPort = ”
SoftVersion = ”
Iflog = False # 是否打印日志
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(‘这是请求包体:’)
print(body)
print(‘这是响应包体:’)
print(data)
print(‘********************************’)

# 创建子账号
# @param friendlyName 必选参数 子帐号名称
def CreateSubAccount(self, friendlyName):

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 + “/SubAccounts?sig=” + sig
# 生成auth
src = self.AccountSid + “:” + self.Batch
auth = base64.encodebytes(src.encode()).decode().strip()
req = urllib2.Request(url)
self.setHttpHeader(req)
req.add_header(“Authorization”, auth)
# xml格式
body = ”'<?xml version=”1.0″ encoding=”utf-8″?><SubAccount><appId>%s</appId>\
<friendlyName>%s</friendlyName>\
</SubAccount>\
”’ % (self.AppId, friendlyName)

if self.BodyType == ‘json’:
# json格式
body = ”'{“friendlyName”: “%s”, “appId”: “%s”}”’ % (friendlyName, self.AppId)
data = ”
req.data = body.encode()
try:
res = urllib2.urlopen(req)
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 locations
except Exception as error:
if self.Iflog:
self.log(url, body, data)
return {‘172001’: ‘网络错误’}

# 获取子帐号
# @param startNo 可选参数 开始的序号,默认从0开始
# @param offset 可选参数 一次查询的*大条数,*小是1条,*大是100条
def getSubAccounts(self, startNo, offset):

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 + “/GetSubAccounts?sig=” + sig
# 生成auth
src = self.AccountSid + “:” + self.Batch
# auth = base64.encodestring(src).strip()
auth = base64.encodebytes(src.encode()).decode().strip()
req = urllib2.Request(url)
self.setHttpHeader(req)
req.add_header(“Authorization”, auth)
# xml格式
body = ”'<?xml version=”1.0″ encoding=”utf-8″?><SubAccount><appId>%s</appId>\
<startNo>%s</startNo><offset>%s</offset>\
</SubAccount>\
”’ % (self.AppId, startNo, offset)

if self.BodyType == ‘json’:
# json格式
body = ”'{“appId”: “%s”, “startNo”: “%s”, “offset”: “%s”}”’ % (self.AppId, startNo, offset)
data = ”
req.data = body.encode()
try:
res = urllib2.urlopen(req)
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 locations
except Exception as error:
if self.Iflog:
self.log(url, body, data)
return {‘172001’: ‘网络错误’}

# 子帐号信息查询
# @param friendlyName 必选参数 子帐号名称

def querySubAccount(self, friendlyName):

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 + “/QuerySubAccountByName?sig=” + sig
# 生成auth
src = self.AccountSid + “:” + self.Batch
# auth = base64.encodestring(src).strip()
auth = base64.encodebytes(src.encode()).decode().strip()
req = urllib2.Request(url)
self.setHttpHeader(req)

req.add_header(“Authorization”, auth)

# 创建包体
body = ”'<?xml version=”1.0″ encoding=”utf-8″?><SubAccount><appId>%s</appId>\
<friendlyName>%s</friendlyName>\
</SubAccount>\
”’ % (self.AppId, friendlyName)
if self.BodyType == ‘json’:
body = ”'{“friendlyName”: “%s”, “appId”: “%s”}”’ % (friendlyName, self.AppId)
data = ”
req.data = body.encode()
try:
res = urllib2.urlopen(req)
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 locations
except Exception as error:
if self.Iflog:
self.log(url, body, data)
return {‘172001’: ‘网络错误’}

# 发送模板短信
# @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).strip()
auth = base64.encodebytes(src.encode()).decode().strip()
req = urllib2.Request(url)
self.setHttpHeader(req)
req.add_header(“Authorization”, auth)
# 创建包体
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.encode()
data = ”
try:
res = urllib2.urlopen(req)
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 locations
except Exception as error:
if self.Iflog:
self.log(url, body, data)
return {‘172001’: ‘网络错误’}

# 外呼通知
# @param to 必选参数 被叫号码
# @param mediaName 可选参数 语音文件名称,格式 wav。与mediaTxt不能同时为空。当不为空时mediaTxt属性失效。
# @param mediaTxt 可选参数 文本内容
# @param displayNum 可选参数 显示的主叫号码
# @param playTimes 可选参数 循环播放次数,1-3次,默认播放1次。
# @param respUrl 可选参数 外呼通知状态通知回调地址,云通讯平台将向该Url地址发送呼叫结果通知。
# @param userData 可选参数 用户私有数据
# @param maxCallTime 可选参数 *大通话时长
# @param speed 可选参数 发音速度
# @param volume 可选参数 音量
# @param pitch 可选参数 音调
# @param bgsound 可选参数 背景音编号

def landingCall(self, to, mediaName, mediaTxt, displayNum, playTimes, respUrl, userData, maxCallTime, speed, volume,
pitch, bgsound):

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 + “/Calls/LandingCalls?sig=” + sig
# 生成auth
src = self.AccountSid + “:” + self.Batch
# auth = base64.encodestring(src).strip()
auth = base64.encodebytes(src.encode()).decode().strip()
req = urllib2.Request(url)
self.setHttpHeader(req)
req.add_header(“Authorization”, auth)

# 创建包体
body = ”'<?xml version=”1.0″ encoding=”utf-8″?><LandingCall>\
<to>%s</to><mediaName>%s</mediaName><mediaTxt>%s</mediaTxt><appId>%s</appId><displayNum>%s</displayNum>\
<playTimes>%s</playTimes><respUrl>%s</respUrl><userData>%s</userData><maxCallTime>%s</maxCallTime><speed>%s</speed>
<volume>%s</volume><pitch>%s</pitch><bgsound>%s</bgsound></LandingCall>\
”’ % (
to, mediaName, mediaTxt, self.AppId, displayNum, playTimes, respUrl, userData, maxCallTime, speed, volume,
pitch, bgsound)
if self.BodyType == ‘json’:
body = ”'{“to”: “%s”, “mediaName”: “%s”,”mediaTxt”: “%s”,”appId”: “%s”,”displayNum”: “%s”,”playTimes”: “%s”,”respUrl”: “%s”,”userData”: “%s”,”maxCallTime”: “%s”,”speed”: “%s”,”volume”: “%s”,”pitch”: “%s”,”bgsound”: “%s”}”’ % (
to, mediaName, mediaTxt, self.AppId, displayNum, playTimes, respUrl, userData, maxCallTime, speed,
volume,
pitch, bgsound)
req.data = body.encode()
data = ”
try:
res = urllib2.urlopen(req)
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 locations
except Exception as error:
if self.Iflog:
self.log(url, body, data)
return {‘172001’: ‘网络错误’}

# 语音验证码
# @param verifyCode 必选参数 验证码内容,为数字和英文字母,不区分大小写,长度4-8位
# @param playTimes 可选参数 播放次数,1-3次
# @param to 必选参数 接收号码
# @param displayNum 可选参数 显示的主叫号码
# @param respUrl 可选参数 语音验证码状态通知回调地址,云通讯平台将向该Url地址发送呼叫结果通知
# @param lang 可选参数 语言类型
# @param userData 可选参数 第三方私有数据

def voiceVerify(self, verifyCode, playTimes, to, displayNum, respUrl, lang, userData):

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 + “/Calls/VoiceVerify?sig=” + sig
# 生成auth
src = self.AccountSid + “:” + self.Batch
# auth = base64.encodestring(src).strip()
auth = base64.encodebytes(src.encode()).decode().strip()
req = urllib2.Request(url)
self.setHttpHeader(req)

req.add_header(“Authorization”, auth)

# 创建包体
body = ”'<?xml version=”1.0″ encoding=”utf-8″?><VoiceVerify>\
<appId>%s</appId><verifyCode>%s</verifyCode><playTimes>%s</playTimes><to>%s</to><respUrl>%s</respUrl>\
<displayNum>%s</displayNum><lang>%s</lang><userData>%s</userData></VoiceVerify>\
”’ % (self.AppId, verifyCode, playTimes, to, respUrl, displayNum, lang, userData)
if self.BodyType == ‘json’:
# if this model is Json ..then do next code
body = ”'{“appId”: “%s”, “verifyCode”: “%s”,”playTimes”: “%s”,”to”: “%s”,”respUrl”: “%s”,”displayNum”: “%s”,”lang”: “%s”,”userData”: “%s”}”’ % (
self.AppId, verifyCode, playTimes, to, respUrl, displayNum, lang, userData)
req.data = body.encode()
data = ”
try:
res = urllib2.urlopen(req)
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 locations
except Exception as error:
if self.Iflog:
self.log(url, body, data)
return {‘172001’: ‘网络错误’}

# IVR外呼
# @param number 必选参数 待呼叫号码,为Dial节点的属性
# @param userdata 可选参数 用户数据,在<startservice>通知中返回,只允许填写数字字符,为Dial节点的属性
# @param record 可选参数 是否录音,可填项为true和false,默认值为false不录音,为Dial节点的属性

def ivrDial(self, number, userdata, record):

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 + “/ivr/dial?sig=” + sig
# 生成auth
src = self.AccountSid + “:” + self.Batch
auth = base64.encodebytes(src.encode()).decode().strip()
req = urllib2.Request(url)
req.add_header(“Accept”, “application/xml”)
req.add_header(“Content-Type”, “application/xml;charset=utf-8”)
req.add_header(“Authorization”, auth)

# 创建包体
body = ”'<?xml version=”1.0″ encoding=”utf-8″?>
<Request>
<Appid>%s</Appid>
<Dial number=”%s” userdata=”%s” record=”%s”></Dial>
</Request>
”’ % (self.AppId, number, userdata, record)
req.data = body.encode()
data = ”
try:
res = urllib2.urlopen(req)
data = res.read()
res.close()
xtj = xmltojson()
locations = xtj.main(data)
if self.Iflog:
self.log(url, body, data)
return locations
except Exception as error:
if self.Iflog:
self.log(url, body, data)
return {‘172001’: ‘网络错误’}

# 话单下载
# @param date 必选参数 day 代表前一天的数据(从00:00 – 23:59),目前只支持按天查询
# @param keywords 可选参数 客户的查询条件,由客户自行定义并提供给云通讯平台。默认不填忽略此参数
def billRecords(self, date, keywords):

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 + “/BillRecords?sig=” + sig
# 生成auth
src = self.AccountSid + “:” + self.Batch
auth = base64.encodebytes(src.encode()).decode().strip()
req = urllib2.Request(url)
self.setHttpHeader(req)
req.add_header(“Authorization”, auth)

# 创建包体
body = ”'<?xml version=”1.0″ encoding=”utf-8″?><BillRecords>\
<appId>%s</appId><date>%s</date><keywords>%s</keywords>\
</BillRecords>\
”’ % (self.AppId, date, keywords)
if self.BodyType == ‘json’:
# if this model is Json ..then do next code
body = ”'{“appId”: “%s”, “date”: “%s”,”keywords”: “%s”}”’ % (self.AppId, date, keywords)
req.data = body.encode()
data = ”
try:
res = urllib2.urlopen(req)
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 locations
except Exception as error:
if self.Iflog:
self.log(url, body, data)
return {‘172001’: ‘网络错误’}

# 主帐号信息查询

def queryAccountInfo(self):

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 + “/AccountInfo?sig=” + sig
# 生成auth
src = self.AccountSid + “:” + self.Batch
auth = base64.encodebytes(src.encode()).decode().strip()
req = urllib2.Request(url)
self.setHttpHeader(req)
body = ”
req.add_header(“Authorization”, auth)
data = ”
try:
res = urllib2.urlopen(req)
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 locations
except Exception as error:
if self.Iflog:
self.log(url, body, data)
return {‘172001’: ‘网络错误’}

# 短信模板查询
# @param templateId 必选参数 模板Id,不带此参数查询全部可用模板

def QuerySMSTemplate(self, templateId):

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/QuerySMSTemplate?sig=” + sig
# 生成auth
src = self.AccountSid + “:” + self.Batch
auth = base64.encodebytes(src.encode()).decode().strip()
req = urllib2.Request(url)
self.setHttpHeader(req)

req.add_header(“Authorization”, auth)

# 创建包体
body = ”'<?xml version=”1.0″ encoding=”utf-8″?><Request>\
<appId>%s</appId><templateId>%s</templateId></Request>
”’ % (self.AppId, templateId)
if self.BodyType == ‘json’:
# if this model is Json ..then do next code
body = ”'{“appId”: “%s”, “templateId”: “%s”}”’ % (self.AppId, templateId)
req.data = body.encode()
data = ”
try:
res = urllib2.urlopen(req)
data = res.read()
res.close()

if self.BodyType == ‘json’:
# json格式
locations = json.loads(data)
else:
# xml格式
xtj = xmltojson()
locations = xtj.main2(data)
if self.Iflog:
self.log(url, body, data)
return locations
except Exception as error:
if self.Iflog:
self.log(url, body, data)
return {‘172001’: ‘网络错误’}

# 呼叫结果查询
# @param callsid 必选参数 呼叫ID

def CallResult(self, callSid):

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 + “/CallResult?sig=” + sig + “&callsid=” + callSid
# 生成auth
src = self.AccountSid + “:” + self.Batch
auth = base64.encodebytes(src.encode()).decode().strip()
req = urllib2.Request(url)
self.setHttpHeader(req)
body = ”
req.add_header(“Authorization”, auth)
data = ”
try:
res = urllib2.urlopen(req)
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 locations
except Exception as error:
if self.Iflog:
self.log(url, body, data)
return {‘172001’: ‘网络错误’}

# 呼叫状态查询
# @param callid 必选参数 一个由32个字符组成的电话唯一标识符
# @param action 可选参数 查询结果通知的回调url地址
def QueryCallState(self, callid, action):

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 + “/ivr/call?sig=” + sig + “&callid=” + callid
# 生成auth
src = self.AccountSid + “:” + self.Batch
auth = base64.encodebytes(src.encode()).decode().strip()
req = urllib2.Request(url)
self.setHttpHeader(req)
req.add_header(“Authorization”, auth)

# 创建包体
body = ”'<?xml version=”1.0″ encoding=”utf-8″?><Request>\
<Appid>%s</Appid><QueryCallState callid=”%s” action=”%s”/>\
</Request>\
”’ % (self.AppId, callid, action)
if self.BodyType == ‘json’:
# if this model is Json ..then do next code
body = ”'{“Appid”:”%s”,”QueryCallState”:{“callid”:”%s”,”action”:”%s”}}”’ % (self.AppId, callid, action)
req.data = body.encode()
data = ”
try:
res = urllib2.urlopen(req)
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 locations
except Exception as error:
if self.Iflog:
self.log(url, body, data)
return {‘172001’: ‘网络错误’}

# 语音文件上传
# @param filename 必选参数 文件名
# @param body 必选参数 二进制串
def MediaFileUpload(self, filename, body):

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 + “/Calls/MediaFileUpload?sig=” + sig + “&appid=” + self.AppId + “&filename=” + filename
# 生成auth
src = self.AccountSid + “:” + self.Batch
auth = base64.encodebytes(src.encode()).decode().strip()
req = urllib2.Request(url)
req.add_header(“Authorization”, auth)
if self.BodyType == ‘json’:
req.add_header(“Accept”, “application/json”)
req.add_header(“Content-Type”, “application/octet-stream”)

else:
req.add_header(“Accept”, “application/xml”)
req.add_header(“Content-Type”, “application/octet-stream”)

# 创建包体
req.data = body.encode()

try:
res = urllib2.urlopen(req)
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 locations
except Exception as error:
if self.Iflog:
self.log(url, body, data)
return {‘172001’: ‘网络错误’}

# 子帐号鉴权
def subAuth(self):
if (self.ServerIP == “”):
print(‘172004’)
print(‘IP为空’)

if (int(self.ServerPort) <= 0):
print(‘172005’)
print(‘端口错误(小于等于0)’)

if (self.SoftVersion == “”):
print(‘172013’)
print(‘版本号为空’)

if (self.SubAccountSid == “”):
print(‘172008’)
print(‘子帐号为空’)

if (self.SubAccountToken == “”):
print(‘172009’)
print(‘子帐号令牌为空’)

if (self.AppId == “”):
print(‘172012’)
print(‘应用ID为空’)

# 主帐号鉴权
def accAuth(self):
if (self.ServerIP == “”):
print(‘172004’)
print(‘IP为空’)

if (int(self.ServerPort) <= 0):
print(‘172005’)
print(‘端口错误(小于等于0)’)

if (self.SoftVersion == “”):
print(‘172013’)
print(‘版本号为空’)

if (self.AccountSid == “”):
print(‘172006’)
print(‘主帐号为空’)

if (self.AccountToken == “”):
print(‘172007’)
print(‘主帐号令牌为空’)

if (self.AppId == “”):
print(‘172012’)
print(‘应用ID为空’)

# 设置包头
def setHttpHeader(self, req):
if self.BodyType == ‘json’:
req.add_header(“Accept”, “application/json”)
req.add_header(“Content-Type”, “application/json;charset=utf-8”)

else:
req.add_header(“Accept”, “application/xml”)
req.add_header(“Content-Type”, “application/xml;charset=utf-8”)

下面就是我们要发送短信需要配置的内容,内容在短信发送平台

# -*- coding:utf-8 -*-

# from .CCPRestSDK import REST
from libs.yuntongxun.CCPRestSDK import REST

# 说明:主账号,登陆云通讯网站后,可在”控制台-应用”中看到开发者主账号ACCOUNT SID
_accountSid = ‘8a216da8***************636c9’

# 说明:主账号Token,登陆云通讯网站后,可在控制台-应用中看到开发者主账号AUTH TOKEN
_accountToken = ‘a064092********************8c2’

# 请使用管理控制台首页的APPID或自己创建应用的APPID
_appId = ‘8a216d***************536cf’

# 说明:请求地址,生产环境配置成app.cloopen.com
_serverIP = ‘app.cloopen.com’

# 说明:请求端口 ,生产环境为8883
_serverPort = “8883”

# 说明:REST API版本号保持不变
_softVersion = ‘2013-12-26′

# 云通讯官方提供的发送短信代码实例
# # 发送模板短信
# # @param to 手机号码
# # @param datas 内容数据 格式为数组 例如:{’12’,’34’},如不需替换请填 ”
# # @param $tempId 模板Id
#
# 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 __new__(cls, *args, **kwargs):
# 判断是否存在类属性_instance,_instance是类CCP的唯一对象,即单例
if not hasattr(CCP, “_instance”):
cls._instance = super(CCP, cls).__new__(cls, *args, **kwargs)
cls._instance.rest = REST(_serverIP, _serverPort, _softVersion)
cls._instance.rest.setAccount(_accountSid, _accountToken)
cls._instance.rest.setAppId(_appId)
return cls._instance

def send_template_sms(self, to, datas, temp_id):
“””发送模板短信”””
# @param to 手机号码
# @param datas 内容数据 格式为数组 例如:{’12’,’34’},如不需替换请填 ”
# @param temp_id 模板Id
result = self.rest.sendTemplateSMS(to, datas, temp_id)
# 如果云通讯发送短信成功,返回的字典数据result中statuCode字段的值为”000000″
# if result.get(“statusCode”) == “000000”:
# # 返回0 表示发送短信成功
# return 0
# else:
# # 返回-1 表示发送失败
# return -1

if __name__ == ‘__main__’:
ccp = CCP()
# 注意: 测试的短信模板编号为1
# 参数1: 给谁发 手机号
# 参数2: 【云通讯】您使用的是云通讯短信模板,您的验证码是{1},请于{2}分钟内正确输入
# 参数3: 模板号 ,默认我们选1
from random import randint

# 随机一个六位数的随机码
sms_code = ‘%06d’ % randint(0, 999999)
print(sms_code)
ccp.send_template_sms(‘***********’, [sms_code, 5], 1)

友情链接: SITEMAP | 旋风加速器官网 | 旋风软件中心 | textarea | 黑洞加速器 | jiaohess | 老王加速器 | 烧饼哥加速器 | 小蓝鸟 | tiktok加速器 | 旋风加速度器 | 旋风加速 | quickq加速器 | 飞驰加速器 | 飞鸟加速器 | 狗急加速器 | hammer加速器 | trafficace | 原子加速器 | 葫芦加速器 | 麦旋风 | 油管加速器 | anycastly | INS加速器 | INS加速器免费版 | 免费vqn加速外网 | 旋风加速器 | 快橙加速器 | 啊哈加速器 | 迷雾通 | 优途加速器 | 海外播 | 坚果加速器 | 海外vqn加速 | 蘑菇加速器 | 毛豆加速器 | 接码平台 | 接码S | 西柚加速器 | 快柠檬加速器 | 黑洞加速 | falemon | 快橙加速器 | anycast加速器 | ibaidu | moneytreeblog | 坚果加速器 | 派币加速器 | 飞鸟加速器 | 毛豆APP | PIKPAK | 安卓vqn免费 | 一元机场加速器 | 一元机场 | 老王加速器 | 黑洞加速器 | 白石山 | 小牛加速器 | 黑洞加速 | 迷雾通官网 | 迷雾通 | 迷雾通加速器 | 十大免费加速神器 | 猎豹加速器 | 蚂蚁加速器 | 坚果加速器 | 黑洞加速 | 银河加速器 | 猎豹加速器 | 海鸥加速器 | 芒果加速器 | 小牛加速器 | 极光加速器 | 黑洞加速 | movabletype中文网 | 猎豹加速器官网 | 烧饼哥加速器官网 | 旋风加速器度器 | 哔咔漫画 | PicACG | 雷霆加速