jiaweiqi 2 anos atrás
pai
commit
1a0aa73806

+ 1 - 11
apps/api/urls.py

@@ -2,18 +2,8 @@
 
 from django.conf.urls import url
 from .views import *
-urlpatterns = [
-    url(r'^callback_authorize/$', CallbackAuthorize.as_view()),
-    url(r'^redirect_authorize/(?P<pk>[0-9]+)/$', RedirectAuthorize.as_view()),
-    url('^(?P<appid>.+)/callback_event/$', CallbackEvent.as_view()),
 
+urlpatterns = [
     url(r'^wechat_notify/(?P<appid>.+)/$', WechatNotifyView.as_view()),
-
-    url(r'^xgj/get_comppany/$', GetCompany.as_view()),
-    url(r'^xgj/get_member_card/$', GetMemberCard.as_view()),
-    url(r'^xgj/get_member_info/$', GetMemberInfo.as_view()),
-    url(r'^xgj/get_member_points/$', GetMemberPoints.as_view()),
-    url(r'^xgj/get_member_record/$', GetMemberRecord.as_view()),
-    url(r'^xgj/get_member_balance/$', GetMemberBalance.as_view()),
 ]
 

+ 18 - 177
apps/api/views.py

@@ -2,10 +2,10 @@
 
 import json
 import xmltodict
+import traceback
 
 from django.db import transaction
 from django.http import HttpResponse
-from apps.customer import customer_log
 from rest_framework.views import APIView
 
 from utils.wx.WXBizMsgCrypt import WXBizMsgCrypt
@@ -14,94 +14,17 @@ from utils import response_ok, response_error
 from utils.wechatpay import WechatPayNotify
 
 from apps.log.models import BizLog
-from apps.WechatTp.models import WechatTp
 from apps.WechatApplet.models import WechatApplet
-from apps.tenant.models import Tenant
-from apps.pay.models import Pay
-from apps.tenant.biz import TenantBiz
-from utils.xgj.xgj import XGJ
-from utils.permission import IsCustomerUser
+from apps.order.models import Pay
+from apps.rebate.bussiness import CustomerRebate
 
 
-class CallbackAuthorize(APIView):
-    '''验证票据(component_verify_ticket)在第三方平台创建审核通过后,微信服务器会向其 ”授权事件接收URL”
-    每隔 10 分钟以 POST 的方式推送 component_verify_ticket 接收 POST 请求后,只需直接返回字符串 success。
-    为了加强安全性,postdata 中的 xml 将使用服务申请时的加解密 key 来进行加密'''
-
-    def post(self, request):
-        sMsgSignature = request.GET.get('msg_signature')
-        sTimeStamp = request.GET.get('timestamp')
-        sNonce = request.GET.get('nonce')
-        sPostData = request.body.decode('utf-8')
-
-        try:
-            component = WechatTp.getDefault()
-            if component:
-                appid = component.getAppid()
-                msg_crypt = WXBizMsgCrypt(component.getToken(), component.getEncodeKey(), appid)
-                ret, decryp_xml = msg_crypt.DecryptMsg(sPostData, sMsgSignature, sTimeStamp, sNonce)
-                data = json.loads(json.dumps(xmltodict.parse(decryp_xml)))['xml']
-                if data['AppId'] == appid:
-                    if data['InfoType'] == 'component_verify_ticket':
-                        component.refreshVerifyTicket(data['ComponentVerifyTicket'])
-                    elif data['InfoType'] == 'unauthorized':
-                        authorizer_appid = data['AuthorizerAppid']
-                        authorizer = WechatApplet.getByAppidAndComponentAppid(authorizer_appid, appid)
-                        if authorizer:
-                            authorizer.revoke()
-        except:
-            pass
-
-        return HttpResponse('success')
-
-
-class RedirectAuthorize(APIView):
-    '''小程序绑定授权回调'''
-
-    def get(self, request, pk):
-        try:
-            with transaction.atomic():
-                tenant = Tenant.objects.select_for_update().filter(id=pk).first()
-                app = TenantBiz.bindWechatApplet(tenant, request.GET.get('auth_code'))
-                BizLog.objects.addnew(None, None, BizLog.INSERT, u'租户绑定小程序, id=%d' % app.id)
-        except Exception as e:
-            return response_error(str(e))
-        return response_ok()
-
-
-class CallbackEvent(APIView):
-    '''消息与事件接收'''
-
-    def post(self, request, appid):
-        appid = appid
-        sMsgSignature = request.GET.get('msg_signature')
-        sTimeStamp = request.GET.get('timestamp')
-        sNonce = request.GET.get('nonce')
-        sPostData = request.body.decode('utf-8')
-
-        try:
-            tp = WechatTp.getDefault()
-            msg_crypt = WXBizMsgCrypt(tp.getToken(), tp.getEncodeKey(), tp.getAppid())
-            ret, decryp_xml = msg_crypt.DecryptMsg(sPostData, sMsgSignature, sTimeStamp, sNonce)
-            data = json.loads(json.dumps(xmltodict.parse(decryp_xml)))['xml']
-            if data['MsgType'] == 'event':
-                app = WechatApplet.getByAppid(appid)
-                if data['Event'] == 'weapp_audit_success':  # 代码审核通过
-                    app.weapp_audit_success()
-                elif data['Event'] == 'weapp_audit_fail':  # 代码审核不通过
-                    app.weapp_audit_fail(data['Reason'])
-                elif data['Event'] == 'weapp_audit_delay':  # 代码审核延后
-                    app.weapp_audit_delay(data['Reason'])
-        except:
-            pass
-        return HttpResponse('success')
-
 class WechatNotifyView(APIView):
 
     def dispatch(self, request, *args, **kwargs):
         appid = kwargs['appid']
         applet = WechatApplet.getByAppid(appid)
-        param = request.body.decode('utf-8')
+        param = request.body
         notify = WechatPayNotify(param, applet.tenant_key)
 
         try:
@@ -114,104 +37,22 @@ class WechatNotifyView(APIView):
                 raise CustomError(u'错误的请求!')
 
             no = data['out_trade_no']
-            amount = int(data['total_fee']) * 100
+            amount = int(data['total_fee'])
+            transaction_id = data['transaction_id']
 
             with transaction.atomic():
                 pay = Pay.getByNo(no)
-                pay.payConfirm(amount)
-                customer_log(pay.customer, BizLog.INSERT, u'支付成功,no=%s' % no, param)
-        except:
+                pay.payConfirm(amount, transaction_id)
+                BizLog.objects.addnew(pay.customer.user, BizLog.INSERT, u'微信支付成功,pay_no=%s' % no, param)
+            # 计算返利
+            # 在这现金返利发红包(不要在同一个事务里边 防止出错导致 订单状态不能正确改变)
+            try:
+                with transaction.atomic():  # 因为在计算 返利的时候使用了select_for_update 这个必须在事务里边
+                    instance = CustomerRebate(pay)
+                    instance.calcul_rebate()
+            except Exception as e:
+                traceback.print_exc()
+        except Exception as e:
+            traceback.print_exc()
             return HttpResponse(WechatPayNotify.response_fail())
         return HttpResponse(WechatPayNotify.response_ok())
-
-
-class GetCompany(APIView):
-    permission_classes = [IsCustomerUser, ]
-
-    def get(self, request):
-        appid = request.GET.get('appid')
-        try:
-            res = XGJ.get_company(appid)
-        except Exception as e:
-            return response_error(str(e))
-        return response_ok(res)
-
-
-class GetMemberCard(APIView):
-    permission_classes = [IsCustomerUser, ]
-
-    def post(self, request):
-        appid = request.POST.get('appid')
-        company_id = request.POST.get('company_id')
-        tel = request.POST.get('tel')
-        number = request.POST.get('number')
-        try:
-            res = XGJ.get_member_card(appid, company_id, tel, number)
-        except Exception as e:
-            return response_error(str(e))
-        return response_ok(res)
-
-
-class GetMemberInfo(APIView):
-    permission_classes = [IsCustomerUser, ]
-
-    def get(self, request):
-        appid = request.GET.get('appid')
-        customer = request.customer
-        if not customer.member_id:
-            raise CustomError(u'请先绑定会员卡')
-        try:
-            res = XGJ.get_member_info(appid, str(customer.member_id))
-        except Exception as e:
-            return response_error(str(e))
-        return response_ok(res)
-
-
-class GetMemberPoints(APIView):
-    permission_classes = [IsCustomerUser, ]
-
-    def get(self, request):
-        appid = request.GET.get('appid')
-        page = request.GET.get('page')
-        pageSize = request.GET.get('pageSize')
-        customer = request.customer
-        if not customer.member_id:
-            raise CustomError(u'请先绑定会员卡')
-        try:
-            res = XGJ.get_member_points(appid, str(customer.member_id), page, pageSize)
-        except Exception as e:
-            return response_error(str(e))
-        return response_ok(res)
-
-
-class GetMemberRecord(APIView):
-    permission_classes = [IsCustomerUser, ]
-
-    def get(self, request):
-        appid = request.GET.get('appid')
-        page = request.GET.get('page')
-        pageSize = request.GET.get('pageSize')
-        customer = request.customer
-        if not customer.member_id:
-            raise CustomError(u'请先绑定会员卡')
-        try:
-            res = XGJ.get_member_record(appid, str(customer.member_id), page, pageSize)
-        except Exception as e:
-            return response_error(str(e))
-        return response_ok(res)
-
-
-class GetMemberBalance(APIView):
-    permission_classes = [IsCustomerUser, ]
-
-    def get(self, request):
-        appid = request.GET.get('appid')
-        customer = request.customer
-        if not customer.member_id:
-            raise CustomError(u'未绑定会员卡')
-        try:
-            res = XGJ.get_member_balance(appid, str(customer.member_id))
-        except Exception as e:
-            return response_error(str(e))
-        return response_ok(res)
-

+ 36 - 2
apps/config/models.py

@@ -51,7 +51,41 @@ class Config(models.Model):
     @staticmethod
     def get_commodity():
         try:
-            commodity = Config.objects.get(property=Config.KEY_DISTRIBUTOR_COMMODITY).value
+            commodity = int(Config.objects.get(property=Config.KEY_DISTRIBUTOR_COMMODITY).value)
             return commodity
         except:
-            return ''
+            return 0
+
+    @staticmethod
+    def get_rebate(first):
+        item_list = [Config.KEY_AGAIN_LEVEL1, Config.KEY_AGAIN_LEVEL2, Config.KEY_AGAIN_LEVEL3, Config.KEY_AGAIN_LEVEL4, Config.KEY_AGAIN_LEVEL5,]
+        if first:
+            item_list = [Config.KEY_FIRST_LEVEL1, Config.KEY_FIRST_LEVEL2, Config.KEY_FIRST_LEVEL3, Config.KEY_FIRST_LEVEL4, Config.KEY_FIRST_LEVEL5,]
+
+        rows = Config.objects.filter(property__in=item_list)
+
+        data = {'one_level': 0, 'two_level': 0, 'three_level': 0, 'four_level': 0, 'five_level': 0}
+        for row in rows:
+            if first:
+                if row.property == Config.KEY_FIRST_LEVEL1:
+                    data['one_level'] = row.value and float(row.value) or 0
+                elif row.property == Config.KEY_FIRST_LEVEL2:
+                    data['two_level'] = row.value and float(row.value) or 0
+                elif row.property == Config.KEY_FIRST_LEVEL3:
+                    data['three_level'] = row.value and float(row.value) or 0
+                elif row.property == Config.KEY_FIRST_LEVEL4:
+                    data['four_level'] = row.value and float(row.value) or 0
+                elif row.property == Config.KEY_FIRST_LEVEL5:
+                    data['five_level'] = row.value and float(row.value) or 0
+            else:
+                if row.property == Config.KEY_AGAIN_LEVEL1:
+                    data['one_level'] = row.value and float(row.value) or 0
+                elif row.property == Config.KEY_AGAIN_LEVEL2:
+                    data['two_level'] = row.value and float(row.value) or 0
+                elif row.property == Config.KEY_AGAIN_LEVEL3:
+                    data['three_level'] = row.value and float(row.value) or 0
+                elif row.property == Config.KEY_AGAIN_LEVEL4:
+                    data['four_level'] = row.value and float(row.value) or 0
+                elif row.property == Config.KEY_AGAIN_LEVEL5:
+                    data['five_level'] = row.value and float(row.value) or 0
+        return data

+ 3 - 1
apps/customer/collection/views.py

@@ -1,5 +1,7 @@
 # coding=utf-8
 
+from django.conf import settings
+
 from rest_framework import generics
 from rest_framework.exceptions import NotFound
 
@@ -12,7 +14,7 @@ from .serializers import CollectionSerializer
 
 class CollectionListViewSet(generics.ListAPIView):
     permission_classes = [IsCustomer, ]
-    queryset = Collection.objects.filter(delete=False)
+    queryset = Collection.objects.filter(delete=False, commodity__delete=False, commodity__status=settings.ONLINE)
     serializer_class = CollectionSerializer
 
     def filter_queryset(self, queryset):

+ 15 - 2
apps/customer/commodity/serializers.py

@@ -43,7 +43,6 @@ class CommodityDetailSerializer(serializers.ModelSerializer):
     price = serializers.SerializerMethodField()
     vip_price = serializers.SerializerMethodField()
     show_image = serializers.SerializerMethodField()
-    # 评论
 
     def get_sale_count(self, obj):
         count = (obj.total_sales or 0) + (obj.initial_sale_count or 0)
@@ -87,7 +86,7 @@ class CommodityDetailSerializer(serializers.ModelSerializer):
     class Meta:
         model = Commodity
         fields = (
-            'id', 'name', 'price', 'vip_price', 'point_price', 'sale_count', 'is_collection', 'carousel_urls', 'details_urls', 'show_image',
+            'id', 'name', 'price', 'vip_price', 'point_price', 'sale_count', 'is_collection', 'carousel_urls', 'details_urls', 'show_image', 'type',
         )
 
 
@@ -97,3 +96,17 @@ class CommodityCategorySerializer(serializers.ModelSerializer):
     class Meta:
         model = Option
         fields = ('id', 'label', )
+
+
+class HomeOptionSerializer(serializers.ModelSerializer):
+    commodity_list = serializers.SerializerMethodField()
+
+    class Meta:
+        model = Option
+        fields = ('id', 'name', 'commodity_list', )
+
+    def get_commodity_list(self, obj):
+        rows = Commodity.objects.filter(category=obj, delete=False, status=settings.ONLINE)
+        serializer = CommoditySerializer(rows, many=True)
+        data = serializer.data
+        return data

+ 1 - 0
apps/customer/commodity/urls.py

@@ -9,6 +9,7 @@ urlpatterns = [
     url(r'^category/$', CommodityCategoryListView.as_view()),
     url(r'^list/$', CommodityListView.as_view()),
     url(r'^detail/(?P<pk>[0-9]+)/$', CommodityDetailView.as_view()),
+    url(r'^home/$', HomeCommodityListView.as_view()),
 ]
 
 router = SimpleRouter()

+ 41 - 1
apps/customer/commodity/views.py

@@ -1,5 +1,7 @@
 # coding=utf-8
 
+import json
+
 from django.db import transaction
 from django.db.models import F
 from django.conf import settings
@@ -23,7 +25,7 @@ from apps.collection.models import Collection
 from apps.option.filters import OptionFilter
 from apps.option.models import Option
 
-from .serializers import CommodityCategorySerializer, CommoditySerializer, CommodityDetailSerializer
+from .serializers import CommodityCategorySerializer, CommoditySerializer, CommodityDetailSerializer, HomeOptionSerializer
 
 
 class CollectionViewSet(GenericViewSet, mixins.ListModelMixin, mixins.RetrieveModelMixin):
@@ -45,6 +47,22 @@ class CollectionViewSet(GenericViewSet, mixins.ListModelMixin, mixins.RetrieveMo
             Collection.addnew(customer, instance)
         return response_ok()
 
+    @action(methods=['post'], detail=False)
+    def batch_collection(self, request):
+        ids = json.loads(request.data.get('ids'))
+        commoditys = self.queryset.filter(id__in=ids)
+
+        with transaction.atomic():
+            for item in commoditys:
+                ct = Collection.objects.filter(customer=request.customer, commodity=item).first()
+                if not ct:
+                    Collection.objects.create(customer=request.customer, commodity=item, create_time=timezone.now())
+                if ct and ct.delete:
+                    ct.delete = False
+                    ct.create_time = timezone.now()
+                    ct.save()
+        return response_ok()
+
     @action(methods=['get'], detail=True)
     def uncollection(self, request, pk):
         instance = self.get_object()
@@ -101,3 +119,25 @@ class CommodityDetailView(generics.RetrieveAPIView):
             raise CustomError(u'未找到相应的商品!')
         serializer = self.get_serializer(instance)
         return response_ok(serializer.data)
+
+
+class HomeCommodityListView(generics.ListAPIView):
+    queryset = Option.objects.filter(type=Option.COMMODITY_CATEGORY, delete=False, enable=True)
+    serializer_class = HomeOptionSerializer
+
+    def filter_queryset(self, queryset):
+        queryset = queryset.filter()
+        f = OptionFilter(self.request.GET, queryset=queryset)
+        return f.qs
+
+    def list(self, request, *args, **kwargs):
+        '''
+        首页商品列表  不分页  每类商品加载6条商品
+        :param request:
+        :param args:
+        :param kwargs:
+        :return:
+        '''
+        queryset = self.filter_queryset(self.get_queryset())
+        serializer = self.get_serializer(queryset, many=True)
+        return response_ok(serializer.data)

+ 2 - 1
apps/customer/distributor/serializers.py

@@ -12,10 +12,11 @@ class DistributorSerializer(serializers.ModelSerializer):
     name = serializers.CharField(source='customer.name', read_only=True)
     total_count = serializers.CharField(source='customer.success_count', read_only=True)
     total_amount = serializers.SerializerMethodField()
+    total_point = serializers.CharField(source='customer.total_point', read_only=True)
 
     class Meta:
         model = SuperiorDistributor
-        fields = ('name', 'total_count', 'total_amount', )
+        fields = ('name', 'total_count', 'total_amount', 'total_point', )
 
     def get_total_amount(self, obj):
         return Formater.formatValueShow(obj.customer.total_amount)

+ 3 - 2
apps/customer/distributor/views.py

@@ -55,12 +55,13 @@ class DistributorView(generics.ListAPIView):
 
     def list(self, request, *args, **kwargs):
         queryset = self.filter_queryset(self.get_queryset())
-        sum_rows = queryset.aggregate(sum_count=Sum('customer__success_count'), sum_amount=Sum('customer__total_amount'))
+        sum_rows = queryset.aggregate(sum_count=Sum('customer__success_count'), sum_amount=Sum('customer__total_amount'), sum_point=Sum('customer__total_point'))
         sum_cash = CashRebate.objects.filter(customer=request.customer).aggregate(sum_amount=Sum('amount'))['sum_amount'] or 0
         sum_point = PointRebate.objects.filter(customer=request.customer).aggregate(sum_amount=Sum('amount'))['sum_amount'] or 0
         footer = {
             'sum_count': sum_rows['sum_count'] or 0,
-            'sum_amount': Formater.formatValueShow(sum_rows['sum_amount']),
+            'sum_amount': Formater.formatValueShow(sum_rows['sum_amount'] or 0),
+            'total_point': sum_rows['sum_point'] or 0,
             'sum_cash': Formater.formatValueShow(sum_cash),
             'sum_point': sum_point,
         }

+ 59 - 1
apps/customer/order/serializers.py

@@ -6,7 +6,7 @@ from rest_framework import serializers
 
 from utils.exceptions import CustomError
 
-from apps.order.models import ShoppingCart
+from apps.order.models import ShoppingCart, Order, OrderDetails
 from apps.base import Formater
 
 
@@ -53,3 +53,61 @@ class ShoppingCartSerializer(serializers.ModelSerializer):
         else:
             instance = super(ShoppingCartSerializer, self).create(validated_data)
         return instance
+
+
+class OderSerializer(serializers.ModelSerializer):
+
+    class Meta:
+        model = Order
+        fields = '__all__'
+
+    def create(self, validated_data):
+        validated_data['customer'] = self.context['request'].customer
+        instance = super(OderSerializer, self).create(validated_data)
+        return instance
+
+
+class OderSimpleSerializer(serializers.ModelSerializer):
+    total_amount = serializers.SerializerMethodField()
+    total_point = serializers.SerializerMethodField()
+    status_text = serializers.CharField(source='get_status_display', read_only=True)
+    details = serializers.SerializerMethodField()
+
+    class Meta:
+        model = Order
+        fields = ('no', 'total_amount', 'total_point', 'status_text', 'details', 'id', 'name', 'tel', 'user_address', )
+
+    def get_total_amount(self, obj):
+        return Formater.formatValueShow(obj.total_amount)
+
+    def get_total_point(self, obj):
+        return '%.2f' % obj.total_point
+
+    def get_details(self, obj):
+        rows = OrderDetails.objects.filter(order=obj)
+        serializer = OderDetailSimpleSerializer(rows, many=True)
+        return serializer.data
+
+
+class OderDetailSimpleSerializer(serializers.ModelSerializer):
+    name = serializers.CharField(source='commodity.name', read_only=True)
+    show_image = serializers.SerializerMethodField()
+    amount = serializers.SerializerMethodField()
+    point_amount = serializers.SerializerMethodField()
+    type = serializers.CharField(source='commodity.type', read_only=True)
+    commodity_id = serializers.CharField(source='commodity.id', read_only=True)
+
+    class Meta:
+        model = OrderDetails
+        fields = ('name', 'show_image', 'amount', 'point_amount', 'count', 'type', 'commodity_id', )
+
+    def get_show_image(self, obj):
+        if obj.commodity and obj.commodity.show_image:
+            return obj.commodity.show_image.get_path()
+        return ''
+
+    def get_amount(self, obj):
+        return Formater.formatValueShow(obj.amount)
+
+    def get_point_amount(self, obj):
+        return '%.2f' % obj.point_amount

+ 2 - 8
apps/customer/order/urls.py

@@ -6,16 +6,10 @@ from rest_framework.routers import SimpleRouter
 from .views import *
 
 urlpatterns = [
-    # url(r'^code2Session/$', WxLoginView.as_view()),
-    # url(r'^wxbind/$', WxBindView.as_view()),
-    # url(r'^setUserInfo/$', SetUserInfoView.as_view()),
-    # url(r'^token/refresh/$', CustomerRefreshTokenView),
-    # url(r'^token/verify/$', CustomerVerifyTokenView),
-    #
-    # url(r'^commodity/', include('apps.customer.commodity.urls'))
+    url(r'^list/$', OrderListView.as_view()),
 ]
 
 router = SimpleRouter()
 router.register(r'cart', ShoppingCartViewSet)
-# router.register(r'', CustomerViewSet)
+router.register(r'', OrderViewSet)
 urlpatterns += router.urls

+ 89 - 4
apps/customer/order/views.py

@@ -1,15 +1,23 @@
 # coding=utf-8
 
+import json
+
 from django.db import transaction
+from django.db.models import Q
+
 from rest_framework.decorators import action
+from rest_framework import generics
 
 from utils import response_ok, response_error
 from utils.exceptions import CustomError
 from utils.permission import IsCustomer
 from utils.custom_modelviewset import CustomModelViewSet
-from apps.order.models import ShoppingCart
-from apps.order.filters import ShoppingCartFilter
-from apps.customer.order.serializers import ShoppingCartSerializer
+from utils.wechatpay import WeChatResponse
+from apps.order.models import ShoppingCart, Order, Pay
+from apps.order.filters import ShoppingCartFilter, OrderFilter
+from apps.customer.order.serializers import ShoppingCartSerializer, OderSerializer, OderSimpleSerializer
+from apps.customer.models import Customer
+from apps.rebate.models import PointLogOrder
 from apps.log.models import BizLog
 
 
@@ -44,7 +52,84 @@ class ShoppingCartViewSet(CustomModelViewSet):
 
     @action(methods=['post'], detail=False)
     def del_cart(self, request):
-        car_ids = request.POST.get('ids').split(',')
+        car_ids = json.loads(request.data.get('ids'))
         with transaction.atomic():
             ShoppingCart.objects.filter(id__in=car_ids, customer=request.customer).delete()
         return response_ok()
+
+
+class OrderListView(generics.ListAPIView):
+    permission_classes = [IsCustomer, ]
+    queryset = Order.objects.filter()
+    serializer_class = OderSimpleSerializer
+
+    def filter_queryset(self, queryset):
+        queryset = queryset.filter(customer=self.request.customer)
+        f = OrderFilter(self.request.GET, queryset=queryset)
+        return f.qs
+
+
+class OrderViewSet(CustomModelViewSet):
+    permission_classes = [IsCustomer, ]
+    queryset = Order.objects.filter()
+    serializer_class = OderSerializer
+
+    def create(self, request, *args, **kwargs):
+        '''
+        创建订单
+        :param request:
+        :param args:
+        :param kwargs:
+        :return:
+        '''
+        openid = request.POST.get('openid')
+        appid = request.POST.get('appid')
+        address_id = request.POST.get('address_id', None)
+        details = json.loads(request.POST.get('details'))
+        if not address_id:
+            raise CustomError(u'请选择收货地址!')
+        with transaction.atomic():
+            serializer = self.get_serializer(data=request.data)
+            serializer.is_valid(raise_exception=True)
+            serializer.save()
+            order = serializer.instance
+            order.generateNo()
+            # 用户收货地址
+            order.set_order_adderss(address_id)
+            # 订单详细
+            order.set_order_detail(details)
+            # 订单支付
+            data = ''
+            if order.total_amount <= 0 and order.total_point <= 0:
+                raise CustomError(u'无效的付款金额')
+            # 下单时如果有积分,直接扣掉积分。如果没有支付或支付失败 取消订单还原积分
+            if order.total_point > 0:
+                PointLogOrder.addnew(order)
+            if order.total_amount > 0:
+                pay, data = Pay.wechatPay(order.total_amount, self.request.customer, appid, openid)
+                order.pay = pay
+            # 没有支付现金的积分也扣过了  直接修改订单状态  如果有现金支付的 通过微信支付回调修改订单状态
+            if not order.pay:
+                order.pointConfirm()
+            order.save()
+            BizLog.objects.addnew(self.request.user, BizLog.INSERT, u'添加订单[%s],id=%d' % (order.no, order.id), request.data)
+        return response_ok(data)
+
+    @action(methods=['post'], detail=True)
+    def pay_order(self, request, pk):
+        '''
+        待支付订单支付  在订单管理 待支付 订单直接支付(由于积分商品在下单的时候积分都已经扣过了  在这就不在扣除积分了)
+        :param request:
+        :param pk:
+        :return:
+        '''
+        openid = request.POST.get('openid')
+        appid = request.POST.get('appid')
+
+        order = self.get_object()
+        print(order.id)
+        if not openid or not appid:
+            raise CustomError(u'参数错误!')
+        with transaction.atomic():
+            data = order.orderPay(openid, appid)
+        return response_ok(data)

+ 2 - 0
apps/customer/urls.py

@@ -12,6 +12,8 @@ urlpatterns = [
     url(r'^token/refresh/$', CustomerRefreshTokenView),
     url(r'^token/verify/$', CustomerVerifyTokenView),
 
+    url(r'^home/$', CustomerHomeView.as_view()),
+
     url(r'^address/', include('apps.customer.address.urls')),
     url(r'^commodity/', include('apps.customer.commodity.urls')),
     url(r'^collection/', include('apps.customer.collection.urls')),

+ 19 - 0
apps/customer/views.py

@@ -15,6 +15,7 @@ from utils.custom_modelviewset import CustomModelViewSet
 from apps.customer.serializers import WechatLoginSerializer, WechatBindSerializer, CustomerSerializer
 from apps.customer.models import Customer
 from apps.customer.filters import CustomerFilter
+from apps.order.models import Order
 from apps.log.models import BizLog
 from apps.base import Formater
 
@@ -55,6 +56,24 @@ class SetUserInfoView(APIView):
         return response_ok({'face': face, 'name': name})
 
 
+class CustomerHomeView(APIView):
+    permission_classes = [IsCustomer, ]
+
+    def get(self, request):
+        customer = self.request.customer
+        rows = Order.objects.filter(customer=customer)
+
+        item = {
+            'point': '%.2f' % customer.points,
+            'balance': Formater.formatValueShow(customer.balance),
+            'wait_pay': rows.filter(status=Order.WAIT_PAY).count(),
+            'wait_dispatch': rows.filter(status=Order.WAIT_DISPATCH).count(),
+            'dispatch': rows.filter(status=Order.CONFIRM_DISPATCH).count(),
+        }
+
+        return response_ok(item)
+
+
 class CustomerRefreshTokenView(RefreshJSONWebToken):
     def post(self, request, *args, **kwargs):
         try:

+ 205 - 7
apps/order/models.py

@@ -3,9 +3,14 @@
 from django.db import models
 from django.conf import settings
 from django.utils import timezone
+from django.db.models import F
+
 from apps.option.models import Option
+from apps.config.models import Config
 from apps.commodity.models import Commodity
-from apps.customer.models import Customer, CustomerAddress
+from apps.customer.models import Customer, CustomerAddress, SuperiorDistributor
+from utils.exceptions import CustomError
+from utils.wechatpay import WechatPay, WeChatResponse
 
 
 class Pay(models.Model):
@@ -39,6 +44,50 @@ class Pay(models.Model):
         )
         default_permissions = ()
 
+    @staticmethod
+    def wechatPay(amount, customer, appid, openid):
+        instance = Pay._addnew(amount, customer)
+        return instance, instance._wechatUnifiedOrder(appid, openid)
+
+    @staticmethod
+    def _addnew(amount, customer):
+        if amount <= 0:
+            raise CustomError(u'无效的付款金额!')
+        pay_no = '{}{}'.format(timezone.now().strftime('%y%m%d%H%M%S'), str(customer.id))
+        pay = Pay.objects.create(no=pay_no, status=Pay.WAIT, precreate_amount=amount, customer=customer)
+        return pay
+
+    def _wechatUnifiedOrder(self, appid, openid):
+        wechatpay = WechatPay(appid)
+        wechatpay.unifiedOrder(self.no, self.precreate_amount, openid)
+        data = wechatpay.getAppString()
+        return data
+
+    @staticmethod
+    def getByNo(no):
+        instance = Pay.objects.filter(no=no).first()
+        if not instance:
+            raise CustomError(u'未找到相应的支付单!')
+        return instance
+
+    def payClosed(self):
+        if self.status != Pay.WAIT:
+            return
+        self.status = Pay.UNDO
+        self.save()
+
+    def payConfirm(self, amount, transaction_id):
+        if self.status != Pay.WAIT:
+            return
+
+        self.status = Pay.PAY
+        self.amount = amount
+        self.transaction_id = transaction_id
+        self.save()
+        order = Order.objects.filter(pay=self).first()
+        if order:
+            order.orderPayConfirm()
+
 
 class ShoppingCart(models.Model):
     commodity_details = models.ForeignKey(Commodity, verbose_name=u'产品明细', on_delete=models.PROTECT)
@@ -56,18 +105,16 @@ class ShoppingCart(models.Model):
 class Order(models.Model):
     WAIT_PAY = 0
     WAIT_DISPATCH = 1
-    WAIT_EVALUATE = 2
-    EVALUATED = 3
-    CANCEL = 4
+    CONFIRM_DISPATCH = 2
+    CANCEL = 3
     STATUS_CHOICES = (
         (WAIT_PAY, u'待付款'),
         (WAIT_DISPATCH, u'待发货'),
-        (WAIT_EVALUATE, u'待评价'),
-        (EVALUATED, u'已评价'),
+        (CONFIRM_DISPATCH, u'已发货'),
         (CANCEL, u'已取消'),
     )
 
-    no = models.CharField(max_length=50, verbose_name=u'订单号', editable=False)
+    no = models.CharField(max_length=50, verbose_name=u'订单号', editable=False, null=True, blank=True)
     pay = models.ForeignKey(Pay, verbose_name=u'支付信息', on_delete=models.PROTECT, null=True, editable=False)
 
     total_count = models.IntegerField(verbose_name=u'总数量', default=0, editable=False)
@@ -96,9 +143,160 @@ class Order(models.Model):
         db_table = "order"
         verbose_name = u"客户订单"
         ordering = ('-id',)
+        index_together = ('status', 'create_time', 'no', )
         default_permissions = ()
         permissions = []
 
+    def generateNo(self):
+        '''
+        生成订单的订单号(注意:该函数最后没有 save 要在调用该函数后save )
+        :return:
+        '''
+        no = '{}{}{:0>4}'.format('XCX', timezone.now().strftime('%Y%m%d'), self.id)
+        self.no = no
+
+    def set_order_adderss(self, address_id):
+        '''
+        下单时保存用户选择的收货地址(注意:该函数最后没有 save 要在调用该函数后save )
+        :param address_id: 收货地址id
+        :return:
+        '''
+        address = CustomerAddress.objects.filter(id=address_id).first()
+        if not address:
+            raise CustomError(u'请选择正确的收货地址!')
+        if address.delete:
+            raise CustomError(u'该收货地址已删除,请选择重新选择收货地址!')
+        self.address = address
+        self.name = address.name
+        self.tel = address.tel
+        self.user_address = address.get_address()
+
+    def set_order_detail(self, details):
+        '''
+        下单时保存选择的商品明细(注意:该函数最后没有 save 要在调用该函数后save )
+        :param details: 商品明细
+        :return:
+        '''
+        total_count = total_amount = total_point = 0
+        create_data = []
+        for item in details:
+            commodity = Commodity.objects.filter(id=item['id']).first()
+            if not commodity:
+                raise CustomError(u'您选择的商品不存在,请刷新后重新选择!')
+            if commodity.delete:
+                raise CustomError(u'商品【{}】已下架!'.format(commodity.name))
+            if commodity.status != settings.ONLINE:
+                raise CustomError(u'商品【{}】已下架!'.format(commodity.name))
+
+            try:
+                count = int(item['count'])
+            except:
+                raise CustomError(u'商品数量错误,请重新选择!')
+            if count <= 0:
+                raise CustomError(u'商品数量错误,请重新选择!')
+
+            amount = point_amount = 0
+            if commodity.type == Commodity.POINT:
+                point_amount = commodity.point_price * count
+            elif commodity.type == Commodity.CASH:
+                amount = commodity.price * count
+            else:
+                continue
+
+            d = OrderDetails(
+                order=self,
+                commodity=commodity,
+                price=commodity.price,
+                point=commodity.point_price,
+                count=count,
+                amount=amount,
+                point_amount=point_amount
+            )
+
+            create_data.append(d)
+
+            total_point += point_amount
+            total_amount += amount
+            total_count += count
+
+        OrderDetails.objects.bulk_create(create_data)
+        self.total_count = total_count
+        self.total_amount = total_amount
+        self.total_point = total_point
+
+    def pointConfirm(self):
+        '''
+        积分兑换 确认兑换成功  当只购买了积分商品的时候 使用本函数确认  有现金商品的时候使用pay下边的确认函数确认
+        注意 order最后没有save()  在调用该函数后order要save()
+        :return:
+        '''
+        if self.status != Order.WAIT_PAY:
+            return
+        self.status = Order.WAIT_DISPATCH
+        commodity_id = Config.get_commodity()
+        # 这一点儿不能用这个  不然 数据customer数据重新保存了 积分那一块儿的就不行了
+        customer = Customer.objects.filter(id=self.customer.id).first()
+
+        detail = OrderDetails.objects.filter(order=self)
+        for item in detail:
+            commodity = item.commodity
+            commodity.total_sales += item.count
+            commodity.save()
+
+            if not commodity_id:
+                continue
+            if commodity.id != commodity_id:
+                continue
+
+            if customer.is_distributor:
+                continue
+            customer.is_distributor = True
+        customer.total_point += self.total_point
+        customer.success_count += 1
+        customer.save()
+
+    def orderPay(self, openid, appid):
+        if self.status != Order.WAIT_PAY:
+            raise CustomError(u'订单费待付款状态,禁止付款!')
+        if self.pay:
+            pay_no = self.pay.no
+            # 先查询订单状态
+            checkRexponse = WeChatResponse(appid)
+            total_fee = checkRexponse.OrderQuery(pay_no)
+            if int(total_fee) == int(self.total_amount):
+                wechatpay = WechatPay(appid)
+                wechatpay.unifiedOrder(pay_no, self.total_amount, openid)
+                data = wechatpay.getAppString()
+                return data
+            self.pay.payClosed()
+
+    def orderPayConfirm(self):
+        self.status = Order.WAIT_DISPATCH
+        self.save()
+
+        # 购买指定的商品 成为分销商
+        commodity_id = Config.get_commodity()
+        point_rule = Config.get_value(Config.KEY_POINT_RULE)
+        customer = Customer.objects.filter(id=self.customer.id).first()
+
+        detail = OrderDetails.objects.filter(order=self)
+        for item in detail:
+            commodity = item.commodity
+            commodity.total_sales += item.count
+            commodity.save()
+
+            if not commodity_id:
+                continue
+            if commodity.id != commodity_id:
+                continue
+            if customer.is_distributor:
+                continue
+            customer.is_distributor = True
+        customer.success_count += 1
+        customer.total_amount += self.total_amount
+        customer.total_point += self.total_point
+        customer.save()
+
 
 class OrderDetails(models.Model):
 

+ 1 - 1
apps/order/views.py

@@ -79,7 +79,7 @@ class OrderViewSet(CustomModelViewSet):
         if express_company.delete:
             raise CustomError(u'该快递公司已被删除!')
         with transaction.atomic():
-            order.status = Order.WAIT_EVALUATE
+            order.status = Order.CONFIRM_DISPATCH
             order.dispatch_time = timezone.now()
             order.dispatch_user = request.user
             order.express_no = express_no

+ 118 - 0
apps/rebate/bussiness.py

@@ -0,0 +1,118 @@
+# coding=utf-8
+
+from django.utils import timezone
+
+from apps.rebate.models import CashRebate, PointRebate, CashRebateLog, PointRebateLog, PointGive, PointGiveLog
+from apps.customer.models import SuperiorDistributor
+from apps.order.models import Order
+from apps.config.models import Config
+
+
+class CustomerRebate(object):
+
+    def __init__(self, pay):
+        self.pay = pay
+        self.order = Order.objects.filter(pay=self.pay).first()
+
+    def cash_rebate(self, ratio, amount, customer):
+        '''
+        计算现金返利  1、2、3级分销商 返现金
+        :param ratio:
+        :param amount:
+        :param customer:
+        :return:
+        '''
+        rebate = CashRebate.objects.create(
+            order=self.order,
+            ratio=ratio,
+            amount=amount,
+            customer=customer,
+            create_time=timezone.now()
+        )
+        CashRebateLog.addnew(rebate)
+
+    def point_rebate(self, ratio, amount, customer):
+        '''
+        计算积分返利  4、5级分销商 返积分
+        :param ratio:
+        :param amount:
+        :param customer:
+        :return:
+        '''
+        rebate = PointRebate.objects.create(
+            order=self.order,
+            ratio=ratio,
+            amount=amount,
+            customer=customer,
+            create_time=timezone.now()
+        )
+        PointRebateLog.addnew(rebate)
+
+    def point_give(self, ratio, amount, customer):
+        '''
+        计算购买商品赠送的积分  购买商品时根据后台设置的比例赠送相应的积分给购买者
+        :param ratio:
+        :param amount:
+        :param customer:
+        :return:
+        '''
+        give = PointGive.objects.create(
+            order=self.order,
+            ratio=ratio,
+            amount=amount,
+            customer=customer,
+            create_time=timezone.now()
+        )
+        PointGiveLog.addnew(give)
+
+    def calcul_rebate(self):
+        '''
+        计算返利并保存log
+        :return:
+        '''
+        if not self.order:
+            return
+        if self.order.total_amount <= 0:
+            return
+        if self.order.status == Order.WAIT_PAY or self.order.status == Order.CANCEL:
+            return
+
+        customer = self.order.customer
+        sd = SuperiorDistributor.objects.filter(customer=customer).first()
+        if not sd:
+            return
+        # 判断是首次购买还是再次购买  首次购买与再次购买返利的比例不同
+        count = Order.objects.filter(customer=customer, status__in=[Order.WAIT_DISPATCH, Order.CONFIRM_DISPATCH]).count()
+        rebate_dic = {}
+        if count > 1:
+            rebate_dic = Config.get_rebate(False)
+        elif count == 1:
+            rebate_dic = Config.get_rebate(True)
+        # 现金保留两位小数, 积分整数
+        total_amount = float(self.order.total_amount or 0)
+
+        if sd.one_level and sd.one_level.is_distributor and rebate_dic['one_level'] > 0:
+            amount = int(round(total_amount * rebate_dic['one_level'] / 100.0, 0))
+            self.cash_rebate(rebate_dic['one_level'], amount, sd.one_level)
+
+        if sd.two_level and sd.two_level.is_distributor and rebate_dic['two_level'] > 0:
+            amount = int(round(total_amount * rebate_dic['two_level']/ 100.0, 0))
+            self.cash_rebate(rebate_dic['two_level'], amount, sd.two_level)
+
+        if sd.three_level and sd.three_level.is_distributor and rebate_dic['three_level'] > 0:
+            amount = int(round(total_amount * rebate_dic['three_level'] / 100.0, 0))
+            self.cash_rebate(rebate_dic['three_level'], amount, sd.three_level)
+
+        if sd.four_level and sd.four_level.is_distributor and rebate_dic['four_level'] > 0:
+            amount = int(round((total_amount / 100.0) * (rebate_dic['four_level'] / 100.0), 0))
+            self.point_rebate(rebate_dic['four_level'], amount, sd.four_level)
+
+        if sd.five_level and sd.five_level.is_distributor and rebate_dic['five_level'] > 0:
+            amount = int(round((total_amount / 100.0) * (rebate_dic['five_level'] / 100.0), 0))
+            self.point_rebate(rebate_dic['five_level'], amount, sd.five_level)
+
+        # 计算购买商品 赠送积分
+        rule = Config.get_value(Config.KEY_POINT_RULE)
+        if rule > 0:
+            amount = int(round((total_amount / 100.0) * (rule / 100.0), 0))
+            self.point_give(rule, amount, customer)

+ 99 - 5
apps/rebate/models.py

@@ -7,6 +7,9 @@ from django.utils import timezone
 
 from apps.customer.models import Customer
 from apps.order.models import Order
+from apps.customer.models import SuperiorDistributor
+
+from utils.exceptions import CustomError
 
 '''
 现金返利及现金变动记录
@@ -28,11 +31,28 @@ class CashLog(models.Model):
     class Meta:
         db_table = "cash_log"
         verbose_name = u'现金日志'
-        ordering = []
-        index_together = ()
+        ordering = ['-happen_time',]
+        index_together = (
+            'happen_time',
+        )
         default_permissions = ()
         permissions = []
 
+    @staticmethod
+    def addnew(customer, type, amount):
+        customer.balance += amount
+        if customer.balance < 0:
+            raise CustomError(u'用户余额不足!')
+        customer.save()
+        instance = CashLog.objects.create(
+            customer=customer,
+            type=type,
+            happen_time=timezone.now(),
+            amount=amount,
+            balance=customer.balance
+        )
+        return instance
+
 
 class CashRebate(models.Model):
 
@@ -63,6 +83,13 @@ class CashRebateLog(models.Model):
         default_permissions = ()
         permissions = []
 
+    @staticmethod
+    def addnew(rebate):
+        customer = Customer.objects.select_for_update().filter(id=rebate.customer.id).first()
+        log = CashLog.addnew(customer, CashLog.CASH_REBATE, rebate.amount)
+        instance = CashRebateLog.objects.create(rebate=rebate, log=log)
+        return instance
+
 '''
 积分返利及积分变动记录
 '''
@@ -72,9 +99,11 @@ class PointLog(models.Model):
 
     POINT_REBATE = 1
     POINT_ORDER = 2
+    POINT_GIVE = 3
     TYPE_CHOICES = (
         (POINT_REBATE, u'积分返利'),
         (POINT_ORDER, u'积分兑换'),
+        (POINT_GIVE, u'赠送积分'),  # 购买商品赠送的积分
     )
 
     customer = models.ForeignKey(Customer, verbose_name=u'客户', on_delete=models.PROTECT)
@@ -86,11 +115,28 @@ class PointLog(models.Model):
     class Meta:
         db_table = "point_log"
         verbose_name = u'积分日志'
-        ordering = []
-        index_together = ()
+        ordering = ['-happen_time',]
+        index_together = (
+            'happen_time',
+        )
         default_permissions = ()
         permissions = []
 
+    @staticmethod
+    def addnew(customer, type, point):
+        customer.points += point
+        if customer.points < 0:
+            raise CustomError(u'用户积分不足!')
+        customer.save()
+        instance = PointLog.objects.create(
+            customer=customer,
+            type=type,
+            happen_time=timezone.now(),
+            amount=point,
+            balance=customer.points
+        )
+        return instance
+
 
 class PointRebate(models.Model):
 
@@ -109,6 +155,23 @@ class PointRebate(models.Model):
         permissions = []
 
 
+class PointGive(models.Model):
+
+    order = models.ForeignKey(Order, verbose_name=u'订单', related_name='point_give_order', editable=False, on_delete=models.PROTECT)
+    ratio = models.FloatField(verbose_name=u'赠送比例', default=0)
+    amount = models.IntegerField(verbose_name=u'赠送积分', default=0)
+    customer = models.ForeignKey(Customer, verbose_name=u'客户', editable=False, on_delete=models.PROTECT)
+    create_time = models.DateTimeField(verbose_name=u"创建时间", default=timezone.now, editable=False)
+
+    class Meta:
+        db_table = "point_give"
+        verbose_name = u'积分返利'
+        ordering = []
+        index_together = ()
+        default_permissions = ()
+        permissions = []
+
+
 class PointLogOrder(models.Model):
 
     order = models.OneToOneField(Order, verbose_name=u'订单', related_name='order', editable=False, on_delete=models.PROTECT)
@@ -122,8 +185,15 @@ class PointLogOrder(models.Model):
         default_permissions = ()
         permissions = []
 
+    @staticmethod
+    def addnew(order):
+        customer = Customer.objects.select_for_update().filter(id=order.customer.id).first()
+        log = PointLog.addnew(customer, PointLog.POINT_ORDER, -order.total_point)
+        instance = PointLogOrder.objects.create(order=order, log=log)
+        return instance
+
 
-class PointLogRebate(models.Model):
+class PointRebateLog(models.Model):
     rebate = models.OneToOneField(PointRebate, verbose_name=u'积分返利', related_name='rebate', editable=False, on_delete=models.PROTECT)
     log = models.OneToOneField(PointLog, verbose_name=u'日志', related_name='rebate_log', editable=False, on_delete=models.PROTECT)
 
@@ -135,5 +205,29 @@ class PointLogRebate(models.Model):
         default_permissions = ()
         permissions = []
 
+    @staticmethod
+    def addnew(rebate):
+        customer = Customer.objects.select_for_update().filter(id=rebate.customer.id).first()
+        log = PointLog.addnew(customer, PointLog.POINT_REBATE, rebate.amount)
+        instance = PointRebateLog.objects.create(rebate=rebate, log=log)
+        return instance
 
 
+class PointGiveLog(models.Model):
+    give = models.OneToOneField(PointGive, verbose_name=u'赠送积分', related_name='give', editable=False, on_delete=models.PROTECT)
+    log = models.OneToOneField(PointLog, verbose_name=u'日志', related_name='give_log', editable=False, on_delete=models.PROTECT)
+
+    class Meta:
+        db_table = "point_log_give"
+        verbose_name = u'赠送积分日志'
+        ordering = []
+        index_together = ()
+        default_permissions = ()
+        permissions = []
+
+    @staticmethod
+    def addnew(give):
+        customer = Customer.objects.select_for_update().filter(id=give.customer.id).first()
+        log = PointLog.addnew(customer, PointLog.POINT_GIVE, give.amount)
+        instance = PointGiveLog.objects.create(give=give, log=log)
+        return instance

+ 2 - 1
cosmetics_shop/settings.py

@@ -45,6 +45,7 @@ INSTALLED_APPS = [
     'django_filters',
 
     'apps.account',
+    'apps.api',
     'apps.collection',
     'apps.commodity',
     'apps.config',
@@ -222,7 +223,7 @@ REST_FRAMEWORK = {
 
 # 导入本地设置
 try:
-    from markwin.local_settings import *
+    from cosmetics_shop.local_settings import *
 except ImportError:
     pass
 

+ 1 - 0
cosmetics_shop/urls.py

@@ -27,6 +27,7 @@ urlpatterns = [
     url(r'^commodity/', include('apps.commodity.urls')),
     url(r'^option/', include('apps.option.urls')),
     url(r'^order/', include('apps.order.urls')),
+    url(r'^api/', include('apps.api.urls')),
 ]
 
 urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)

+ 4 - 4
uis/views/commodity/edit.html

@@ -54,28 +54,28 @@
                         <div class="layui-form-item" id="price_item">
                             <label class="layui-form-label"><font color='red' size="4">*</font>销售价格:</label>
                             <div class="layui-input-block">
-                                <input type="text" id="id_price" name="price" lay-verify="numberGtZ|required" placeholder="请输入销售价" autocomplete="off" class="layui-input">
+                                <input type="text" id="id_price" name="price" lay-verify="numberGtZ|required" placeholder="请输入销售价" autocomplete="off" class="layui-input">
                             </div>
                         </div>
 
                         <div class="layui-form-item" id="vip_price_item">
                             <label class="layui-form-label"><font color='red' size="4">*</font>会员价格:</label>
                             <div class="layui-input-block">
-                                <input type="text" id="id_vip_price" name="vip_price" lay-verify="numberGtZ|required" placeholder="请输入销售限价折扣" autocomplete="off" class="layui-input">
+                                <input type="text" id="id_vip_price" name="vip_price" lay-verify="numberGtZ|required" placeholder="请输入会员价格" autocomplete="off" class="layui-input">
                             </div>
                         </div>
 
                         <div class="layui-form-item" id="point_price_item" hidden>
                             <label class="layui-form-label"><font color='red' size="4">*</font>积分价格:</label>
                             <div class="layui-input-block">
-                                <input type="text" id="id_point_price" name="point_price" lay-verify="intGtz" placeholder="请输入销售限价折扣" autocomplete="off" class="layui-input">
+                                <input type="text" id="id_point_price" name="point_price" lay-verify="intGtz" placeholder="请输入积分价格" autocomplete="off" class="layui-input">
                             </div>
                         </div>
 
                         <div class="layui-form-item">
                             <label class="layui-form-label">起始销量:</label>
                             <div class="layui-input-block">
-                                <input type="text" name="initial_sale_count" lay-verify="intGtz|required" placeholder="请输入" value="0" class="layui-input">
+                                <input type="text" name="initial_sale_count" lay-verify="intGtz|required" placeholder="请输入起始销量" value="0" class="layui-input">
                             </div>
                         </div>
 

+ 1 - 1
uis/views/customer/index.html

@@ -86,7 +86,7 @@
       ,cols: [[
         {field:'name', title:'名称',width: 120}
        ,{field:'tel', title:'电话',width: 150}
-       ,{field:'gender_text', title:'性别',width: 80}
+      // ,{field:'gender_text', title:'性别',width: 80}
        ,{field:'is_distributor_text', title:'分销商',width: 80}
        ,{field:'balance', align: 'right', title:'余额',width: 120}
        ,{field:'points', align:'right', title:'积分', width:120}

+ 3 - 4
uis/views/order/index.html

@@ -47,9 +47,8 @@
                                 <option value="">订单状态</option>
                                 <option value="0">待付款</option>
                                 <option value="1">待发货</option>
-                                <option value="2">待评价</option>
-                                <option value="3">已评价</option>
-                                <option value="4">已取消</option>
+                                <option value="2">已发货</option>
+                                <option value="3">已取消</option>
                             </select>
                         </div>
                         <div class="seach_items">
@@ -121,7 +120,7 @@
        ,{field:'cancel_reason', title:'取消订单原因',width: 150}
        ,{field:'cancel_user_text', title:'取消人',width: 80}
        ,{field:'cancel_time', title:'取消时间',width: 150}
-       ,{field:'notes', title:'备注',width: 150}
+       ,{field:'notes', title:'买家留言',width: 150}
         ,{width:150, align:'center', fixed: 'right', toolbar: '#datagrid-operate-bar'}
       ]]
       ,totalRow:false

+ 56 - 7
utils/wechatpay.py

@@ -9,6 +9,7 @@ from hashlib import md5
 from django.conf import settings
 
 from utils.exceptions import CustomError
+from apps.WechatApplet.models import WechatApplet
 
 # 微信支付sign_type
 WEIXIN_SIGN_TYPE = 'MD5'
@@ -21,25 +22,34 @@ WEIXIN_UNIFIED_ORDER_URL = 'https://api.mch.weixin.qq.com/pay/unifiedorder'
 # 微信查询订单URL
 WEIXIN_QUERY_ORDER_URL = 'https://api.mch.weixin.qq.com/pay/orderquery'
 # 微信支付回调API
-WEIXIN_CALLBACK_API = 'https://xapp.aiche360.cn/api/wechat_notify/'
+# WEIXIN_CALLBACK_API = 'https://xapp.aiche360.cn/api/wechat_notify/'
+
+
+def getApp(appid):
+    wxapp = WechatApplet.objects.filter(authorizer_appid=appid).first()
+    if not wxapp:
+        raise CustomError(u'小程序appid认证失败!')
+    return wxapp
+
 
 class WechatPay():
 
-    def __init__(self, appid, mch_id, merchant_key):
+    def __init__(self, appid):
+        wxapp = getApp(appid)
         self.params = {
             'appid': appid,
-            'mch_id': mch_id,
+            'mch_id': wxapp.agent_num,
             'nonce_str': '',
             'sign_type': WEIXIN_SIGN_TYPE,
             'body': WEIXIN_BODY,
             'out_trade_no': '',
             'total_fee': '',
             'spbill_create_ip': WEIXIN_SPBILL_CREATE_IP,
-            'notify_url': WEIXIN_CALLBACK_API + appid + '/',
+            'notify_url': wxapp.callback_api + appid + '/',
             'trade_type': 'JSAPI'
         }
         self.prepay_id = None
-        self.merchant_key = merchant_key
+        self.merchant_key = wxapp.agent_key
 
     def getAppString(self):
         data = {
@@ -53,9 +63,9 @@ class WechatPay():
         data.pop('appId')
         return data
 
-    def unifiedOrder(self,out_trade_no,total_fee, openid):
+    def unifiedOrder(self, out_trade_no, total_fee, openid):
         self.params['out_trade_no'] = out_trade_no
-        self.params['total_fee'] = int(round(total_fee / 100,0))
+        self.params['total_fee'] = int(round(total_fee, 0))
         self.params['openid'] = openid
         self.params['nonce_str'] = generate_nonce_str()
         self.params['sign'] = generate_sign(self.params, self.merchant_key)
@@ -77,6 +87,45 @@ class WechatPay():
 
         return result['xml']
 
+
+class WeChatResponse():
+    def __init__(self, appid):
+        wxapp = getApp(appid)
+        self.params = {
+            'appid': appid,
+            'mch_id': wxapp.agent_num,
+            'nonce_str': '',
+            'sign_type': WEIXIN_SIGN_TYPE,
+            'sign': '',
+            'out_trade_no': '',
+        }
+        self.prepay_id = None
+        self.merchant_key = wxapp.agent_key
+
+    def OrderQuery(self, out_trade_no):
+        '''
+        查询订单
+        :param out_trade_no:
+        :return:
+        '''
+        self.params['out_trade_no'] = out_trade_no
+        self.params['nonce_str'] = generate_nonce_str()
+        self.params['sign'] = generate_sign(self.params, self.merchant_key)
+        data = xmltodict.unparse({'xml': self.params}, pretty=True, full_document=False).encode('utf-8')
+        headers = {'Content-Type': 'application/xml'}
+        res = requests.post(WEIXIN_QUERY_ORDER_URL, data=data, headers=headers)
+        if res.status_code != 200:
+            raise CustomError(u'微信请求失败!')
+        result = json.loads(json.dumps(xmltodict.parse(res.content)))
+
+        if result['xml']['return_code'] != 'SUCCESS':
+            raise CustomError(u'微信通信失败![%s]' % result['xml']['return_msg'])
+        print(u'微信交易状态![%s]' % (result['xml']['trade_state_desc']))
+        if result['xml']['trade_state'] == 'NOTPAY':
+            return result['xml']['total_fee']
+        return 0
+
+
 class WechatPayNotify():
     def __init__(self,params, merchant_key):
         self.params = params