python 实现短信验证码发送

时间:2024-03-07 13:03:51

1、短信网关model

 1 # -*- coding: utf-8 -*-
 2 from __future__ import unicode_literals
 3 
 4 from django.db import models
 5 from django.template import Context
 6 from django.template import Template as DjangoTemplate
 7 from django.utils.safestring import mark_safe
 8 from django.utils.translation import ugettext_lazy as _
 9 import json
10 import requests
11 
12 # Create your models here.
13 class SmsSendingProfile(models.Model):
14     TYPE_CHOICES = (
15         (\'common\', \'管理\'),
16         (\'phish\', \'钓鱼\')
17     )
18     """短信网关:包括以下属性(短信网关名称,网关URL,请求参数,用途)"""
19     name = models.CharField(max_length=100, verbose_name=\'名称\', help_text=\'短信网关名称,必填,最多100个字符\')
20     url = models.CharField(max_length=2083, verbose_name=\'网关URL\', help_text=\'网关URL,必填,最多2083个字符\')  # IE limit URL length to 2083
21     params = models.TextField(max_length=5000, verbose_name=\'请求参数\', help_text=\'请求参数,必填,最多5000个字符\')
22 
23     type = models.CharField(_(\'用途\'), choices=TYPE_CHOICES, max_length=15, default=\'common\', help_text=\'请选择用途\')
24 
25     def test(self, send_to, content):
26         \'\'\'
27         测试
28         :param send_to: 发送至
29         :param content: 邮件内容
30         :return: 无返回值
31         \'\'\'
32         if not send_to:
33             raise Exception(\'未指定手机号码\')
34         if content.strip() == \'\':
35             content = \'【红山瑞达】这是一条测试短信,发送自意识测评系统。退订回N\'
36         context = Context({
37             \'to\': send_to,
38             \'content\': mark_safe(content)
39         })
40 
41         resp = requests.post(self.url, data=json.loads(DjangoTemplate(self.params).render(context)))
42         if resp.json()[\'status\'] != \'success\':
43             raise Exception(\'发送测试短信失败\')
44 
45     def __unicode__(self):
46         return self.name
47 
48     class Meta:
49         verbose_name = \'短信网关\'
50         verbose_name_plural = \'短信网关\'
View Code

2、初始化短信网关数据

1     smssendingprofile1.user = user
2     smssendingprofile1.name = \'短信网关(管理)\'
3     smssendingprofile1.type = \'common\'
4     smssendingprofile1.url = \'https://api.mysubmail.com/message/send.json\'
5     smssendingprofile1.params = \'{"appid":"25524","to":"{{to}}","content":"{{content}}","signature":"7342ec5109e8e734de84730b746e4e18"}\'
6     smssendingprofile1.save()
View Code

3、发送手机验证码接口

 1 # -*- coding: utf-8 -*-
 2 from __future__ import unicode_literals
 3 
 4 from django.shortcuts import render, HttpResponse
 5 from django.template import Template as DjangoTemplate
 6 from django.template import Context
 7 from django.views.decorators.csrf import csrf_exempt
 8 from interfance.models import SmsSendingProfile
 9 from django.utils.safestring import mark_safe
10 import requests
11 import random
12 import json
13 import demjson
14 
15 
16 def index(request):
17     return  render(request, \'index.html\')
18 
19 def verification_code():
20     """
21     生成手机验证码
22     """
23     num = \'\'
24     for x in xrange(6):
25         num += str(random.randint(0, 9))
26     return num
27 
28 @csrf_exempt
29 def sms_verification(request):
30     phone = request.POST.get(\'phone\', \'\')
31     code = verification_code()
32 
33     if not phone:
34         return HttpResponse(json.dumps({\'code\': 403, \'status\': \'failed\', \'data\': \'手机号码为空\'}))
35 
36     sms_profile = SmsSendingProfile.objects.filter(type=\'common\').first()  # 短信网关对象
37     text = \'【红瑞教育培训系统】 尊敬的用户,您的验证码为:{},两分钟内有效,请勿将验证码告知他人。退订回N\'.format(code)
38     context = Context({
39         \'to\': phone,
40         \'content\': mark_safe(text)
41     })
42     print context,\'3333\'
43     resp = requests.post(sms_profile.url,data=json.loads(DjangoTemplate(sms_profile.params).render(context)))
44     #requests模块发送post请求去请求短信网关url,参数等:{"appid":"25524","to":"{{to}}","content":"{{content}}","signature":"7342ec5109e8e734de84730b746e4e18"},然后用 ontext 来传递数据给它
45     print resp.json()
46     if resp.json()[\'status\'] != \'success\':
47         return HttpResponse(json.dumps({\'code\': 403, \'status\': {\'status\': \'failed\'}}))
48 
49     return HttpResponse(json.dumps({\'code\': 200, \'status\': demjson.decode(resp.text), \'data\': code}))
View Code

4、前端获取验证码

  1 {% load static %}
  2 <!DOCTYPE html>
  3 <html lang="en">
  4 <head>
  5     <meta charset="UTF-8">
  6     <title>Title</title>
  7     <link rel="stylesheet" href="{% static \'tips/css/sweet-alert.css\' %}">
  8 
  9 </head>
 10 <body>
 11  <form action="#" method="post">
 12      {% csrf_token %}
 13      <input type="text" id="tel" name="tel" class="tel" placeholder="手机">
 14      <div class="clearfix" style="padding-top: 25px;">
 15         <input type="text" id="sms" name="sms" class="sms" placeholder="请输入验证码">
 16         <button id="send_sms">发送验证码</button>
 17      </div>
 18 </form>
 19 <script src="{% static \'tips/js/sweet-alert.min.js\' %}"></script>
 20 <script src="{% static \'js/jquery-1.8.2.min.js\' %}"></script>
 21 <script>
 22     var sms_number
 23     var duration = 120
 24     var send = 60
 25     var timer_send = null
 26     var timer_duration = null
 27     var duration_left
 28 
 29     function initCountdown(timer, count, type) {
 30         timer = setInterval(function () {
 31             if (type === \'send\') {
 32                 count--
 33 
 34                 if ($(\'#send_sms\').length) {
 35                     $(\'#send_sms\').html(\'重发(\' + count + \'秒)\')
 36                 } else if ($(\'#send_sms_forget\').length) {
 37                     $(\'#send_sms_forget\').html(\'重发(\' + count + \'秒)\')
 38                 }
 39             } else if (type === \'duration\') {
 40                 count--
 41             }
 42 
 43             if (count < 0 && type === \'send\') {
 44                 send = 60
 45                 if ($(\'#send_sms\').length) {
 46                     $(\'#send_sms\').html(\'发送验证码\')
 47                 } else if ($(\'#send_sms_forget\').length) {
 48                     $(\'#send_sms_forget\').html(\'发送验证码\')
 49                 }
 50                 clearInterval(timer)
 51             }
 52 
 53             if (count < 0 && type === \'duration\') {
 54                 duration_left = count
 55                 clearInterval(timer)
 56             }
 57         }, 1000)
 58     }
 59 
 60     $(\'#send_sms\').on(\'click\', function (e) {
 61         var event = window.event || event
 62         event.preventDefault()
 63         if ($(this).html() === \'发送验证码\') {
 64             $.ajax({
 65                 url: \'/sms_verification/\',
 66                 type: \'post\',
 67                 data: {
 68                     phone: $(\'#tel\').val()
 69                 },
 70                 dataType: \'json\',
 71                 success: function (data, status) {
 72                     if (data.status.status === \'success\') {
 73                         sms_number = data.data
 74                         duration = 120
 75                         initCountdown(timer_send, send, \'send\')
 76                         initCountdown(timer_duration, duration, \'duration\')
 77                     } else {
 78                         swal("发送失败", \'验证码发送失败,请检查个人信息的手机号是否正确\', "error");
 79                     }
 80                 }
 81             })
 82         }
 83     })
 84 
 85     $(\'#send_sms_forget\').on(\'click\', function (e) {
 86         var event = window.event || event
 87         event.preventDefault()
 88         var _this = $(this)
 89         $.ajax({
 90             url: \'/verify_user/\',
 91             type: \'post\',
 92             dataType: \'json\',
 93             data: {
 94                 phone: $(\'#tel\').val()
 95             },
 96             success: function (data, status) {
 97                 console.log(data.data == true)
 98                 if (data.data == true) {
 99                     if (_this.html() === \'发送验证码\') {
100                         $.ajax({
101                             url: \'/sms_verification/\',
102                             type: \'post\',
103                             data: {
104                                 phone: $(\'#tel\').val()
105                             },
106                             dataType: \'json\',
107                             success: function (data, status) {
108                                 if (data.status.status === \'success\') {
109                                     sms_number = data.data
110                                     duration = 120
111                                     initCountdown(timer_send, send, \'send\')
112                                     initCountdown(timer_duration, duration, \'duration\')
113                                 } else {
114                                     swal("发送失败", \'验证码发送失败,请检查个人信息的手机号是否正确\', "error");
115                                 }
116                             }
117                         })
118                     }
119                 }
120             }
121         })
122     })
123 
124 
125 
126 </script>
127 </body>
128 </html>
View Code

###########################

可直接用的函数

1、判断访问来源是pc端还是手机端

 1 def judge_pc_or_mobile(ua):
 2             """
 3             判断访问来源是pc端还是手机端
 4             :param ua: 访问来源头信息中的User-Agent字段内容
 5             :return:
 6             """
 7             factor = ua
 8             is_mobile = False
 9             _long_matches = r\'googlebot-mobile|android|avantgo|blackberry|blazer|elaine|hiptop|ip(hone|od)|kindle|midp|mmp\' \
10                             r\'|mobile|o2|opera mini|palm( os)?|pda|plucker|pocket|psp|smartphone|symbian|treo|up\.(browser|link)\' \
11                             r\'|vodafone|wap|windows ce; (iemobile|ppc)|xiino|maemo|fennec\'
12             _long_matches = re.compile(_long_matches, re.IGNORECASE)
13             _short_matches = r\'1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)\' \
14                              r\'|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)\' \
15                              r\'|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw\' \
16                              r\'|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8\' \
17                              r\'|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit\' \
18                              r\'|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)\' \
19                              r\'|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji\' \
20                              r\'|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|e\-|e\/|\-[a-w])|libw|lynx\' \
21                              r\'|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(di|rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi\' \
22                              r\'|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)\' \
23                              r\'|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg\' \
24                              r\'|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21\' \
25                              r\'|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-\' \
26                              r\'|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it\' \
27                              r\'|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)\' \
28                              r\'|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)\' \
29                              r\'|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit\' \
30                              r\'|wi(g |nc|nw)|wmlb|wonu|x700|xda(\-|2|g)|yas\-|your|zeto|zte\-\'
31 
32             _short_matches = re.compile(_short_matches, re.IGNORECASE)
33 
34             if _long_matches.search(factor):
35                 is_mobile = True
36             user_agent = factor[0:4]
37             if _short_matches.search(user_agent):
38                 is_mobile = True
39 
40             return is_mobile
View Code

2、生成手机验证码

1 def verification_code():
2             """
3             生成手机验证码
4             """
5             num = \'\'
6             for x in xrange(6):
7                 num += str(random.randint(0, 9))
8             return num
View Code

 3、验证文件大小

 1 def formatsize(byte):
 2             """
 3             验证文件大小
 4             :param byte:
 5             :return:
 6             """
 7             try:
 8                 byte = float(byte)
 9                 KB = round(byte / 1024, 2)
10             except:
11                 print("传入的字节格式不对")
12                 return "Error"
13 
14             if KB >= 1024:
15                 MB = round(KB / 1024, 2)
16                 if MB >= 1024:
17                     G = round(MB / 1024, 2)
18                     return "%sG" % (G)
19                 else:
20                     return "%sMB" % (MB)
21             else:
22                 return "%sKB" % (KB)
View Code

4、时间统计

 1 def changetime(alltime):
 2         day = 24 * 60 * 60
 3         hour = 60 * 60
 4         min = 60
 5         if alltime < 60:
 6             return "%d 秒" % math.ceil(alltime)
 7         elif alltime > day:
 8             days = divmod(alltime, day)
 9             return "%d 天 %s" % (int(days[0]), changetime(days[1]))
10         elif alltime > hour:
11             hours = divmod(alltime, hour)
12             return \'%d 小时 %s\' % (int(hours[0]), changetime(hours[1]))
13         else:
14             mins = divmod(alltime, min)
15             return "%d 分钟 %d 秒" % (int(mins[0]), math.ceil(mins[1]))
View Code

5、计算视频时长

 1 # coding: utf-8
 2         import os
 3         import datetime
 4         from moviepy.editor import VideoFileClip
 5 
 6 
 7         class FileCheck(object):
 8             def __init__(self, filename):
 9                 self.filename = filename
10 
11             def time_convert(self, size):  # 单位换算
12                 m, h = 60, 60 ** 2
13                 if size < m:
14                     return datetime.timedelta(hours=00, minutes=00, seconds=int(size))
15                 if size < h:
16                     return datetime.timedelta(hours=00, minutes=int(size / m), seconds=int(size % m))
17                 else:
18                     return datetime.timedelta(hours=int(size / h), minutes=int(size % h / m), seconds=int(size % h % m))
19 
20             def get_file_times(self):
21                 u"""
22                 获取视频时长(s:秒)
23                 """
24                 clip = VideoFileClip(self.filename)
25                 file_time = self.time_convert(clip.duration)
26                 return file_time
27 
28             def get_filesize(self):
29                 u"""
30                 获取文件大小(M: 兆)
31                 """
32                 file_byte = os.path.getsize(self.filename)
33                 return self.size_convert(file_byte)
34 
35             def size_convert(self, size):  # 单位换算
36                 K, M, G = 1024, 1024 ** 2, 1024 ** 3
37                 if size >= G:
38                     return str(size / G) + \'GB\'
39                 elif size >= M:
40                     return str(size / M) + \'MB\'
41                 elif size >= K:
42                     return str(size / K) + \'KB\'
43                 else:
44                     return str(size) + \'B\'
View Code