Django 微信小程序 API 是依赖于 django-rest-framework 制作的restful api,封装了微信小程序的登陆,用户资料更新,微信小程序支付等一系列操作。为开发者提供微信小程序后台的简便操作。
(已完成用户登录,更新用户信息,以及微信小程序支付等一部分API,其他功能完善中……)
pip install django_miniprogram_api
-
添加 "miniprogram_api" 和 django-rest-framework 相关的 modules 以及 配置 到 INSTALLED_APPS,并且添加 WECHAT_MINIPROGRAM_CONFIG 配置文件::
INSTALLED_APPS = [ 'miniprogram_api', 'rest_framework.authtoken', 'rest_framework' ] WECHAT_MINIPROGRAM_CONFIG = { "APPID": "", "SECRET": "", "WECHAT_PAY": { "MCH_ID": "", # 微信支付商户号 "KEY": "", # API密钥 "NOTIFICATION_URL": '', # 微信支付回调地址 } } REST_FRAMEWORK = { 'DEFAULT_PERMISSION_CLASSES': [ ... 'rest_framework.authentication.BasicAuthentication', # add this 'rest_framework.authentication.TokenAuthentication', # add this ], 'DEFAULT_PARSER_CLASSES': ( 'rest_framework.parsers.JSONParser', 'rest_framework_xml.parsers.XMLParser', ), }
-
配置小程序登陆 url /miniprogram_auth/ 到你项目的 urls.py::
url(r'^miniprogram_auth/', include('miniprogram_api.urls')),
-
运行
python manage.py migrate
来创建 WeChatAccount 模型. -
运行测试服务器
python manage.py runserver 127.0.0.1:8000
就可以开始使用了
请求
http://127.0.0.1/miniprogram_auth/login
method: post,
body:
{
"code": "061YsgK50ru0wC1uCHH50D2mK50YsgKa"
}
登陆模块包括了微信 auth.code2Session 接口,开发者通过调用 wx.login() 获取临时登录凭证code,发送给 我们的 Login api,获取 django 的用户登录状态 Token。
返回
{
"token": "fa7cd4cdb5554a9b69b876d6c6bf775ac6be250d", // 返回的token 需要包含在 request header
"user_id": 1
}
在你的请求头包含token信息,要注意的是如果你没有自定义的登录状态,例如:用户手机号邮箱注册登录,那么请在之后的api中都使用同样的token请求头。
Authorization: Token fa7cd4cdb5554a9b69b876d6c6bf775ac6be250d
请求
http://127.0.0.1/miniprogram_auth/updateUserInfo
method: post,
body:
{
"iv":"QRWwdpUUx9zaN4fXGM4Asw==",
"encryptedData": "F7VcR8vKZqzaEqS18f7qJ3VuYLl5AjExEHldqC3og3XOKlZPg+U9ki/onlrjrG9OLZDyJrno/nEegXH9V/1sMzGFpCCqhR9MHVTaq9fyANOVazniVmkzwysD0dwwk9bj4Uulz3KuqtTwoI2VFXEAmuj0kzCG1atqCo5RXZnZ30M8O3mbnSPAvDb6pEBBgT6YoQGuIskYQ82kIO3Z/ZtX8XCcmYAjagUkie1CGZUcYd5VxtSL6iGd+HVwxC1rspvda1OcgIdRlU/tIA3Euhbd4qKuqlmR6LJVdZNs9gg/CMY1ZGcRQnz8cbQWUqFOEaZQHU/oiXeDmo5V/HeQXzv9c+lgZ+SMk81VNLC8/T4SF5ivaoULHV/Th+jqYKDjJGwDAbM4tK+4Gkb45QFny3ZDh/09Fk9TwtfR2nkH/Wxpyyhkp0DPbhvd8oq8wH13I0XbsO0WuM0D8YpZF+H74CiiPDiKRzPEpLKU2nCWdlpHDZ0="
}
开发者通过调用接口(如 wx.getUserInfo)获取数据时,接口会同时返回 encryptedData, iv 数据,将此数据发送给updateUserInfo api,API 将会解密数据,以获取用户信息并返回。(此操作一般在小程序授权用户信息时使用,微信小程序的新登录规则,登陆实际上是限制的 wx.getUserInfo 接口)
返回
{
"token": "fa7cd4cdb5554a9b69b876d6c6bf775ac6be250d",
"wechat": {
"id": 1,
"nickName": "TINCHY",
"avatarUrl": "https://wx.qlogo.cn/mmopen/vi_32/Q0j4TwGTfTLp9mKpmqTUic0TmCMo6Cbibmsvmo6Vt3NGdP0cZOYRwoGPe13LsvHEicoZGvjq6syaeG0GGWJOrqCbA/132",
"gender": "1",
"city": "Shanghai",
"province": null,
"country": null,
"user": 1
}
}
微信支付的api因为每一个操作都要求不同,不同用户不同场景都有需求,因此没有封装HTTP API,但是提供了一个简单封装的object,以及提供了一个订单状态 Model:PayOrder
想要获取订单状态,请将自己的商品 OneToOne 到 PayOrder, 例如:
class PickUpOrder(models.Model):
wechat_order = models.OneToOneField(PayOrder)
...
@receiver(post_save, sender=PickUpOrder)
def create_order(sender, instance, created, **kwargs):
if created:
PayOrder.objects.create(pickuporder=instance, outTradeNo='')
接口返回等数据请查询微信支付官方文档 https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1
WeChatPay().unified_order(
spbill_create_ip='''小程序用户的IP地址''',
open_id='''小程序用户的open id''',
body='''商品描述''',
order_id='''订单id,必须唯一,建议使用日期时间戳''',
total_fee='''订单金额,单位为分!!!!'''
)
简单例子:
微信统一下单接口:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1
from .model import PickupOrder # 这个model是我的测试model,用于订单查询
from django.conf import settings # 导入 settings
from .wechat_pay import WeChatPay, WeChatSignHelper # 导入 微信支付 api 以及 签名验证
from miniprogram_api.model import WeChatAccount
from rest_framework import views, status
class WeChatPayAPIView(views.APIView):
permission_classes = [IsAuthenticated]
def post(self, request):
from django.utils.datetime_safe import datetime
data = request.data
_id = data['id']
if not PickupOrder.objects.filter(id=data['id']).exists():
raise ValidationError('This order does not exists')
item = PickupOrder.objects.get(id=data['id'])
if not item.payorder.paid: # 如果未付款
outTradeNo = datetime.utcnow().strftime('%Y%m%d%H%M%S%f')[:-3] # 生成 order_id 用时间精确到分秒以保证订单号的唯一性
item.order_id = outTradeNo
item.payorder.outTradeNo = outTradeNo # 将订单号保存到 数据库
item.save()
wechat_user = WeChatAccount.objects.get(user=self.request.user)
wp = WeChatPay()
address = self.request.META.get('HTTP_X_FORWARDED_FOR') # 获取小程序访问用户的 ip 地址
if address:
ip = address.split(',')[0]
else:
ip = address.META.get('REMOTE_ADDR')
res = wp.unified_order(spbill_create_ip=ip,open_id=wechat_user.union_id, body=item.car_type.desc, total_fee=item.fee, order_id=item.order_id)
if res['return_code'] == 'SUCCESS' and res['result_code'] == 'SUCCESS':
pay_sign = {
'appId': settings.WECHAT_MINIPROGRAM_CONFIG['APPID'],
'nonceStr': wp.ranstr(16),
'package': 'prepay_id='+res['prepay_id'],
'signType': 'MD5',
'timeStamp': str(time.time())
}
sign = WeChatSignHelper(pay_sign, settings.WECHAT_MINIPROGRAM_CONFIG['WECHAT_PAY']['KEY']).getSign()
pay_sign['paySign'] = sign # 签名验证支付订单的正确性
return Response({'pay_sign': pay_sign}) # 返回给小程序发起小程序的支付接口
else:
return Response("Make order failed", status=status.HTTP_406_NOT_ACCEPTABLE)
下单之后,系统会根据您在settings.py中设置的 NOTIFICATION_URL 进行回调,来更新用户的订单状态。务必设置正确。(本地环境运行的服务器,微信无法进行回调,务必在生产或者测试服务器上运行)
WECHAT_MINIPROGRAM_CONFIG = {
"WECHAT_PAY": {
"NOTIFICATION_URL": 'http://www.example.com/miniprogram_auth/wechatPayCallback', # 填写你的服务器地址加回调域名
}
}
微信查询订单接口:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_2
WeChatPay().order_query(
transaction_id='''微信的订单号,建议优先使用''',
out_trade_no='''商户系统内部订单号,要求32个字符内, 这里指的是 order_id, 即订单号'''
)
# transaction_id 和 out_trade_no 只需要选一个,不要全部填写
微信关闭订单接口:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_3
WeChatPay().close_order(
out_trade_no='''商户系统内部订单号,要求32个字符内, 这里指的是 order_id, 即订单号'''
)
BSD 3-Clause License
Tinchy:[email protected]