1、登录前端页面 Login.vue
< template>
< div class = " login" >
< div class = " box" >
< i class = " el-icon-close" @click = " close_login" > </ i>
< div class = " content" >
< div class = " nav" >
< span :class = " {active: login_method === ' is_pwd' }"
@click = " change_login_method(' is_pwd' )" > 密码登录</ span>
< span :class = " {active: login_method === ' is_sms' }"
@click = " change_login_method(' is_sms' )" > 短信登录</ span>
</ div>
< el-form v-if = " login_method === ' is_pwd' " >
< el-input
placeholder = " 用户名/手机号/邮箱"
prefix-icon = " el-icon-user"
v-model = " username"
clearable >
</ el-input>
< el-input
placeholder = " 密码"
prefix-icon = " el-icon-key"
v-model = " password"
clearable
show-password >
</ el-input>
< el-button type = " primary" > 登录</ el-button>
</ el-form>
< el-form v-if = " login_method === ' is_sms' " >
< el-input
placeholder = " 手机号"
prefix-icon = " el-icon-phone-outline"
v-model = " mobile"
clearable
@blur = " check_mobile" >
</ el-input>
< el-input
placeholder = " 验证码"
prefix-icon = " el-icon-chat-line-round"
v-model = " sms"
clearable >
< template slot = " append" >
< span class = " sms" @click = " send_sms" > {{ sms_interval }}</ span>
</ template>
</ el-input>
< el-button type = " primary" > 登录</ el-button>
</ el-form>
< div class = " foot" >
< span @click = " go_register" > 立即注册</ span>
</ div>
</ div>
</ div>
</ div>
</ template>
< script>
export default {
name: "Login" ,
data ( ) {
return {
username: '' ,
password: '' ,
mobile: '' ,
sms: '' ,
login_method: 'is_pwd' ,
sms_interval: '获取验证码' ,
is_send: false ,
}
} ,
methods: {
close_login ( ) {
this . $emit ( 'close' )
} ,
go_register ( ) {
this . $emit ( 'go' )
} ,
change_login_method ( method) {
this . login_method = method;
} ,
check_mobile ( ) {
if ( ! this . mobile) return ;
if ( ! this . mobile. match ( /^1[3-9][0-9]{9}$/ ) ) {
this . $message ( {
message: '手机号有误' ,
type: 'warning' ,
duration: 1000 ,
onClose: ( ) => {
this . mobile = '' ;
}
} ) ;
return false ;
}
this . is_send = true ;
} ,
send_sms ( ) {
if ( ! this . is_send) return ;
this . is_send = false ;
let sms_interval_time = 60 ;
this . sms_interval = "发送中..." ;
let timer = setInterval ( ( ) => {
if ( sms_interval_time <= 1 ) {
clearInterval ( timer) ;
this . sms_interval = "获取验证码" ;
this . is_send = true ;
} else {
sms_interval_time -= 1 ;
this . sms_interval = ` ${ sms_interval_time} 秒后再发` ;
}
} , 1000 ) ;
}
}
}
</ script>
< style scoped >
.login {
width : 100vw;
height : 100vh;
position : fixed;
top : 0;
left : 0;
z-index : 10;
background-color : rgba ( 0, 0, 0, 0.3) ;
}
.box {
width : 400px;
height : 420px;
background-color : white;
border-radius : 10px;
position : relative;
top : calc ( 50vh - 210px) ;
left : calc ( 50vw - 200px) ;
}
.el-icon-close {
position : absolute;
font-weight : bold;
font-size : 20px;
top : 10px;
right : 10px;
cursor : pointer;
}
.el-icon-close:hover {
color : darkred;
}
.content {
position : absolute;
top : 40px;
width : 280px;
left : 60px;
}
.nav {
font-size : 20px;
height : 38px;
border-bottom : 2px solid darkgrey;
}
.nav > span {
margin : 0 20px 0 35px;
color : darkgrey;
user-select : none;
cursor : pointer;
padding-bottom : 10px;
border-bottom : 2px solid darkgrey;
}
.nav > span.active {
color : black;
border-bottom : 3px solid black;
padding-bottom : 9px;
}
.el-input, .el-button {
margin-top : 40px;
}
.el-button {
width : 100%;
font-size : 18px;
}
.foot > span {
float : right;
margin-top : 20px;
color : orange;
cursor : pointer;
}
.sms {
color : orange;
cursor : pointer;
display : inline-block;
width : 70px;
text-align : center;
user-select : none;
}
</ style>
2、注册前端页面 Register.vue
< template>
< div class = " register" >
< div class = " box" >
< i class = " el-icon-close" @click = " close_register" > </ i>
< div class = " content" >
< div class = " nav" >
< span class = " active" > 新用户注册</ span>
</ div>
< el-form>
< el-input
placeholder = " 手机号"
prefix-icon = " el-icon-phone-outline"
v-model = " mobile"
clearable
@blur = " check_mobile" >
</ el-input>
< el-input
placeholder = " 密码"
prefix-icon = " el-icon-key"
v-model = " password"
clearable
show-password >
</ el-input>
< el-input
placeholder = " 验证码"
prefix-icon = " el-icon-chat-line-round"
v-model = " sms"
clearable >
< template slot = " append" >
< span class = " sms" @click = " send_sms" > {{ sms_interval }}</ span>
</ template>
</ el-input>
< el-button type = " primary" > 注册</ el-button>
</ el-form>
< div class = " foot" >
< span @click = " go_login" > 立即登录</ span>
</ div>
</ div>
</ div>
</ div>
</ template>
< script>
export default {
name: "Register" ,
data ( ) {
return {
mobile: '' ,
password: '' ,
sms: '' ,
sms_interval: '获取验证码' ,
is_send: false ,
}
} ,
methods: {
close_register ( ) {
this . $emit ( 'close' , false )
} ,
go_login ( ) {
this . $emit ( 'go' )
} ,
check_mobile ( ) {
if ( ! this . mobile) return ;
if ( ! this . mobile. match ( /^1[3-9][0-9]{9}$/ ) ) {
this . $message ( {
message: '手机号有误' ,
type: 'warning' ,
duration: 1000 ,
onClose: ( ) => {
this . mobile = '' ;
}
} ) ;
return false ;
}
this . is_send = true ;
} ,
send_sms ( ) {
if ( ! this . is_send) return ;
this . is_send = false ;
let sms_interval_time = 60 ;
this . sms_interval = "发送中..." ;
let timer = setInterval ( ( ) => {
if ( sms_interval_time <= 1 ) {
clearInterval ( timer) ;
this . sms_interval = "获取验证码" ;
this . is_send = true ;
} else {
sms_interval_time -= 1 ;
this . sms_interval = ` ${ sms_interval_time} 秒后再发` ;
}
} , 1000 ) ;
}
}
}
</ script>
< style scoped >
.register {
width : 100vw;
height : 100vh;
position : fixed;
top : 0;
left : 0;
z-index : 10;
background-color : rgba ( 0, 0, 0, 0.3) ;
}
.box {
width : 400px;
height : 480px;
background-color : white;
border-radius : 10px;
position : relative;
top : calc ( 50vh - 240px) ;
left : calc ( 50vw - 200px) ;
}
.el-icon-close {
position : absolute;
font-weight : bold;
font-size : 20px;
top : 10px;
right : 10px;
cursor : pointer;
}
.el-icon-close:hover {
color : darkred;
}
.content {
position : absolute;
top : 40px;
width : 280px;
left : 60px;
}
.nav {
font-size : 20px;
height : 38px;
border-bottom : 2px solid darkgrey;
}
.nav > span {
margin-left : 90px;
color : darkgrey;
user-select : none;
cursor : pointer;
padding-bottom : 10px;
border-bottom : 2px solid darkgrey;
}
.nav > span.active {
color : black;
border-bottom : 3px solid black;
padding-bottom : 9px;
}
.el-input, .el-button {
margin-top : 40px;
}
.el-button {
width : 100%;
font-size : 18px;
}
.foot > span {
float : right;
margin-top : 20px;
color : orange;
cursor : pointer;
}
.sms {
color : orange;
cursor : pointer;
display : inline-block;
width : 70px;
text-align : center;
user-select : none;
}
</ style>
3、头部组件 Header.vue
< template>
< div class = " header" >
< div class = " slogan" >
< p> 老男孩IT教育 | 帮助有志向的年轻人通过努力学习获得体面的工作和生活</ p>
</ div>
< div class = " nav" >
< ul class = " left-part" >
< li class = " logo" >
< router-link to = " /" >
< img src = " ../assets/img/head-logo.svg" alt = " " >
</ router-link>
</ li>
< li class = " ele" >
< span @click = " goPage(' /free-course' )" :class = " {active: url_path === ' /free-course' }" > 免费课</ span>
</ li>
< li class = " ele" >
< span @click = " goPage(' /actual-course' )" :class = " {active: url_path === ' /actual-course' }" > 实战课</ span>
</ li>
< li class = " ele" >
< span @click = " goPage(' /light-course' )" :class = " {active: url_path === ' /light-course' }" > 轻课</ span>
</ li>
</ ul>
< div class = " right-part" >
< span @click = " put_login" > 登录</ span> |
< span @click = " put_register" > 注册</ span>
< Login v-if = " is_login" @close = " close_login" @go = " put_register" />
< Register v-if = " is_register" @close = " close_register" @go = " put_login" />
</ div>
</ div>
</ div>
</ template>
< script>
import Login from "./Login" ;
import Register from "./Register" ;
export default {
name: "Header" ,
data ( ) {
return {
url_path: sessionStorage. url_path || '/' ,
is_login: false ,
is_register: false ,
username: '' ,
}
} ,
methods: {
goPage ( url_path) {
if ( this . url_path !== url_path) {
this . $router. push ( url_path) ;
}
sessionStorage. url_path = url_path;
} ,
put_login ( ) {
this . is_login = true ;
this . is_register = false ;
} ,
put_register ( ) {
this . is_login = false ;
this . is_register = true ;
} ,
close_login ( ) {
this . is_login = false ;
this . username = this . $cookies. get ( 'username' )
} ,
close_register ( ) {
this . is_register = false ;
} ,
logout ( ) {
this . $cookies. remove ( 'username' )
this . $cookies. remove ( 'token' )
this . $cookies. remove ( 'icon' )
this . $cookies. remove ( 'id' )
this . username = '' ;
}
} ,
created ( ) {
this . username = this . $cookies. get ( 'username' )
} ,
components: {
Login,
Register,
}
}
</ script>
< style scoped >
.header {
background-color : white;
box-shadow : 0 0 5px 0 #aaa;
}
.header:after {
content : "" ;
display : block;
clear : both;
}
.slogan {
background-color : #eee;
height : 40px;
}
.slogan p {
width : 1200px;
margin : 0 auto;
color : #aaa;
font-size : 13px;
line-height : 40px;
}
.nav {
background-color : white;
user-select : none;
width : 1200px;
margin : 0 auto;
}
.nav ul {
padding : 15px 0;
float : left;
}
.nav ul:after {
clear : both;
content : '' ;
display : block;
}
.nav ul li {
float : left;
}
.logo {
margin-right : 20px;
}
.ele {
margin : 0 20px;
}
.ele span {
display : block;
font : 15px/36px '微软雅黑' ;
border-bottom : 2px solid transparent;
cursor : pointer;
}
.ele span:hover {
border-bottom-color : orange;
}
.ele span.active {
color : orange;
border-bottom-color : orange;
}
.right-part {
float : right;
}
.right-part .line {
margin : 0 10px;
}
.right-part span {
line-height : 68px;
cursor : pointer;
}
</ style>
4、多方式登录接口
1 、前台提供手机号和验证码完成登录
接口:
前台填完手机号, 往后台发送校验手机号的请求, 如果存在继续, 不存在提示注册 手机号存在与否接口
前台点击发送验证码, 将手机再次发送给后台, 后台将手机号通知给第三方, 发送短信 手机验证码接口
前台点击登录提交手机号与验证码, 完成验证码登录 验证码登录接口
2 、前台提供手机号、验证码、密码完成注册
接口:
前台填完手机号, 往后台发送校验手机号的请求, 如果不存在继续, 存在提示登录 手机号存在与否接口
前台点击发送验证码, 将手机再次发送给后台, 后台将手机号通知给第三方, 发送短信 手机验证码接口
前台点击注册提交手机号、验证码及密码, 完成验证码注册 验证码注册接口
总结:
多方式登录接口
手机号存在与否接口
手机验证码接口
验证码登录接口
验证码注册接口
4.1、路由层
from django. urls import path
from user import views
from rest_framework. routers import SimpleRouter
router = SimpleRouter( )
router. register( '' , views. LoginView, basename= 'loginview' )
urlpatterns = [
]
urlpatterns += router. urls
4.2、视图层
from django. shortcuts import render
from rest_framework. viewsets import ViewSet
from rest_framework. decorators import action
from . serializer import LoginSerializer
from utils. response import APIResponse
class LoginView ( ViewSet) :
@action( methods= [ 'post' ] , detail= False )
def login ( self, request, * args, ** kwargs) :
serializer = LoginSerializer( data= request. data, context= {
'request' : request,
} )
if serializer. is_valid( ) :
token = serializer. context[ 'token' ]
user = serializer. context[ 'user' ]
icon = serializer. context[ 'icon' ]
return APIResponse( token= token, username= user. username, icon= icon, id = user. id )
else :
return APIResponse( status= 1 , msg= '用户或密码错误' )
4.3、序列化类
from rest_framework import serializers
from rest_framework. validators import ValidationError
from rest_framework_jwt. utils import jwt_payload_handler, jwt_encode_handler
from django. conf import settings
from . models import User
class LoginSerializer ( serializers. ModelSerializer) :
username = serializers. CharField( )
class Meta :
model = User
fields = [ 'id' , 'username' , 'icon' , 'password' ]
extra_kwargs = {
'username' : { 'write_only' : True } ,
'password' : { 'write_only' : True } ,
}
def _get_user ( self, attrs) :
"""
获取用户
:param attrs:
:return:
"""
username = attrs. get( 'username' )
password = attrs. get( 'password' )
import re
if re. match( r'^1[3-9][0-9]{9}$' , username) :
user = User. objects. filter ( mobile= username, is_active= True ) . first( )
elif re. match( r'^.+@.+$' , username) :
user = User. objects. filter ( email= username, is_active= True ) . first( )
else :
user = User. objects. filter ( username= username, is_active= True ) . first( )
if user and user. check_password( password) :
return user
raise ValidationError( '用户或密码错误' )
def _get_token ( self, user) :
payload = jwt_payload_handler( user)
token = jwt_encode_handler( payload)
return token
def validate ( self, attrs) :
user = self. _get_user( attrs)
token = self. _get_token( user)
request = self. context[ 'request' ]
icon = 'http://%s%s%s' % ( request. META[ 'HTTP_HOST' ] , settings. MEDIA_URL, user. icon)
self. context[ 'token' ] = token
self. context[ 'user' ] = user
self. context[ 'icon' ] = icon
return attrs
4.4、Login.vue
< template>
< div class = " login" >
< div class = " box" >
< i class = " el-icon-close" @click = " close_login" > </ i>
< div class = " content" >
< div class = " nav" >
< span :class = " {active: login_method === ' is_pwd' }"
@click = " change_login_method(' is_pwd' )" > 密码登录</ span>
< span :class = " {active: login_method === ' is_sms' }"
@click = " change_login_method(' is_sms' )" > 短信登录</ span>
</ div>
< el-form v-if = " login_method === ' is_pwd' " >
< el-input
placeholder = " 用户名/手机号/邮箱"
prefix-icon = " el-icon-user"
v-model = " username"
clearable >
</ el-input>
< el-input
placeholder = " 密码"
prefix-icon = " el-icon-key"
v-model = " password"
clearable
show-password >
</ el-input>
< el-button type = " primary" @click = " login_pwd" > 登录</ el-button>
</ el-form>
< el-form v-if = " login_method === ' is_sms' " >
< el-input
placeholder = " 手机号"
prefix-icon = " el-icon-phone-outline"
v-model = " mobile"
clearable
@blur = " check_mobile" >
</ el-input>
< el-input
placeholder = " 验证码"
prefix-icon = " el-icon-chat-line-round"
v-model = " sms"
clearable >
< template slot = " append" >
< span class = " sms" @click = " send_sms" > {{ sms_interval }}</ span>
</ template>
</ el-input>
< el-button type = " primary" > 登录</ el-button>
</ el-form>
< div class = " foot" >
< span @click = " go_register" > 立即注册</ span>
</ div>
</ div>
</ div>
</ div>
</ template>
< script>
export default {
name: "Login" ,
data ( ) {
return {
username: '' ,
password: '' ,
mobile: '' ,
sms: '' ,
login_method: 'is_pwd' ,
sms_interval: '获取验证码' ,
is_send: false ,
}
} ,
methods: {
close_login ( ) {
this . $emit ( 'close' )
} ,
go_register ( ) {
this . $emit ( 'go' )
} ,
change_login_method ( method) {
this . login_method = method;
} ,
check_mobile ( ) {
if ( ! this . mobile) return ;
if ( ! this . mobile. match ( /^1[3-9][0-9]{9}$/ ) ) {
this . $message ( {
message: '手机号有误' ,
type: 'warning' ,
duration: 1000 ,
onClose: ( ) => {
this . mobile = '' ;
}
} ) ;
return false ;
}
this . is_send = true ;
} ,
send_sms ( ) {
if ( ! this . is_send) return ;
this . is_send = false ;
let sms_interval_time = 60 ;
this . sms_interval = "发送中..." ;
let timer = setInterval ( ( ) => {
if ( sms_interval_time <= 1 ) {
clearInterval ( timer) ;
this . sms_interval = "获取验证码" ;
this . is_send = true ;
} else {
sms_interval_time -= 1 ;
this . sms_interval = ` ${ sms_interval_time} 秒后再发` ;
}
} , 1000 ) ;
} ,
login_pwd ( ) {
this . $axios. post ( this . $settings. base_url + '/user/login/' , {
username: this . username,
password: this . password,
} ) . then ( item => {
if ( item. data. status == 0 ) {
this . $cookies. set ( 'username' , item. data. username, '7d' ) ;
this . $cookies. set ( 'token' , item. data. token, '7d' ) ;
this . $cookies. set ( 'icon' , item. data. icon, '7d' ) ;
this . $cookies. set ( 'id' , item. data. id, '7d' ) ;
this . close_login ( )
} else {
this . $message ( {
message: '用户名或密码有误' ,
type: 'error' ,
duration: 1000 ,
onClose: ( ) => {
this . username = '' ;
this . password = '' ;
}
} ) ;
}
} )
} ,
}
}
</ script>
< style scoped >
.login {
width : 100vw;
height : 100vh;
position : fixed;
top : 0;
left : 0;
z-index : 10;
background-color : rgba ( 0, 0, 0, 0.3) ;
}
.box {
width : 400px;
height : 420px;
background-color : white;
border-radius : 10px;
position : relative;
top : calc ( 50vh - 210px) ;
left : calc ( 50vw - 200px) ;
}
.el-icon-close {
position : absolute;
font-weight : bold;
font-size : 20px;
top : 10px;
right : 10px;
cursor : pointer;
}
.el-icon-close:hover {
color : darkred;
}
.content {
position : absolute;
top : 40px;
width : 280px;
left : 60px;
}
.nav {
font-size : 20px;
height : 38px;
border-bottom : 2px solid darkgrey;
}
.nav > span {
margin : 0 20px 0 35px;
color : darkgrey;
user-select : none;
cursor : pointer;
padding-bottom : 10px;
border-bottom : 2px solid darkgrey;
}
.nav > span.active {
color : black;
border-bottom : 3px solid black;
padding-bottom : 9px;
}
.el-input, .el-button {
margin-top : 40px;
}
.el-button {
width : 100%;
font-size : 18px;
}
.foot > span {
float : right;
margin-top : 20px;
color : orange;
cursor : pointer;
}
.sms {
color : orange;
cursor : pointer;
display : inline-block;
width : 70px;
text-align : center;
user-select : none;
}
</ style>
4.5、Header.vue
< template>
< div class = " header" >
< div class = " slogan" >
< p> 老男孩IT教育 | 帮助有志向的年轻人通过努力学习获得体面的工作和生活</ p>
</ div>
< div class = " nav" >
< ul class = " left-part" >
< li class = " logo" >
< router-link to = " /" >
< img src = " ../assets/img/head-logo.svg" alt = " " >
</ router-link>
</ li>
< li class = " ele" >
< span @click = " goPage(' /free-course' )" :class = " {active: url_path === ' /free-course' }" > 免费课</ span>
</ li>
< li class = " ele" >
< span @click = " goPage(' /actual-course' )" :class = " {active: url_path === ' /actual-course' }" > 实战课</ span>
</ li>
< li class = " ele" >
< span @click = " goPage(' /light-course' )" :class = " {active: url_path === ' /light-course' }" > 轻课</ span>
</ li>
</ ul>
< div class = " right-part" v-if = " username" >
< span> {{username}}</ span> |
< span @click = " logout" > 注销</ span>
</ div>
< div class = " right-part" v-else >
< span @click = " put_login" > 登录</ span> |
< span @click = " put_register" > 注册</ span>
< Login v-if = " is_login" @close = " close_login" @go = " put_register" />
< Register v-if = " is_register" @close = " close_register" @go = " put_login" />
</ div>
</ div>
</ div>
</ template>
< script>
import Login from "./Login" ;
import Register from "./Register" ;
export default {
name: "Header" ,
data ( ) {
return {
url_path: sessionStorage. url_path || '/' ,
is_login: false ,
is_register: false ,
username: '' ,
}
} ,
methods: {
goPage ( url_path) {
if ( this . url_path !== url_path) {
this . $router. push ( url_path) ;
}
sessionStorage. url_path = url_path;
} ,
put_login ( ) {
this . is_login = true ;
this . is_register = false ;
} ,
put_register ( ) {
this . is_login = false ;
this . is_register = true ;
} ,
close_login ( ) {
this . is_login = false ;
this . username = this . $cookies. get ( 'username' )
} ,
close_register ( ) {
this . is_register = false ;
} ,
logout ( ) {
this . $cookies. remove ( 'username' )
this . $cookies. remove ( 'token' )
this . $cookies. remove ( 'icon' )
this . $cookies. remove ( 'id' )
this . username = '' ;
}
} ,
created ( ) {
this . username = this . $cookies. get ( 'username' )
} ,
components: {
Login,
Register,
}
}
</ script>
< style scoped >
.header {
background-color : white;
box-shadow : 0 0 5px 0 #aaa;
}
.header:after {
content : "" ;
display : block;
clear : both;
}
.slogan {
background-color : #eee;
height : 40px;
}
.slogan p {
width : 1200px;
margin : 0 auto;
color : #aaa;
font-size : 13px;
line-height : 40px;
}
.nav {
background-color : white;
user-select : none;
width : 1200px;
margin : 0 auto;
}
.nav ul {
padding : 15px 0;
float : left;
}
.nav ul:after {
clear : both;
content : '' ;
display : block;
}
.nav ul li {
float : left;
}
.logo {
margin-right : 20px;
}
.ele {
margin : 0 20px;
}
.ele span {
display : block;
font : 15px/36px '微软雅黑' ;
border-bottom : 2px solid transparent;
cursor : pointer;
}
.ele span:hover {
border-bottom-color : orange;
}
.ele span.active {
color : orange;
border-bottom-color : orange;
}
.right-part {
float : right;
}
.right-part .line {
margin : 0 10px;
}
.right-part span {
line-height : 68px;
cursor : pointer;
}
</ style>
5、校验手机号是否存在接口
@action( methods= [ 'get' ] , detail= False )
def check_mobile ( self, request, * args, ** kwargs) :
mobile = request. GET. get( 'mobile' )
import re
if re. match( r'^1[3-9][0-9]{9}$' , mobile) :
user = User. objects. filter ( mobile= mobile) . first( )
if user:
return APIResponse( msg= '手机号已存在' )
else :
return APIResponse( status= 1 , msg= '手机号未注册' )
return APIResponse( status= 1 , msg= '手机号不合法' )
6、短信验证码介绍
1 、阿里大于短信, 腾讯的短信平台
2 、充钱购买短信, 腾讯提供接口, 向他们的接口发请求, 腾讯给对应的手机发短信
3 、使用腾讯短信平台步骤:
( 1 ) 创建短信签名: 申请一个公众号, 把公众号的截图, 上传, 申请后台审核
( 2 ) 创建短信正文模板: 填写模板, 通过审核
( 3 ) 等待审核, 通过以后发送短信:https: // cloud. tencent. com/ document/ product/ 382 / 11672
4 、api和sdk的区别
api: 是一堆http的接口, 有了接口就可以调用接口发短信, 跟语言无关
sdk: 软件开发工具包, 分语言, 这个公司帮你使用各类编程语言封装好了, 只需要调用它固定的方法, 就能完 成发短信
5 、使用腾讯短信提供的sdk
pip install qcloudsms_py
appid = 1400009099
appkey = "9ff91d87c2cd7cd0ea762f141975d1df37481d48700d70ac37470aefc60f9bad"
phone_numbers = [ "21212313123" , "12345678902" , "12345678903" ]
template_id = 7839
sms_sign = "腾讯云"
from qcloudsms_py import SmsSingleSender
from qcloudsms_py. httpclient import HTTPError
ssender = SmsSingleSender( appid, appkey)
params = [ "5678" ]
try :
result = ssender. send_with_param( 86 , phone_numbers[ 0 ] , template_id, params, sign= sms_sign, extend= "" , ext= "" )
except HTTPError as e:
print ( e)
except Exception as e:
print ( e)
print ( result)