@@ -2,15 +2,18 @@ |
||
2 | 2 |
|
3 | 3 |
from __future__ import division |
4 | 4 |
|
5 |
+import json |
|
6 |
+ |
|
5 | 7 |
from django.conf import settings |
6 | 8 |
from django_logit import logit |
7 | 9 |
from django_response import response |
8 | 10 |
from paginator import pagination |
9 | 11 |
from TimeConvert import TimeConvert as tc |
10 | 12 |
|
11 |
-from maintenance.models import MaintenaceInfo |
|
13 |
+from maintenance.models import ExpressCompanyInfo, MaintenaceInfo |
|
12 | 14 |
from utils.admin_utils import is_admin, is_maintenanceman |
13 | 15 |
from utils.error.errno_utils import MaintenanceStatusCode |
16 |
+from utils.kuaidi.synquery import KuaiDi100 |
|
14 | 17 |
|
15 | 18 |
|
16 | 19 |
@logit |
@@ -29,6 +32,11 @@ def maintenance_add(request): |
||
29 | 32 |
tracking_number = request.POST.get('tracking_number', '') |
30 | 33 |
maintenance_status = request.POST.get('maintenance_status', u'寄出运送中') |
31 | 34 |
|
35 |
+ try: |
|
36 |
+ company = ExpressCompanyInfo.objects.get(name=express_name, status=True) |
|
37 |
+ except ExpressCompanyInfo.DoesNotExist: |
|
38 |
+ company = None |
|
39 |
+ |
|
32 | 40 |
maintenance = MaintenaceInfo.objects.create( |
33 | 41 |
user_id=user_id, |
34 | 42 |
name=name, |
@@ -41,6 +49,7 @@ def maintenance_add(request): |
||
41 | 49 |
point_id=point_id, |
42 | 50 |
point_name=point_name, |
43 | 51 |
express_name=express_name, |
52 |
+ express_com=company.com if company else '', |
|
44 | 53 |
tracking_number=tracking_number, |
45 | 54 |
maintenance_status=maintenance_status, |
46 | 55 |
maintenance_status_at={maintenance_status: tc.utc_datetime()} |
@@ -113,11 +122,21 @@ def maintenance_update(request): |
||
113 | 122 |
if point_name: |
114 | 123 |
maintenance.point_name = point_name |
115 | 124 |
if express_name: |
125 |
+ try: |
|
126 |
+ company = ExpressCompanyInfo.objects.get(name=express_name, status=True) |
|
127 |
+ except ExpressCompanyInfo.DoesNotExist: |
|
128 |
+ company = None |
|
116 | 129 |
maintenance.express_name = express_name |
130 |
+ maintenance.express_com = company.com if company else '' |
|
117 | 131 |
if tracking_number: |
118 | 132 |
maintenance.tracking_number = tracking_number |
119 | 133 |
if back_express_name: |
134 |
+ try: |
|
135 |
+ company = ExpressCompanyInfo.objects.get(name=back_express_name, status=True) |
|
136 |
+ except ExpressCompanyInfo.DoesNotExist: |
|
137 |
+ company = None |
|
120 | 138 |
maintenance.back_express_name = back_express_name |
139 |
+ maintenance.back_express_com = company.com if company else '' |
|
121 | 140 |
if back_tracking_number: |
122 | 141 |
maintenance.back_tracking_number = back_tracking_number |
123 | 142 |
if maintenance_status: |
@@ -165,3 +184,51 @@ def maintenance_detail(request): |
||
165 | 184 |
return response(data={ |
166 | 185 |
'maintenace': maintenance.data, |
167 | 186 |
}) |
187 |
+ |
|
188 |
+ |
|
189 |
+def is_tracking_signed(tracking_info): |
|
190 |
+ if not tracking_info: |
|
191 |
+ return False |
|
192 |
+ items = tracking_info.get('data', []) |
|
193 |
+ if not items: |
|
194 |
+ return False |
|
195 |
+ return items[0].get('status') == u'签收' |
|
196 |
+ |
|
197 |
+ |
|
198 |
+@logit |
|
199 |
+def maintenance_tracking_info(request): |
|
200 |
+ maintenance_id = request.POST.get('maintenance_id', '') |
|
201 |
+ type_ = request.POST.get('type', 'tracking') # tracking / back_tracking |
|
202 |
+ |
|
203 |
+ try: |
|
204 |
+ maintenance = MaintenaceInfo.objects.get(id=maintenance_id, status=True) |
|
205 |
+ except MaintenaceInfo.DoesNotExist: |
|
206 |
+ return response(MaintenanceStatusCode.MAINTENACE_NOT_FOUND) |
|
207 |
+ |
|
208 |
+ tracking_info = {} |
|
209 |
+ if type_ == 'tracking': |
|
210 |
+ if maintenance.express_com and maintenance.tracking_number: |
|
211 |
+ tracking_info = KuaiDi100().track(maintenance.express_com, maintenance.tracking_number) |
|
212 |
+ else: |
|
213 |
+ if maintenance.back_express_com and maintenance.back_tracking_number: |
|
214 |
+ tracking_info = KuaiDi100().track(maintenance.back_express_com, maintenance.back_tracking_number) |
|
215 |
+ |
|
216 |
+ if tracking_info: |
|
217 |
+ try: |
|
218 |
+ tracking_info = json.loads(tracking_info) |
|
219 |
+ except Exception: |
|
220 |
+ tracking_info = {} |
|
221 |
+ |
|
222 |
+ if tracking_info: |
|
223 |
+ if type_ == 'tracking': |
|
224 |
+ maintenance.tracking_info = tracking_info |
|
225 |
+ maintenance.tracking_signed = is_tracking_signed(tracking_info) |
|
226 |
+ else: |
|
227 |
+ maintenance.back_tracking_info = tracking_info |
|
228 |
+ maintenance.back_tracking_signed = is_tracking_signed(tracking_info) |
|
229 |
+ maintenance.save() |
|
230 |
+ |
|
231 |
+ return response(data={ |
|
232 |
+ 'type': type_, |
|
233 |
+ 'tracking_info': tracking_info, |
|
234 |
+ }) |
@@ -277,4 +277,6 @@ urlpatterns += [ |
||
277 | 277 |
|
278 | 278 |
url(r'^admin/maintenance/update$', maintenance_views.maintenance_update, name='maintenance_update'), |
279 | 279 |
url(r'^admin/maintenance/list$', maintenance_views.maintenance_list, name='maintenance_list'), |
280 |
+ |
|
281 |
+ url(r'^maintenance/tracking/info$', maintenance_views.maintenance_tracking_info, name='maintenance_tracking_info'), |
|
280 | 282 |
] |
@@ -419,6 +419,12 @@ KODO_DEFAULT_BRAND_DOMAIN = '' |
||
419 | 419 |
GIS_2_ADMINISTRATIVE_DIVISION = 'https://apis.map.qq.com/ws/geocoder/v1/?key=4FNBZ-TIIKW-MWJRQ-RHZJN-W6F7Q-BFBKX&location={0},{1}' |
420 | 420 |
PHONE_2_ADMINISTRATIVE_DIVISION = 'https://www.baifubao.com/callback?cmd=1059&callback=phone&phone={0}' |
421 | 421 |
|
422 |
+# 快递100 |
|
423 |
+KUAIDI00 = { |
|
424 |
+ 'key': '', |
|
425 |
+ 'customer': '', |
|
426 |
+} |
|
427 |
+ |
|
422 | 428 |
TESTING_SNS = ['000000'] |
423 | 429 |
|
424 | 430 |
COMPONENT_CALLBACK_CONFIG = { |
@@ -10,11 +10,11 @@ class MaintenancePointInfoAdmin(admin.ModelAdmin): |
||
10 | 10 |
|
11 | 11 |
|
12 | 12 |
class ExpressCompanyInfoAdmin(admin.ModelAdmin): |
13 |
- list_display = ('name', 'status', 'created_at', 'updated_at') |
|
13 |
+ list_display = ('name', 'com', 'status', 'created_at', 'updated_at') |
|
14 | 14 |
|
15 | 15 |
|
16 | 16 |
class MaintenanceInfoAdmin(admin.ModelAdmin): |
17 |
- list_display = ('user_id', 'name', 'phone', 'address', 'sn', 'desc', 'point_id', 'point_name', 'express_name', 'tracking_number', 'back_express_name', 'back_tracking_number', 'maintenance_status', 'status', 'created_at', 'updated_at') |
|
17 |
+ list_display = ('user_id', 'name', 'phone', 'address', 'sn', 'desc', 'point_id', 'point_name', 'express_name', 'express_com', 'tracking_number', 'tracking_signed', 'back_express_name', 'back_express_com', 'back_tracking_number', 'back_tracking_signed', 'maintenance_status', 'status', 'created_at', 'updated_at') |
|
18 | 18 |
|
19 | 19 |
|
20 | 20 |
admin.site.register(MaintenacePointInfo, MaintenancePointInfoAdmin) |
@@ -0,0 +1,26 @@ |
||
1 |
+# -*- coding: utf-8 -*- |
|
2 |
+# Generated by Django 1.11.29 on 2021-09-22 08:46 |
|
3 |
+from __future__ import unicode_literals |
|
4 |
+ |
|
5 |
+from django.db import migrations |
|
6 |
+import jsonfield.fields |
|
7 |
+ |
|
8 |
+ |
|
9 |
+class Migration(migrations.Migration): |
|
10 |
+ |
|
11 |
+ dependencies = [ |
|
12 |
+ ('maintenance', '0007_auto_20210922_1522'), |
|
13 |
+ ] |
|
14 |
+ |
|
15 |
+ operations = [ |
|
16 |
+ migrations.AddField( |
|
17 |
+ model_name='maintenaceinfo', |
|
18 |
+ name='back_tracking_info', |
|
19 |
+ field=jsonfield.fields.JSONField(default={}, help_text='\u5bc4\u56de\u5feb\u9012\u4fe1\u606f', verbose_name='back_tracking_info'), |
|
20 |
+ ), |
|
21 |
+ migrations.AddField( |
|
22 |
+ model_name='maintenaceinfo', |
|
23 |
+ name='tracking_info', |
|
24 |
+ field=jsonfield.fields.JSONField(default={}, help_text='\u5feb\u9012\u4fe1\u606f', verbose_name='tracking_info'), |
|
25 |
+ ), |
|
26 |
+ ] |
@@ -0,0 +1,20 @@ |
||
1 |
+# -*- coding: utf-8 -*- |
|
2 |
+# Generated by Django 1.11.29 on 2021-09-22 09:00 |
|
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 |
+ ('maintenance', '0008_auto_20210922_1646'), |
|
12 |
+ ] |
|
13 |
+ |
|
14 |
+ operations = [ |
|
15 |
+ migrations.AddField( |
|
16 |
+ model_name='expresscompanyinfo', |
|
17 |
+ name='com', |
|
18 |
+ field=models.CharField(blank=True, help_text='\u7f16\u7801', max_length=255, null=True, verbose_name='com'), |
|
19 |
+ ), |
|
20 |
+ ] |
@@ -0,0 +1,25 @@ |
||
1 |
+# -*- coding: utf-8 -*- |
|
2 |
+# Generated by Django 1.11.29 on 2021-09-22 09:04 |
|
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 |
+ ('maintenance', '0009_expresscompanyinfo_com'), |
|
12 |
+ ] |
|
13 |
+ |
|
14 |
+ operations = [ |
|
15 |
+ migrations.AddField( |
|
16 |
+ model_name='maintenaceinfo', |
|
17 |
+ name='back_express_com', |
|
18 |
+ field=models.CharField(blank=True, help_text='\u5bc4\u56de\u5feb\u9012\u7f16\u7801', max_length=255, null=True, verbose_name='back_express_com'), |
|
19 |
+ ), |
|
20 |
+ migrations.AddField( |
|
21 |
+ model_name='maintenaceinfo', |
|
22 |
+ name='express_com', |
|
23 |
+ field=models.CharField(blank=True, help_text='\u5feb\u9012\u7f16\u7801', max_length=255, null=True, verbose_name='express_com'), |
|
24 |
+ ), |
|
25 |
+ ] |
@@ -0,0 +1,41 @@ |
||
1 |
+# -*- coding: utf-8 -*- |
|
2 |
+# Generated by Django 1.11.29 on 2021-09-22 09:27 |
|
3 |
+from __future__ import unicode_literals |
|
4 |
+ |
|
5 |
+from django.db import migrations, models |
|
6 |
+import jsonfield.fields |
|
7 |
+ |
|
8 |
+ |
|
9 |
+class Migration(migrations.Migration): |
|
10 |
+ |
|
11 |
+ dependencies = [ |
|
12 |
+ ('maintenance', '0010_auto_20210922_1704'), |
|
13 |
+ ] |
|
14 |
+ |
|
15 |
+ operations = [ |
|
16 |
+ migrations.AddField( |
|
17 |
+ model_name='maintenaceinfo', |
|
18 |
+ name='back_tracking_signed', |
|
19 |
+ field=models.BooleanField(default=False, help_text='\u5bc4\u56de\u5feb\u9012\u662f\u5426\u5df2\u7b7e\u6536', verbose_name='back_tracking_signed'), |
|
20 |
+ ), |
|
21 |
+ migrations.AddField( |
|
22 |
+ model_name='maintenaceinfo', |
|
23 |
+ name='tracking_signed', |
|
24 |
+ field=models.BooleanField(default=False, help_text='\u5feb\u9012\u662f\u5426\u5df2\u7b7e\u6536', verbose_name='tracking_signed'), |
|
25 |
+ ), |
|
26 |
+ migrations.AlterField( |
|
27 |
+ model_name='maintenaceinfo', |
|
28 |
+ name='back_tracking_info', |
|
29 |
+ field=jsonfield.fields.JSONField(blank=True, default={}, help_text='\u5bc4\u56de\u5feb\u9012\u4fe1\u606f', null=True, verbose_name='back_tracking_info'), |
|
30 |
+ ), |
|
31 |
+ migrations.AlterField( |
|
32 |
+ model_name='maintenaceinfo', |
|
33 |
+ name='maintenance_status_at', |
|
34 |
+ field=jsonfield.fields.JSONField(blank=True, default={}, help_text='\u7ef4\u4fee\u72b6\u6001\u53d8\u66f4\u65f6\u95f4', null=True, verbose_name='maintenance_status_at'), |
|
35 |
+ ), |
|
36 |
+ migrations.AlterField( |
|
37 |
+ model_name='maintenaceinfo', |
|
38 |
+ name='tracking_info', |
|
39 |
+ field=jsonfield.fields.JSONField(blank=True, default={}, help_text='\u5feb\u9012\u4fe1\u606f', null=True, verbose_name='tracking_info'), |
|
40 |
+ ), |
|
41 |
+ ] |
@@ -35,6 +35,7 @@ class MaintenacePointInfo(BaseModelMixin): |
||
35 | 35 |
|
36 | 36 |
class ExpressCompanyInfo(BaseModelMixin): |
37 | 37 |
name = models.CharField(_(u'name'), max_length=255, blank=True, null=True, help_text=u'名称') |
38 |
+ com = models.CharField(_(u'com'), max_length=255, blank=True, null=True, help_text=u'编码') |
|
38 | 39 |
|
39 | 40 |
class Meta: |
40 | 41 |
verbose_name = _(u'快递公司信息') |
@@ -48,6 +49,7 @@ class ExpressCompanyInfo(BaseModelMixin): |
||
48 | 49 |
return { |
49 | 50 |
'id': self.pk, |
50 | 51 |
'name': self.name, |
52 |
+ 'com': self.com, |
|
51 | 53 |
} |
52 | 54 |
|
53 | 55 |
|
@@ -67,14 +69,20 @@ class MaintenaceInfo(BaseModelMixin): |
||
67 | 69 |
point_name = models.CharField(_(u'point_name'), max_length=255, blank=True, null=True, help_text=u'维修点名称') |
68 | 70 |
|
69 | 71 |
express_name = models.CharField(_(u'express_name'), max_length=255, blank=True, null=True, help_text=u'快递公司') |
72 |
+ express_com = models.CharField(_(u'express_com'), max_length=255, blank=True, null=True, help_text=u'快递编码') |
|
70 | 73 |
tracking_number = models.CharField(_(u'tracking_number'), max_length=255, blank=True, null=True, help_text=u'快递单号') |
74 |
+ tracking_info = JSONField(_(u'tracking_info'), blank=True, null=True, default={}, help_text=u'快递信息') |
|
75 |
+ tracking_signed = models.BooleanField(_(u'tracking_signed'), default=False, help_text=u'快递是否已签收') |
|
71 | 76 |
|
72 | 77 |
back_express_name = models.CharField(_(u'back_express_name'), max_length=255, blank=True, null=True, help_text=u'寄回快递公司') |
78 |
+ back_express_com = models.CharField(_(u'back_express_com'), max_length=255, blank=True, null=True, help_text=u'寄回快递编码') |
|
73 | 79 |
back_tracking_number = models.CharField(_(u'back_tracking_number'), max_length=255, blank=True, null=True, help_text=u'寄回快递单号') |
80 |
+ back_tracking_info = JSONField(_(u'back_tracking_info'), blank=True, null=True, default={}, help_text=u'寄回快递信息') |
|
81 |
+ back_tracking_signed = models.BooleanField(_(u'back_tracking_signed'), default=False, help_text=u'寄回快递是否已签收') |
|
74 | 82 |
|
75 | 83 |
# 寄出运送中、已签收修理中、已修复寄回、寄回签收 |
76 | 84 |
maintenance_status = models.CharField(_(u'maintenance_status'), max_length=8, default=u'寄出运送中', help_text=u'维修状态') |
77 |
- maintenance_status_at = JSONField(_(u'maintenance_status_at'), default={}, help_text=u'维修状态变更时间') |
|
85 |
+ maintenance_status_at = JSONField(_(u'maintenance_status_at'), blank=True, null=True, default={}, help_text=u'维修状态变更时间') |
|
78 | 86 |
|
79 | 87 |
class Meta: |
80 | 88 |
verbose_name = _(u'维修信息') |
@@ -104,9 +112,15 @@ class MaintenaceInfo(BaseModelMixin): |
||
104 | 112 |
'point_id': self.point_id, |
105 | 113 |
'point_name': self.point_name, |
106 | 114 |
'express_name': self.express_name, |
115 |
+ 'express_com': self.express_com, |
|
107 | 116 |
'tracking_number': self.tracking_number, |
117 |
+ 'tracking_info': self.tracking_info, |
|
118 |
+ 'tracking_signed': self.tracking_signed, |
|
108 | 119 |
'back_express_name': self.back_express_name, |
120 |
+ 'back_express_com': self.back_express_com, |
|
109 | 121 |
'back_tracking_number': self.back_tracking_number, |
122 |
+ 'back_tracking_info': self.back_tracking_info, |
|
123 |
+ 'back_tracking_signed': self.back_tracking_signed, |
|
110 | 124 |
'maintenance_status': self.maintenance_status, |
111 | 125 |
'maintenance_status_at': {k: tc.local_string(utc_dt=tc.string_to_utc_datetime(v, format='%Y-%m-%dT%H:%M:%S.%fZ')) for k, v in self.maintenance_status_at.items()}, |
112 | 126 |
'created_at': tc.local_string(utc_dt=self.created_at), |
@@ -0,0 +1,22 @@ |
||
1 |
+# -*- coding: utf-8 -*-' |
|
2 |
+ |
|
3 |
+import requests |
|
4 |
+ |
|
5 |
+ |
|
6 |
+class KuaiDi100: |
|
7 |
+ def __init__(self): |
|
8 |
+ self.key = '' # TODO 客户授权key |
|
9 |
+ self.url = 'https://www.kuaidi100.com/autonumber/auto' # 请求地址 |
|
10 |
+ |
|
11 |
+ def auto_number(self, num): |
|
12 |
+ """ |
|
13 |
+ 智能单号识别 |
|
14 |
+ :param num: 快递单号 |
|
15 |
+ :return: requests.Response.text |
|
16 |
+ """ |
|
17 |
+ req_params = {'key': self.key, 'num': num} |
|
18 |
+ return requests.post(self.url, req_params).text # 发送请求 |
|
19 |
+ |
|
20 |
+ |
|
21 |
+result = KuaiDi100().auto_number('YT9693083639795') |
|
22 |
+print(result) |
@@ -0,0 +1,103 @@ |
||
1 |
+# -*- coding: utf-8 -*-' |
|
2 |
+ |
|
3 |
+import hashlib |
|
4 |
+import json |
|
5 |
+import time |
|
6 |
+ |
|
7 |
+import requests |
|
8 |
+ |
|
9 |
+ |
|
10 |
+class KuaiDi100: |
|
11 |
+ def __init__(self): |
|
12 |
+ self.key = '' # TODO 客户授权key |
|
13 |
+ self.secret = '' # TODO 电子面单secret |
|
14 |
+ self.url = 'https://poll.kuaidi100.com/print/billparcels.do' # 请求地址 |
|
15 |
+ |
|
16 |
+ def submit(self, param, settings): |
|
17 |
+ """ |
|
18 |
+ 发货单打印 |
|
19 |
+ :param param: 模板配置信息和自定义参数信息 |
|
20 |
+ :param settings: 纸张配置信息 |
|
21 |
+ :return: requests.Response.text |
|
22 |
+ """ |
|
23 |
+ timestamp = str(time.time()) |
|
24 |
+ md = hashlib.md5() |
|
25 |
+ param_str = json.dumps(param) |
|
26 |
+ temp_sign = param_str + timestamp + self.key + self.secret |
|
27 |
+ md.update(temp_sign.encode()) |
|
28 |
+ sign = md.hexdigest().upper() |
|
29 |
+ req_params = { |
|
30 |
+ 'method': 'billparcels', |
|
31 |
+ 'key': self.key, |
|
32 |
+ 't': timestamp, |
|
33 |
+ 'sign': sign, |
|
34 |
+ 'param': param_str, |
|
35 |
+ 'settings': json.dumps(settings) |
|
36 |
+ } |
|
37 |
+ return requests.post(self.url, req_params).text # 发送请求 |
|
38 |
+ |
|
39 |
+ |
|
40 |
+param = { |
|
41 |
+ "tempid": "xxxx", # 模板编码,通过管理后台的打印发货单模板配置信息获取 |
|
42 |
+ "siid": "xxxx", # 打印设备码,通过打印机输出的设备码进行获取 |
|
43 |
+ "callBackUrl": "https://www.baidu.com/fhd/callback", # 打印状态对调地址 |
|
44 |
+ "petName": "kd100", # 自定义参数 |
|
45 |
+ "recName": "小百", # 自定义参数 |
|
46 |
+ "recPhone": "10086", # 自定义参数 |
|
47 |
+ "payTime": "2021-01-15 15:40:55", # 自定义参数 |
|
48 |
+ "expressName": "德邦快递", # 自定义参数 |
|
49 |
+ "printTime": "2021-01-15 15:41:30", # 自定义参数 |
|
50 |
+ "printCount": "1", # 自定义参数 |
|
51 |
+ "address": "广东省深圳市南山区金蝶软件园", # 自定义参数 |
|
52 |
+ "total": "21", "remark": "购物小票作为购物凭证,请妥善保管,您有任何疑问,请咨询服务热线 123456798", # 自定义参数 |
|
53 |
+ "img0": { # 图片参数,多图片时用img0,img1,img2等追加 |
|
54 |
+ "type": "code_128", |
|
55 |
+ "content": "887921256577", |
|
56 |
+ "width": 350, |
|
57 |
+ "height": 100 |
|
58 |
+ }, |
|
59 |
+ "tab0": [ # 表格参数,多表格时用tab0,tab1,tab2等追加对象 |
|
60 |
+ { |
|
61 |
+ "prodName": "热敏纸", |
|
62 |
+ "count": "5", |
|
63 |
+ "specs": "76*130", |
|
64 |
+ "unitPrice": "30", |
|
65 |
+ "price": "150" |
|
66 |
+ }, |
|
67 |
+ { |
|
68 |
+ "prodName": "热敏纸", |
|
69 |
+ "count": "10", |
|
70 |
+ "specs": "100*180", |
|
71 |
+ "unitPrice": "50", |
|
72 |
+ "price": "500" |
|
73 |
+ }, |
|
74 |
+ { |
|
75 |
+ "prodName": "续打纸", |
|
76 |
+ "count": "5", |
|
77 |
+ "specs": "", |
|
78 |
+ "unitPrice": "40", |
|
79 |
+ "price": "200" |
|
80 |
+ }, |
|
81 |
+ { |
|
82 |
+ "prodName": "云打印机", |
|
83 |
+ "count": "1", |
|
84 |
+ "specs": "二代", |
|
85 |
+ "unitPrice": "499", |
|
86 |
+ "price": "499" |
|
87 |
+ } |
|
88 |
+ ] |
|
89 |
+} |
|
90 |
+ |
|
91 |
+settings = { |
|
92 |
+ "pageWidth": 100, # 纸张宽,单位mm,默认值:100 |
|
93 |
+ "pageHeight": 180, # 纸张高,单位mm ,续打纸张时,该字段设置为null或空串 |
|
94 |
+ "margins": { # 边距 |
|
95 |
+ "top": 5, # 上边距,单位:mm,默认:0 |
|
96 |
+ "bottom": 5, # 下边距,单位:mm,默认:0 |
|
97 |
+ "left": 5, # 左边距,单位:mm,默认:0 |
|
98 |
+ "right": 5 # 右边距,单位:mm,默认:0 |
|
99 |
+ } |
|
100 |
+} |
|
101 |
+ |
|
102 |
+result = KuaiDi100().submit(param, settings) |
|
103 |
+print(result) |
@@ -0,0 +1,48 @@ |
||
1 |
+# -*- coding: utf-8 -*-' |
|
2 |
+ |
|
3 |
+import hashlib |
|
4 |
+import json |
|
5 |
+ |
|
6 |
+import requests |
|
7 |
+ |
|
8 |
+ |
|
9 |
+class KuaiDi100: |
|
10 |
+ def __init__(self): |
|
11 |
+ self.key = '' # TODO 客户授权key |
|
12 |
+ self.customer = '' # TODO 查询公司编号 |
|
13 |
+ self.url = 'https://poll.kuaidi100.com/poll/maptrack.do' # 请求地址 |
|
14 |
+ |
|
15 |
+ def map_track(self, com, num, phone, ship_from, ship_to, orderTime): |
|
16 |
+ """ |
|
17 |
+ 快递查询地图轨迹 |
|
18 |
+ :param com: 查询的快递公司的编码,一律用小写字母 |
|
19 |
+ :param num: 查询的快递单号,单号的最大长度是32个字符 |
|
20 |
+ :param phone: 收件人或寄件人的手机号或固话(也可以填写后四位,如果是固话,请不要上传分机号) |
|
21 |
+ :param ship_from: 出发地城市,省-市-区,非必填,填了有助于提升签收状态的判断的准确率,请尽量提供 |
|
22 |
+ :param ship_to: 目的地城市,省-市-区,非必填,填了有助于提升签收状态的判断的准确率,且到达目的地后会加大监控频率,请尽量提供 |
|
23 |
+ :param orderTime: 订单下单时间,格式为(yyyy-MM-dd HH:mm:ss)如:2020-12-16 12:59:59 |
|
24 |
+ :return: requests.Response.text |
|
25 |
+ """ |
|
26 |
+ param = { |
|
27 |
+ 'com': com, |
|
28 |
+ 'num': num, |
|
29 |
+ 'phone': phone, |
|
30 |
+ 'from': ship_from, |
|
31 |
+ 'to': ship_to, |
|
32 |
+ 'show': '0', # 返回数据格式。0:json(默认),1:xml,2:html,3:text |
|
33 |
+ 'order': 'desc', # 返回结果排序方式。desc:降序(默认),asc:升序 |
|
34 |
+ 'orderTime': orderTime |
|
35 |
+ } |
|
36 |
+ param_str = json.dumps(param) # 转json字符串 |
|
37 |
+ |
|
38 |
+ # 签名加密, 用于验证身份, 按param + key + customer 的顺序进行MD5加密(注意加密后字符串要转大写), 不需要“+”号 |
|
39 |
+ temp_sign = param_str + self.key + self.customer |
|
40 |
+ md = hashlib.md5() |
|
41 |
+ md.update(temp_sign.encode()) |
|
42 |
+ sign = md.hexdigest().upper() |
|
43 |
+ request_data = {'customer': self.customer, 'param': param_str, 'sign': sign} |
|
44 |
+ return requests.post(self.url, request_data).text # 发送请求 |
|
45 |
+ |
|
46 |
+ |
|
47 |
+result = KuaiDi100().map_track('yuantong', 'YT9693083639795', '', '广东省江门市', '广东省深圳市', '2021-08-01 20:04:44') |
|
48 |
+print(result) |
@@ -0,0 +1,48 @@ |
||
1 |
+# -*- coding: utf-8 -*-' |
|
2 |
+ |
|
3 |
+import hashlib |
|
4 |
+ |
|
5 |
+import requests |
|
6 |
+ |
|
7 |
+ |
|
8 |
+class KuaiDi100: |
|
9 |
+ def __init__(self): |
|
10 |
+ self.key = '' # TODO 客户授权key |
|
11 |
+ self.userid = '' # TODO 查询公司编号 |
|
12 |
+ md = hashlib.md5() |
|
13 |
+ md.update((self.key + self.userid).encode()) |
|
14 |
+ self.sign = md.hexdigest().upper() |
|
15 |
+ self.url = 'https://apisms.kuaidi100.com/sms/send.do' # 接口地址,或者 http://apisms.kuaidi100.com:9502/sms/send.do |
|
16 |
+ |
|
17 |
+ def send_sms(self, seller, phone, tid, sms_content, order_id): |
|
18 |
+ """ |
|
19 |
+ 短信发送 |
|
20 |
+ :param seller: 商户名称签名;最好用简称,该字段信息会在短信标签处显示。不要超过5个字符 |
|
21 |
+ :param phone: 接收短信手机号 |
|
22 |
+ :param tid: 短信模板ID |
|
23 |
+ :param sms_content: 短信模板替换内容 |
|
24 |
+ :param order_id: 外部订单号:当该短信发送模板有回调地址时,外部订单号会返回给调用者,方便用户更新数据 |
|
25 |
+ :return: requests.Response.text |
|
26 |
+ """ |
|
27 |
+ req_params = { |
|
28 |
+ 'sign': self.sign, # 加密签名信息:MD5(key + userid);加密后字符串转大写 |
|
29 |
+ 'userid': self.userid, # 我方分配给贵司的的短信接口用户ID,点击查看账号信息 |
|
30 |
+ 'seller': seller, # 商户名称签名;最好用简称,该字段信息会在短信标签处显示。不要超过5个字符 |
|
31 |
+ 'phone': phone, # 接收短信手机号 |
|
32 |
+ 'tid': tid, # 短信模板ID |
|
33 |
+ 'content': sms_content, # 短信模板替换内容 |
|
34 |
+ 'outorder': order_id, # 外部订单号:当该短信发送模板有回调地址时,外部订单号会返回给调用者,方便用户更新数据 |
|
35 |
+ # 'callback': 'https//www.baidu.com/kd100/callback' # 回调地址:如果客户在发送短信时填写该参数,将按照这个参数回调短信发送状态;如果为空,将按照模板配置的地址回调短信发送状态;如果两个参数都不填写,将不会回调通知状态 |
|
36 |
+ } |
|
37 |
+ |
|
38 |
+ return requests.post(self.url, req_params).text # 发送请求 |
|
39 |
+ |
|
40 |
+ |
|
41 |
+content = { # 短信模板替换内容 |
|
42 |
+ "接收人姓名": "小百", |
|
43 |
+ "公司名": "快递100", |
|
44 |
+ "快递单号": "154893238584", |
|
45 |
+ "url": "https://www.kuaidi100.com" |
|
46 |
+} |
|
47 |
+result = KuaiDi100().send_sms('快递100', '13800138000', '11', content, '123456789') |
|
48 |
+print(result) |
@@ -0,0 +1,52 @@ |
||
1 |
+# -*- coding: utf-8 -*-' |
|
2 |
+ |
|
3 |
+import json |
|
4 |
+ |
|
5 |
+import requests |
|
6 |
+ |
|
7 |
+ |
|
8 |
+class KuaiDi100: |
|
9 |
+ def __init__(self): |
|
10 |
+ self.key = '' # TODO 客户授权key |
|
11 |
+ self.url = 'https://poll.kuaidi100.com/poll' # 请求地址 |
|
12 |
+ |
|
13 |
+ def submit(self, com, num, phone, ship_from, ship_to): |
|
14 |
+ """ |
|
15 |
+ 物流轨迹订阅 |
|
16 |
+ :param com: 快递公司编码 |
|
17 |
+ :param num: 快递单号 |
|
18 |
+ :param phone: 收件人或寄件人的手机号或固话(也可以填写后四位,如果是固话,请不要上传分机号) |
|
19 |
+ :param ship_from: 出发地城市,省-市-区,非必填,填了有助于提升签收状态的判断的准确率,请尽量提供 |
|
20 |
+ :param ship_to: 目的地城市,省-市-区,非必填,填了有助于提升签收状态的判断的准确率,且到达目的地后会加大监控频率,请尽量提供 |
|
21 |
+ :return: requests.Response.text |
|
22 |
+ """ |
|
23 |
+ param = { |
|
24 |
+ 'company': com, |
|
25 |
+ 'number': num, |
|
26 |
+ 'from': ship_from, |
|
27 |
+ 'to': ship_to, |
|
28 |
+ 'key': self.key, |
|
29 |
+ 'parameters': { |
|
30 |
+ 'callbackurl': 'https://www.baidu.com/kd100/callback', # 回调接口的地址。如果需要在推送信息回传自己业务参数,可以在回调地址URL后面拼接上去,例如:https://www.baidu.com/kd100/callback?orderId=123 |
|
31 |
+ 'salt': None, # 签名用随机字符串。32位自定义字符串。添加该参数,则推送的时候会增加sign给贵司校验消息的可靠性 |
|
32 |
+ 'resultv2': '1', # 添加此字段表示开通行政区域解析功能。0:关闭(默认),1:开通行政区域解析功能 |
|
33 |
+ 'autoCom': '0', # 添加此字段且将此值设为1,则表示开始智能判断单号所属公司的功能,开启后,company字段可为空,即只传运单号(number字段),我方收到后会根据单号判断出其所属的快递公司(即company字段)。建议只有在无法知道单号对应的快递公司(即company的值)的情况下才开启此功能 |
|
34 |
+ 'interCom': '0', # 添加此字段且将此值设为1,则表示开启国际版,开启后,若订阅的单号(即number字段)属于国际单号,会返回出发国与目的国两个国家的跟踪信息,本功能暂时只支持邮政体系(国际类的邮政小包、EMS)内的快递公司,若单号我方识别为非国际单,即使添加本字段,也不会返回destResult元素组 |
|
35 |
+ 'departureCountry': '', # 出发国家编码,interCom=1的国际单号最好提供该值 |
|
36 |
+ 'departureCom': '', # 出发国家快递公司的编码,interCom=1的国际单号最好提供该值 |
|
37 |
+ 'destinationCountry': '', # 目的国家编码,interCom=1的国际单号最好提供该值 |
|
38 |
+ 'destinationCom': '', # 目的国家快递公司的编码,interCom=1的国际单号最好提供该值 |
|
39 |
+ 'phone': phone |
|
40 |
+ } |
|
41 |
+ } |
|
42 |
+ |
|
43 |
+ req_params = { |
|
44 |
+ 'schema': 'json', # 查询公司编号 |
|
45 |
+ 'param': json.dumps(param) # 参数数据 |
|
46 |
+ } |
|
47 |
+ |
|
48 |
+ return requests.post(self.url, req_params).text # 发送请求 |
|
49 |
+ |
|
50 |
+ |
|
51 |
+result = KuaiDi100().submit('yuantong', 'YT9693083639795', '', '江门市', '深圳市') |
|
52 |
+print(result) |
@@ -0,0 +1,48 @@ |
||
1 |
+# -*- coding: utf-8 -*-' |
|
2 |
+ |
|
3 |
+import hashlib |
|
4 |
+import json |
|
5 |
+ |
|
6 |
+import requests |
|
7 |
+from django.conf import settings |
|
8 |
+ |
|
9 |
+ |
|
10 |
+class KuaiDi100: |
|
11 |
+ def __init__(self): |
|
12 |
+ self.key = settings.KUAIDI00.get('key', '') # TODO 客户授权key |
|
13 |
+ self.customer = settings.KUAIDI00.get('customer', '') # TODO 查询公司编号 |
|
14 |
+ self.url = 'https://poll.kuaidi100.com/poll/query.do' # 请求地址 |
|
15 |
+ |
|
16 |
+ def track(self, com, num, phone=None, ship_from=None, ship_to=None): |
|
17 |
+ """ |
|
18 |
+ 物流轨迹实时查询: https://api.kuaidi100.com/document/5f0ffb5ebc8da837cbd8aefc.html |
|
19 |
+ :param com: 查询的快递公司的编码,一律用小写字母 |
|
20 |
+ :param num: 查询的快递单号,单号的最大长度是32个字符 |
|
21 |
+ :param phone: 收件人或寄件人的手机号或固话(也可以填写后四位,如果是固话,请不要上传分机号) |
|
22 |
+ :param ship_from: 出发地城市,省-市-区,非必填,填了有助于提升签收状态的判断的准确率,请尽量提供 |
|
23 |
+ :param ship_to: 目的地城市,省-市-区,非必填,填了有助于提升签收状态的判断的准确率,且到达目的地后会加大监控频率,请尽量提供 |
|
24 |
+ :return: requests.Response.text |
|
25 |
+ """ |
|
26 |
+ param = { |
|
27 |
+ 'com': com, |
|
28 |
+ 'num': num, |
|
29 |
+ 'phone': phone, |
|
30 |
+ 'from': ship_from, |
|
31 |
+ 'to': ship_to, |
|
32 |
+ 'resultv2': '1', # 添加此字段表示开通行政区域解析功能。0:关闭(默认),1:开通行政区域解析功能,2:开通行政解析功能并且返回出发、目的及当前城市信息 |
|
33 |
+ 'show': '0', # 返回数据格式。0:json(默认),1:xml,2:html,3:text |
|
34 |
+ 'order': 'desc' # 返回结果排序方式。desc:降序(默认),asc:升序 |
|
35 |
+ } |
|
36 |
+ param_str = json.dumps(param) # 转json字符串 |
|
37 |
+ |
|
38 |
+ # 签名加密, 用于验证身份, 按param + key + customer 的顺序进行MD5加密(注意加密后字符串要转大写), 不需要“+”号 |
|
39 |
+ temp_sign = param_str + self.key + self.customer |
|
40 |
+ md = hashlib.md5() |
|
41 |
+ md.update(temp_sign.encode()) |
|
42 |
+ sign = md.hexdigest().upper() |
|
43 |
+ request_data = {'customer': self.customer, 'param': param_str, 'sign': sign} |
|
44 |
+ return requests.post(self.url, request_data).text # 发送请求 |
|
45 |
+ |
|
46 |
+ |
|
47 |
+# result = KuaiDi100().track('yuantong', 'YT9693083639795', '', '广东省江门市', '广东省深圳市') |
|
48 |
+# print(result) |