/td>
+ 'goodsInfo': {
+ 'BrandID': brand_pk,
+ 'Brand': brand.brand_name if brand else '',
+ 'ModelID': model_pk,
+ 'Model': (model.model_full_name or model.model_name) if model else '',
+ 'DistributorID': distributor_pk,
+ 'SerialNo': sn,
+ },
+ 'has_unexpired_activity': has_unexpired_activity,
+ 'coupon_info': coupon_info,
+ })
@@ -214,6 +214,7 @@ urlpatterns += [ |
||
| 214 | 214 |
urlpatterns += [ |
| 215 | 215 |
url(r'^encrypt$', encrypt_views.encrypt, name='encrypt'), |
| 216 | 216 |
url(r'^decrypt$', encrypt_views.decrypt, name='decrypt'), |
| 217 |
+ url(r'^decrypt2$', encrypt_views.decrypt2, name='decrypt2'), |
|
| 217 | 218 |
] |
| 218 | 219 |
|
| 219 | 220 |
urlpatterns += [ |
@@ -57,6 +57,7 @@ INSTALLED_APPS = ( |
||
| 57 | 57 |
'guideline', |
| 58 | 58 |
'integral', |
| 59 | 59 |
'logs', |
| 60 |
+ 'marketcode', |
|
| 60 | 61 |
'mch', |
| 61 | 62 |
'message', |
| 62 | 63 |
'miniapp', |
@@ -252,12 +253,12 @@ QINIU = {
|
||
| 252 | 253 |
'secret_key': '05sCekniLCgM6-d_PxrH8sFjvEOsx3ev-FgS7R-k', |
| 253 | 254 |
'bucket_default': 'photo', |
| 254 | 255 |
'buckets': {
|
| 255 |
- 'original': 'http://orf3sfb8s.bkt.clouddn.com', |
|
| 256 |
- 'photo': 'http://orf3lnlmb.bkt.clouddn.com', |
|
| 257 |
- 'prettify': 'http://orzfu8zxw.bkt.clouddn.com', |
|
| 258 |
- 'thumbnail': 'http://orf3ahvt6.bkt.clouddn.com', |
|
| 259 |
- 'thumbnail2': 'http://orf3muf5n.bkt.clouddn.com', |
|
| 260 |
- 'watermark': 'http://orf3qne9f.bkt.clouddn.com', |
|
| 256 |
+ 'original': 'http://original.img.pai.ai', |
|
| 257 |
+ 'photo': 'http://photo.img.pai.ai', |
|
| 258 |
+ 'prettify': 'http://prettify.img.pai.ai', |
|
| 259 |
+ 'thumbnail': 'http://thumbnail.img.pai.ai', |
|
| 260 |
+ 'thumbnail2': 'http://thumbnail2.img.pai.ai', |
|
| 261 |
+ 'watermark': 'http://watermark.img.pai.ai', |
|
| 261 | 262 |
} |
| 262 | 263 |
} |
| 263 | 264 |
|
@@ -419,6 +420,16 @@ PHONE_2_ADMINISTRATIVE_DIVISION = 'https://www.baifubao.com/callback?cmd=1059&ca |
||
| 419 | 420 |
|
| 420 | 421 |
TESTING_SNS = ['000000'] |
| 421 | 422 |
|
| 423 |
+COMPONENT_CALLBACK_CONFIG = {
|
|
| 424 |
+ 'tousername': 'brand_id', |
|
| 425 |
+} |
|
| 426 |
+ |
|
| 427 |
+# 测试文件 |
|
| 428 |
+TESTING_ZBAR = os.path.join(BASE_DIR, 'utils/zbar/zbar.jpg').replace('\\', '/')
|
|
| 429 |
+ |
|
| 430 |
+# 一物一码设置 |
|
| 431 |
+KODO_MARKET_CODE_ENABLED = False |
|
| 432 |
+ |
|
| 422 | 433 |
# 开发调试相关配置 |
| 423 | 434 |
if DEBUG: |
| 424 | 435 |
try: |
@@ -7,7 +7,7 @@ from logs.models import MchInfoDecryptLogInfo, MchInfoEncryptLogInfo, MchLogInfo |
||
| 7 | 7 |
|
| 8 | 8 |
|
| 9 | 9 |
class MchInfoEncryptLogInfoAdmin(Readonly2ModelAdmin, admin.ModelAdmin): |
| 10 |
- list_display = ('plaintext', 'alg', 'ciphertext', 'brand_pk', 'model_pk', 'distributor_pk', 'sn', 'operator_id', 'is_send_redpack', 'redpack_amount', 'redpack_max_amount', 'has_send_redpack', 'redpack_send_amount', 'user_id', 'nickname', 'is_clerk_send_redpack', 'clerk_redpack_amount', 'clerk_redpack_max_amount', 'has_clerk_send_redpack', 'clerk_redpack_send_amount', 'clerk_user_id', 'clerk_nickname', 'status', 'created_at', 'updated_at')
|
|
| 10 |
+ list_display = ('plaintext', 'alg', 'ciphertext', 'brand_pk', 'model_pk', 'distributor_pk', 'sn', 'code', 'code_url', 'operator_id', 'is_send_redpack', 'redpack_amount', 'redpack_max_amount', 'has_send_redpack', 'redpack_send_amount', 'user_id', 'nickname', 'is_clerk_send_redpack', 'clerk_redpack_amount', 'clerk_redpack_max_amount', 'has_clerk_send_redpack', 'clerk_redpack_send_amount', 'clerk_user_id', 'clerk_nickname', 'status', 'created_at', 'updated_at')
|
|
| 11 | 11 |
list_filter = ('alg', 'brand_pk', 'model_pk', 'distributor_pk', 'operator_id', 'is_send_redpack', 'has_send_redpack', 'is_clerk_send_redpack', 'has_clerk_send_redpack', 'status')
|
| 12 | 12 |
readonly_fields_exclude = ('is_send_redpack', 'redpack_amount', 'redpack_max_amount', 'is_clerk_send_redpack', 'clerk_redpack_amount', 'clerk_redpack_max_amount')
|
| 13 | 13 |
|
@@ -0,0 +1,25 @@ |
||
| 1 |
+# -*- coding: utf-8 -*- |
|
| 2 |
+# Generated by Django 1.11.28 on 2020-03-22 21:25 |
|
| 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 |
+ ('logs', '0013_mchinfoencryptloginfo_user_ids'),
|
|
| 12 |
+ ] |
|
| 13 |
+ |
|
| 14 |
+ operations = [ |
|
| 15 |
+ migrations.AddField( |
|
| 16 |
+ model_name='mchinfoencryptloginfo', |
|
| 17 |
+ name='code', |
|
| 18 |
+ field=models.CharField(blank=True, db_index=True, help_text='\u4e5d\u4f4d\u7684\u5b57\u7b26\u4e32\u539f\u59cb\u7801', max_length=16, null=True, verbose_name='code'), |
|
| 19 |
+ ), |
|
| 20 |
+ migrations.AddField( |
|
| 21 |
+ model_name='mchinfoencryptloginfo', |
|
| 22 |
+ name='code_url', |
|
| 23 |
+ field=models.CharField(blank=True, db_index=True, help_text='28\u4f4d\u666e\u901a\u7801\u5b57\u7b26\t', max_length=128, null=True, verbose_name='code_url'), |
|
| 24 |
+ ), |
|
| 25 |
+ ] |
@@ -18,6 +18,10 @@ class MchInfoEncryptLogInfo(BaseModelMixin): |
||
| 18 | 18 |
|
| 19 | 19 |
sn = models.CharField(_(u'sn'), max_length=32, blank=True, null=True, help_text=u'序列号', db_index=True) |
| 20 | 20 |
|
| 21 |
+ # 一物一码 |
|
| 22 |
+ code = models.CharField(_(u'code'), max_length=16, blank=True, null=True, help_text=u'九位的字符串原始码', db_index=True) |
|
| 23 |
+ code_url = models.CharField(_(u'code_url'), max_length=128, blank=True, null=True, help_text=u'28位普通码字符 ', db_index=True) |
|
| 24 |
+ |
|
| 21 | 25 |
operator_id = models.CharField(_(u'operator_id'), max_length=32, blank=True, null=True, help_text=u'操作员唯一标识', db_index=True) |
| 22 | 26 |
|
| 23 | 27 |
is_send_redpack = models.BooleanField(_(u'is_send_redpack'), default=False, help_text=u'是否发放红包', db_index=True) |
@@ -0,0 +1,12 @@ |
||
| 1 |
+# -*- coding: utf-8 -*- |
|
| 2 |
+ |
|
| 3 |
+from django.contrib import admin |
|
| 4 |
+ |
|
| 5 |
+from marketcode.models import MarketCodeInfo |
|
| 6 |
+ |
|
| 7 |
+ |
|
| 8 |
+class MarketCodeInfoAdmin(admin.ModelAdmin): |
|
| 9 |
+ list_display = ('isv_application_id', 'application_id', 'code', 'code_url', 'has_used', 'status', 'created_at', 'updated_at')
|
|
| 10 |
+ |
|
| 11 |
+ |
|
| 12 |
+admin.site.register(MarketCodeInfo, MarketCodeInfoAdmin) |
@@ -0,0 +1,8 @@ |
||
| 1 |
+# -*- coding: utf-8 -*- |
|
| 2 |
+from __future__ import unicode_literals |
|
| 3 |
+ |
|
| 4 |
+from django.apps import AppConfig |
|
| 5 |
+ |
|
| 6 |
+ |
|
| 7 |
+class MarketcodeConfig(AppConfig): |
|
| 8 |
+ name = 'marketcode' |
@@ -0,0 +1,34 @@ |
||
| 1 |
+# -*- coding: utf-8 -*- |
|
| 2 |
+# Generated by Django 1.11.26 on 2020-01-13 10:32 |
|
| 3 |
+from __future__ import unicode_literals |
|
| 4 |
+ |
|
| 5 |
+from django.db import migrations, models |
|
| 6 |
+ |
|
| 7 |
+ |
|
| 8 |
+class Migration(migrations.Migration): |
|
| 9 |
+ |
|
| 10 |
+ initial = True |
|
| 11 |
+ |
|
| 12 |
+ dependencies = [ |
|
| 13 |
+ ] |
|
| 14 |
+ |
|
| 15 |
+ operations = [ |
|
| 16 |
+ migrations.CreateModel( |
|
| 17 |
+ name='MarketCodeInfo', |
|
| 18 |
+ fields=[ |
|
| 19 |
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
| 20 |
+ ('status', models.BooleanField(db_index=True, default=True, help_text='Status', verbose_name='status')),
|
|
| 21 |
+ ('created_at', models.DateTimeField(auto_now_add=True, help_text='Create Time', verbose_name='created_at')),
|
|
| 22 |
+ ('updated_at', models.DateTimeField(auto_now=True, help_text='Update Time', verbose_name='updated_at')),
|
|
| 23 |
+ ('isv_application_id', models.CharField(blank=True, db_index=True, help_text='\u5916\u90e8\u5355\u53f7', max_length=128, null=True, verbose_name='isv_application_id')),
|
|
| 24 |
+ ('application_id', models.IntegerField(db_index=True, default=0, help_text='\u7533\u8bf7\u5355\u53f7', verbose_name='application_id')),
|
|
| 25 |
+ ('code', models.CharField(blank=True, db_index=True, help_text='\u4e5d\u4f4d\u7684\u5b57\u7b26\u4e32\u539f\u59cb\u7801', max_length=16, null=True, verbose_name='code')),
|
|
| 26 |
+ ('code_url', models.CharField(blank=True, db_index=True, help_text='28\u4f4d\u666e\u901a\u7801\u5b57\u7b26\t', max_length=128, null=True, verbose_name='code_url')),
|
|
| 27 |
+ ('has_used', models.BooleanField(db_index=True, default=True, help_text='\u662f\u5426\u5df2\u4f7f\u7528', verbose_name='has_used')),
|
|
| 28 |
+ ], |
|
| 29 |
+ options={
|
|
| 30 |
+ 'verbose_name': '\u4e00\u7269\u4e00\u7801\u4fe1\u606f', |
|
| 31 |
+ 'verbose_name_plural': '\u4e00\u7269\u4e00\u7801\u4fe1\u606f', |
|
| 32 |
+ }, |
|
| 33 |
+ ), |
|
| 34 |
+ ] |
@@ -0,0 +1,20 @@ |
||
| 1 |
+# -*- coding: utf-8 -*- |
|
| 2 |
+# Generated by Django 1.11.26 on 2020-01-13 10:51 |
|
| 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 |
+ ('marketcode', '0001_initial'),
|
|
| 12 |
+ ] |
|
| 13 |
+ |
|
| 14 |
+ operations = [ |
|
| 15 |
+ migrations.AlterField( |
|
| 16 |
+ model_name='marketcodeinfo', |
|
| 17 |
+ name='has_used', |
|
| 18 |
+ field=models.BooleanField(db_index=True, default=False, help_text='\u662f\u5426\u5df2\u4f7f\u7528', verbose_name='has_used'), |
|
| 19 |
+ ), |
|
| 20 |
+ ] |
@@ -0,0 +1,25 @@ |
||
| 1 |
+# -*- coding: utf-8 -*- |
|
| 2 |
+# Generated by Django 1.11.26 on 2020-01-13 18:20 |
|
| 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 |
+ ('marketcode', '0002_auto_20200113_1851'),
|
|
| 12 |
+ ] |
|
| 13 |
+ |
|
| 14 |
+ operations = [ |
|
| 15 |
+ migrations.AddField( |
|
| 16 |
+ model_name='marketcodeinfo', |
|
| 17 |
+ name='code_index', |
|
| 18 |
+ field=models.IntegerField(default=0, help_text='\u8be5\u7801\u5728\u6279\u6b21\u4e2d\u7684\u504f\u79fb\u91cf\t', verbose_name='code_index'), |
|
| 19 |
+ ), |
|
| 20 |
+ migrations.AddField( |
|
| 21 |
+ model_name='marketcodeinfo', |
|
| 22 |
+ name='lattice', |
|
| 23 |
+ field=models.CharField(blank=True, help_text='361 \u5b57\u8282\u7684 01 \u70b9\u9635\uff0c\u7528\u4e8e\u652f\u6301\u751f\u6210 19 * 19 \u7684\u5fae\u578b\u7801\uff0c0 \u4e3a\u767d\uff0c1 \u4e3a\u9ed1', max_length=361, null=True, verbose_name='code'), |
|
| 24 |
+ ), |
|
| 25 |
+ ] |
@@ -0,0 +1,24 @@ |
||
| 1 |
+# -*- coding: utf-8 -*- |
|
| 2 |
+ |
|
| 3 |
+from django.db import models |
|
| 4 |
+from django.utils.translation import ugettext_lazy as _ |
|
| 5 |
+from django_models_ext import BaseModelMixin |
|
| 6 |
+ |
|
| 7 |
+ |
|
| 8 |
+class MarketCodeInfo(BaseModelMixin): |
|
| 9 |
+ isv_application_id = models.CharField(_(u'isv_application_id'), max_length=128, blank=True, null=True, help_text=u'外部单号', db_index=True) |
|
| 10 |
+ application_id = models.IntegerField(_(u'application_id'), default=0, help_text=u'申请单号', db_index=True) |
|
| 11 |
+ |
|
| 12 |
+ lattice = models.CharField(_(u'code'), max_length=361, blank=True, null=True, help_text=u'361 字节的 01 点阵,用于支持生成 19 * 19 的微型码,0 为白,1 为黑') |
|
| 13 |
+ code = models.CharField(_(u'code'), max_length=16, blank=True, null=True, help_text=u'九位的字符串原始码', db_index=True) |
|
| 14 |
+ code_index = models.IntegerField(_(u'code_index'), default=0, help_text=u'该码在批次中的偏移量 ') |
|
| 15 |
+ code_url = models.CharField(_(u'code_url'), max_length=128, blank=True, null=True, help_text=u'28位普通码字符 ', db_index=True) |
|
| 16 |
+ |
|
| 17 |
+ has_used = models.BooleanField(_(u'has_used'), default=False, help_text=_(u'是否已使用'), db_index=True) |
|
| 18 |
+ |
|
| 19 |
+ class Meta: |
|
| 20 |
+ verbose_name = _(u'一物一码信息') |
|
| 21 |
+ verbose_name_plural = _(u'一物一码信息') |
|
| 22 |
+ |
|
| 23 |
+ def __unicode__(self): |
|
| 24 |
+ return unicode(self.pk) |
@@ -0,0 +1,6 @@ |
||
| 1 |
+# -*- coding: utf-8 -*- |
|
| 2 |
+from __future__ import unicode_literals |
|
| 3 |
+ |
|
| 4 |
+from django.test import TestCase |
|
| 5 |
+ |
|
| 6 |
+# Create your tests here. |
@@ -0,0 +1,6 @@ |
||
| 1 |
+# -*- coding: utf-8 -*- |
|
| 2 |
+from __future__ import unicode_literals |
|
| 3 |
+ |
|
| 4 |
+from django.shortcuts import render |
|
| 5 |
+ |
|
| 6 |
+# Create your views here. |
@@ -0,0 +1,41 @@ |
||
| 1 |
+# -*- coding: utf-8 -*- |
|
| 2 |
+ |
|
| 3 |
+from django.conf import settings |
|
| 4 |
+from pywe_marketcode import applycodedownload |
|
| 5 |
+from pywe_storage import RedisStorage |
|
| 6 |
+ |
|
| 7 |
+from marketcode.models import MarketCodeInfo |
|
| 8 |
+from utils.redis.connect import r |
|
| 9 |
+ |
|
| 10 |
+ |
|
| 11 |
+WECHAT = settings.WECHAT |
|
| 12 |
+ |
|
| 13 |
+ |
|
| 14 |
+def marketcodedownload(application_id, code_start, code_end, isv_application_id=''): |
|
| 15 |
+ wxcfg = WECHAT.get('JSAPI', {})
|
|
| 16 |
+ |
|
| 17 |
+ appid = wxcfg.get('appID')
|
|
| 18 |
+ secret = wxcfg.get('appsecret')
|
|
| 19 |
+ |
|
| 20 |
+ codes = applycodedownload(application_id=application_id, code_start=code_start, code_end=code_end, appid=appid, secret=secret, token=None, storage=RedisStorage(r)) |
|
| 21 |
+ |
|
| 22 |
+ lattice, code, code_index, code_url = '' |
|
| 23 |
+ for idx, item in enumerate(codes): |
|
| 24 |
+ if idx % 4 == 0: |
|
| 25 |
+ lattice = item |
|
| 26 |
+ if idx % 4 == 1: |
|
| 27 |
+ code = item |
|
| 28 |
+ if idx % 4 == 2: |
|
| 29 |
+ code_index = item |
|
| 30 |
+ if idx % 4 == 3: |
|
| 31 |
+ code_url = item |
|
| 32 |
+ MarketCodeInfo.objects.create( |
|
| 33 |
+ isv_application_id=isv_application_id, |
|
| 34 |
+ application_id=application_id, |
|
| 35 |
+ lattice=lattice, |
|
| 36 |
+ code=code, |
|
| 37 |
+ code_index=code_index, |
|
| 38 |
+ code_url=code_url |
|
| 39 |
+ ) |
|
| 40 |
+ |
|
| 41 |
+ |
@@ -2,6 +2,7 @@ pywe-card==1.0.0 |
||
| 2 | 2 |
pywe-component==1.0.1 |
| 3 | 3 |
pywe-component-preauthcode==1.0.3 |
| 4 | 4 |
pywe-jssdk==1.1.0 |
| 5 |
+pywe-marketcode==1.0.1 |
|
| 5 | 6 |
pywe-membercard==1.0.3 |
| 6 | 7 |
pywe-miniapp==1.1.5 |
| 7 | 8 |
pywe-oauth==1.0.7 |
@@ -59,6 +59,39 @@ class ProductStatusCode(BaseStatusCode): |
||
| 59 | 59 |
PRODUCT_NOT_USED = StatusCodeField(502012, 'Product Not Used', description=u'产品未使用') |
| 60 | 60 |
|
| 61 | 61 |
|
| 62 |
+class MemberGoodStatusCode(BaseStatusCode): |
|
| 63 |
+ """ 会员商品相关错误码 5035xx """ |
|
| 64 |
+ GOOD_NOT_FOUND = StatusCodeField(503501, 'Good Not Found', description=u'商品不存在') |
|
| 65 |
+ |
|
| 66 |
+ GOOD_NO_EXCHANGE_PERMISSION = StatusCodeField(503502, 'Good No Exchange Permission', description=u'商品无兑换权限') |
|
| 67 |
+ GOOD_INTEGRAL_NOT_ENOUGH = StatusCodeField(503503, 'Good Integral Not Enough', description=u'商品兑换积分不足') |
|
| 68 |
+ GOOD_STOCK_NOT_ENOUGH = StatusCodeField(503504, 'Good Integral Not Enough', description=u'商品库存不足') |
|
| 69 |
+ |
|
| 70 |
+ |
|
| 71 |
+class MemberRightStatusCode(BaseStatusCode): |
|
| 72 |
+ """ 会员商品相关错误码 5036xx """ |
|
| 73 |
+ RIGHT_NOT_FOUND = StatusCodeField(503601, 'Right Not Found', description=u'权益不存在') |
|
| 74 |
+ |
|
| 75 |
+ |
|
| 76 |
+class MemberActivityStatusCode(BaseStatusCode): |
|
| 77 |
+ """ 会员活动相关错误码 5037xx """ |
|
| 78 |
+ ACTIVITY_NOT_FOUND = StatusCodeField(503701, 'Activity Not Found', description=u'活动不存在') |
|
| 79 |
+ |
|
| 80 |
+ |
|
| 81 |
+class MemberCouponStatusCode(BaseStatusCode): |
|
| 82 |
+ """ 会员优惠券相关错误码 5040xx """ |
|
| 83 |
+ USER_COUPON_NOT_FOUND = StatusCodeField(504001, 'User Coupon Not Found', description=u'用户优惠券不存在') |
|
| 84 |
+ |
|
| 85 |
+ USER_COUPON_HAS_USED = StatusCodeField(504010, 'User Coupon Has Used', description=u'用户优惠券已使用') |
|
| 86 |
+ USER_COUPON_NOT_ACTIVED = StatusCodeField(504011, 'User Coupon Not Actived', description=u'用户优惠券未生效') |
|
| 87 |
+ USER_COUPON_HAS_EXPIRED = StatusCodeField(504012, 'User Coupon Has Expired', description=u'用户优惠券已过期') |
|
| 88 |
+ |
|
| 89 |
+ |
|
| 90 |
+class MarketCodeStatusCode(BaseStatusCode): |
|
| 91 |
+ """ 一物一码相关错误码 5050xx """ |
|
| 92 |
+ MARKET_CODE_NOT_FOUND = StatusCodeField(505001, 'Market Code Not Found', description=u'一物一码不存在') |
|
| 93 |
+ |
|
| 94 |
+ |
|
| 62 | 95 |
class LensmanStatusCode(BaseStatusCode): |
| 63 | 96 |
""" 摄影师相关错误码 4000xx """ |
| 64 | 97 |
LENSMAN_NOT_FOUND = StatusCodeField(400001, 'Lensman Not Found', description=u'摄影师不存在') |