123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147 |
- # coding=utf-8
- import random
- from urllib import request, parse
- import re
- import math
- from django.db import models
- from django.utils import timezone
- from utils.exceptions import CustomError
- from apps.wechat.models import Wechat
- class XGJSMS:
- def __init__(self):
- self.SMS_URL = 'http://sms.zzliaoyuan.com:8088'
- self.SMS_PRODUCT_NOTIFY = 30 # 通知短信的代码
- self.success_result = {'Code': u'OK', 'Message': u'短信提交成功'}
- self.false_result = {'Code': u'FALSE', 'Message': u'短信提交失败'}
- def _do_request(self, req):
- try:
- resp = request.urlopen(req)
- except Exception as e:
- raise CustomError(u"短信平台错误")
- if resp.getcode() != 200:
- raise CustomError(u'短信平台错误')
- return resp.read()
- def send(self, sms_token, sms_sign, mobile, content):
- content = u"【%s】%s" % (sms_sign, content)
- url = '%s/balance/?token=%s' % (self.SMS_URL, sms_token)
- req = request.Request(url)
- try:
- resp = self._do_request(req)
- except CustomError as e:
- self.false_result['Message'] = e.get_error_msg()
- return self.false_result
- p = '<Product id="%s">([\d]+?)</Product>' % self.SMS_PRODUCT_NOTIFY
- r = re.search(p, resp.decode('utf-8'))
- if r == None:
- self.false_result['Message'] = u'短信平台账号余额不足'
- return self.false_result
- else:
- balance = int(r.groups()[0])
- fee_count = 1
- if len(content) > 70:
- fee_count = int(math.ceil(len(content) / 65.0))
- if balance < 1 or balance < 1 * fee_count:
- self.false_result['Message'] = u'短信平台账号余额不足'
- return self.false_result
- postDict = {'token': sms_token, 'product': self.SMS_PRODUCT_NOTIFY, 'numbers': mobile, 'content': content.encode('utf-8')}
- postData = parse.urlencode(postDict).encode('utf-8')
- url = self.SMS_URL + "/submit/"
- req = request.Request(url, postData)
- req.add_header('content-Type', "application/x-www-form-urlencoded; charset=UTF-8")
- try:
- resp = self._do_request(req)
- except CustomError as e:
- self.false_result['Message'] = e.get_error_msg()
- return self.false_result
- r = re.search("<Errors>([\s\S]+?)</Errors>", resp.decode('utf-8'))
- if r != None:
- self.false_result['Message'] = u'短信平台返回错误[%s]' % r.groups()[0]
- return self.false_result
- return self.success_result
- class XGJVCode(models.Model):
- SUCCESSED = 0
- FAILED = 1
- STATUS_CHOICES = (
- (SUCCESSED, u'发送成功'),
- (FAILED, u'发送失败'),
- )
- vcode = models.CharField(verbose_name=u'验证码', max_length=4)
- mobile = models.CharField(verbose_name=u'手机号', max_length=11)
- create_time = models.DateTimeField(verbose_name=u'时间', auto_now_add=True)
- status = models.PositiveSmallIntegerField(choices=STATUS_CHOICES, verbose_name=u"状态", editable=False, default=SUCCESSED)
- error = models.CharField(verbose_name=u"错误原因", null=True, max_length=500)
- class Meta:
- db_table = "xgj_vcode"
- verbose_name = u"销管佳短信验证码"
- ordering = ['-id']
- default_permissions = ()
- @staticmethod
- def send(mobile, appid, captcha_key=None, captcha=None):
- # 参数说明:
- # token:
- # numbers: 手机号 以半角逗号分隔多个手机号码
- # content: 短信内容,中文使用utf-8编码
- # product:产品代码 只够买一个产品时可以省略该参数
- # schedule:定时发送时间 非必填
- if mobile == '' or not mobile:
- raise CustomError(u"无效的手机号!")
- app = Wechat.objects.filter(appid=appid).first()
- if not app:
- raise CustomError(u'未找到相应小程序')
- vcs = XGJVCode.objects.filter(mobile=mobile).order_by('-id')
- if vcs.count() > 0:
- vc = vcs[0]
- if (timezone.now() - vc.create_time).seconds < 60:
- raise CustomError(u'获取太频繁,请稍后再试!')
- code = str(random.randint(1234, 9999))
- str_code = u'短信验证码为:' + code + u'。为了保障您的账户安全,请勿泄露给他人,有效期为10分钟。'
- sms = XGJSMS()
- result = sms.send(app.sms_token, app.sms_sign, mobile, str_code)
- if result['Code'] == 'OK':
- XGJVCode.objects.create(mobile=mobile, vcode=code)
- else:
- XGJVCode.objects.create(mobile=mobile, vcode=code, status=XGJVCode.FAILED, error=result['Message'])
- raise CustomError(u"发送失败,请重试!")
- @staticmethod
- def verify(mobile, vcode):
- if mobile is None or vcode is None:
- raise CustomError(u'参数错误!')
- vc = XGJVCode.objects.filter(mobile=mobile).order_by('-id').first()
- if vc:
- if vc.vcode == vcode:
- if (timezone.now() - vc.create_time).seconds > 600:
- raise CustomError(u'验证码已过期!')
- else:
- raise CustomError(u'验证码错误!')
- else:
- raise CustomError(u'该手机号未发送短信验证码!')
|