@@ -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 |