123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139 |
- # -*- coding: utf-8 -*-
- # !/usr/bin/env python
- import logging
- import urllib
- from typing import TYPE_CHECKING
- from apilib.utils_url import add_query
- from apps.web.core import AlipayMixin
- from library.alipay import AliException
- from .base import AuthBridge
- if TYPE_CHECKING:
- from apps.web.core.models import AliApp
- logger = logging.getLogger(__name__)
- class AlipayAuthBridge(AuthBridge, AlipayMixin):
- auth_code_key = 'auth_code'
- # 静默跳转,无需用户点击授权
- AUTH_SCOPE_BASE = 'auth_base'
- # 需要用户显式点击授权
- AUTH_SCOPE_USER = 'auth_user'
- # 测试网关oauth
- DEV_ALIPAY_OAUTH_URL = \
- 'https://openauth.alipaydev.com/oauth2/publicAppAuthorize.htm?' + \
- 'app_id={appid}&scope={scope}&redirect_uri={encoded_return_uri}&state={state}'
- # 生产环境网关oauth
- PRODUCTION_ALIPAY_OAUTH_URL = \
- 'https://openauth.alipay.com/oauth2/publicAppAuthorize.htm?' + \
- 'app_id={appid}&scope={scope}&redirect_uri={encoded_return_uri}&state={state}'
- def __init__(self, app):
- # type: (AliApp)->None
- super(AlipayAuthBridge, self).__init__(app)
- if self.debug:
- self._auth_gateway_tmpl = self.DEV_ALIPAY_OAUTH_URL
- else:
- self._auth_gateway_tmpl = self.PRODUCTION_ALIPAY_OAUTH_URL
- def generate_auth_url(self, redirect_uri, payload, scope):
- """
- 参数名 是否必须 描述
- app_id 是 开发者应用的app_id
- scope 是 接口权限值,目前只支持auth_user和auth_base两个值
- redirect_uri 是 回调页面
- state 否
- 商户自定义参数,用户授权后,
- 重定向到redirect_uri时会原样回传给商户。
- 为防止CSRF攻击,建议开发者请求授权时传入state参数,
- 该参数要做到既不可预测,又可以证明客户端和当前第三方网站的登录认证状态存在关联。
- ```
- 关于scope的说明:
- auth_base:以auth_base为scope发起的网页授权,是用来获取进入页面的用户的userId的,
- 并且是静默授权并自动跳转到回调页的。用户感知的就是直接进入了回调页(通常是业务页面)。
- auth_user:以auth_user为scope发起的网页授权,是用来获取用户的基本信息的(比如头像、昵称等)。
- 但这种授权需要用户手动同意,用户同意后,就可在授权后获取到该用户的基本信息。若想获取用户信息,scope的值中需要有该值存在,
- 如scope=auth_user, auth_base。
- ```
- :return: <str>url
- """
- logger.debug('generate_auth_callback_url enter. bridge = {}, '
- 'callback url = {}; payload = {}'.format(repr(self), redirect_uri, payload))
- callback_url = add_query(redirect_uri, {'payload': payload})
- encoded_return_uri = urllib.quote_plus(callback_url)
- result = self._auth_gateway_tmpl.format(appid = self.appid,
- scope = scope,
- encoded_return_uri = encoded_return_uri,
- state = '')
- logger.debug('generate_auth_callback_url success. result = {}'.format(str(result)))
- return result
- def generate_auth_url_base_scope(self,
- redirect_uri,
- payload = None):
- return self.generate_auth_url(payload = payload,
- scope = self.AUTH_SCOPE_BASE,
- redirect_uri = redirect_uri)
- def generate_auth_url_user_scope(self,
- redirect_uri,
- payload = None):
- return self.generate_auth_url(payload = payload,
- scope = self.AUTH_SCOPE_USER,
- redirect_uri = redirect_uri)
- def get_user_info(self, auth_code, refresh_token = None):
- logger.debug(
- 'get alipay user info by bridge = {}, auth_code = {}, refresh_token = {}'.format(
- repr(self), auth_code, refresh_token))
- auth_token = self.client.api_alipay_system_oauth_token(auth_code = auth_code, refresh_token = refresh_token)
- response = self.client.api_alipay_user_info_share(auth_token = auth_token['access_token'])
- logger.debug('alipay user info = {}'.format(response))
- if response['code'] == u'10000':
- result = {
- 'openId': response.get('user_id'),
- 'avatar': response.get('avatar', ''),
- 'nickname': response.get('nick_name', ''),
- 'province': response.get('province', ''),
- 'city': response.get('city', ''),
- 'extra': {
- 'is_student_certified': response.get('is_student_certified', ''),
- 'user_type': response.get('user_type', ''),
- 'user_status': response.get('user_status', ''),
- 'is_certified': response.get('is_certified', '')
- }
- }
- sex = response.get('gender', 'unknown').lower()
- if sex == 'm':
- result['sex'] = 1
- elif sex == 'f':
- result['sex'] = 2
- else:
- result['sex'] = 0
- return result
- else:
- raise AliException(
- errCode = response['code'],
- errMsg = response['msg'],
- client = self.client)
|