コード例 #1
0
ファイル: deposit.py プロジェクト: LyanJin/check-pay
    def post(self):
        """
        发货通知,由商户实现
        :return:
        """
        if not EnvironEnum.is_local_evn(current_app.config['FLASK_ENV']):
            # 无论如何都记录一条log
            current_app.logger.info('path: %s, ip: %s, args: %s, data: %s',
                                     url_for("gateway_demo_notify"), IpKit.get_remote_ip(), request.args,
                                     request.json)

        form, error = DepositNotifyForm.request_validate()
        if error:
            return error.as_response()

        checker = GatewayFormChecker(form.merchant_id.data)

        # 1. IP白名单校验
        if not checker.verify_ip(form.client_ip.data):
            current_app.logger.error('msg: %s, ip: %s, white ips: %s', GatewayIPError.message, IpKit.get_remote_ip(),
                                     checker.get_white_ips())
            return GatewayIPError().as_response()

        # 2. 签名校验
        sign_fields = form.get_sign_fields()
        if not checker.verify_sign(form.sign.data, sign_fields):
            current_app.logger.error('msg: %s, sign: %s, fields: %s, sign_str: %s',
                                     GatewaySignError.message, form.sign.data, sign_fields,
                                     checker.get_sign_str(sign_fields))
            return GatewaySignError().as_response()

        # 商户自己的业务逻辑处理
        current_app.logger.info('notify success: %s', form.json_data)

        return ResponseSuccess().as_response()
コード例 #2
0
    def post(self):
        client_ip = IpKit.get_remote_ip()

        if not EnvironEnum.is_local_evn(current_app.config['FLASK_ENV']):
            # 无论如何都记录一条log
            current_app.logger.info('Gpay deposit callback, ip: %s, data: %s',
                                    IpKit.get_remote_ip(), request.form)

        sys_tx_id = request.form['company_order_num']
        tx_amount = request.form['amount']
        pw_trade_id = request.form['mownecum_order_num']

        if not CallbackGpay.check_ip(client_ip):
            current_app.logger.fatal(
                'ip not allow, client_ip: %s, data: %s, body: %s', client_ip,
                request.args, request.form)
            return BaseResponse(
                '{"company_order_num":"%s", "mownecum_order_num":"%s", "status":"1", "error_msg":"%s"}'
                % (sys_tx_id, pw_trade_id, "订单状态已更新"))

        order = DepositTransactionCtl.get_order(sys_tx_id)
        if not order:
            current_app.logger.error('gpay: no found order, order id: %s' %
                                     (sys_tx_id))
            return BaseResponse(
                '{"company_order_num":"%s", "mownecum_order_num":"%s", "status":"0", "error_msg":"%s"}'
                % (sys_tx_id, pw_trade_id, "查不到该订单"))

        if order.state.name != OrderStateEnum.INIT.name:
            return BaseResponse(
                '{"company_order_num":"%s", "mownecum_order_num":"%s", "status":"1", "error_msg":"%s"}'
                % (sys_tx_id, pw_trade_id, "订单状态已更新"))

        sorted_fields = [
            "pay_time", "bank_id", "amount", "company_order_num",
            "mownecum_order_num", "pay_card_num", "pay_card_name", "channel",
            "area", "fee", "transaction_charge", "deposit_mode"
        ]

        request_str = "".join([request.form.get(k, "") for k in sorted_fields])
        sign = request.form['key']
        flag = CallbackGpay.check_sign(sign, request_str)

        if not flag:
            current_app.logger.fatal(
                'invalid sign, client_ip: %s, data: %s, body: %s', client_ip,
                request.args, request_str)
            return BaseResponse(
                '{"company_order_num":"%s", "mownecum_order_num":"%s", "status":"0", "error_msg":"%s"}'
                % (sys_tx_id, pw_trade_id, "更新订单状态失败"))

        if not DepositTransactionCtl.success_order_process(
                order, decimal.Decimal(tx_amount), pw_trade_id):
            return BaseResponse(
                '{"company_order_num":"%s", "mownecum_order_num":"%s", "status":"0", "error_msg":"%s"}'
                % (sys_tx_id, pw_trade_id, "更新订单状态失败"))

        return BaseResponse(
            '{"company_order_num":"%s", "mownecum_order_num":"%s", "status":"1", "error_msg":""}'
            % (sys_tx_id, pw_trade_id))
コード例 #3
0
ファイル: config.py プロジェクト: LyanJin/check-pay
    def post(self):
        """
        充值请求
        """
        if not EnvironEnum.is_local_evn(current_app.config['FLASK_ENV']):
            # 无论如何都记录一条log
            current_app.logger.info('path: %s, ip: %s, args: %s, data: %s',
                                    url_for("gateway_config_get"),
                                    IpKit.get_remote_ip(), request.args,
                                    request.json)

        form, error = DepositConfigForm.request_validate()
        if error:
            return error.as_response()

        merchant = form.merchant_id.data

        checker = GatewayFormChecker(merchant)

        # 1. IP白名单校验
        if not checker.verify_ip(form.client_ip.data):
            current_app.logger.error('msg: %s, ip: %s, white ips: %s',
                                     GatewayIPError.message,
                                     IpKit.get_remote_ip(),
                                     checker.get_white_ips())
            return GatewayIPError().as_response()

        # 2. 签名校验
        sign_fields = form.get_sign_fields()
        if not checker.verify_sign(form.sign.data, sign_fields):
            current_app.logger.error(
                'msg: %s, sign: %s, fields: %s, sign_str: %s',
                GatewaySignError.message, form.sign.data, sign_fields,
                checker.get_sign_str(sign_fields))
            return GatewaySignError().as_response()

        # 3. 返回可用的支付方式以及限额
        # 充值每种支付类型的限额
        payment_types = ChannelListHelper.get_channels_for_gateway(
            merchant,
            PayTypeEnum.DEPOSIT,
            client_ip=form.user_ip.data,
        )
        # 提现限额
        # limit_min, limit_max = ChannelLimitCacheCtl(PayTypeEnum.WITHDRAW).get_channel_limit()
        limit_min, limit_max = ChannelListHelper.get_channel_limit_range(
            merchant=merchant,
            payment_way=PayTypeEnum.WITHDRAW,
            client_ip=form.user_ip.data,
        )

        withdraw_config = dict(
            limit_min=limit_min,  # 最小限额列表的最小值
            limit_max=limit_max,  # 最大限额列表的最大值
        )

        return GatewayResponseConfig(bs_data=dict(
            payment_types=payment_types,
            withdraw_config=withdraw_config,
        )).as_response()
コード例 #4
0
ファイル: pony_pay.py プロジェクト: LyanJin/check-pay
    def get(self):
        """
        立马付充值回调
        :return:
        """
        if not EnvironEnum.is_local_evn(current_app.config['FLASK_ENV']):
            # 无论如何都记录一条log
            current_app.logger.info(
                'ponypay withdraw callback, ip: %s, data: %s',
                IpKit.get_remote_ip(), request.args)

        form, error = PonyPayWithdrawForm().request_validate()
        if error:
            current_app.logger.fatal('msg: %s, data: %s', error.message,
                                     request.args)
            return BaseResponse('FAIlURE')

        # 交易订单id
        tx_id = form.corderid.data
        # 实际支付金额
        tx_amount = Decimal(form.money.data)
        # 订单状态: 成功/失败
        status = form.status.data
        # 签名
        sign = form.sign.data
        # 客户端IP
        client_ip = form.client_ip.data

        order = WithdrawTransactionCtl.get_order(tx_id)
        if not order:
            return BaseResponse('FAIlURE')

        channel_config = ChannelConfig.query_by_channel_id(order.channel_id)
        controller = WithdrawCallbackPonypay(channel_config.channel_enum)

        # IP白名单校验
        if not controller.check_ip(client_ip):
            current_app.logger.fatal('ip not allow, client_ip: %s, data: %s',
                                     client_ip, request.args)
            return BaseResponse('FAIlURE')

        # 签名验证
        if not controller.check_sign(tx_id, tx_amount, sign):
            current_app.logger.fatal('invalid sign, client_ip: %s, data: %s',
                                     client_ip, request.args)
            return BaseResponse('FAIlURE')

        if status == '1':
            # 支付成功
            if not WithdrawTransactionCtl.order_success(order, tx_amount):
                return BaseResponse('FAIlURE')
        else:
            # 支付失败
            if not WithdrawTransactionCtl.order_fail(order):
                return BaseResponse('FAIlURE')

        return BaseResponse('SUCCESS')
コード例 #5
0
    def post(self):
        """
        极付,充值回调,极付的回调只会只订单成功后才通知,如果处理失败,通道侧会每隔十秒重新请求一次,共请求十次
        :return:
        """
        if not EnvironEnum.is_local_evn(current_app.config['FLASK_ENV']):
            # 无论如何都记录一条log
            current_app.logger.info('jifu deposit callback, ip: %s, data: %s',
                                    IpKit.get_remote_ip(), request.form)

        form, error = JifuCallbackForm().request_validate()
        if error:
            current_app.logger.fatal('msg: %s, data: %s', error.message,
                                     request.form)
            return BaseResponse(error.message)

        # 交易订单id
        sys_tx_id = form.remark.data
        # 通道订单id
        channel_tx_id = form.id.data
        # 实际支付金额
        tx_amount = Decimal(form.money.data)
        # 客户端IP
        client_ip = form.client_ip.data

        # IP白名单校验
        checker = DepositCallbackJifu(ChannelConfigEnum.CHANNEL_7001)
        if not checker.check_ip(client_ip):
            current_app.logger.fatal('ip not allow, client_ip: %s, data: %s',
                                     client_ip, form.form_data)
            return BaseResponse('ip not allow')

        # 签名验证
        if not checker.check_sign(form.get_sign_fields(), form.get_raw_sign()):
            current_app.logger.fatal('invalid sign, client_ip: %s, data: %s',
                                     client_ip, form.form_data)
            return BaseResponse('invalid sign')

        order = DepositTransactionCtl.get_order(sys_tx_id)
        if not order:
            return BaseResponse('no order found for sys_tx_id: %s', sys_tx_id)

        if order.channel_tx_id != channel_tx_id:
            # 根据API文档的建议,之前已经将code放入数据库的channel_tx_id中,等回调时拿来比对
            current_app.logger.fatal(
                'invalid channel_tx_id, client_ip: %s, channel_tx_id: %s, data: %s',
                client_ip, order.channel_tx_id, form.form_data)
            return BaseResponse('invalid channel_tx_id')

        # 支付成功
        if not DepositTransactionCtl.success_order_process(
                order, tx_amount, channel_tx_id):
            return BaseResponse('order process failed, sys_tx_id: %s',
                                sys_tx_id)

        # 成功返回小写字符串success
        return BaseResponse('success')
コード例 #6
0
ファイル: pony_pay.py プロジェクト: LyanJin/check-pay
    def get(self):
        """
        立马付,充值回调
        :return:
        """
        if not EnvironEnum.is_local_evn(current_app.config['FLASK_ENV']):
            # 无论如何都记录一条log
            current_app.logger.info(
                'ponypay deposit callback, ip: %s, data: %s',
                IpKit.get_remote_ip(), request.args)

        form, error = PonyPayForm().request_validate()
        if error:
            current_app.logger.fatal('msg: %s, data: %s', error.message,
                                     request.args)
            return BaseResponse(error.message)

        # 交易订单id
        tx_id = form.orderid.data
        # 充值通道 订单id
        channel_tx_id = form.porder.data
        # 实际支付金额
        tx_amount = Decimal(form.money.data)
        # 订单状态: 成功/失败
        status = form.status.data
        # 客户端IP
        client_ip = form.client_ip.data

        # IP白名单校验
        if not CallbackPonypay.check_ip(client_ip):
            current_app.logger.fatal('ip not allow, client_ip: %s, data: %s',
                                     client_ip, request.args)
            return BaseResponse('FAIlURE')

        # 签名验证
        if not CallbackPonypay.check_sign(form):
            current_app.logger.fatal('invalid sign, client_ip: %s, data: %s',
                                     client_ip, request.args)
            return BaseResponse('FAIlURE')

        order = DepositTransactionCtl.get_order(tx_id)
        if not order:
            return BaseResponse('FAIlURE')

        if status == '1':
            # 支付成功
            if not DepositTransactionCtl.success_order_process(
                    order, tx_amount, channel_tx_id):
                return BaseResponse('FAIlURE')
        else:
            # 支付失败
            if not DepositTransactionCtl.failed_order_process(
                    order, tx_amount, channel_tx_id):
                return BaseResponse('FAIlURE')

        return BaseResponse('SUCCESS')
コード例 #7
0
    def post(self):
        client_ip = IpKit.get_remote_ip()
        third_config = ThirdPayConfig.EpayTong_PAY_DEPOSIT.value

        if not EnvironEnum.is_local_evn(current_app.config['FLASK_ENV']):
            # 无论如何都记录一条log
            current_app.logger.info(
                'epaytong deposit callback, ip: %s, data: %s',
                IpKit.get_remote_ip(), request.form)

        if not CallbackEpayTong.check_ip(client_ip):
            current_app.logger.fatal(
                'ip not allow, client_ip: %s, data: %s, body: %s', client_ip,
                request.args, request.form)
            return BaseResponse('FAIlURE')

        sys_tx_id = request.form['order_no']
        order = DepositTransactionCtl.get_order(sys_tx_id)
        if not order:
            current_app.logger.error('epaytong: no found order, order id: %s' %
                                     (sys_tx_id))
            return BaseResponse('FAILURE')

        no_need_field = ['signType', 'sign']
        sorted_fields = sorted([k for k in request.form.keys()])
        request_str = "&".join([
            "{}={}".format(k, request.form[k]) for k in sorted_fields
            if (request.form[k] == 0 or request.form[k] == "0"
                or request.form[k]) and k not in no_need_field
        ])
        sign = request.form['sign']
        sign_str = request_str + third_config['secret_key']
        flag = CallbackEpayTong.check_sign(sign, sign_str)

        if not flag:
            current_app.logger.fatal(
                'invalid sign, client_ip: %s, data: %s, body: %s', client_ip,
                request.args, request_str)
            return ResponseSuccess(code=500, message='签名错误').as_response()

        tx_amount = request.form['price']
        pwTradeId = request.form['notify_id']

        status = request.form['is_success']
        trade = request.form['trade_status']
        if status == 'T' and trade == "TRADE_FINISHED":
            if not DepositTransactionCtl.success_order_process(
                    order, decimal.Decimal(tx_amount), pwTradeId):
                return BaseResponse('FAIlURE')
        else:
            if not DepositTransactionCtl.failed_order_process(
                    order, decimal.Decimal(tx_amount), pwTradeId):
                return BaseResponse('FAIlURE')

        return BaseResponse('success')
コード例 #8
0
ファイル: deposit.py プロジェクト: LyanJin/check-pay
    def get(self):
        """
        渲染第三方跳转页面
        :return:
        """
        if not EnvironEnum.is_local_evn(current_app.config['FLASK_ENV']):
            # 无论如何都记录一条log
            current_app.logger.info('path: %s, ip: %s, args: %s, data: %s',
                                     url_for("gateway_deposit_redirect"), IpKit.get_remote_ip(), request.args,
                                     request.json)

        return DepositHelper.render_page()
コード例 #9
0
    def post(self):
        if not EnvironEnum.is_local_evn(current_app.config['FLASK_ENV']):
            # 无论如何都记录一条log
            current_app.logger.info(
                'one pay deposit callback, ip: %s, data: %s, headers: %s, json data:%s',
                IpKit.get_remote_ip(), request.form, request.headers,
                request.json)

        client_ip = IpKit.get_remote_ip()

        if not CallbackOnePay.check_ip(client_ip):
            current_app.logger.fatal('ip not allow, client_ip: %s, data: %s',
                                     client_ip, request.args)
            return BaseResponse('FAIlURE')

        sys_tx_id = request.form['merchantTradeId']
        order = DepositTransactionCtl.get_order(sys_tx_id)
        if not order:
            current_app.logger.error('OnePay: no found order, order id: %s' %
                                     (sys_tx_id))
            return BaseResponse('FAILURE')

        no_need_field = ['signType', 'sign']
        sorted_fields = sorted([k for k in request.form.keys()])
        request_str = "&".join([
            "{}={}".format(k, request.form[k]) for k in sorted_fields
            if k not in no_need_field and request.form[k]
        ])
        sign = request.form['sign']

        flag = CallbackOnePay.check_sign(sign, request_str)

        if not flag:
            current_app.logger.fatal(
                'invalid sign, client_ip: %s, data: %s, body: %s', client_ip,
                request.args, request_str)
            return ResponseSuccess(code=500, message='签名错误').as_response()

        tx_amount = request.form['amountFee']
        pwTradeId = request.form['pwTradeId']

        status = request.form['tradeStatus']
        if status == 'PS_PAYMENT_FAIL':
            if not DepositTransactionCtl.failed_order_process(
                    order, decimal.Decimal(tx_amount), pwTradeId):
                return BaseResponse('FAIlURE')
        elif status == 'PS_PAYMENT_SUCCESS':
            if not DepositTransactionCtl.success_order_process(
                    order, decimal.Decimal(tx_amount), pwTradeId):
                return BaseResponse('FAIlURE')

        return BaseResponse('SUCCESS')
コード例 #10
0
ファイル: yinsao_pay.py プロジェクト: LyanJin/check-pay
    def post(self):
        if not EnvironEnum.is_local_evn(current_app.config['FLASK_ENV']):
            # 无论如何都记录一条log
            current_app.logger.info('yinsao withdraw callback, ip: %s, data: %s, headers: %s', IpKit.get_remote_ip(),
                                    request.form, request.headers)

        # form, error = YinSaoForm.request_validate()
        # if error:
        #     current_app.logger.fatal('msg: %s, data: %s', error.message, request.json)
        #     return BaseResponse('FAIlURE')

        client_ip = IpKit.get_remote_ip()

        if not CallbackYinSao.check_ip(client_ip):
            current_app.logger.fatal('ip not allow, client_ip: %s, data: %s', client_ip, request.args)
            return BaseResponse('FAIlURE')

        data = {k: v for k, v in request.form.items()}

        tx_amount = Decimal(data['transAmt']) / Decimal('100')
        sys_tx_id = data['orderNo']

        signature = data.pop('signature')
        key_list = sorted(list(data.keys()))
        request_str = "&".join(["{}={}".format(field, data[field]) for field in key_list if field != "risk"])
        sign = CallbackYinSao.generate_sign(request_str)
        flag = CallbackYinSao.check_sign(signature, sign)

        if not flag:
            current_app.logger.fatal('invalid sign, data: %s, sign: %s, signature: %s', client_ip, data, sign, signature)
            return BaseResponse('FAIlURE')

        order = WithdrawTransactionCtl.get_order(sys_tx_id)
        if not order:
            return BaseResponse('FAIlURE')

        if str(data['respCode']) == '0000':
            # 支付成功
            if not WithdrawTransactionCtl.order_success(order, tx_amount):
                return BaseResponse('FAILURE')
        else:
            # 支付失败
            if not WithdrawTransactionCtl.order_fail(order):
                return BaseResponse('FAIlURE')

        return BaseResponse('SUCCESS')
コード例 #11
0
    def get(self):
        """
        Tong yi Pay,充值回调
        :return:
        """
        if not EnvironEnum.is_local_evn(current_app.config['FLASK_ENV']):
            # 无论如何都记录一条log
            current_app.logger.info('tong yi deposit callback, ip: %s, data: %s', IpKit.get_remote_ip(), request.args)

        client_ip = IpKit.get_remote_ip()
        if not CallbackTongYiPay.check_ip(client_ip):
            current_app.logger.error('ip not allow, client_ip: %s, data: %s, body: %s', client_ip, request.args,
                                    request.json)

        sign = request.args.get("sign")
        keys = sorted(list(request.args.keys()))
        sign_str = "&".join(["{}={}".format(k, request.args.get(k)) for k in keys if k not in ['sign'] and request.args.get(k, False)])
        flag = CallbackTongYiPay.check_sign(sign, sign_str)
        if not flag:
            current_app.logger.error('invalid sign, client_ip: %s, data: %s, body: %s', client_ip, request.args,
                                     sign_str)
            return BaseResponse('error')

        order_id = request.args.get('order')

        order = DepositTransactionCtl.get_order(order_id)
        if not order:
            current_app.logger.error('invalid order: order_id: %s', order_id)
            return BaseResponse('FAIlURE')

        if order.state.name == OrderStateEnum.SUCCESS.name:
            return BaseResponse('SUCCESS')

        channel_tx_id = request.args.get('orderId', False)

        state = request.args.get('status', 0)
        tx_amount = request.args.get('money', 0)

        if str(state) == "2" or str(state) == "3":
            if not DepositTransactionCtl.success_order_process(order, Decimal(tx_amount), channel_tx_id):
                return BaseResponse('FAIlURE')

        return BaseResponse('SUCCESS')
コード例 #12
0
    def post(self):
        """
        BestPay,充值回调
        :return:
        """
        if not EnvironEnum.is_local_evn(current_app.config['FLASK_ENV']):
            # 无论如何都记录一条log
            current_app.logger.info('BestPay deposit callback, ip: %s, data: %s', IpKit.get_remote_ip(), request.form)

        client_ip = IpKit.get_remote_ip()
        if not CallbackBestPay.check_ip(client_ip):
            current_app.logger.error('ip not allow, client_ip: %s, data: %s, body: %s', client_ip, request.args,
                                     request.form)
            return BaseResponse('error')

        data = request.form['deposit_result']
        resp_body = json.loads(data)

        third_config = ThirdPayConfig.BESTPAY_DEPOSIT.value
        sign = resp_body["sign"]
        resp_type = resp_body["type"]
        if resp_type != "deposit_result":
            return BaseResponse('error')
        data = resp_body["data"]

        print(data)
        if isinstance(data, list):
            sign_str = json.dumps(data)
        else:
            sign_str = data
        sign_str += third_config['secret_key']
        flag = CallbackBestPay.check_sign(sign, sign_str)
        if not flag:
            current_app.logger.error('invalid sign, client_ip: %s, data: %s, body: %s', client_ip, request.args,
                                     sign_str)
            return BaseResponse('error')

        data_list = json.loads(data)
        flag = 'error'
        for data_dict in data_list:

            order_id = data_dict['client_postscript']
            tx_amount = data_dict['amount']
            channel_tx_id = data_dict['order_number']
            client_transtype = data_dict['client_transtype']
            deposit_cardnumber = data_dict['deposit_cardnumber']
            user_name = data_dict['client_accountname']
            deposit_time = data_dict['deposit_time']

            try:
                order_id = int(order_id)
            except Exception as e:
                if client_transtype == '微信转账':
                    DateTimeKit.time_delta()
                    log = OrderTransferLog.query_transfer_log_by_user_info(
                        deposit_cardnumber=deposit_cardnumber,
                        amount='{:.2f}'.format(float(tx_amount)),
                        deposit_time=deposit_time
                    )
                else:

                    log = OrderTransferLog.query_transfer_log_by_user_info(
                        deposit_cardnumber=deposit_cardnumber,
                        amount='{:.2f}'.format(float(tx_amount)),
                        client_accountname=user_name,
                        deposit_time=deposit_time
                    )
                current_app.logger.info("转账信息数据", log)
                if log:

                    for o in log:

                        order = DepositTransactionCtl.get_order_by_order_id(order_id=o.order_id)
                        if not order or order.state.name != OrderStateEnum.INIT.name:
                            continue

                        if DepositTransactionCtl.success_order_process(order, Decimal(str(tx_amount)), channel_tx_id):
                            OrderTransferLog.update_transfer_log(order_id=order.order_id)
                            flag = "success"

            else:

                log = OrderTransferLog.query_transfer_log(order_id=order_id)
                if not log:
                    continue

                order = DepositTransactionCtl.get_order_by_order_id(order_id=log.order_id)

                if not order or order.state.name != OrderStateEnum.INIT.name:
                    continue

                if DepositTransactionCtl.success_order_process(order, Decimal(str(tx_amount)), channel_tx_id):
                    OrderTransferLog.update_transfer_log(order_id=order.order_id)
                    flag = "success"

        return BaseResponse(flag)
コード例 #13
0
    def post(self):
        """
        充值请求
        """
        if not EnvironEnum.is_local_evn(current_app.config['FLASK_ENV']):
            # 无论如何都记录一条log
            current_app.logger.info('path: %s, ip: %s, args: %s, data: %s',
                                    url_for("gateway_withdraw_request"),
                                    IpKit.get_remote_ip(), request.args,
                                    request.json)

        form, error = WithdrawRequestForm.request_validate()
        if error:
            return error.as_response()

        checker = GatewayFormChecker(form.merchant_id.data)

        # 1. IP白名单校验
        if not checker.verify_ip(form.client_ip.data):
            current_app.logger.error('msg: %s, ip: %s, white ips: %s',
                                     GatewayIPError.message,
                                     IpKit.get_remote_ip(),
                                     checker.get_white_ips())
            return GatewayIPError().as_response()

        # 2. 签名校验
        sign_fields = form.get_sign_fields()
        if not checker.verify_sign(form.sign.data, sign_fields):
            current_app.logger.error(
                'msg: %s, sign: %s, fields: %s, sign_str: %s',
                GatewaySignError.message, form.sign.data, sign_fields,
                checker.get_sign_str(sign_fields))
            return GatewaySignError().as_response()

        # 3. 获取用户对象
        user = checker.get_fake_user(form.user_id.data)

        # 银行卡信息
        bank_info = BankCard.generate_model(
            bank_name=form.bank_type.data.desc,
            bank_code=form.bank_type.data.bank_code,
            card_no=form.card_no.data,
            account_name=form.account_name.data,
            branch=form.branch.data or '',
            province=form.province.data or '',
            city=form.city.data or '',
        )

        # 4. 创建订单
        order, error = WithdrawTransactionCtl.order_create(
            user=user,
            amount=form.amount.data,
            client_ip=form.user_ip.data,
            notify_url=form.notify_url.data,
            mch_tx_id=form.mch_tx_id.data,
            bank_info=bank_info.bank_info_dict,
            extra=form.extra.data,
        )
        if error:
            return error.as_response()

        return GatewayResponseWithdraw(bs_data=dict(
            sys_tx_id=order.sys_tx_id,
            mch_tx_id=order.mch_tx_id,
        )).as_response()
コード例 #14
0
ファイル: withdraw_ctl.py プロジェクト: LyanJin/check-pay
    def order_deal(cls,
                   admin_account,
                   order_id,
                   merchant,
                   channel_id,
                   test=False):
        """

        :param admin_account:
        :param order_id:
        :param merchant:
        :param channel_id:
        :param test: 单元测试填写
        :return:
        """
        params = copy.deepcopy(locals())
        params.pop('cls')

        if EnvironEnum.is_production(current_app.config['FLASK_ENV']) and test:
            # 非调试环境不该填写 channel_tx_id,应该发送请求到第三方去申请
            raise RuntimeError('invalid test param')

        order = OrderWithdraw.query_by_order_id(merchant, order_id)
        if not order:
            msg = '%s, params: %s' % (NoSuchWithdrawOrderError.message, params)
            current_app.logger.error(msg)
            return NoSuchWithdrawOrderError()

        if order.state != OrderStateEnum.ALLOC:
            msg = '%s, params: %s, state: %s, tx_id: %s' % (
                NotAllocOrderError.message, params, order.state.desc,
                order.sys_tx_id)
            current_app.logger.error(msg)
            return NotAllocOrderError(message=NotAllocOrderError.message +
                                      ", 订单状态:" + order.state.desc)

        channel_config = ProxyChannelConfig.query_by_channel_id(channel_id)
        if not channel_config:
            msg = '%s, params: %s' % (InvalidChannelError.message, params)
            current_app.logger.error(msg)
            return InvalidChannelError()

        bank_card = order.get_bank_card()
        if not bank_card:
            msg = '%s, params: %s' % (WithdrawBankNoExistError.message, params)
            current_app.logger.error(msg)
            return WithdrawBankNoExistError()

        # 开始更新订单,根据通道计算费率和成本
        # 通道收取的手续费
        channel_cost = FeeCalculator.calc_cost(order.amount,
                                               channel_config.fee_type,
                                               channel_config.fee)
        tx_amount = order.amount

        channel_enum = channel_config.channel_enum
        if channel_enum.plus_fee_for_withdraw():
            # 特殊通道,要发起金额要加上手续费,通道测扣除手续费才是实际到账金额
            # 实际提款金额=发起金额+通道手续费
            tx_amount += channel_cost

        # 发起支付
        launch_pay = channel_enum.get_launch_pay_func(PayTypeEnum.WITHDRAW)

        if not test:
            # 第三方返回由第三方生成交易ID:channel_tx_id
            rst = launch_pay(
                dict(order_id=order.order_id,
                     tx_id=order.sys_tx_id,
                     amount=tx_amount,
                     channel_cost=channel_cost,
                     bank_code=bank_card.bank_code,
                     bank_name=bank_card.bank_name,
                     bank_account=bank_card.account_name,
                     bank_number=bank_card.card_no,
                     bank_address=bank_card.bank_address,
                     bank_branch=bank_card.branch,
                     province=bank_card.province,
                     city=bank_card.city))

            current_app.logger.info('withdraw launch_pay, params: %s, rst: %s',
                                    params, rst)

            if rst['code'] != 0:
                # 不要改变订单状态,让客服去选择其它通道重试
                # cls.order_fail(order, client_ip)
                current_app.logger.error(
                    '%s, %s, params: %s' %
                    (FailedLaunchWithdrawError.message, rst['msg'], params))
                return FailedLaunchWithdrawError(message=rst['msg'])

        # 发起成功后更新状态为处理中
        order, _ = OrderUpdateCtl.update_order_event(
            order.order_id,
            uid=order.uid,
            merchant=merchant,
            state=OrderStateEnum.DEALING,
            channel_id=channel_id,
            cost=channel_cost,
            deal_time=DateTimeKit.get_cur_datetime(),
            op_account=admin_account,
        )
        if not order:
            msg = '%s, params: %s' % (WithdrawUpdateDealingError.message,
                                      params)
            current_app.logger.error(msg)
            return WithdrawUpdateDealingError()

        return ResponseSuccess()
コード例 #15
0
    def post(self):
        """
        RuKouMy,充值回调
        :return:
        """
        client_ip = IpKit.get_remote_ip()

        if not EnvironEnum.is_local_evn(current_app.config['FLASK_ENV']):
            # 无论如何都记录一条log
            current_app.logger.info(
                'RuKouMy deposit callback, ip: %s, json: %s',
                IpKit.get_remote_ip(), request.json)

        if not CallbackRuKouMy.check_ip(client_ip):
            current_app.logger.error(
                'ip not allow, client_ip: %s, data: %s, body: %s', client_ip,
                request.args, request.json)
            return BaseResponse('error')

        resp_body = request.json

        sign = resp_body.pop("sign")
        sorted_params = sorted(list(resp_body.keys()))
        resp_body['real_amount'] = "{:.2f}".format(
            int(resp_body['real_amount']))
        resp_body['pay_amount'] = "{:.2f}".format(int(resp_body['pay_amount']))

        sign_str = "&".join([
            "{}={}".format(k, resp_body[k]) for k in sorted_params
            if resp_body.get(k, False) or k in ["code"]
        ])

        flag = CallbackRuKouMy.check_sign(sign, sign_str)
        if not flag:
            current_app.logger.error(
                'invalid sign, data: %s, sign: %s, data: %s', client_ip, sign,
                sign_str)
            return BaseResponse('error')

        order_id = resp_body['order_id']
        order = DepositTransactionCtl.get_order(order_id)

        if not order:
            return BaseResponse('success')

        if order.state.name == OrderStateEnum.SUCCESS.name:
            return BaseResponse('success')

        tx_amount = Decimal(str(request.json['real_amount']))
        channel_tx_id = request.json['order_no']

        code = resp_body['code']
        if code == 0:
            # 支付成功
            if not DepositTransactionCtl.success_order_process(
                    order, tx_amount, channel_tx_id):
                return BaseResponse('error')
        else:
            # 支付失败
            if not DepositTransactionCtl.failed_order_process(
                    order, tx_amount, channel_tx_id):
                return BaseResponse('error')

        return BaseResponse('success')
コード例 #16
0
ファイル: zhuanyifu_pay.py プロジェクト: LyanJin/check-pay
    def post(self):
        if not EnvironEnum.is_local_evn(current_app.config['FLASK_ENV']):
            # 无论如何都记录一条log
            current_app.logger.info(
                'zhuanyifu deposit callback, ip: %s, data: %s, headers: %s',
                IpKit.get_remote_ip(), request.json, request.headers)
        event = request.headers.get('ChinaRailway-Event')
        signature = request.headers.get('ChinaRailway-Signature')
        form, error = ZhuanYeFuWithdrawForm().request_validate()
        if error:
            current_app.logger.fatal('msg: %s, data: %s', error.message,
                                     request.args)
            return BaseResponse('FAIlURE')

        client_ip = form.client_ip.data
        tx_amount = Decimal(form.amount.data)
        fee = Decimal(form.fee.data)
        channel_tx_id = form.transaction.data

        # if not CallbackZYF.check_ip(client_ip):
        #     current_app.logger.fatal('ip not allow, client_ip: %s, data: %s, body: %s', client_ip, request.args,
        #                              request.json)
        #     return ResponseSuccess(code=500, message='ip not allow').as_response()

        pp = signature.split('.')
        if event != "Charge.Succeeded":
            return ResponseSuccess(code=500).as_response()

        order = DepositTransactionCtl.get_order(form.order.data)
        if not order:
            return ResponseSuccess(
                code=500, message='curr order no found').as_response()

        curr_status = order.state
        if curr_status != OrderStateEnum.INIT:
            return ResponseSuccess(
                code=500,
                message='curr order status must be DEALING').as_response()

        channel_config = ChannelConfig.query_by_channel_id(order.channel_id)
        # 检查通道手续费与系统计算出的手续费
        channel_cost = FeeCalculator.calc_cost(order.amount,
                                               channel_config.fee_type,
                                               channel_config.fee)
        if Decimal(fee) != channel_cost:
            current_app.logger.error(
                "ZYF deposit fee info order_id:{}, channel_fee: {}, channel_cost:{}"
                .format(order.order_id, Decimal(fee), channel_cost))
        flag = CallbackZYF.check_sign(pp=pp, channel_config=channel_config)
        if not flag:
            current_app.logger.fatal(
                'invalid sign, client_ip: %s, data: %s, body: %s', client_ip,
                request.args, request.json)
            return ResponseSuccess(code=500, message='签名错误').as_response()

        status = form.status.data

        if str(status) == '1':
            if not DepositTransactionCtl.success_order_process(
                    order, tx_amount, channel_tx_id, client_ip):
                return ResponseSuccess(code=500,
                                       message='订单状态更新失败').as_response()
            else:
                return ResponseSuccess(code=500, message='签名错误').as_response()

        elif str(status) == '2':
            if not DepositTransactionCtl.failed_order_process(
                    order, tx_amount, channel_tx_id, client_ip):
                return ResponseSuccess(code=500,
                                       message='订单状态更新失败').as_response()

        elif str(status) == '0':
            pass

        return ResponseSuccess(code=204).as_response()
コード例 #17
0
ファイル: deposit.py プロジェクト: LyanJin/check-pay
    def post(self):
        """
        充值请求
        """
        if not EnvironEnum.is_local_evn(current_app.config['FLASK_ENV']):
            # 无论如何都记录一条log
            current_app.logger.info('path: %s, ip: %s, args: %s, data: %s',
                                     url_for("gateway_deposit_request"), IpKit.get_remote_ip(), request.args,
                                     request.json)

        form, error = DepositRequestForm.request_validate()
        if error:
            return error.as_response()

        checker = GatewayFormChecker(form.merchant_id.data)

        # 1. IP白名单校验
        if not checker.verify_ip(form.client_ip.data):
            current_app.logger.error('msg: %s, ip: %s, white ips: %s', GatewayIPError.message, IpKit.get_remote_ip(),
                                     checker.get_white_ips())
            return GatewayIPError().as_response()

        # 2. 签名校验
        sign_fields = form.get_sign_fields()
        if not checker.verify_sign(form.sign.data, sign_fields):
            current_app.logger.error('msg: %s, sign: %s, fields: %s, sign_str: %s',
                                     GatewaySignError.message, form.sign.data, sign_fields,
                                     checker.get_sign_str(sign_fields))
            return GatewaySignError().as_response()

        # 3. 获取对应支付方式下的充值通道
        channel = ChannelListHelper.get_one_channel_by_payment_type(
            merchant=form.merchant_id.data,
            payment_type=form.payment_type.data,
            amount=form.amount.data,
            client_ip=form.user_ip.data,
        )
        if not channel:
            current_app.logger.error("no channel found, request data: %s", form.get_data())
            return GatewayChannelError().as_response()

        # # 境外IP检查
        # if channel.is_ip_forbidden(form.user_ip.data):
        #     return GatewayDepositError(message="此通道不支持境外IP,请使用VPN后重试").as_response()

        # 4. 获取用户对象
        user = checker.get_fake_user(form.user_id.data)

        # 5. 发起支付
        rst = DepositHelper.do_deposit_request(
            client_ip=form.user_ip.data,
            user_agent=form.user_agent.data,
            user=user,
            amount=form.amount.data,
            channel_enum=channel.channel_enum,
            notify_url=form.notify_url.data,
            result_url=form.result_url.data,
            mch_tx_id=form.mch_tx_id.data,
            extra=form.extra.data,
            source=OrderSourceEnum.TESTING if form.merchant_id.data.is_test else OrderSourceEnum.ONLINE,
            in_type=InterfaceTypeEnum.API,
        )
        if rst['error']:
            return GatewayDepositError(message=rst['error'])

        # 6. 解析URL
        ps_rst = DepositHelper.parse_result(
            data=rst['data'],
            order_id=rst['order'].order_id,
            endpoint='gateway_deposit_redirect',
            channel_enum=channel.channel_enum,
        )

        return GatewayResponseDeposit(bs_data=dict(
            redirect_url=ps_rst['redirect_url'],
            valid_time=ps_rst['valid_time'],
            sys_tx_id=rst['order'].sys_tx_id,
            mch_tx_id=rst['order'].mch_tx_id,
        )).as_response()
コード例 #18
0
    def post(self):
        if not EnvironEnum.is_local_evn(current_app.config['FLASK_ENV']):
            # 无论如何都记录一条log
            current_app.logger.info(
                'onepay withdraw callback, ip: %s, headers: %s, json data: %s',
                IpKit.get_remote_ip(), request.headers, request.json)

        # form, error = YinSaoForm.request_validate()
        # if error:
        #     current_app.logger.fatal('msg: %s, data: %s', error.message, request.json)
        #     return BaseResponse('FAIlURE')

        current_app.logger.fatal(
            'onepay withdraw callback, ip: %s, form data: %s, headers: %s, json data: %s',
            IpKit.get_remote_ip(), request.form, request.headers, request.json)

        client_ip = IpKit.get_remote_ip()

        if not CallbackOnePay.check_ip(client_ip):
            current_app.logger.fatal('ip not allow, client_ip: %s, data: %s',
                                     client_ip, request.args)
            return BaseResponse('FAIlURE')

        flag = request.json['flag']
        if flag == 'FAILED':
            return BaseResponse('FAIlURE')

        data = {k: v for k, v in request.json['data'].items()}
        no_need_sign = ['totalFactorage', 'sign', 'signType', 'detailList']

        signature = data.pop('sign')
        key_list = sorted(list(data.keys()))
        request_str = "&".join([
            "{}={}".format(field, data[field]) for field in key_list
            if data.get(field, False) and field not in no_need_sign
        ])

        flag = CallbackOnePay.check_sign(signature, request_str)

        if not flag:
            current_app.logger.fatal(
                'invalid sign, data: %s, sign: %s, data: %s', client_ip, data,
                signature, request_str)
            return BaseResponse('FAIlURE')

        withdraw_order = request.json['data']['detailList'][0]
        tx_id = withdraw_order['serialNo']
        tx_amount = withdraw_order['amount']
        order = WithdrawTransactionCtl.get_order(tx_id)
        if not order:
            return BaseResponse('FAIlURE')

        if str(withdraw_order['tradeStatus']) == '1':
            # 支付成功
            if not WithdrawTransactionCtl.order_success(
                    order, decimal.Decimal(tx_amount)):
                return BaseResponse('FAILURE')
        elif str(withdraw_order['tradeStatus']) == '2':
            # 支付失败
            if not WithdrawTransactionCtl.order_fail(order):
                return BaseResponse('FAIlURE')

        return BaseResponse('SUCCESS')
コード例 #19
0
ファイル: kuaihui_pay.py プロジェクト: LyanJin/check-pay
    def post(self):
        """
        快汇支付,充值回调
        :return:
        """
        if not EnvironEnum.is_local_evn(current_app.config['FLASK_ENV']):
            # 无论如何都记录一条log
            current_app.logger.info(
                'kuaihui deposit callback, ip: %s, args: %s, data: %s',
                IpKit.get_remote_ip(), request.args, request.json)

        form, error = KhpayForm().request_validate()
        if error:
            current_app.logger.fatal('msg: %s, args: %s, data: %s',
                                     error.message, request.args, request.json)
            return BaseResponse(error.message)

        # 交易订单id
        tx_id = form.client_ordid.data
        # 充值通道 订单id
        channel_tx_id = form.ordid.data
        # 实际支付金额
        tx_amount = Decimal(form.amount.data)
        # 订单状态: 成功/失败
        status = form.status.data
        # 客户端IP
        client_ip = form.client_ip.data
        custid = form.custid.data
        kuai_hui_dict = {
            "PAY5f34c380-b8e6-11e9-9edc-511803f475f9":
            ThirdPayConfig.KUAIHUI.value,
            "PAY5f34c380-b8e6-11e9-9edc-511803f475f9":
            ThirdPayConfig.KUAIHUI_0bd0d8.value
        }
        # 签名验证
        if not CallbackKhpay.check_sign(form, kuai_hui_dict[custid]):
            current_app.logger.fatal('invalid sign, client_ip: %s, data: %s',
                                     client_ip, request.json)
            return BaseResponse('FAIlURE')

        # IP白名单校验
        if not CallbackKhpay.check_ip(client_ip):
            current_app.logger.fatal('ip not allow, client_ip: %s, data: %s',
                                     client_ip, request.json)
            return BaseResponse('FAIlURE')

        order = DepositTransactionCtl.get_order(tx_id)
        if not order:
            return BaseResponse('FAIlURE')

        if order.state.is_final_state:
            # 已经通知了就返回成功
            return BaseResponse('{"status_code": 200}')

        if status == 'waiting':
            return BaseResponse('FAIlURE')

        if status == 'finish':
            # 支付成功
            if not DepositTransactionCtl.success_order_process(
                    order, tx_amount, channel_tx_id):
                return BaseResponse('FAIlURE')
        else:
            # 支付失败
            if not DepositTransactionCtl.failed_order_process(
                    order, tx_amount, channel_tx_id):
                return BaseResponse('FAIlURE')

        return BaseResponse('{"status_code": 200}')
コード例 #20
0
ファイル: deposit_ctl.py プロジェクト: LyanJin/check-pay
    def do_notify(cls, order, op_account=None, comment=None):
        """
        网关回调通知
        :return:
        """
        rst = dict(msg=None)
        if not order.notify_url:
            # 不需要通知
            rst['msg'] = "没有通知URL,不需要发送通知"
            return rst

        if order.state not in OrderStateEnum.get_final_states() and \
                EnvironEnum.is_production(current_app.config['FLASK_ENV']):
            rst['msg'] = "订单不是成功/失败状态,还没有完成,不能通知商户"
            return rst

        data = dict(
            merchant_id=order.merchant.value,
            amount=str(order.amount),
            tx_amount=str(order.tx_amount),
            mch_tx_id=order.mch_tx_id,
            sys_tx_id=order.sys_tx_id,
            state=order.state.name,
        )

        data['sign'] = GatewaySign(order.merchant).generate_sign(data)
        data['extra'] = order.extra

        try:
            current_app.logger.info('do_notify: %s, data: %s',
                                    order.notify_url, data)
            rsp = requests.post(order.notify_url, json=data)
            current_app.logger.info('do_notify: %s, status code: %s, data: %s',
                                    order.notify_url, rsp.status_code,
                                    rsp.text)
        except:
            current_app.logger.fatal(traceback.format_exc())
            current_app.logger.error('do_notify, url: %s, request data: %s',
                                     order.notify_url, data)
            rst['msg'] = "通知失败,HTTP网络异常"
            return rst

        if rsp.status_code != 200:
            current_app.logger.error(
                'do_notify, url: %s, request data: %s, response data: %s',
                order.notify_url, data, rsp.text)
            rst['msg'] = "通知失败,HTTP status_code非200:%s" % rsp.status_code
            return rst

        try:
            json_data = rsp.json()
        except:
            current_app.logger.error(
                'do_notify, url: %s, request data: %s, response data: %s',
                order.notify_url, data, rsp.text)
            current_app.logger.fatal(traceback.format_exc())
            rst['msg'] = "通知失败,无法解析json数据"
            return rst

        if json_data['error_code'] != 200:
            rst['msg'] = "通知失败,error_code非200:%s" % json_data['error_code']
            current_app.logger.error(
                'do_notify, url: %s, request data: %s, response data: %s',
                order.notify_url, data, json_data)
            return rst

        # 更新订单通知完成
        if order.deliver != DeliverStateEnum.DONE:
            order, ref_id = OrderUpdateCtl.update_order_event(
                order_id=order.order_id,
                uid=order.uid,
                merchant=order.merchant,
                deliver=DeliverStateEnum.DONE,
                op_account=op_account,
                comment=comment,
            )
            if not order:
                rst['msg'] = '订单更新失败, 请研发检查错误日志, sys_tx_id: %s' % (
                    order.sys_tx_id, )
                current_app.logger.fatal(rst['msg'])
                return rst

        rst['msg'] = "通知成功"
        return rst
コード例 #21
0
ファイル: zhuanyifu_pay.py プロジェクト: LyanJin/check-pay
    def post(self):
        """
        专一付代付回调
        :return:
        """
        if not EnvironEnum.is_local_evn(current_app.config['FLASK_ENV']):
            # 无论如何都记录一条log
            current_app.logger.info(
                'zhuanyifu withdraw callback, ip: %s, data: %s, headers: %s',
                IpKit.get_remote_ip(), request.json, request.headers)

        event = request.headers.get('ChinaRailway-Event')
        signature = request.headers.get('ChinaRailway-Signature')

        form, error = ZhuanYeFuWithdrawForm().request_validate()
        if error:
            current_app.logger.fatal('msg: %s, data: %s', error.message,
                                     request.args)
            return BaseResponse('FAIlURE')

        pp = signature.split('.')

        if event != "Pay.Succeeded":
            return ResponseSuccess(code=500).as_response()

        # 交易ID
        tx_id = form.order.data
        fee = Decimal(form.fee.data)
        order = WithdrawTransactionCtl.get_order(tx_id)
        if not order:
            return ResponseSuccess(
                code=500, message='curr order no found').as_response()

        curr_status = order.state
        if curr_status != OrderStateEnum.DEALING:
            return ResponseSuccess(
                code=500,
                message='curr order status must be DEALING').as_response()

        print(order.channel_id, form.order.data, order.merchant,
              order.create_time, order.order_id, order.uid)

        channel_config = ProxyChannelConfig.query_by_channel_id(
            order.channel_id)
        channel_cost = FeeCalculator.calc_cost(order.amount,
                                               channel_config.fee_type,
                                               channel_config.fee)
        if fee != channel_cost:
            current_app.logger.error(
                "ZYF withdraw fee info order_id:{}, channel_fee: {}, channel_cost:{}"
                .format(order.order_id, fee, channel_cost))

        try:
            flag = CryptoKit.rsa_verify(
                pp[1], pp[0],
                channel_config.channel_enum.conf['plat_public_key'])
            if flag != True:
                return ResponseSuccess(code=500, message='签名错误').as_response()
        except Exception as e:
            return ResponseSuccess(code=500).as_response()

        # 代付金额
        tx_amount = Decimal(form.amount.data)
        # 代付费率
        fee = Decimal(form.fee.data)
        # 通道订单号
        transaction = form.transaction.data
        client_ip = form.client_ip.data
        status = form.status.data

        if str(status) == "1":
            """
            修改订单状态, 记录代付费率
            """
            if not WithdrawTransactionCtl.order_success(order, tx_amount):
                return ResponseSuccess(code=500).as_response()

        elif str(status) == "2":
            """
            代付订单失败, 
            1.给用户退款,给商户退款+手续费
            2. 修改订单状态 
            """
            # order = WithdrawTransactionCtl.get_order(merchant, order_id)
            if not WithdrawTransactionCtl.order_fail(order):
                return ResponseSuccess(code=500).as_response()

        return ResponseSuccess(code=204).as_response()