models.py 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. # coding=utf-8
  2. import random
  3. from urllib import request, parse
  4. import re
  5. import math
  6. from django.db import models
  7. from django.utils import timezone
  8. from utils.exceptions import CustomError
  9. from apps.wechat.models import Wechat
  10. class XGJSMS:
  11. def __init__(self):
  12. self.SMS_URL = 'http://sms.zzliaoyuan.com:8088'
  13. self.SMS_PRODUCT_NOTIFY = 30 # 通知短信的代码
  14. self.success_result = {'Code': u'OK', 'Message': u'短信提交成功'}
  15. self.false_result = {'Code': u'FALSE', 'Message': u'短信提交失败'}
  16. def _do_request(self, req):
  17. try:
  18. resp = request.urlopen(req)
  19. except Exception as e:
  20. raise CustomError(u"短信平台错误")
  21. if resp.getcode() != 200:
  22. raise CustomError(u'短信平台错误')
  23. return resp.read()
  24. def send(self, sms_token, sms_sign, mobile, content):
  25. content = u"【%s】%s" % (sms_sign, content)
  26. url = '%s/balance/?token=%s' % (self.SMS_URL, sms_token)
  27. req = request.Request(url)
  28. try:
  29. resp = self._do_request(req)
  30. except CustomError as e:
  31. self.false_result['Message'] = e.get_error_msg()
  32. return self.false_result
  33. p = '<Product id="%s">([\d]+?)</Product>' % self.SMS_PRODUCT_NOTIFY
  34. r = re.search(p, resp.decode('utf-8'))
  35. if r == None:
  36. self.false_result['Message'] = u'短信平台账号余额不足'
  37. return self.false_result
  38. else:
  39. balance = int(r.groups()[0])
  40. fee_count = 1
  41. if len(content) > 70:
  42. fee_count = int(math.ceil(len(content) / 65.0))
  43. if balance < 1 or balance < 1 * fee_count:
  44. self.false_result['Message'] = u'短信平台账号余额不足'
  45. return self.false_result
  46. postDict = {'token': sms_token, 'product': self.SMS_PRODUCT_NOTIFY, 'numbers': mobile, 'content': content.encode('utf-8')}
  47. postData = parse.urlencode(postDict).encode('utf-8')
  48. url = self.SMS_URL + "/submit/"
  49. req = request.Request(url, postData)
  50. req.add_header('content-Type', "application/x-www-form-urlencoded; charset=UTF-8")
  51. try:
  52. resp = self._do_request(req)
  53. except CustomError as e:
  54. self.false_result['Message'] = e.get_error_msg()
  55. return self.false_result
  56. r = re.search("<Errors>([\s\S]+?)</Errors>", resp.decode('utf-8'))
  57. if r != None:
  58. self.false_result['Message'] = u'短信平台返回错误[%s]' % r.groups()[0]
  59. return self.false_result
  60. return self.success_result
  61. class XGJVCode(models.Model):
  62. SUCCESSED = 0
  63. FAILED = 1
  64. STATUS_CHOICES = (
  65. (SUCCESSED, u'发送成功'),
  66. (FAILED, u'发送失败'),
  67. )
  68. vcode = models.CharField(verbose_name=u'验证码', max_length=4)
  69. mobile = models.CharField(verbose_name=u'手机号', max_length=11)
  70. create_time = models.DateTimeField(verbose_name=u'时间', auto_now_add=True)
  71. status = models.PositiveSmallIntegerField(choices=STATUS_CHOICES, verbose_name=u"状态", editable=False, default=SUCCESSED)
  72. error = models.CharField(verbose_name=u"错误原因", null=True, max_length=500)
  73. class Meta:
  74. db_table = "xgj_vcode"
  75. verbose_name = u"销管佳短信验证码"
  76. ordering = ['-id']
  77. default_permissions = ()
  78. @staticmethod
  79. def send(mobile, appid, type, captcha_key=None, captcha=None):
  80. # 参数说明:
  81. # token:
  82. # numbers: 手机号 以半角逗号分隔多个手机号码
  83. # content: 短信内容,中文使用utf-8编码
  84. # product:产品代码 只够买一个产品时可以省略该参数
  85. # schedule:定时发送时间 非必填
  86. if mobile == '' or not mobile:
  87. raise CustomError(u"无效的手机号!")
  88. app = Wechat.objects.filter(appid=appid).first()
  89. if not app:
  90. raise CustomError(u'参数无效')
  91. vcs = XGJVCode.objects.filter(mobile=mobile, type=type).order_by('-id')
  92. if vcs.count() > 0:
  93. vc = vcs[0]
  94. if (timezone.now() - vc.create_time).seconds < 60:
  95. raise CustomError(u'获取太频繁,请稍后再试!')
  96. code = str(random.randint(1234, 9999))
  97. str_code = u'短信验证码为:' + code + u'。为了保障您的账户安全,请勿泄露给他人,有效期为10分钟。'
  98. sms = XGJSMS()
  99. result = sms.send(app.sms_token, app.sms_sign, mobile, str_code)
  100. if result['Code'] == 'OK':
  101. XGJVCode.objects.create(mobile=mobile, vcode=code, type=type)
  102. else:
  103. XGJVCode.objects.create(mobile=mobile, vcode=code, type=type, status=XGJVCode.FAILED, error=result['Message'])
  104. raise CustomError(u"发送失败,请重试!")
  105. @staticmethod
  106. def verify(mobile, vcode, type):
  107. if mobile is None or vcode is None:
  108. raise CustomError(u'参数错误!')
  109. vc = XGJVCode.objects.filter(mobile=mobile, type=type).order_by('-id').first()
  110. if vc:
  111. if vc.vcode == vcode:
  112. if (timezone.now() - vc.create_time).seconds > 600:
  113. raise CustomError(u'验证码已过期!')
  114. else:
  115. raise CustomError(u'验证码错误!')
  116. else:
  117. raise CustomError(u'该手机号未发送短信验证码!')