@@ -6,6 +6,7 @@ from pay.models import OrderInfo |
||
| 6 | 6 |
|
| 7 | 7 |
|
| 8 | 8 |
class OrderInfoAdmin(admin.ModelAdmin): |
| 9 |
+ readonly_fields = ('order_id', 'prepay_id', 'transaction_id', 'unifiedorder_result', 'notify_msg')
|
|
| 9 | 10 |
list_display = ('order_id', 'photo_type', 'photo_status', 'from_uid', 'to_uid', 'pay_status', 'paid_at', 'reback_status', 'reback_at', 'status', 'created_at', 'updated_at')
|
| 10 | 11 |
list_filter = ('photo_type', 'photo_status', 'pay_status', 'reback_status', 'status')
|
| 11 | 12 |
|
@@ -0,0 +1,30 @@ |
||
| 1 |
+# -*- coding: utf-8 -*- |
|
| 2 |
+# Generated by Django 1.11.3 on 2017-07-13 23:59 |
|
| 3 |
+from __future__ import unicode_literals |
|
| 4 |
+ |
|
| 5 |
+from django.db import migrations, models |
|
| 6 |
+ |
|
| 7 |
+ |
|
| 8 |
+class Migration(migrations.Migration): |
|
| 9 |
+ |
|
| 10 |
+ dependencies = [ |
|
| 11 |
+ ('pay', '0007_orderinfo_unifiedorder_result'),
|
|
| 12 |
+ ] |
|
| 13 |
+ |
|
| 14 |
+ operations = [ |
|
| 15 |
+ migrations.AddField( |
|
| 16 |
+ model_name='orderinfo', |
|
| 17 |
+ name='notify_msg', |
|
| 18 |
+ field=models.TextField(blank=True, help_text='\u56de\u8c03\u4fe1\u606f', null=True, verbose_name='notify_msg'), |
|
| 19 |
+ ), |
|
| 20 |
+ migrations.AddField( |
|
| 21 |
+ model_name='orderinfo', |
|
| 22 |
+ name='prepay_id', |
|
| 23 |
+ field=models.CharField(blank=True, help_text='\u9884\u652f\u4ed8\u4ea4\u6613\u4f1a\u8bdd\u6807\u8bc6', max_length=255, null=True, verbose_name='prepay_id'), |
|
| 24 |
+ ), |
|
| 25 |
+ migrations.AddField( |
|
| 26 |
+ model_name='orderinfo', |
|
| 27 |
+ name='transaction_id', |
|
| 28 |
+ field=models.CharField(blank=True, help_text='\u5fae\u4fe1\u8ba2\u5355\u53f7', max_length=255, null=True, verbose_name='transaction_id'), |
|
| 29 |
+ ), |
|
| 30 |
+ ] |
@@ -53,6 +53,9 @@ class OrderInfo(CreateUpdateMixin): |
||
| 53 | 53 |
|
| 54 | 54 |
order_id = ShortUUIDField(_(u'order_id'), max_length=255, help_text=u'订单唯一标识', db_index=True) |
| 55 | 55 |
|
| 56 |
+ prepay_id = models.CharField(_('prepay_id'), max_length=255, blank=True, null=True, help_text=u'预支付交易会话标识')
|
|
| 57 |
+ transaction_id = models.CharField(_('transaction_id'), max_length=255, blank=True, null=True, help_text=u'微信订单号')
|
|
| 58 |
+ |
|
| 56 | 59 |
group_id = models.CharField(_(u'group_id'), max_length=255, blank=True, null=True, help_text=u'群组唯一标识', db_index=True) |
| 57 | 60 |
session_id = models.CharField(_(u'session_id'), max_length=255, blank=True, null=True, help_text=u'照片组唯一标识,同 PhotosInfo 表', db_index=True) |
| 58 | 61 |
photo_id = models.CharField(_(u'photo_id'), max_length=255, blank=True, null=True, help_text=u'飞图唯一标识', db_index=True) |
@@ -75,7 +78,10 @@ class OrderInfo(CreateUpdateMixin): |
||
| 75 | 78 |
reback_status = models.BooleanField(_(u'reback_status'), default=False, help_text=u'退款状态', db_index=True) |
| 76 | 79 |
reback_at = models.DateTimeField(_(u'reback_at'), blank=True, null=True, help_text=_(u'退款时间')) |
| 77 | 80 |
|
| 81 |
+ # 微信统一下单 |
|
| 78 | 82 |
unifiedorder_result = models.TextField(_(u'unifiedorder_result'), blank=True, null=True, help_text=_(u'统一下单结果')) |
| 83 |
+ # 微信支付回调 |
|
| 84 |
+ notify_msg = models.TextField(_('notify_msg'), blank=True, null=True, help_text=u'回调信息')
|
|
| 79 | 85 |
|
| 80 | 86 |
class Meta: |
| 81 | 87 |
verbose_name = _('orderinfo')
|
@@ -1,6 +1,5 @@ |
||
| 1 | 1 |
# -*- coding: utf-8 -*- |
| 2 | 2 |
|
| 3 |
-import xmltodict |
|
| 4 | 3 |
from django.conf import settings |
| 5 | 4 |
from django.db import transaction |
| 6 | 5 |
from django.shortcuts import HttpResponse |
@@ -9,6 +8,8 @@ from paginator import pagination |
||
| 9 | 8 |
from pywe_exception import WeChatPayException |
| 10 | 9 |
from pywe_pay import WeChatPay |
| 11 | 10 |
from pywe_response import WXPAY_NOTIFY_FAIL, WXPAY_NOTIFY_SUCCESS |
| 11 |
+from pywe_sign import check_signature |
|
| 12 |
+from pywe_xml import xml_to_dict |
|
| 12 | 13 |
from TimeConvert import TimeConvert as tc |
| 13 | 14 |
|
| 14 | 15 |
from account.models import UserIncomeExpensesInfo, UserInfo |
@@ -100,6 +101,9 @@ def wx_order_create_api(request): |
||
| 100 | 101 |
return response(OrderStatusCode.WX_UNIFIED_ORDER_FAIL) |
| 101 | 102 |
|
| 102 | 103 |
prepay_id = prepay_data.get('prepay_id', '')
|
| 104 |
+ order.prepay_id = prepay_id |
|
| 105 |
+ order.save() |
|
| 106 |
+ |
|
| 103 | 107 |
if trade_type == 'JSAPI' or trade_type == 'MINIAPP': |
| 104 | 108 |
wxpay_params = wxpay.jsapi.get_jsapi_params(prepay_id) |
| 105 | 109 |
elif trade_type == 'APP': |
@@ -204,7 +208,7 @@ def wx_order_query_api(request): |
||
| 204 | 208 |
# 订单查询 |
| 205 | 209 |
query_data = wxpay.order.query(transaction_id, order_id) |
| 206 | 210 |
# 签名校验 |
| 207 |
- if not wxpay.check_signature(query_data): |
|
| 211 |
+ if not check_signature(query_data): |
|
| 208 | 212 |
return response(OrderStatusCode.SIGN_CHECK_FAIL) |
| 209 | 213 |
|
| 210 | 214 |
# 交易状态 |
@@ -262,36 +266,36 @@ def wx_order_detail_api(request): |
||
| 262 | 266 |
@transaction.atomic |
| 263 | 267 |
def wx_notify_url_api(request): |
| 264 | 268 |
""" 支付异步通知回调地址 """ |
| 265 |
- try: |
|
| 266 |
- data = xmltodict.parse(request.body)['xml'] |
|
| 267 |
- except xmltodict.ParsingInterrupted: |
|
| 268 |
- # 解析 XML 失败 |
|
| 269 |
+ data = xml_to_dict(request.body) |
|
| 270 |
+ if isinstance(data, basestring): |
|
| 269 | 271 |
return HttpResponse(WXPAY_NOTIFY_FAIL) |
| 270 | 272 |
|
| 271 | 273 |
trade_type = data.get('trade_type', '')
|
| 272 | 274 |
|
| 273 |
- # 根据 trade_type 获取 wechat 配置 |
|
| 274 |
- wechat = WECHAT.get(trade_type, {})
|
|
| 275 |
- # WeChatPay 初始化 |
|
| 276 |
- wxpay = WeChatPay(wechat.get('appID'), wechat.get('apiKey'), wechat.get('mchID'))
|
|
| 277 |
- |
|
| 278 | 275 |
# 签名校验 |
| 279 |
- if not wxpay.check_signature(data): |
|
| 280 |
- return response(OrderStatusCode.SIGN_CHECK_FAIL) |
|
| 276 |
+ if not check_signature(data, settings.WECHAT.get(trade_type, {}).get('apiKey')):
|
|
| 277 |
+ return HttpResponse(WXPAY_NOTIFY_FAIL) |
|
| 281 | 278 |
|
| 282 |
- out_trade_no = data.get('out_trade_no', '')
|
|
| 279 |
+ # 通信标识 |
|
| 283 | 280 |
return_code = data.get('return_code', '')
|
| 284 |
- result_code = data.get('result_code', '')
|
|
| 285 |
- |
|
| 286 |
- if return_code != 'SUCCESS' or result_code != 'SUCCESS': |
|
| 281 |
+ if return_code != 'SUCCESS': |
|
| 287 | 282 |
return HttpResponse(WXPAY_NOTIFY_FAIL) |
| 288 | 283 |
|
| 284 |
+ out_trade_no = data.get('out_trade_no', '')
|
|
| 289 | 285 |
try: |
| 290 | 286 |
order = OrderInfo.objects.get(order_id=out_trade_no) |
| 291 | 287 |
except OrderInfo.DoesNotExist: |
| 292 | 288 |
return response(OrderStatusCode.WX_ORDER_NOT_FOUND) |
| 293 | 289 |
|
| 294 |
- order_paid_success(order) |
|
| 290 |
+ order.notify_msg = request.body |
|
| 291 |
+ order.transaction_id = data.get('transaction_id', '')
|
|
| 292 |
+ order.save() |
|
| 293 |
+ |
|
| 294 |
+ result_code = data.get('result_code', '')
|
|
| 295 |
+ if result_code == 'SUCCESS': |
|
| 296 |
+ order_paid_success(order) |
|
| 297 |
+ else: |
|
| 298 |
+ order_paid_fail(order) |
|
| 295 | 299 |
|
| 296 | 300 |
return HttpResponse(WXPAY_NOTIFY_SUCCESS) |
| 297 | 301 |
|
@@ -31,6 +31,8 @@ pywe-miniapp==1.0.0 |
||
| 31 | 31 |
pywe-oauth==1.0.3 |
| 32 | 32 |
pywe-pay==1.0.5 |
| 33 | 33 |
pywe-response==1.0.1 |
| 34 |
+pywe-sign==1.0.5 |
|
| 35 |
+pywe-xml==1.0.0 |
|
| 34 | 36 |
qiniu==7.1.4 |
| 35 | 37 |
redis-extensions==1.0.50 |
| 36 | 38 |
requests==2.18.1 |