{"id":22206420,"url":"https://github.com/xavier-lam/wechat-django","last_synced_at":"2025-05-16T00:07:16.884Z","repository":{"id":62588617,"uuid":"171990883","full_name":"Xavier-Lam/wechat-django","owner":"Xavier-Lam","description":"WeChat-Django旨在为接入微信公众平台的django开发者提供便捷的微信功能封装及最基本的后台管理支持","archived":false,"fork":false,"pushed_at":"2024-12-11T05:36:34.000Z","size":1680,"stargazers_count":203,"open_issues_count":2,"forks_count":64,"subscribers_count":8,"default_branch":"master","last_synced_at":"2025-05-09T07:32:42.346Z","etag":null,"topics":["django","wechat","wechatpay","weixin","wx"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Xavier-Lam.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-02-22T03:51:44.000Z","updated_at":"2025-05-08T12:43:27.000Z","dependencies_parsed_at":"2024-01-16T22:21:56.199Z","dependency_job_id":"5556b0e1-a427-4992-b07f-2abe36819732","html_url":"https://github.com/Xavier-Lam/wechat-django","commit_stats":null,"previous_names":[],"tags_count":9,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Xavier-Lam%2Fwechat-django","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Xavier-Lam%2Fwechat-django/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Xavier-Lam%2Fwechat-django/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Xavier-Lam%2Fwechat-django/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Xavier-Lam","download_url":"https://codeload.github.com/Xavier-Lam/wechat-django/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254442854,"owners_count":22071878,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["django","wechat","wechatpay","weixin","wx"],"created_at":"2024-12-02T18:11:45.932Z","updated_at":"2025-05-16T00:07:11.867Z","avatar_url":"https://github.com/Xavier-Lam.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# WeChat-Django\n\n[![PyPI](https://img.shields.io/pypi/v/wechat-django.svg)](https://pypi.org/project/wechat-django)\n[![Build Status](https://travis-ci.org/Xavier-Lam/wechat-django.svg?branch=master)](https://travis-ci.org/Xavier-Lam/wechat-django)\n[![Donate with Bitcoin](https://en.cryptobadges.io/badge/micro/1BdJG31zinrMFWxRt2utGBU2jdpv8xSgju)](https://en.cryptobadges.io/donate/1BdJG31zinrMFWxRt2utGBU2jdpv8xSgju)\n\n**WeChat-Django**旨在为接入微信公众平台的django开发者提供便捷的微信及微信支付功能封装及基本的[**后台管理支持**](docs/admin.md).\n\n项目官方地址: https://github.com/Xavier-Lam/wechat-django\n\n本拓展基于[wechatpy](https://github.com/jxtech/wechatpy) ,支持的最低django版本为1.11. WeChat-Django只是一个预览版本,可能存在较多bug并且有api及数据结构变更可能,请密切关注[CHANGELOG](CHANGELOG.md)).\n\n目录\n======\n- [功能](#%e5%8a%9f%e8%83%bd)\n- [安装及配置](#%e5%ae%89%e8%a3%85%e5%8f%8a%e9%85%8d%e7%bd%ae)\n  - [初次安装](#%e5%88%9d%e6%ac%a1%e5%ae%89%e8%a3%85)\n  - [直接加入项目](#%e7%9b%b4%e6%8e%a5%e5%8a%a0%e5%85%a5%e9%a1%b9%e7%9b%ae)\n  - [更新](#%e6%9b%b4%e6%96%b0)\n  - [配置](#%e9%85%8d%e7%bd%ae)\n  - [日志](#%e6%97%a5%e5%bf%97)\n  - [注意事项](#%e6%b3%a8%e6%84%8f%e4%ba%8b%e9%a1%b9)\n- [部分功能使用说明](#%e9%83%a8%e5%88%86%e5%8a%9f%e8%83%bd%e4%bd%bf%e7%94%a8%e8%af%b4%e6%98%8e)\n  - [网页授权](#%e7%bd%91%e9%a1%b5%e6%8e%88%e6%9d%83)\n  - [小程序授权](#%e5%b0%8f%e7%a8%8b%e5%ba%8f%e6%8e%88%e6%9d%83)\n    - [小程序信息加解密及用户数据更新](#%e5%b0%8f%e7%a8%8b%e5%ba%8f%e4%bf%a1%e6%81%af%e5%8a%a0%e8%a7%a3%e5%af%86%e5%8f%8a%e7%94%a8%e6%88%b7%e6%95%b0%e6%8d%ae%e6%9b%b4%e6%96%b0)\n  - [主动调用微信api](#%e4%b8%bb%e5%8a%a8%e8%b0%83%e7%94%a8%e5%be%ae%e4%bf%a1api)\n  - [自定义微信回复](#%e8%87%aa%e5%ae%9a%e4%b9%89%e5%be%ae%e4%bf%a1%e5%9b%9e%e5%a4%8d)\n  - [微信支付](#%e5%be%ae%e4%bf%a1%e6%94%af%e4%bb%98)\n    - [统一下单](#%e7%bb%9f%e4%b8%80%e4%b8%8b%e5%8d%95)\n    - [订单更新(回调)通知](#%e8%ae%a2%e5%8d%95%e6%9b%b4%e6%96%b0%e5%9b%9e%e8%b0%83%e9%80%9a%e7%9f%a5)\n  - [django-rest-framework](#django-rest-framework)\n- [后台使用简介](#%e5%90%8e%e5%8f%b0%e4%bd%bf%e7%94%a8%e7%ae%80%e4%bb%8b)\n- [示例项目](#%e7%a4%ba%e4%be%8b%e9%a1%b9%e7%9b%ae)\n- [TODOS:](#todos)\n  - [计划的功能](#%e8%ae%a1%e5%88%92%e7%9a%84%e5%8a%9f%e8%83%bd)\n  - [已知bugs](#%e5%b7%b2%e7%9f%a5bugs)\n- [Changelog](#changelog)\n\n\n## 功能\n* 公众号管理\n* 同步用户及用户查看,备注,用户标签管理\n* 菜单同步,查看及发布\n* 同步公众号自动回复,管理自动回复,转发和自定义自动回复业务,接收消息日志\n* 模板消息模板的同步及发送\n* 永久素材,图文的同步及查看\n* 微信网页授权\n* [微信jsapi配置](docs/cookbook/web.md#jsapi)\n* 主动调用微信api封装\n* 微信支付api封装\n* 微信支付订单管理及信号\n* 后台权限管理\n* django-rest-framework APIView兼容\n* 迁移公众号自动回复/菜单/素材(不建议)\n\n## 安装及配置\n### 初次安装\n1. 运行**pip install wechat-django[cryptography]** 或 **pip install wechat-django[pycrypto]** 安装\n2. 在settings.py的**INSTALLED_APPS中添加wechat_django**\n3. 运行**manage.py migrate wechat_django** 来更新数据库结构\n4. 在urls.py 中引入wechat_django.sites.wechat.urls, 将其配置到urlpatterns中\n5. 在settings.py中,设置`USE_TZ = True`\n\n至此,您已可以开始轻松使用wechat_django.项目尚未提供具体的使用文档,如需客制化需求,烦请先阅读代码\n\n### 直接加入项目\n想使用最新特性或是自行编辑代码,可clone本项目后,采用pip install -e 直接安装到你的django项目目录\n\n### 更新\n1. 运行**pip install -U wechat-django**\n2. 运行**python manage.py migrate** 来更新数据库结构\n\n### 配置\n一般而言,默认配置足以满足需求\n\n| 参数名 | 默认值 | 说明 |\n| --- | --- | --- |\n| WECHAT_SITE_HOST | None | 用于接收微信回调的默认域名 |\n| WECHAT_SITE_HTTPS | True | 接收微信回调域名是否是https |\n| WECHAT_PATCHADMINSITE | True | 是否将django默认的adminsite替换为wechat_django默认的adminsite, 默认替换 |\n| WECHAT_SESSIONSTORAGE | \"django.core.cache.cache\" | 用于存储微信accesstoken等数据的[`wechatpy.session.SessionStorage`](https://wechatpy.readthedocs.io/zh_CN/master/quickstart.html#id10) 对象,或接收 `wechat_django.models.WeChatApp` 对象并生成其实例的工厂方法 |\n| WECHAT_MESSAGETIMEOFFSET | 180 | 微信请求消息时,timestamp与服务器时间差超过该值的请求将被抛弃 |\n| WECHAT_MESSAGENOREPEATNONCE | True | 是否对微信消息防重放检查 默认检查 |\n\n### 日志\n| logger | 说明 |\n| --- | --- |\n| wechat.admin.{appname} | admin异常日志 最低级别warning |\n| wechat.api.{appname} | api日志 最低级别debug |\n| wechat.handler.{appname} | 消息处理日志 最低级别debug |\n| wechat.oauth.{appname} | 网页授权异常日志 最低级别warning |\n| wechat.site.{appname} | 站点view异常日志(如素材代理) 最低级别warning |\n\n### 注意事项\n* 框架默认采用django的cache管理accesstoken,如果有多个进程,或是多台机器部署,请确保所有worker使用公用cache以免造成token争用,如果希望不使用django的cache管理accesstoken,可以在配置项中定义SessionStorage\n* 请确保在https环境下部署,否则有secretkey泄露的风险\n\n## 部分功能使用说明\n### 网页授权\n可通过`wechat_django.oauth.wechat_auth`装饰器进行网页授权,授权后,request将被附上一个名为wechat的`wechat_django.oauth.WeChatOAuthInfo` 对象,可通过 request.wechat.user 拿到`wechat_django.models.WeChatUser`实例,通过 request.wechat.app 拿到`wechat_django.models.WeChatApp`实例,以下是一个基本示例\n\n    from wechat_django import wechat_auth\n\n    @wechat_auth(\"your_app_name\")\n    def your_view(request, *args, **kwargs):\n        \"\"\":type request: wechat_django.requests.WeChatOAuthRequest\"\"\"\n        user = request.wechat.user\n\n对于默认重定向行为不满意的,可以自定义response,具体的参数说明参见`wechat_django.oauth.wechat_auth`装饰器的docstring\n\n对于class based view,可继承`wechat_django.oauth.WeChatOAuthView`类,具体参见代码\n\n\n### 小程序授权\n通过`wechat_django.models.WeChatApp.auth`进行授权,输入客户端传来的code, 输出一个用户对象以及原始响应.这个方法只能拿到用户的openid与unionid.\n\n    from wechat_django.models import WeChatApp\n    app = WeChatApp.objects.get_by_name(\"your app name\")\n    user, data = app.auth(code)\n\n对于授权后得到的session_key,框架会持久化至数据库,此后可以通过调用`wechat_django.models.WeChatUser.session`来执行相关操作.\n\nauth方法同样适用于网页授权,第二个参数填写网页授权的scope,默认base.\n\n#### 小程序信息加解密及用户数据更新\n对于已经进行过小程序授权并且session_key尚未过期的用户,可以使用`wechat_django.models.Session.decrypt_message`来解密客户端传来的敏感数据\n\n    encrypted_data = \"\"\n    iv = \"\"\n    try:\n        data = user.session.decrypt_message(\n            encrypted_data, iv)\n    except ValueError:\n        pass # 无法正确解密数据 session_key可能过期了\n\n\n亦可使用`wechat_django.models.Session.validate_message`来校验客户端传来的数据\n\n    from wechatpy.exceptions import InvalidSignatureException\n\n    signature = \"\"\n    raw_data = \"\"\n    try:\n        data = user.session.validate_message(raw_data, signature)\n    except InvalidSignatureException:\n        pass # 签名错误 session_key可能过期了\n\n客户端调用`wx.getUserInfo`,可将rawData与signature传递至后端,后端通过调用`wechat_django.models.Session.validate_message`与`wechat_django.models.User.update`来更新用户信息\n\n    from django.http.response import HttpResponse\n    from wechatpy.exceptions import InvalidSignatureException\n\n    signature = request.POST[\"signature\"]\n    raw_data = request.POST[\"rawData\"]\n    \n    try:\n        data = user.session.validate_message(raw_data, signature)\n    except InvalidSignatureException:\n        return HttpResponse(status=401)\n\n使用update方法更新用户数据\n\n    user.update(data)\n\n### 主动调用微信api\n    from wechat_django.models import WeChatApp\n    app = WeChatApp.get_by_name(\"your app name\")\n    data = app.client.user.get_followers()\n\n具体client的使用方式,请移步[wechatpy文档](https://wechatpy.readthedocs.io/zh_CN/master/client/index.html)\n\n### 自定义微信回复\n在后台配置自定义回复,填写自定义回复处理代码的路径,代码须由 `wechat_django.handler.message_handler` 装饰对应的方法接收一个 `wechat_django.models.WeChatMessageInfo` 对象,返回字符串或一个 [`wechatpy.replies.BaseReply`](https://wechatpy.readthedocs.io/zh_CN/master/replies.html) 对象\n\n    from wechat_django import message_handler\n\n    @message_handler\n    def custom_business(message):\n        \"\"\"\n        :type message: wechat_django.models.WeChatMessageInfo\n        \"\"\"\n        user = message.user\n        msg = message.message\n        text = \"hello, {0}! we received a {1} message.\".format(\n            user, msg.type)\n        return TextReply(content=text.encode())\n\n### 微信支付\n使用微信支付,需要在INSTALLED_APP的`wechat_django`后添加`wechat_django.pay`.\n\n#### 统一下单\n\n    from wechat_django.models import WeChatApp\n    app = WeChatApp.objects.get_by_name(\"your app name\")\n    order = app.pay.create_order(\n        user=\"user-instance\", body=\"body\", total_fee=1,\n        out_trade_no=\"***debug***20190613001\") # 也可以用openid=\"openid\"代替user参数\n    prepay = order.prepay(request)\n\n将jsapi参数交给前端\n\n    jsapi_params = order.jsapi_params(prepay[\"prepay_id\"])\n\n主动查询订单状态\n\n    order.sync()\n\n#### 订单更新(回调)通知\n\n当订单更新时,会发出`wechat_django.pay.signals.order_updated`信号,sender为订单`wechat_django.utils.func.Static(\"{appname}.{payname}\")`.信号提供4个变量\n\n| 变量 | 说明 |\n| --- | --- |\n| result | 订单结果(`wechat_django.pay.models.UnifiedOrderResult`) |\n| order | 更新的订单(`wechat_django.pay.models.UnifiedOrder`) |\n| state | 订单状态(`wechat_django.pay.models.UnifiedOrderResult.State`) |\n| attach | 结果附带的信息(生成订单时传给微信服务器的attach) |\n\n使用示例\n\n    from django.dispatch import receiver\n    from wechat_django.pay import signals\n    \n    @receiver(signals.order_updated)\n    def order_updated(result, order, state, attach):\n        if state == UnifiedOrderResult.State.SUCCESS:\n            pass\n\n\u003e 注意! 每次主动调用,微信通知或是后台重新触发都会发送信号,请自行确保订单成功信号逻辑只执行一次!\n\n### django-rest-framework\n本项目class-based OAuth授权兼容django-rest-framework.\n\n  1. 构造一个继承`wechat_django.oauth.WeChatOAuthViewMixin`的视图类;\n  2. 在视图类中定义`appname`属性;\n  3. 根据需要,定义`permission_classes`(如若资源必须授权才可访问,请在permission_classes中添加`wechat_django.oauth.WeChatAuthenticated`);\n  4. 根据需要,自行处理异常,在`handle_exception`方法中捕获`rest_framework.exceptions.NotAuthenticated`,自行处理.\n\n可以参见示例项目的[rest.py](sample/wechat/rest.py)文件.\n\n## 后台使用简介\n参见[管理后台使用简介](docs/admin.md) 文档\n\n## 示例项目\n可参考[本项目sample文件夹](sample)\n\n## TODOS:\n* 是否可做成migrate权限全自助?重构权限模块?\n* 可选加密存储敏感数据\n* [Cookbook](docs/cookbook/readme.md)\n* app层面的message log和reply log\n* 完善单元测试\n* 后台表单验证\n\n### 计划的功能\n* 命令行工具\n* 第三方平台接入\n* accesstoken开放给第三方并对接第三方accesstoken\n* 客服消息/对话\n* 清理及保护永久素材\n* 回复及一些查询缓存\n* 菜单及消息处理程序的导入导出\n* 素材Storage\n\n### 已知bugs\n* 多次同步消息处理器会重复生成永久素材\n\n## [Changelog](CHANGELOG.md)\n\n\nXavier-Lam@NetDragon","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fxavier-lam%2Fwechat-django","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fxavier-lam%2Fwechat-django","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fxavier-lam%2Fwechat-django/lists"}