add api wx_order_query_api

Brightcells лет %!s(int64=9): %!d(string=назад)
Родитель
Сommit
0f425ae151
5 измененных файлов с 132 добавлено и 4 удалено
  1. 1 0
      api/urls.py
  2. 19 0
      pay/migrations/0002_orderinfo_trade_type.py
  3. 16 1
      pay/models.py
  4. 91 3
      pay/views.py
  5. 5 0
      utils/error/errno_utils.py

+ 1 - 0
api/urls.py

@@ -77,6 +77,7 @@ urlpatterns += [
77 77
 # 支付相关
78 78
 urlpatterns += [
79 79
     url(r'^wx/order_create$', pay_views.wx_order_create_api, name='wx_order_create_api'),  # 订单创建
80
+    url(r'^wx/order_query$', pay_views.wx_order_query_api, name='wx_order_query_api'),  # 订单查询
80 81
     url(r'^wx/notify_url$', pay_views.wx_notify_url_api, name='wx_notify_url_api'),  # 支付异步通知回调地址
81 82
 ]
82 83
 

+ 19 - 0
pay/migrations/0002_orderinfo_trade_type.py

@@ -0,0 +1,19 @@
1
+# -*- coding: utf-8 -*-
2
+from __future__ import unicode_literals
3
+
4
+from django.db import models, migrations
5
+
6
+
7
+class Migration(migrations.Migration):
8
+
9
+    dependencies = [
10
+        ('pay', '0001_initial'),
11
+    ]
12
+
13
+    operations = [
14
+        migrations.AddField(
15
+            model_name='orderinfo',
16
+            name='trade_type',
17
+            field=models.CharField(help_text='\u652f\u4ed8\u65b9\u5f0f', max_length=255, null=True, verbose_name='trade_type', blank=True),
18
+        ),
19
+    ]

+ 16 - 1
pay/models.py

@@ -10,13 +10,26 @@ from pai2.basemodels import CreateUpdateMixin
10 10
 
11 11
 
12 12
 class OrderInfo(CreateUpdateMixin):
13
+    """
14
+    # Trade State of Wechat Query
15
+    SUCCESS ——— 支付成功
16
+    REFUND ——— 转入退款
17
+    NOTPAY ——— 未支付
18
+    CLOSED ——— 已关闭
19
+    REVOKED ——— 已撤销(刷卡支付)
20
+    USERPAYING ——— 用户支付中
21
+    PAYERROR ——— 支付失败(其他原因,如银行返回失败)
22
+    """
23
+
13 24
     WAITING_PAY = 0
14 25
     PAID = 1
15
-    # DELETED = 2
26
+    FAIL = 2
27
+    # DELETED = 9
16 28
 
17 29
     PAY_STATUS = (
18 30
         (WAITING_PAY, u'待支付'),
19 31
         (PAID, u'已支付'),
32
+        (FAIL, u'已失败'),
20 33
         # (DELETED, u'已删除'),
21 34
     )
22 35
 
@@ -29,6 +42,8 @@ class OrderInfo(CreateUpdateMixin):
29 42
     body = models.CharField(_(u'body'), max_length=255, blank=True, null=True, help_text=u'商品描述')
30 43
     total_fee = models.IntegerField(_(u'total_fee'), default=0, help_text=u'总金额')
31 44
 
45
+    trade_type = models.CharField(_('trade_type'), max_length=255, blank=True, null=True, help_text=u'支付方式')
46
+
32 47
     pay_status = models.IntegerField(_(u'pay_status'), choices=PAY_STATUS, default=WAITING_PAY, help_text=u'支付状态', db_index=True)
33 48
     paid_at = models.DateTimeField(_(u'paid_at'), blank=True, null=True, help_text=_(u'支付时间'))
34 49
 

+ 91 - 3
pay/views.py

@@ -45,7 +45,13 @@ def wx_order_create_api(request):
45 45
     wxpay = WeChatPay(wechat.get('appID'), wechat.get('apiKey'), wechat.get('mchID'))
46 46
 
47 47
     # 生成订单
48
-    order = OrderInfo.objects.create(from_uid=from_uid, to_lid=to_lid, to_uid=to_uid, total_fee=total_fee)
48
+    order = OrderInfo.objects.create(
49
+        from_uid=from_uid,
50
+        to_lid=to_lid,
51
+        to_uid=to_uid,
52
+        total_fee=total_fee,
53
+        trade_type=trade_type,
54
+    )
49 55
 
50 56
     try:
51 57
         prepay_data = wxpay.order.create(
@@ -67,6 +73,8 @@ def wx_order_create_api(request):
67 73
 
68 74
     return JsonResponse({
69 75
         'status': 200,
76
+        'message': 'Order Create Success',
77
+        'description': u'订单创建成功',
70 78
         'data': {
71 79
             'order_id': order.order_id,
72 80
             'prepay_id': prepay_id,
@@ -84,6 +92,75 @@ def order_paid_success(order):
84 92
     order.save()
85 93
 
86 94
 
95
+def order_paid_fail(order):
96
+    if order.pay_status == OrderInfo.FAIL:
97
+        return
98
+
99
+    order.pay_status = OrderInfo.FAIL
100
+    order.save()
101
+
102
+
103
+@logit
104
+@transaction.atomic
105
+def wx_order_query_api(request):
106
+    """
107
+    订单查询
108
+    :param request:
109
+    :return:
110
+    """
111
+    order_id = request.POST.get('order_id', '')
112
+    transaction_id = request.POST.get('transaction_id', '')
113
+
114
+    try:
115
+        order = OrderInfo.objects.get(order_id=order_id)
116
+    except OrderInfo.DoesNotExist:
117
+        return response(OrderStatusCode.WX_ORDER_NOT_FOUND)
118
+
119
+    if order.pay_status == OrderInfo.PAID:
120
+        return JsonResponse({
121
+            'status': 200,
122
+            'message': 'Order Pay Success',
123
+            'description': u'订单支付成功',
124
+            'data': {
125
+
126
+            }
127
+        })
128
+    elif order.pay_status == OrderInfo.FAIL:
129
+        return response(OrderStatusCode.WX_ORDER_PAY_FAIL)
130
+
131
+    # 根据 trade_type 获取 wechat 配置
132
+    wechat = WECHAT.get(order.trade_type, {})
133
+    # WeChatPay 初始化
134
+    wxpay = WeChatPay(wechat.get('appID'), wechat.get('apiKey'), wechat.get('mchID'))
135
+
136
+    # 订单查询
137
+    query_data = wxpay.order.query(transaction_id, order_id)
138
+    # 签名校验
139
+    if not wxpay.check_signature(query_data):
140
+        return response(OrderStatusCode.SIGN_CHECK_FAIL)
141
+
142
+    # 交易状态
143
+    trade_state = query_data.get('trade_state')
144
+    # 订单状态判断更新
145
+    if trade_state == 'SUCCESS':  # 订单支付成功
146
+        order_paid_success(order)
147
+        return JsonResponse({
148
+            'status': 200,
149
+            'message': 'Order Pay Success',
150
+            'description': u'订单支付成功',
151
+            'data': {
152
+
153
+            }
154
+        })
155
+    elif trade_state == 'NOTPAY':  # 订单未支付
156
+        return response(OrderStatusCode.WX_ORDER_NOT_PAY)
157
+    elif trade_state == 'USERPAYING':  # 订单支付中
158
+        return response(OrderStatusCode.WX_ORDER_PAYING)
159
+    else:  # 订单支付失败
160
+        order_paid_fail(order)
161
+        return response(OrderStatusCode.WX_ORDER_PAY_FAIL)
162
+
163
+
87 164
 @logit
88 165
 @transaction.atomic
89 166
 def wx_notify_url_api(request):
@@ -98,6 +175,17 @@ def wx_notify_url_api(request):
98 175
         # 解析 XML 失败
99 176
         return HttpResponse(settings.WXPAY_NOTIFY_FAIL)
100 177
 
178
+    trade_type = data.get('trade_type', '')
179
+
180
+    # 根据 trade_type 获取 wechat 配置
181
+    wechat = WECHAT.get(trade_type, {})
182
+    # WeChatPay 初始化
183
+    wxpay = WeChatPay(wechat.get('appID'), wechat.get('apiKey'), wechat.get('mchID'))
184
+
185
+    # 签名校验
186
+    if not wxpay.check_signature(data):
187
+        return response(OrderStatusCode.SIGN_CHECK_FAIL)
188
+
101 189
     out_trade_no = data.get('out_trade_no', '')
102 190
     return_code = data.get('return_code', '')
103 191
     result_code = data.get('result_code', '')
@@ -106,9 +194,9 @@ def wx_notify_url_api(request):
106 194
         return HttpResponse(settings.WXPAY_NOTIFY_FAIL)
107 195
 
108 196
     try:
109
-        order = OrderInfo.objects.get(order=out_trade_no)
197
+        order = OrderInfo.objects.get(order_id=out_trade_no)
110 198
     except OrderInfo.DoesNotExist:
111
-        return HttpResponse(settings.WXPAY_NOTIFY_FAIL)
199
+        return response(OrderStatusCode.WX_ORDER_NOT_FOUND)
112 200
 
113 201
     order_paid_success(order)
114 202
 

+ 5 - 0
utils/error/errno_utils.py

@@ -64,6 +64,11 @@ class GroupPhotoStatusCode(BaseStatusCode):
64 64
 class OrderStatusCode(BaseStatusCode):
65 65
     """ 订单/支付相关错误码 4040xx """
66 66
     WX_UNIFIED_ORDER_FAIL = StatusCodeField(404000, u'WX Unified Order Fail', description=u'微信统一下单失败')
67
+    WX_ORDER_NOT_FOUND = StatusCodeField(404001, u'WX Order Not Found', description=u'订单不存在')
68
+    WX_ORDER_NOT_PAY = StatusCodeField(404002, u'WX Order Not Pay', description=u'订单未支付')
69
+    WX_ORDER_PAYING = StatusCodeField(404003, u'WX Order Paying', description=u'订单支付中')
70
+    WX_ORDER_PAY_FAIL = StatusCodeField(404009, u'WX Order Pay Fail', description=u'微信支付失败')
71
+    SIGN_CHECK_FAIL = StatusCodeField(404010, u'Sign Check Fail', description=u'签名校验失败')
67 72
 
68 73
 
69 74
 class MessageStatusCode(BaseStatusCode):