2022Flink大数据比赛项目-焦点科技大数据编程大赛

news2024/12/28 20:17:01

文章目录

  • 0.数据获取
  • 1.需求概要
  • 2.数据标准
    • 2.1.输入数据格式
    • 2.2.输出数据格式
    • 2.3.数据主键及关系
  • 3.表详细
    • 1.order_info
    • 2.bill_info
    • 3.bill_item
    • 4.ord_pay
    • 5.ord_pay_log
    • 6.pay_method
    • 7.pay_bank_card
  • 4.开发工具、语言版本、工具版本
  • 5.赛题解答
    • 数据分流
    • 任务1
    • 任务2
    • 任务3
    • 小结
  • 附录

0.数据获取

链接: https://pan.baidu.com/s/1NlmbN1cX4K9jYbYQm-IJUw 提取码: qw12
本项目适合有一定flink经验的同学学习或者巩固基础、提升使用。

1.需求概要

在实际的市场交易中为了防范银行卡信息泄露,需要风控系统对存在所有用户操作进行监控,对存在潜在风险的行为进行及时告警。以下是具体风控规则:
规则1:单个用户在一天内,付款超过1万元
源数据:order_info
规则2:在绑卡操作中发现2个不同用户绑定了同一张银行卡;
源数据:pay_method,pay_bank_card
规则3:在付款过程中,发现单个用户在5分钟内使用了10张以上的银行卡付款;
源数据:全部7张表

2.数据标准

2.1.输入数据格式

实际环境下,各数据会以JSON格式组成,发送到Kafka的一个topic里;此次比赛提供了一个Source 文件用来模拟现实的数据生成。

2.2.输出数据格式

经过计算触发了风控规则告警的以JSON格式在控制台输出

字段名 字段英文名 数据类型 内容描述
风控规则ID risk_id String 触发告警的风控规则序号,如发现不同账户绑定了同一张银行卡时,规则ID输出”1“
风控描述 risk_msg String 触发规则内容描述,如:发现不同账户绑定了同一张银行卡时,内容可以为 “不同账户绑定了同一张银行卡!user_id:userId1, userId2,card_no:1234567890123”
买家用户ID b_user_id Array[String] 触发风控买家用户ID,可能有多个

例:{“risk_id”:“1”,“risk_msg”:“不同账户绑定了同一张银行卡!user_id:userId1, userId2;card_no:1234567890123”,“b_user_id”:[“12345678”, “987654321”]}

2.3.数据主键及关系

在这里插入图片描述

3.表详细

1.order_info

字段名 字段说明 字段类型 是否业务主键 备注
ORDER_ID 订单ID String PK
B_USER_ID 买家用户id String
TOTAL_PAY 支付金额 Double
ORD_STATUS 订单状态 String 1-未支付 2-已支付 3-待发货 4-配送中 5-已完成 6-未支付已关闭
ADDER_NO 添加人id String
ADDER_NAME 添加人姓名 String
ADD_TIME 添加时间 Timestamp
UPDATER_NO 更新人id String
UPDATER_NAME 更新人姓名 String
UPDATE_TIME 更新时间 Timestamp

2.bill_info

字段名 字段说明 字段类型 是否业务主键 备注
BILL_ID 账单ID String PK
S_USER_ID 卖家用户ID String
B_USER_ID 买家用户ID String
ORDER_ID 关联的订单ID String 商品订单ORDER_INFO、平台服务订单SER_ORD_PF、收费计划订单PRICE_PLAN_ORD
ADDER_NO 添加人编号 String
ADDER_NAME 添加人姓名 String
ADD_TIME 添加时间 Timestamp
UPDATER_NO 更新人编号 String
UPDATER_NAME 更新人姓名 String
UPDATE_TIME 更新时间 Timestamp

3.bill_item

字段名 字段说明 字段类型 是否业务主键 备注
BILL_ITEM_ID 账单明细ID String PK
BILL_ID 账单ID String
ORD_PAY_ID 支付订单号 String
ORD_PAY_BATCH_ID 支付批次号 String
ADDER_NO 添加人编号 String
ADDER_NAME 添加人姓名 String
ADD_TIME 添加时间 Timestamp
UPDATER_NO 更新人编号 String
UPDATER_NAME 更新人姓名 String
UPDATE_TIME 更新时间 Timestamp

4.ord_pay

字段名 字段说明 字段类型 是否业务主键 备注
ORD_PAY_ID 主键 String PK
ORD_PAY_BATCH_ID 订单给的批次号 String 表 ORD_PAY_BATCH表的主键
B_USER_ID 买家的编号 String ORD_INFO表的B_USER_ID
PAY_METHOD_ID 支付方式id String 关联PAY_METHOD表主键
ADDER_NO 添加人编号 String
ADDER_NAME 添加人姓名 String
ADD_TIME 添加时间 Timestamp
UPDATER_NO 修改人编号 String
UPDATER_NAME 修改人姓名 String
UPDATE_TIME 修改时间 Timestamp

5.ord_pay_log

字段名 字段说明 字段类型 是否业务主键 备注
ORD_PAY_LOG_ID 主键 String PK
ORD_PAY_ID ORD_PAY 表主键 String 表ORD_PAY 表主键
ORD_PAY_BATCH_ID 订单给的批次号 String 表 ORD_PAY_BATCH表的主键
B_USER_ID 买家的编号 String ORD_INFO表的B_USER_ID
PAY_METHOD_ID 支付方式id String 关联PAY_METHOD表主键
ADDER_NO 添加人编号 String
ADDER_NAME 添加人姓名 String
ADD_TIME 添加时间 Timestamp
UPDATER_NO 修改人编号 String
UPDATER_NAME 修改人姓名 String
UPDATE_TIME 修改时间 Timestamp

6.pay_method

字段名 字段说明 字段类型 是否业务主键 备注
PAY_METHOD_ID 支付方式id String PK
PAY_TYPE_FLAG 支付种类标识 String 0 卡
PAY_RELATE_ID 支付方式id(卡或账户id) String 关联PAY_BANK_CARD的主键
B_USER_ID 用户ID,USER_INFO表的PK String
ADDER_NO 添加人编号 String
ADDER_NAME 添加人姓名 String
ADD_TIME 添加时间 Timestamp
UPDATER_NO 修改人编号 String
UPDATER_NAME 修改人姓名 String
UPDATE_TIME 修改时间 Timestamp

7.pay_bank_card

字段名 字段说明 字段类型 是否业务主键 备注
PAY_BANK_CARD_ID 主键 PK String PK
B_USER_ID 用户id String
CARD_NO 用户填写的银行卡号 String
ADDER_NO 添加人编号 String
ADDER_NAME 添加人姓名 String
ADD_TIME 添加时间 Timestamp
UPDATER_NO 修改人编号 String
UPDATER_NAME 修改人姓名 String
UPDATE_TIME 修改时间 Timestamp

4.开发工具、语言版本、工具版本

IDE:idea
scala sdk 2.12.11
java jdk 1.8
flink 1.13.0

5.赛题解答

以下解答,只是我个人的一些解答方案,仅供参考。如果你有好的建议,可以在评论区告诉我。
相应的POJO类见6附录

数据分流

将表进行整理后得到如下有用信息

  表               字段
   order_info       ORDER_ID,B_USER_ID,TOTAL_PAY,ADD_TIME
   bill_info        BILL_ID,ORDER_ID
   bill_item        BILL_ID,ORD_PAY_ID
   order_pay        ORD_PAY_ID,PAY_METHOD_ID
   pay_method       PAY_METHOD_ID,PAY_RELATE_ID
   pay_bank_card    PAY_BANK_CARD_ID,B_USER_ID,CARD_NO

数据分流,将多信息流从发送流中分离出来。

 		//支付银行卡流(pay_method,pay_bank_card)
        OutputTag<PayCard> payCardOutputTag = new OutputTag<PayCard>("paycard") {};
        //订单流
        OutputTag<BillInfo> billInfoOutputTag = new OutputTag<BillInfo>("billinfo") {};
        //订单明细流
        OutputTag<BillItem> billItemOutputTag = new OutputTag<BillItem>("billitem") {};
        //订单支付流
        OutputTag<OrderPay> orderPayOutputTag = new OutputTag<OrderPay>("orderpay") {};
        //订单支付日志流
        OutputTag<OrderPayLog> orderPayLogOutputTag = new OutputTag<OrderPayLog>("orderpaylog") {};
        //支付主流costStream(orderId,bUserId,totalPay,addTime)
        SingleOutputStreamOperator<OrderInfo> costStream = inputStream.process(
                new ProcessFunction<String, OrderInfo>()  {
                    @Override
                    public void processElement(String s, Context context, Collector<OrderInfo> collector) throws Exception {
                        JSONObject jsonObject1 = JSONObject.parseObject(s);
                        String orderInfo = jsonObject1.getString("order_info");
                        String payMethod = jsonObject1.getString("pay_method");
                        String payBankCard = jsonObject1.getString("pay_bank_card");
                        String billInfo = jsonObject1.getString("bill_info");
                        String billItem = jsonObject1.getString("bill_item");
                        String orderPay = jsonObject1.getString("ord_pay");
                        String orderPayLog = jsonObject1.getString("ord_pay_log");

                        if (null != orderInfo) {
                            JSONObject orderJson = JSONObject.parseObject(orderInfo);
                            Integer status=orderJson.getInteger("ORD_STATUS");
                            //只需要已支付状态的数据
                            if(status==2) {
                                collector.collect(new OrderInfo(orderJson.getString("ORDER_ID"), orderJson.getString("B_USER_ID")
                                        , orderJson.getDouble("TOTAL_PAY"), orderJson.getString("ADD_TIME")));
                            }
                        } else if (null != payMethod) {
                            JSONObject payCardJson = JSONObject.parseObject(payMethod);
                            String payMethodId = payCardJson.getString("PAY_METHOD_ID");
                            String payBankCardId = payCardJson.getString("PAY_RELATE_ID");
                            //等于0,则为卡.如果对应的支付方式是卡,那么我们将cardNO加入支付银行卡流中
                            if(payCardJson.getInteger("PAY_TYPE_FLAG")==0){
                                if(checkPayIsCard.containsKey(payBankCardId)) {
                                    //设置payMethodId
                                    PayCard payCard = checkPayIsCard.get(payBankCardId);
                                    payCard.setPayMethodId(payMethodId);
                                    //加入payCard流
                                    context.output(payCardOutputTag,payCard);
                                    //清除该支付状态
                                    checkPayIsCard.remove(payBankCardId);
                                }
                            }else {
                                //清除该支付状态
                                checkPayIsCard.remove(payBankCardId);
                            }
                        }else if(null != payBankCard){//可以改为和payMethodStream的双流join.但是注意时间延迟。多流join时需要注意等待时间等等
                            JSONObject payCard = JSONObject.parseObject(payBankCard);
                            String payBankCardId = payCard.getString("PAY_BANK_CARD_ID");
                            checkPayIsCard.put(payBankCardId, new PayCard("",payCard.getString("B_USER_ID"), payCard.getString("CARD_NO")));
                        }else if(null!=billInfo){
                            JSONObject billJson = JSONObject.parseObject(billInfo);
                            context.output(billInfoOutputTag,new BillInfo(billJson.getString("BILL_ID"),billJson.getString("ORDER_ID")));
                        }else if(null!=billItem){
                            JSONObject billItemJson = JSONObject.parseObject(billItem);
                            context.output(billItemOutputTag,new BillItem(billItemJson.getString("BILL_ID"),billItemJson.getString("ORD_PAY_ID")));
                        }else if(null!=orderPay){
                            JSONObject orderPayJson = JSONObject.parseObject(orderPay);
                            context.output(orderPayOutputTag,new OrderPay(orderPayJson.getString("ORD_PAY_ID"),orderPayJson.getString("PAY_METHOD_ID")));
                        }else if(null!=orderPayLog){
                            JSONObject orderPayLogJson = JSONObject.parseObject(orderPayLog);
                            context.output(orderPayOutputTag,new OrderPay(orderPayLogJson.getString("ORD_PAY_ID"),orderPayLogJson.getString("PAY_METHOD_ID")));
                        }
                    }
                });

        //获取支付银行卡流
        DataStream<PayCard> payCardStream = costStream.getSideOutput(payCardOutputTag);
        //获取订单流
        DataStream<BillInfo> billInfoStream = costStream.getSideOutput(billInfoOutputTag);
        //获取订单明细流
        DataStream<BillItem> billItemStream = costStream.getSideOutput(billItemOutputTag);
        //获取订单支付流
        DataStream<OrderPay> orderPayStream = costStream.getSideOutput(orderPayOutputTag);
        //获取订单支付日志流
        DataStream<OrderPayLog> orderPayLogStream = costStream.getSideOutput(orderPayLogOutputTag);

其中也可以换成filter操作对数据流一个一个的过滤来得到分流。

任务1

单个用户在一天内,付款超过1万元
其中costStream是已经支付状态的数据流

SingleOutputStreamOperator<DangerousMessage> dangerousMessage1Stream = costStream
                .keyBy("bUserId")
                .process(new KeyedProcessFunction<Tuple, OrderInfo, DangerousMessage>() {
            private ValueState<Double> costState;
            private ValueState<String> timeState;

            @Override
            public void open(Configuration parameters) throws Exception {
                costState = getRuntimeContext().getState(new ValueStateDescriptor<Double>("cost-value", Double.class));
                timeState = getRuntimeContext().getState(new ValueStateDescriptor< String>("time-value",  String.class));
            }

            @Override
            public void processElement(OrderInfo orderInfo, Context ctx, Collector<DangerousMessage> collector) throws Exception {
                String buyUser = orderInfo.getbUserId();
                Double cost = orderInfo.gettotalPay();
                String now = orderInfo.getaddTime();
                //只看支付大于0的账单,避免重复报警
                if (cost!=0.0) {
                    if (costState.value() == null) {
                        costState.update(cost);
                        timeState.update(now);
                        if (cost > costLimit) {
                            collector.collect(new DangerousMessage("1", "0", buyUser,cost,now));
                        }
                    }else {
                        String start = timeState.value();
                        Double lastCost=costState.value();
                        SimpleDateFormat fmt = new SimpleDateFormat("yyyyMMdd");
                        //如果为同一天
                        if (fmt.parse(start).equals(fmt.parse(now))) {
                            Double costSum = cost + lastCost;
                            costState.update(costSum);
                            if (costSum > costLimit) {
                                /*一天内出现多次总和超过1万,应该多次警报,不清空状态(比如在一段时间,
                                在1万以上还持续增加,则可认为非常高风险,我们可能需要打电话等方式提醒用户,
                                所以这里选择不清空状态)*/
                                collector.collect(new DangerousMessage("1", "0", buyUser,costSum,now));
                            }
                        } else {
                            costState.update(cost);
                            timeState.update(now);
                        }
                    }
                }
            }

            @Override
            public void close() throws Exception {
                costState.clear();
                timeState.clear();
            }
        });

任务2

在绑卡操作中发现2个不同用户绑定了同一张银行卡
其中payCardStream是pay_method和ord_pay的关联流

SingleOutputStreamOperator<DangerousMessage> dangerousMessage2Stream = payCardStream
                .keyBy("cardNo")
                .process(new KeyedProcessFunction<Tuple, PayCard, DangerousMessage>() {
                    private ListState<String> payCardState;

                    @Override
                    public void open(Configuration parameters) throws Exception {
                        payCardState = getRuntimeContext().getListState(new ListStateDescriptor<String>("pay-value", String.class));
                    }

                    @Override
                    public void processElement(PayCard payCard, Context ctx, Collector<DangerousMessage> collector) throws Exception {
                        String payCardUser = payCard.getbUserId();
                        String cardNo = payCard.getcardNo();
                        if(isEmpty(payCardState.get())){
                            payCardState.add(payCardUser);
                        }else{
                            Iterable<String> users = payCardState.get();
                            boolean flag=false;
                            for (String user:users) {
                                if(payCardUser.equals(user)){
                                    flag=true;
                                    break;
                                }
                            }
                            if(!flag) {
                                String conflictUsers ="";
                                for (String user:users) {
                                    conflictUsers+="\""+user+"\",";
                                }
                                conflictUsers+="\""+payCardUser+"\"";
                                payCardState.add(payCardUser);
                                collector.collect(new DangerousMessage("2", cardNo,conflictUsers,0.0,""));
                            }
                        }
                }

                @Override
                public void close() throws Exception {
                    payCardState.clear();
                }
            });

任务3

在付款过程中,发现单个用户在5分钟内使用了10张以上的银行卡付款
使用table sql进行多流join操作

		//使用table sql进行多流join
        Table orderInfoTable = tableEnv.fromDataStream(costStream);
        Table payCardTable = tableEnv.fromDataStream(payCardStream);
        Table billInfoTable = tableEnv.fromDataStream(billInfoStream);
        Table billItemTable = tableEnv.fromDataStream(billItemStream);
        Table orderPayTable = tableEnv.fromDataStream(orderPayStream);
        Table orderPayLogTable = tableEnv.fromDataStream(orderPayLogStream);
        tableEnv.createTemporaryView("order_info",orderInfoTable );
        tableEnv.createTemporaryView("pay_card",payCardTable );
        tableEnv.createTemporaryView("bill_info",billInfoTable );
        tableEnv.createTemporaryView("bill_item",billItemTable );
        tableEnv.createTemporaryView("order_pay",orderPayTable );
        tableEnv.createTemporaryView("order_pay_log",orderPayLogTable );
        //多流join,这里需要注意不能再直接使用costStream来做join操作,而是orderinfo的支付过程和已支付的所有数据。最好的做法是将costStream流的筛选工作直接放到任务一中,而非放到最开始的分流操作中。
        String sql="select order_info.bUserId bUserId,order_info.addTime addTime,pay_card.cardNo cardNo from order_info " +
                                        "join bill_info on order_info.orderId=bill_info.orderId " +
                                        "join bill_item on bill_info.billId=bill_item.billId " +
                                        "join order_pay on bill_item.orderPayId=order_pay.orderPayId " +
                                        "join pay_card on  order_pay.payMethodId=pay_card.payMethodId  ";

        Table resultTable = tableEnv.sqlQuery(sql);
        DataStream<Tuple2<Boolean, OverPayCard>> joinPayCardStream = tableEnv.toRetractStream(resultTable, OverPayCard.class);
//        joinPayCardStream.print("join");

        SingleOutputStreamOperator<DangerousMessage> dangerousMessage3Stream = joinPayCardStream.map(line -> {
            return line.f1;
        }).assignTimestampsAndWatermarks(new AscendingTimestampExtractor<OverPayCard>() {
            @Override
            public long extractAscendingTimestamp(OverPayCard o) {
                String addTime = o.addTime;
                Calendar c = Calendar.getInstance();
                try {
                    c.setTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(addTime));
                } catch (ParseException e) {
                    e.printStackTrace();
                }
                return c.getTimeInMillis();
            }
        })
                .keyBy("bUserId")
                //滑动窗口设置太小报风险的情况会大量重复,所以这里设置1 minute
                .window(SlidingEventTimeWindows.of(Time.minutes(windowSizeLimit), Time.minutes(windowSlideSizeLimit)))
                .aggregate(new MyaggregateFunction(), new CountBankCardsFunction());

聚合操作类:

 public static class MyaggregateFunction implements AggregateFunction<OverPayCard, Set<String>, Set<String>> {
        @Override
        public Set<String> createAccumulator() {
            return new HashSet<>();
        }

        @Override
        public Set<String> add(OverPayCard overPayCard, Set<String> strings) {
            strings.add(overPayCard.cardNo);
            return strings;
        }

        @Override
        public Set<String> getResult(Set<String> strings) {
            return strings;
        }

        @Override
        public Set<String> merge(Set<String> strings, Set<String> acc1) {
            strings.addAll(acc1);
            return strings;
        }
    }

    public static class CountBankCardsFunction implements WindowFunction<Set<String>, DangerousMessage, Tuple, TimeWindow> {
        @Override
        public void apply(Tuple tuple, TimeWindow window, Iterable<Set<String>> input, Collector<DangerousMessage> out) throws Exception {
            String bUserId=tuple.getField(0);
            Integer count=input.iterator().next().size();
            if(count>cardLimit){//应该改为count>=cardLimit
                String bankCards ="";
                Integer l=0;
                for(String card:input.iterator().next()){
                    bankCards+="\""+card+"\"";
                    l++;
                    if(l<count){
                        bankCards+=',';
                    }
                }
                out.collect(new DangerousMessage("3",bankCards,bUserId,0.0,""));
            }
        }
    }

小结

问题一、二的问题不是很大,不过很多地方还是可以继续优化的。问题三,解答存在一些问题,比如这里其实不能直接使用第一问中的costream作为其中的一个join流,因为第一问中要求的是付款1万元,所以需要使用已支付状态的数据。但是第三问中,题目提示“在付款过程中”,这句话表明只要有开始使用卡就要算在其内,而不只是已支付状态。另外这里和主办方工程师沟通,这里还有个问题是10张以上银行卡是包括10张的,所以count>cardLimit需要改为>=
当上述两个问题改过之后,能够输出一些数据,但是不全,可能会存在多流join等待时间(因为这些流并非同时到达的。这方面我了解比较少,所以欢迎大家给出自己的见解)的相关问题。

附录

package riskAssessment.Bean;

public class BillInfo {
    public  String billId;
    public  String orderId;

    public BillInfo() {
    }

    public BillInfo(String billId, String orderId) {
        this.billId = billId;
        this.orderId = orderId;
    }

    public String getBillId() {
        return billId;
    }

    public void setBillId(String billId) {
        this.billId = billId;
    }

    public String getOrderId() {
        return orderId;
    }

    public void setOrderId(String orderId) {
        this.orderId = orderId;
    }

    @Override
    public String toString() {
        return "BillInfo{" +
                "billId='" + billId + '\'' +
                ", orderId='" + orderId + '\'' +
                '}';
    }
}

package riskAssessment.Bean;

public class BillItem {
    public String billId;
    public String orderPayId;

    public BillItem() {
    }

    public BillItem(String billId, String orderPayId) {
        this.billId = billId;
        this.orderPayId = orderPayId;
    }

    public String getBillId() {
        return billId;
    }

    public void setBillId(String billId) {
        this.billId = billId;
    }

    public String getOrderPayId() {
        return orderPayId;
    }

    public void setOrderPayId(String orderPayId) {
        this.orderPayId = orderPayId;
    }

    @Override
    public String toString() {
        return "BillItem{" +
                "billId='" + billId + '\'' +
                ", orderPayId='" + orderPayId + '\'' +
                '}';
    }
}

package riskAssessment.Bean;


public class DangerousMessage {
    public DangerousMessage() {
    }
    public String risk_id;
    public String card_no;
    public String b_user_id;
    public Double totoal_pay;
    public String time;

    public DangerousMessage(String risk_id, String card_no, String b_user_id, Double totoal_pay, String time) {
        this.risk_id = risk_id;
        this.card_no = card_no;
        this.b_user_id = b_user_id;
        this.totoal_pay = totoal_pay;
        this.time = time;
    }

    public Double getTotoal_pay() {
        return totoal_pay;
    }

    public void setTotoal_pay(Double totoal_pay) {
        this.totoal_pay = totoal_pay;
    }

    public String getTime() {
        return time;
    }

    public void setTime(String time) {
        this.time = time;
    }

    public String getRisk_id() {
        return risk_id;
    }

    public void setRisk_id(String risk_id) {
        this.risk_id = risk_id;
    }

    public String getCard_no() {
        return card_no;
    }

    public void setCard_no(String card_no) {
        this.card_no = card_no;
    }

    public String getB_user_id() {
        return b_user_id;
    }

    public void setB_user_id(String b_user_id) {
        this.b_user_id = b_user_id;
    }

    @Override
    public String toString() {
        if(risk_id=="1"){
            return "{\"risk_id\":\"" + risk_id + "\"" +
                    ",\"risk_msg\":\"单个用户在一天内,付款超过1万元!" +"\""+
                    ",\"b_user_id\":\""+ b_user_id +"\""+
                    ",\"time\":\"" +time+"\"" +
                    ",\"total_pay\":\"" +totoal_pay.toString()+"\"" +
                    "}";
        }else if(risk_id=="2"){
            return "{\"risk_id\":\"" + risk_id + "\"" +
                    ",\"risk_msg\":\"不同账户绑定了同一张银行卡!"  + "\"" +
                    ",\"card_no\":\"" + card_no + '\"' +
                    ",\"b_user_id\":[" + b_user_id + "]}";
        }else{
            return "{\"risk_id\":\"" + risk_id + "\"" +
                    ",\"risk_msg\":\"单个用户在5分钟内使用了10张以上的银行卡付款!"  + "\"" +
                    ",\"b_user_id\":\"" + b_user_id+'\"'+
                    ",\"card_no\":[" + card_no  + "]}";
        }
    }
}

package riskAssessment.Bean;


public class OrderInfo{
    public String orderId;
    public String bUserId;
    public Double totalPay;
    public String addTime;

    public OrderInfo() {
    }

    public OrderInfo(String orderId, String bUserId, Double totalPay, String addTime) {
        this.orderId = orderId;
        this.bUserId = bUserId;
        this.totalPay = totalPay;
        this.addTime = addTime;
    }

    public String getorderId() {
        return orderId;
    }

    public void setorderId(String orderId) {
        this.orderId = orderId;
    }

    public String getbUserId() {
        return bUserId;
    }

    public void setbUserId(String bUserId) {
        this.bUserId = bUserId;
    }

    public Double gettotalPay() {
        return totalPay;
    }

    public void settotalPay(Double totalPay) {
        this.totalPay = totalPay;
    }

    public String getaddTime() {
        return addTime;
    }

    public void setaddTime(String addTime) {
        this.addTime = addTime;
    }

    @Override
    public String toString() {
        return "OrderInfo{" +
                "orderId='" + orderId + '\'' +
                ", bUserId='" + bUserId + '\'' +
                ", totalPay=" + totalPay +
                ", addTime=" + addTime +
                '}';
    }
}

package riskAssessment.Bean;

public class OrderPay {
    public String orderPayId;
    public String payMethodId;

    public OrderPay() {
    }

    public OrderPay(String orderPayId, String payMethodId) {
        this.orderPayId = orderPayId;
        this.payMethodId = payMethodId;
    }

    public String getOrderPayId() {
        return orderPayId;
    }

    public void setOrderPayId(String orderPayId) {
        this.orderPayId = orderPayId;
    }

    public String getPayMethodId() {
        return payMethodId;
    }

    public void setPayMethodId(String payMethodId) {
        this.payMethodId = payMethodId;
    }

    @Override
    public String toString() {
        return "OrderPay{" +
                "orderPayId='" + orderPayId + '\'' +
                ", payMethodId='" + payMethodId + '\'' +
                '}';
    }
}

package riskAssessment.Bean;

public class OrderPayLog {
    public String orderPayId;
    public String payMethodId;

    public OrderPayLog(String orderPayId, String payMethodId) {
        this.orderPayId = orderPayId;
        this.payMethodId = payMethodId;
    }

    public OrderPayLog() {
    }

    public String getOrderPayId() {
        return orderPayId;
    }

    public void setOrderPayId(String orderPayId) {
        this.orderPayId = orderPayId;
    }

    public String getPayMethodId() {
        return payMethodId;
    }

    public void setPayMethodId(String payMethodId) {
        this.payMethodId = payMethodId;
    }

    @Override
    public String toString() {
        return "OrderPayLog{" +
                "orderPayId='" + orderPayId + '\'' +
                ", payMethodId='" + payMethodId + '\'' +
                '}';
    }
}

package riskAssessment.Bean;

public class OverPayCard {
    public String bUserId;
    public String addTime;
    public String cardNo;

    public OverPayCard() {
    }

    public OverPayCard(String bUserId, String addTime, String cardNo) {
        this.bUserId = bUserId;
        this.addTime = addTime;
        this.cardNo = cardNo;
    }

    public String getbUserId() {
        return bUserId;
    }

    public void setbUserId(String bUserId) {
        this.bUserId = bUserId;
    }

    public String getAddTime() {
        return addTime;
    }

    public void setAddTime(String addTime) {
        this.addTime = addTime;
    }

    public String getCardNo() {
        return cardNo;
    }

    public void setCardNo(String cardNo) {
        this.cardNo = cardNo;
    }

    @Override
    public String toString() {
        return "OverPayCard{" +
                "bUserId='" + bUserId + '\'' +
                ", addTime=" + addTime +
                ", cardNo='" + cardNo + '\'' +
                '}';
    }
}

package riskAssessment.Bean;

public class PayCard {
    public String payMethodId;
    public String bUserId;
    public String cardNo;

    public PayCard() {
    }

    public String getPayMethodId() {
        return payMethodId;
    }

    public void setPayMethodId(String payMethodId) {
        this.payMethodId = payMethodId;
    }

    public String getCardNo() {
        return cardNo;
    }

    public void setCardNo(String cardNo) {
        this.cardNo = cardNo;
    }


    public String getbUserId() {
        return bUserId;
    }

    public void setbUserId(String bUserId) {
        this.bUserId = bUserId;
    }

    public String getcardNo() {
        return cardNo;
    }

    public void setcardNo(String cardNo) {
        this.cardNo = cardNo;
    }

    public PayCard(String payMethodId, String bUserId, String cardNo) {
        this.payMethodId = payMethodId;
        this.bUserId = bUserId;
        this.cardNo = cardNo;
    }

    @Override
    public String toString() {
        return "PayCard{" +
                "payMethodId='" + payMethodId + '\'' +
                ", bUserId='" + bUserId + '\'' +
                ", cardNo='" + cardNo + '\'' +
                '}';
    }
}

大家有任何问题都可以在评论区留言,我一定尽我所能解答。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/43263.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

股票详情接口是怎样开发的?

一般情况下&#xff0c;在量化市场中&#xff0c;投资者使用的辅助炒股软件就包括很多数据接口&#xff0c;特别是股票详情接口系统更为可见&#xff0c;不过在使用之前&#xff0c;也是需要提前了解清楚它的开发原理&#xff0c;以及使用规则等&#xff0c;那么它是怎样开发出…

麦芽糖-链霉亲和素maltose-Streptavidins链霉亲和素-PEG-麦芽糖

麦芽糖-链霉亲和素maltose-Streptavidins链霉亲和素-PEG-麦芽糖 中文名称&#xff1a;麦芽糖-链霉亲和素 英文名称&#xff1a;maltose-Streptavidins 别称&#xff1a;链霉亲和素修饰麦芽糖&#xff0c;链霉亲和素-麦芽糖 提供PEG接枝修饰麦芽糖&#xff0c;麦芽糖-聚…

易观千帆 | 2022年10月银行APP月活跃用户规模盘点

易观分析&#xff1a;易观千帆数据显示&#xff0c;10月手机银行服务应用活跃人数52285.79万&#xff0c;环比下降3.52%。手机银行服务应用月活规模经历了连续5个月的持续增长后&#xff0c;10月出现下降。 10月城商行手机银行服务应用活跃人数3565.56万&#xff0c;环比下降2…

线程的概念和创建【javaee初阶】

目录 一、认识线程 二、多线程程序 2.1 实现Java多线程程序 方法1 继承 Thread &#xff0c;重写run 方法2 实现 Runnable 接口 方法3 匿名内部类创建 Thread 子类对象 方法4 匿名内部类创建 Runnable 子类对象 方法5 lambda 表达式创建 Runnable 子类对象 三、多线程的…

Kamiya丨Kamiya艾美捷小鼠高敏CRP ELISA说明书

Kamiya艾美捷小鼠高敏CRP ELISA预期用途&#xff1a; 小鼠高敏CRP ELISA是一种高灵敏度的双位点酶联免疫分析&#xff08;ELISA&#xff09;定量测定小鼠生物样品中的C-反应蛋白&#xff08;CRP&#xff09;。仅供研究使用。 引言 急性期蛋白质是血浆蛋白质&#xff0c;其在感…

交互作用的深入剖析

1.原理说明 交互作用(Interaction effect)指两个或多个因素&#xff08;比如A因素和B因素&#xff09;对于某项&#xff08;比如身高&#xff09;的影响时&#xff0c;A因素和B因素各个水平之间是否存在着相互作用关系。比如A因素为性别&#xff0c;B因素为区域&#xff0c;男…

Springboot+vue+java幼儿园管理系统

开发语言&#xff1a;Java 框架&#xff1a;springboot 前端框架:vue.js JDK版本&#xff1a;JDK1.8 服务器&#xff1a;tomcat8 数据库&#xff1a;mysql 5.7 数据库工具&#xff1a;Navicat11 开发软件&#xff1a;eclipse/idea 目 录 第一章 绪 论 1 1.1背景及意义 1…

Android Qcom Sensor架构学习

Android Sensor Brief Flow Android Sensor Specific Flow ADSP SSC ADSP.VT.5.4.1/adsp_proc/ssc_api/pb/ ADSP.VT.5.4.1/adsp_proc/ssc/sensors ADSP.VT.5.4.1/adsp_proc/ssc/frameworksADSP Framework初始化的时候首先通过load image并初始化的静态加载方式register_static…

数据结构期末刷题

写在前面 此篇文章是在网络上搜集的题目&#xff0c;每一题都可能出现错误&#xff0c;如果各位大佬发现了错误&#xff0c;请在评论区回复一下&#xff0c;看到了就会改 树 根据遍历序列&#xff0c;画树&#xff0c;求另外一种遍历序列 以下中序遍历简称为中序&#xff0…

电路设计 > eMMC应用和PCB layout布局布线参考设计

目录 eMMC介绍 eMMC信号大体介绍 EMMC4.5和5.0封装和兼容性对比 EMMC5.0和5.1封装和兼容性对比 PCB Layout建议 PCB layout参考设计 参考设计1 参考设计2 参考设计3 参考设计4 参考设计5​​​​​​​ eMMC介绍 主要针对现在主流的eMMC5.0以及以上版本。 eMMC信号…

centos 7 安装node-red

一、安装nodejs https://nodejs.org/en/download/ 将其上传到服务器/usr/local/src目录下 下载之后是xz文件&#xff0c;解压xz文件 xz -d node-v16.18.1-linux-x64.tar.xz 解压之后会多一个tar文件&#xff0c;解压tar文件 tar -vxf node-v16.18.1-linux-x64.tar mkdir …

Navicat远程连接MySQL服务器

文章目录一、准备二、配置Navicat允许远程连接MySQL数据库1、使用Navicat直接连接MySQL2、使用 Navicat 通过 SSH 远程登录后再本地方式连接 MySQL3、查看连接为什么使用ssh登录1.便捷性Navicat:数据库可视化工具 一、准备 一台开启 SSH 登录的 Ubuntu 服务器 或 已开启远程登…

PyTorch学习笔记-神经网络Torch.NN基本骨架的使用及卷积原理

1. torch.nn.Module介绍 torch.nn 能够帮助我们更优雅地训练神经网络&#xff0c;使神经网络代码更加简洁和灵活。官方文档&#xff1a;Torch.NN。 在文档中可以看到第一块内容叫做 Container&#xff08;容器&#xff09;&#xff0c;这就相当于神经网络的骨架&#xff0c;C…

U2Net——U-Net套U-Net——套娃式图像分割算法

U2Net1 相关参考2 U2−NetU^2-NetU2−Net 网络结构3 网络代码和测试1 相关参考 论文名称&#xff1a; U2-Net: Goging Deeper with Nested U-Structure for Salient Object Detetion 论文地址&#xff1a; https://arxiv.org/abs/2005.09007 官方源码&#xff1a; https://git…

机器视觉_工业相机及相关配件选型

文章目录工业相机一、 概述二、 相机参数1. 传感器芯片1.1. CCD&CMOS1.2. CCD1.3. CMOS1.4. 靶面1.5. 传感器芯片选型2. 黑白or彩色3. 帧数⭐4. 接口类型4.1. POE供电三、相关硬件1. 镜头1.1. 焦距2. 光源3. 控制器4. 工控机5. 线缆6. 交换机四、参考工业相机 一、 概述 …

基于FPGA的呼叫设备verilog开发

欢迎订阅《FPGA学习入门100例教程》、《MATLAB学习入门100例教程》 目录 一、理论基础 二、核心程序 三、测试结果 一、理论基础 随着集成电路技术的发展&#xff0c;电子设计自动化&#xff08;EDA&#xff09;逐渐成为重要的设计手段&#xff0c;已经广泛应用于模拟与数字…

Vite+Vue3+TS项目创建及基本环境搭建

1.vite项目搭建 可以按照vite官网操作&#xff1a;https://cn.vitejs.dev/guide/features.html#typescript npm create vitelatest自定义template模板 vscode-文件-首选项-配置用户代码片段-vue.json 添加如下代码即可快速创建vue模板 {"template": {"pref…

做好供应商关系管理,让企业采购交易更简单

大家都知道&#xff0c;企业想要采购到物美价廉的产品与服务&#xff0c;就必须做好相应的供应商管理工作。而其中供应商关系管理是采购过程中至关重要的环节&#xff0c;也是能让企业有效地与供应商之间保持良好关系&#xff0c;这不仅有利于促进采供双方共赢&#xff0c;而且…

Netty入门--传统IO与NIO详解

文章目录IO模型传统阻塞的IO模型--BIOClient端案例Server端案例NIO&#xff08;Java non-blocking IO&#xff09;非阻塞IONIO的三大组件 Channel Selector BufferBuffer&#xff08;缓冲区&#xff09;Channel&#xff08;通道&#xff09;Channe的分类&#xff0c;与Buffer的…

【Spring(六)】使用篇:AOP在开发中的使用

有关Spring的所有文章都收录于我的专栏&#xff1a;&#x1f449;Spring&#x1f448; 目录 一、前言 二、演示 三、切面类中声明通知方法 四、使用 相关文章 【Spring&#xff08;一&#xff09;】如何获取对象&#xff08;Bean&#xff09;【Spring&#xff08;一&#xff09…