Beispiel #1
0
    def _pay_detail(self, body, mount_price, opayno, openid):
        body = re.sub("[\s+\.\!\/_,$%^*(+\"\'\-_]+|[+——!,。?、~@#¥%……&*()]+", '', body)
        current_app.logger.info('get mount price {}'.format(mount_price))
        mount_price = 0.01 if API_HOST != 'https://planet.sanbinit.cn' else mount_price  # todo 测试域名下来之后配置

        current_app.logger.info('openid is {}, out_trade_no is {} '.format(openid, opayno))
        # 微信支付的单位是'分', 支付宝使用的单位是'元'

        try:
            body = body[:16] + '...'
            current_app.logger.info('body is {}, wechatpay'.format(body))
            wechat_pay_dict = {
                'body': body,
                'out_trade_no': opayno,
                'total_fee': int(mount_price * 100),
                'attach': 'attach',
                'spbill_create_ip': request.remote_addr
            }

            if not openid:
                raise StatusError('用户未使用微信登录')
            # wechat_pay_dict.update(dict(trade_type="JSAPI", openid=openid))
            wechat_pay_dict.update({
                'trade_type': 'JSAPI',
                'openid': openid
            })
            raw = self.wx_pay.jsapi(**wechat_pay_dict)

        except WeixinPayError as e:
            raise SystemError('微信支付异常: {}'.format('.'.join(e.args)))

        return raw
Beispiel #2
0
    def _pay_to_bankcard(self, cn):
        """
        付款到银行卡号
        :param cn:
        :return:
        """
        try:
            enc_bank_no = self._to_encrypt(cn.CNcardNo)
            enc_true_name = self._to_encrypt(cn.CNcardName)
            bank_code = WexinBankCode(cn.CNbankName).zh_value
        except Exception as e:
            current_app.logger.error('提现到银行卡,参数加密出错:{}'.format(e))
            raise ParamsError('服务器繁忙,请稍后再试')

        try:
            result = self.wx_pay.pay_individual_to_card(
                partner_trade_no=self.wx_pay.nonce_str,
                enc_bank_no=enc_bank_no,
                enc_true_name=enc_true_name,
                bank_code=bank_code,
                amount=int(Decimal(cn.CNcashNum).quantize(Decimal('0.00')) * 100)
            )
            current_app.logger.info('微信提现到银行卡, response: {}'.format(request))
        except Exception as e:
            current_app.logger.error('微信提现返回错误:{}'.format(e))
            raise StatusError('微信商户平台: {}'.format(e))
        return result
Beispiel #3
0
    def product_verified(self):
        """商品核销"""
        data = parameter_required('param')
        param = data.get('param')
        try:
            omid, secret_usid = str(param).split('&')
            if not omid.startswith('omid'):
                raise ValueError
        except ValueError:
            raise ParamsError('该二维码无效')
        current_app.logger.info('omid: {}, secret_usid: {}'.format(omid, secret_usid))
        omid = str(omid).split('=')[-1]
        secret_usid = str(secret_usid).split('=')[-1]
        current_app.logger.info('splited, omid: {}, secret_usid: {}'.format(omid, secret_usid))
        if not omid or not secret_usid:
            raise StatusError('该试用码无效')
        ticket_usid = self.cuser._base_decode(secret_usid)
        ticket_user = User.query.filter(User.isdelete == false(),
                                        User.USid == ticket_usid).first_('无效试用码')
        om = OrderMain.query.filter(OrderMain.isdelete == false(),
                                    OrderMain.OMid == omid).first_('订单状态异常')
        if om.OMstatus != OrderStatus.has_won.value:
            current_app.logger.error('om status: {}'.format(om.TSOstatus))
            raise StatusError('提示:该二维码已被核销过')
        pr = Product.query.filter(Product.PRid == om.PRid).first()
        if pr.PRtimeLimeted and (pr.PRuseStartTime <= datetime.now() <= pr.PRuseEndTime):
            raise StatusError('当前时间不在该券有效使用时间内')

        user = User.query.join(ProductVerifier, ProductVerifier.PVphone == User.UStelephone
                               ).join(Product, Product.SUid == ProductVerifier.SUid
                                      ).filter(User.isdelete == false(), User.USid == getattr(request, 'user').id,
                                               ProductVerifier.SUid == pr.SUid
                                               ).first_('请确认您是否拥有该券的核销权限')

        with db.auto_commit():
            # 订单改状态
            om.update({'OMstatus': OrderStatus.completed.value})
            db.session.add(om)
            # 核销记录
            tvr = ProductVerifiedRecord.create({'PVRid': str(uuid.uuid1()),
                                                'ownerId': ticket_user.USid,
                                                'VerifierId': user.USid,
                                                'OMid': om.OMid,
                                                'param': param})
            db.session.add(tvr)
        return Success('二维码验证成功', data=tvr.PVRid)
Beispiel #4
0
 def _check_time(self, time_model, fmt='%Y/%m/%d'):
     if isinstance(time_model, datetime):
         return time_model.strftime(fmt)
     else:
         try:
             return datetime.strptime(str(time_model), '%Y-%m-%d %H:%M:%S').strftime(fmt)
         except:
             current_app.logger.error('时间转换错误')
             raise StatusError('系统异常,请联系客服解决')
Beispiel #5
0
 def img_check(filepath, msg='图片'):
     """
     图片校验
     :param msg: msg
     :param filepath: 完整的绝对路径
     :return:
     """
     try:
         filesize = os.path.getsize(filepath)
     except FileNotFoundError:
         current_app.logger.error('FileNotFoundError: {}'.format(filepath))
         raise StatusError('服务器繁忙, 请稍后再试')
     current_app.logger.info('size {} MB'.format(
         round(filesize / 1048576, 2)))
     if filesize > 1024 * 1024:
         current_app.logger.info(
             'content size out of limit, path :{}'.format(filepath))
         # 图片太大
         from PIL import Image
         img = Image.open(filepath)
         x, y = img.size
         x_ = 750
         y_ = int(y * (x / x_))
         if y_ > 1000:
             y_ = 1000
         time_now = datetime.now()
         year = str(time_now.year)
         month = str(time_now.month)
         day = str(time_now.day)
         tmp_path = os.path.join(current_app.config['BASEDIR'], 'img',
                                 'temp', year, month, day)
         if not os.path.isdir(tmp_path):
             os.makedirs(tmp_path)
         tmp_path = os.path.join(tmp_path, os.path.basename(filepath))
         img.resize((x_, y_), Image.LANCZOS).save(tmp_path)
         filepath = tmp_path
         current_app.logger.info('compressed size {} MB, path :{}'.format(
             round(os.path.getsize(filepath) / 1048576, 2), filepath))
     try:
         check_result = mp_miniprogram.img_sec_check(filepath)
         current_app.logger.info(check_result)
     except WeixinMPError as e:
         current_app.logger.info('error is {}'.format(e))
         current_app.logger.error('傻逼在发黄色图片  usid = {}'.format(
             getattr(request, 'user').id))
         raise ParamsError('{}可能存在违法违规等不良信息,请检查后重试'.format(msg))
Beispiel #6
0
 def pay_to_user(self, cn):
     """
     付款到用户微信零钱
     :return:
     """
     user = User.query.filter_by_(USid=cn.USid).first_("提现用户状态异常,请检查后重试")
     try:
         result = self.wx_pay.pay_individual(
             partner_trade_no=self.wx_pay.nonce_str,
             openid=user.USopenid2,
             amount=int(Decimal(cn.CNcashNum).quantize(Decimal('0.00')) * 100),
             desc="优惠下沙-零钱转出",
             spbill_create_ip=self.wx_pay.remote_addr
         )
         current_app.logger.info('微信提现到零钱, response: {}'.format(request))
     except Exception as e:
         current_app.logger.error('微信提现返回错误:{}'.format(e))
         raise StatusError('微信商户平台: {}'.format(e))
     return result
Beispiel #7
0
    def set_verifier(self):
        form = SetVerifier().valid_data()
        if is_admin():
            suid = form.suid.data
            assert suid, '供应商未指定'
        elif is_supplizer():
            suid = request.user.id
        else:
            raise AuthorityError()
        sup = Supplizer.query.filter(
            Supplizer.isdelete == false(),
            Supplizer.SUstatus == UserStatus.usual.value,
            Supplizer.SUid == suid).first_('供应商状态异常')
        if sup.SUgrade != SupplizerGrade.ticket.value:
            raise StatusError('仅虚拟商品供应商可设置核销员')
        phone_list = form.phone_list.data
        tvid_list = []
        instence_list = []
        phone_list = {}.fromkeys(phone_list).keys()
        with db.auto_commit():
            for phone in phone_list:
                User.query.filter(
                    User.isdelete == false(),
                    User.UStelephone == phone).first_(f'没有手机号为 {phone} 用户 ')
                tv = ProductVerifier.query.filter_by(SUid=suid,
                                                     PVphone=phone).first()
                if not tv:
                    tv = ProductVerifier.create({
                        'PVid': str(uuid.uuid1()),
                        'SUid': suid,
                        'PVphone': phone
                    })
                    instence_list.append(tv)
                tvid_list.append(tv.PVid)

            db.session.add_all(instence_list)
            # 删除无效的
            ProductVerifier.query.filter(
                ProductVerifier.isdelete == false(),
                ProductVerifier.SUid == suid,
                ProductVerifier.PVid.notin_(tvid_list)).delete_(
                    synchronize_session=False)
        return Success('修改成功', data=suid)
Beispiel #8
0
    def pay(self):
        """购买"""
        data = parameter_required()
        prid, ompaytype = data.get('prid'), data.get('ompaytype')
        try:
            ompaytype = PayType(int(ompaytype)).value
        except (ValueError, AttributeError, TypeError):
            raise ParamsError('支付方式错误')

        # if not is_user():
        #     raise AuthorityError

        user = self._current_user('请重新登录')
        opayno = self._opayno()
        now = datetime.now()
        product = Product.query.filter(Product.PRid == prid, Product.PRstatus == ProductStatus.active.value,
                                       Product.isdelete == false()).first_('商品已下架')

        if product.PRtimeLimeted:
            starttime = self._check_time(product.PRissueStartTime)
            endtime = self._check_time(product.PRissueEndTime)
            if starttime and now < starttime:
                raise StatusError('商品未到发放时间')
            if endtime and now > endtime:
                raise StatusError('商品已过发放时间')
        trade = self._query_traded(prid, user.USid)  # 直购不限制
        redirect = False
        omid = str(uuid.uuid1())

        with db.auto_commit():
            if ompaytype == PayType.cash.value:
                # 直购
                mount_price = Decimal(product.PRtruePrice)
                if mount_price == Decimal('0'):
                    redirect = True
                trade = False
            elif ompaytype == PayType.scorepay.value:
                # 活跃分
                # if not user.USrealname:  # 暂时除去实名验证
                #     raise StatusError('用户未进行信用认证')
                if not product.PRtimeLimeted:
                    raise StatusError('活跃分支持限时商品')
                mount_price = 0
                redirect = True
            else:
                raise StatusError('支付方式错误')
            if trade:
                raise StatusError('您已申请成功,请在“我的 - 我的试用”中查看')
            omdict = {
                "OMid": omid,
                "OMno": self._generic_omno(),
                "OPayno": opayno,
                "USid": user.USid,
                "PRid": prid,
                "OMmount": product.PRlinePrice,
                "OMtrueMount": mount_price,
                "OMpayType": ompaytype,
                "PRcreateId": product.CreatorId,
                "PRname": product.PRname,
                "PRimg": product.PRimg,
                "OPnum": 1,  # 目前没有添加数量
            }
            if ompaytype == PayType.cash.value:
                user_subcommision = UserSubCommission.query.filter(UserSubCommission.USid == user.USid,
                                                                   UserSubCommission.isdelete == 0)\
                    .first()
                user_super_level = user_subcommision.USCsuperlevel
                if user_super_level == 3:
                    pass
                elif user_super_level == 2:
                    omdict.setdefault('UPperid3', user_subcommision.USCsupper3)
                elif user_super_level == 1:
                    omdict.setdefault('UPperid2', user_subcommision.USCsupper2)
                    omdict.setdefault('UPperid3', user_subcommision.USCsupper3)
                else:
                    omdict.setdefault('UPperid', user_subcommision.USCsupper1)
                    omdict.setdefault('UPperid2', user_subcommision.USCsupper2)
                    omdict.setdefault('UPperid3', user_subcommision.USCsupper3)
            if data.get('shareid'):
                omdict.setdefault('UPshareid', data.get('shareid'))
                # 极差分佣暂时不需要
                # omdict.setdefault('USCommission1', user.USCommission1)
                # omdict.setdefault('USCommission2', user.USCommission2)
                # omdict.setdefault('USCommission3', user.USCommission3)
            om = OrderMain.create(omdict)
            # product.PRnum -= 1  # 商品库存修改 # 0618 fix 非商品逻辑,不能改库存数

            # 月销量 修改或新增
            today = datetime.now()
            month_sale_instance = ProductMonthSaleValue.query.filter(
                ProductMonthSaleValue.isdelete == false(),
                ProductMonthSaleValue.PRid == product.PRid,
                extract('month', ProductMonthSaleValue.createtime) == today.month,
                extract('year', ProductMonthSaleValue.createtime) == today.year,
            ).first()
            if not month_sale_instance:
                month_sale_instance = ProductMonthSaleValue.create({'PMSVid': str(uuid.uuid1()),
                                                                    'PRid': prid,
                                                                    'PMSVnum': 1,
                                                                    'PMSVfakenum': 1
                                                                    })
            else:
                month_sale_instance.update({'PMSVnum': ProductMonthSaleValue.PMSVnum + 1,
                                            'PMSVfakenum': ProductMonthSaleValue.PMSVfakenum + 1})
            db.session.add(month_sale_instance)

            db.session.add(product)
            db.session.add(om)
        body = product.PRname[:16] + '...'
        openid = user.USopenid1
        # 直购订单 不付款 5秒后 自动取消
        if not product.PRtimeLimeted:
            # add_async_task(auto_cancle_order, now + timedelta(minutes=1), (omid,), conn_id='autocancle{}'.format(omid))
            auto_cancle_order.apply_async(args=(omid,), countdown=5, expires=10, queue='high_priority')
        pay_args = self._add_pay_detail(opayno=opayno, body=body, mount_price=mount_price, openid=openid,
                                        opayType=ompaytype, redirect=redirect)
        response = {
            'pay_type': 'wechat_pay',
            'opaytype': ompaytype,
            # 'tscode': tscode_list,
            'args': pay_args,
            'redirect': redirect
        }
        current_app.logger.info('response = {}'.format(response))
        return Success(data=response)
Beispiel #9
0
 def level_commisions(cls):
     commision = cls.query.filter(cls.isdelete == False).first()
     if commision:
         level_commision = json.loads(commision.Levelcommision)
         return level_commision
     raise StatusError('项目需要初始化')
Beispiel #10
0
 def devide_rate_baseline(cls):
     commision = cls.query.filter(cls.isdelete == False).first()
     if commision:
         level_commision = json.loads(commision.Levelcommision)
         return level_commision[-1]
     raise StatusError('项目需要初始化')
Beispiel #11
0
    def update_product(self):
        """编辑商品"""
        if is_admin():
            product_from = ProductFrom.platform.value
        elif is_supplizer():
            product_from = ProductFrom.supplizer.value
        else:
            raise AuthorityError('当前用户无权进行该操作')
        data = parameter_required('prid')
        product = Product.query.filter(Product.isdelete == false(),
                                       Product.PRid == data.get('prid')).first_('未找到该商品信息')
        if Product.query.filter(Product.isdelete == false(), Product.PRname == data.get('prname'),
                                Product.PRid != Product.PRid, Product.PRstatus != ProductStatus.over.value).first():
            raise ParamsError('该商品名已存在')
        approval_flag = 0
        with db.auto_commit():
            if data.get('delete'):
                if product.PRstatus == ProductStatus.active.value:
                    raise ParamsError('无法直接删除正在发放中的商品')
                if OrderMain.query.filter(OrderMain.isdelete == false(),
                                          OrderMain.OMstatus > OrderStatus.not_won.value,
                                          OrderMain.PRid == product.PRid).first():
                    raise StatusError('暂时无法直接删除已产生购买记录的商品')
                product.update({'isdelete': True})
                # 取消异步任务
                cancel_async_task('start_product{}'.format(product.PRid))
                cancel_async_task('end_product{}'.format(product.PRid))
                self.base_admin.create_action(AdminActionS.delete.value, 'Product', product.PRid)
                # 同时将正在进行的审批流改为取消
                self.base_approval.cancel_approval(product.PRid, request.user.id)
            elif data.get('interrupt'):
                if product.PRstatus > ProductStatus.active.value:
                    raise StatusError('该状态下无法中止')
                product.update({'PRstatus': ProductStatus.interrupt.value})
                cancel_async_task('start_product{}'.format(product.PRid))
                cancel_async_task('end_product{}'.format(product.PRid))
                self.base_admin.create_action(AdminActionS.update.value, 'Product', product.PRid)
                # 同时将正在进行的审批流改为取消
                self.base_approval.cancel_approval(product.PRid, request.user.id)
            else:
                approval_flag = 1
                if product.PRstatus < ProductStatus.interrupt.value:
                    raise ParamsError('仅可编辑已中止发放或已结束的商品')
                product_dict = self._validate_ticket_param(data)
                product_dict.update({'PRname': data.get('prname'),
                                     'PRimg': data.get('primg'),
                                     'PRdetails': data.get('prdetails'),
                                     # 'PRstatus': ProductStatus.ready.value if product_dict.get(
                                     #     'PRtimeLimeted') else ProductStatus.active.value,
                                     'PRstatus': ProductStatus.pending.value
                                     })
                self.base_approval.cancel_approval(product.PRid, request.user.id)  # 同时将正在进行的审批流改为取消
                if product.PRstatus == ProductStatus.interrupt.value:  # 中止的情况
                    current_app.logger.info('edit interrupt ticket')
                    product.update(product_dict, null='not')
                else:  # 已结束的情况,重新发起
                    current_app.logger.info('edit ended ticket')
                    product_dict.update({'PRid': str(uuid.uuid1()),
                                         'CreatorId': getattr(request, 'user').id,
                                         'CreatorType': getattr(request, 'user').model})
                    product = Product.create(product_dict)
                cancel_async_task('start_product{}'.format(product.PRid))
                cancel_async_task('end_product{}'.format(product.PRid))

                self.base_admin.create_action(AdminActionS.insert.value, 'Product', product.PRid)
            db.session.add(product)
        if approval_flag:
            self.base_approval.create_approval('toshelves', request.user.id, product.PRid, product_from)
        return Success('编辑成功', data={'prid': product.PRid})