Python 實現微信小程序的用戶登錄


     小程序可以通過官方提供的登錄能力來獲取用戶身份的標示,具體文檔可以參考 這里,通過流程時序可以看到,對於需要和前端配合的服務端開發,主要實現的就是通過小程序提供的 code 換取用戶的 openid 和 session_key,並用換取到的 openid 和 secret_key 作為自定義的登錄態。分析后得知,作為小程序后端的開發,主要實現以下幾部分內容:

  - 提供一個 HTTP 接口,供小程序方使用,傳遞 code;

   - 換取用戶身份標識;

   - 維護一個自定義的登錄態;

       - 需要存儲用戶的 openid,以備后續使用。

 

1. 提供給小程序一個 HTTP 接口,接口使用 Tornado 框架

     為了簡化思路,下面代碼都沒有做各種異常處理!

class LoginHandler(RequestHandler):

    def post(self):
        req_data = json.loads(self.request.body)

        js_code = req_data.get('js_code')

        # 這里是換取用戶的信息
        user_info = get_user_info(js_code=js_code)

        openid = user_info['openid']
        session_key = user_info['session_key']
        user_uuid = str(uuid.uuid4())  # 暴露給小程序端的用戶標示
        
        # 用來維護用戶的登錄態
        User.save_user_session(
            user_uuid=user_uuid,
            openid=openid,
            session_key=session_key
        )
        # 微信小程序不能設置cookie,把用戶信息存在了 headers 中
        self.set_header('Authorization', user_uuid)
        
        # 存儲用戶信息
        User.save_user_info(open_id=openid)

        self.set_status(204)

 

2. 換取用戶身份標示,直接使用 Requests 請求微信的相關接口,獲取數據

 1 def get_user_info(js_code):
 2 
 3     req_params = {
 4         "appid": 'app_id',  # 小程序的 ID
 5         "secret": 'secret',  # 小程序的 secret
 6         "js_code": js_code,
 7         "grant_type": 'authorization_code'
 8     }
 9     req_result = requests.get('https://api.weixin.qq.com/sns/jscode2session', 
10                               params=req_params, timeout=3, verify=False)
11     return req_result.json()

3. 維護一個自定義的登錄態,使用了 Redis

 1 user_redis = StrictRedis.from_url('redis//localhost:6379')
 2 
 3 
 4  class User(object):
 5 
 6     REDIS_EXPIRES = 7 * 24 * 60 * 60
 7 
 8     @classmethod
 9     def save_user_session(cls, user_uuid, openid, session_key):
10         user_session_value = {
11             'openid': openid,
12             'session_key': session_key
13         }
14         user_session_key = 'US:' + user_uuid
15         with user_redis.pipeline(transaction=False) as pipe:
16             pipe.hmset(user_session_key, user_session_value)
17             pipe.expire(user_session_key, cls.REDIS_EXPIRES)
18             pipe.execute()

 

4. 存儲用戶信息,以備后用,這里使用了 MySQL,ORM 使用的是 SQLAlchemy

 1 from sqlalchemy import create_engine
 2 from sqlalchemy.ext.declarative import declarative_base
 3 
 4 # mysql 相關設置
 5 engine = create_engine('mysql://root:@localhost/wechat')
 6 conn = engine.connect()
 7 
 8 Base = declarative_base()
 9 Base.metadata.reflect(engine)
10 tables = Base.metadata.tables
11 
12 class User(object):
13     table = tables['user']
14     
15     @classmethod
16     def save_user_info(cls, open_id):
17         #  存儲用戶信息
18         sql = cls.table.insert().values(open_id=open_id)
19         conn.execute(sql)

SQL 語句

CREATE TABLE `user` (
  `id` int(20) unsigned NOT NULL AUTO_INCREMENT,
  `open_id` varchar(32) NOT NULL COMMENT '用戶 open_id',
  `created_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '創建時間',
  `updated_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新時間',
  PRIMARY KEY (`id`),
  KEY `idx_oid` (`open_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

 

全部代碼可以點擊 這里 獲取!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM