123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243 |
- # -*- coding: utf-8 -*-
- # !/usr/bin/env python
- """
- 短信模块
- 主要用于对经销商和代理商发送短信,以及通知内部工作人员系统状态(如微信提现账户余额不足等鼓掌信息)
- """
- import string
- import random
- import logging
- from typing import Tuple
- from django.conf import settings
- from apps import serviceCache
- from apps.web.core.messages import SmsVendorCode
- from apps.web.utils import LimitAttemptsManager
- logger = logging.getLogger(__name__)
- class SMSSender(object):
- TEMPLATE = None
- """
- `ref` http://docs.ucpaas.com/doku.php?id=%E7%9F%AD%E4%BF%A1%E9%AA%8C%E8%AF%81:sms_demo
- 参数 描述 示例 位置
- token 用户密钥“Auth Token” 23f757bad208226ec301e117e40006ed 可在后台首页获取“Auth Token”
- sid 用户的账号唯一标识“Account Sid” da3f8e03476844bddb3fd45abb24f2d0 可在后台首页获取“Account Sid”
- appid 创建应用时系统分配的唯一标示(appId) 2d92c6132139467b989d087c84a365d8 获取路径后台→应用管理→点击需要对接应用,查看appId
- templateId 可在后台短信产品→选择接入的应用→短信模板-模板ID,查看该模板ID 1000001 可在后台短信产品对应应用的“短信模板”中查看
- """
- def __init__(self, vendor = SmsVendorCode.UCPAAS):
- self.vendor = vendor
- def generate_code(self, size = 4):
- return "".join(random.choice(string.digits) for _ in range(size))
- def send(self, phoneNumber, templateName, msg, productName = u'管理后台'.encode('utf-8'), verifyCode = False):
- """
- :param verifyCode:
- :param phoneNumber:
- :param templateName:
- :param msg:
- :param productName: 代理商定制产品名称
- :return: dict
- """
- if not settings.SEND_SMS_IS_ALLOWED:
- return {}
- if self.vendor == SmsVendorCode.UCPAAS:
- from library.sms.ucpaas import Sender as UcpassSmsSender
- sender = UcpassSmsSender() # type: UcpassSmsSender
- elif self.vendor == SmsVendorCode.ALIYUN:
- from library.sms.aliyun import Sender as AliyunSmsSender
- sender = AliyunSmsSender() # type: AliyunSmsSender
- elif self.vendor == SmsVendorCode.ZTHY:
- from library.sms.zthy import Sender as ZTHYSmsSender
- sender = ZTHYSmsSender()
- else:
- logger.error('not support the sms platform.')
- return {'result': False, 'msg': '系统错误,请联系平台客服'}
- return sender.send(phoneNumber = phoneNumber,
- templateName = templateName,
- msg = msg,
- productName = productName,
- verifyCode = verifyCode)
- class GenericSMSProvider(object):
- def __init__(self, node):
- self.node = node
- self.keygen = lambda phoneNumber: '%s-%s' % (self.node, phoneNumber)
- def get_code(self, key):
- return serviceCache.get(key)
- def set_code(self, key, value, time = 60):
- return serviceCache.set(key, value, time)
- def get(self, phoneNumber, productName, vendor = SmsVendorCode.UCPAAS):
- # type: (str, str, str)->Tuple[bool, basestring]
- if phoneNumber is None:
- return False, u'请填写手机号码'
- key = self.keygen(phoneNumber)
- preSmsCode = self.get_code(key)
- if preSmsCode:
- return False, u'操作过于频繁'
- sender = SMSSender(vendor = vendor) # type: SMSSender
- curSmsCode = sender.generate_code()
- response = sender.send(phoneNumber = phoneNumber,
- templateName = 'CAPTCHA_TEMPLATE_ID',
- msg = curSmsCode,
- productName = productName,
- verifyCode = True)
- if response['result'] == True:
- self.set_code(key, curSmsCode, 60)
- return response['result'], response['msg']
- def verify(self, phoneNumber, smsCode):
- # type: (str, str)->Tuple[bool, basestring]
- if settings.SKIP_VERIFY_SMS:
- return True, u'跳过验证码校验'
- limitManager = LimitAttemptsManager(identifier = phoneNumber, category = self.node)
- if limitManager.is_exceeded_limit():
- return False, u'超出输入错误次数限制,请明日再试'
- cachedSMSCode = self.get_code(self.keygen(phoneNumber))
- if not cachedSMSCode:
- return False, u'验证码已失效,请重新获取验证码'
- if cachedSMSCode != smsCode:
- limitManager.incr()
- return False, u'验证码输入错误,您还可输入%s次' % limitManager.times_left()
- else:
- return True, ''
- class RegisterSMSProvider(GenericSMSProvider):
- pass
- class ForgotPwdSMSProvider(GenericSMSProvider):
- pass
- class WithdrawSMSProvider(GenericSMSProvider):
- pass
- class AutoWithdrawSMSProvider(GenericSMSProvider):
- pass
- class BindWechatSMSProvider(GenericSMSProvider):
- pass
- class BindWalletWechatSMSProvider(GenericSMSProvider):
- pass
- class MobileVerifySMSProvider(GenericSMSProvider):
- def get(self, phoneNumber, productName, vendor = SmsVendorCode.UCPAAS,
- openId = None): # type: (str, str, str, str)->Tuple[bool, basestring]
- if openId:
- limitManager = LimitAttemptsManager(identifier = openId, category = self.node)
- if limitManager.is_exceeded_limit():
- return False, u'超出最大短信限制'
- limitManager.incr()
- return super(MobileVerifySMSProvider, self).get(phoneNumber, productName, vendor)
- class EditMonitorSMSProvider(GenericSMSProvider):
- def get(self, phoneNumber, productName, vendor = SmsVendorCode.UCPAAS):
- # type: (str, str, str)->Tuple[bool, basestring]
- if phoneNumber is None:
- return False, u'请填写手机号码'
- key = self.keygen(phoneNumber)
- preSmsCode = self.get_code(key)
- if preSmsCode:
- return False, u'操作过于频繁'
- sender = SMSSender(vendor = vendor) # type: SMSSender
- curSmsCode = sender.generate_code()
- response = sender.send(phoneNumber = phoneNumber,
- templateName = 'EDIT_MONITOR_ID',
- msg = curSmsCode,
- productName = productName,
- verifyCode = True)
- if response['result'] == True:
- self.set_code(key, curSmsCode, 60)
- return response['result'], response['msg']
- class MonitorWithdrawSMSProvider(GenericSMSProvider):
- def get(self, phoneNumber, productName, vendor = SmsVendorCode.UCPAAS):
- # type: (str, str, str)->Tuple[bool, basestring]
- if phoneNumber is None:
- return False, u'请填写手机号码'
- key = self.keygen(phoneNumber)
- preSmsCode = self.get_code(key)
- if preSmsCode:
- return False, u'操作过于频繁'
- sender = SMSSender(vendor = vendor) # type: SMSSender
- curSmsCode = sender.generate_code()
- response = sender.send(phoneNumber = phoneNumber,
- templateName = 'DEALER_MONITOR_WITHDRAW_ID',
- msg = curSmsCode,
- productName = productName,
- verifyCode = True)
- if response['result'] == True:
- self.set_code(key, curSmsCode, 60)
- return response['result'], response['msg']
- dealerRegisterSMSProvider = RegisterSMSProvider('dealer-reg')
- dealerForgotPwdSMSProvider = ForgotPwdSMSProvider('dealer-forgot-pwd')
- dealerWithdrawSMSProvider = WithdrawSMSProvider('dealer-withdraw')
- dealerAutoWithdrawSMSProvider = AutoWithdrawSMSProvider('dealer-auto-withdraw')
- dealerBindWechatSMSProvider = BindWechatSMSProvider('dealer-bind-wechat')
- dealerBindWalletWechatSMSProvider = BindWalletWechatSMSProvider('dealer-bind-wallet')
- dealerEditMonitorSMSProvider = EditMonitorSMSProvider('dealer-edit-monitor')
- dealerMonitorWithdrawSMSProvider = MonitorWithdrawSMSProvider('dealer-monitor-withdraw')
- agentRegisterSMSProvider = RegisterSMSProvider('agent-reg')
- agentWithdrawSMSProvider = WithdrawSMSProvider('agent-withdraw')
- agentBindWalletWechatSMSProvider = BindWalletWechatSMSProvider('agent-bind-wallet')
- userMobileVerifySMSProvider = MobileVerifySMSProvider('user-mobile-verify')
- managerRegisterSMSProvider = RegisterSMSProvider('manager-reg')
- managerForgotPwdSMSProvider = ForgotPwdSMSProvider('manager-forgot-pwd')
|