支付

一、后台模块梳理

后台登录

访问/admin/login.jsp,进行登录,修改login.jsp的访问路径

创建AdminController,映射路径为:/admin/auser, login方法中处理登录功能;并存储凭证

登录成功后,跳转到/admin/admin.jsp页面

public String adminLogin(HttpServletRequest request, HttpServletResponse response){
    //1. 获取参数
    String username = request.getParameter("username");
    String password = request.getParameter("password");

    //2. 在业务层处理
    User user = userService.login(username,password);
    if(user!=null){
        if(user.getU_role()==0){  //非管理员
            request.setAttribute("msg","非管理员用户不能登录");
        }else{ //管理员账户
            request.getSession().setAttribute(ConstUtils.ADMIN,user);
            return ConstUtils.FOR+"/admin/admin.jsp";
        }
    }else{
        request.setAttribute("msg","管理员账户或密码出错");
    }
    return ConstUtils.FOR+"/admin/login.jsp";

}

展示用户信息

在admin.jsp页面中点击”会员管理“,在userList.jsp中,发ajax请求,在后端将集合数据转JSON回传到前端

public String show(HttpServletRequest request,HttpServletResponse response){
    //1.通过业务层调用方法,返回user集合
    List<User> list = userService.showUsers();
    //2. 再将集合转json数据,回传到前端
    return new Gson().toJson(list);
}

删除与搜索

删除功能:

在userList.jsp页面中,点击”删除“,根据uid删除指定的记录;删除完成后,跳转到展示页面

public String delete(HttpServletRequest request, HttpServletResponse response){
    String id = request.getParameter("id");
    int res = userService.deleteById(id);
    System.out.println("删除:"+id);
    return show(request,response);
}

搜索功能:

在userList.jsp页面中,传用户名,在后端模糊匹配用户名或性别,进行查询

public String search(HttpServletRequest request, HttpServletResponse response){
    String username = request.getParameter("username");
    String gender = request.getParameter("gender");
    System.out.println("username-->"+username+";gender-->"+gender);

    if(username.equals("")&&gender.equals("")){ //如果都没有取到值,则显示所有
        return show(request,response); //查所有
    }else{
        List<User> list = userService.showUsers(username,gender);
        return new Gson().toJson(list);
    }
}
public List<User> selectAll(String username, String gender) throws SQLException {
    String value = "";
    boolean flag = false;
    if(!username.equals("")){  //用户名的匹配
        value = "u_name like '%"+username+"%'";
        flag = true;
    }
    if(!gender.equals("")){
        if(flag){
            value += "and u_sex = '"+gender+"'";
        }else{
            value += "u_sex = '"+gender+"'";
        }
    }
    String sql = "select * from user where "+value;  
    System.out.println("sql--->"+sql);
    return runner.query(sql,new BeanListHandler<>(User.class));
}

权限管理

权限管理的必要性: 如果没有权限管理,那么账户没有登录,也可以访问到后端重要的服务器资源中,有安全隐患问题。

具体操作:进入后端的访问,都需要在过滤器中进行拦截检查:如果有登录凭证,或login.jsp或后端访问需要放行,其余的拦截住

@WebFilter("/admin/*")
public class AdminLoginFilter implements Filter {
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;

        //判断是否有登录凭证, 如果有,则放行
        User user = (User) request.getSession().getAttribute(ConstUtils.ADMIN);
        if(user!=null){
            filterChain.doFilter(request,response);  //有凭证则放行
        }else{
            String uri = request.getRequestURI();  //获取访问的部分路径

            String type = request.getParameter("action");
            System.out.println("uri--->"+uri+"; action-->"+type);
            //如果是后台的login登录和login.jsp,需要放行
            if(uri.endsWith("login.jsp")||(uri.endsWith("auser")&&"adminLogin".equals(type))){
                filterChain.doFilter(request,response);  //放行
            }else{
                response.sendRedirect(request.getContextPath()+"/admin/login.jsp");
            }
        }
    }
}

二、订单详情

前端处理

点击"订单详情"后,需要从后端带回展示数据;查看orderDetail.jsp页面中需要展示的数据

从页面中可看出,需要返回订单对象,里面包含了地址属性及详情属性集合;订单详情中包含了商品。

<tr>
    <td>订单编号:</td>
    <td>${od.o_id}</td>
    <td>订单时间:</td>
    <td>${od.o_time}</td>
</tr>
<tr>
    <td>收件人:</td>
    <td>${od.addr.a_name}</td>
    <td>联系电话:</td>
    <td>${od.addr.a_phone}</td>
</tr>
...

后端展示

实体类中的属性包含:

public class Orders {
  //... 
  //订单中包含地址和订单集合属性
  private Address addr; //每个订单中由一条地址信息
  private List<Item> list;  //订单里面包含详情集合
}
public class Item {
  //...
  private Product goods;  //详情中包含商品属性
}

控制层处理:

//订单详情展示
public String showDetail(HttpServletRequest request, HttpServletResponse response){
    String oid = request.getParameter("oid"); //获取OID
    Orders orders = orderService.showDetail(oid); //展示订单与详情
    request.setAttribute("od",orders);
    return ConstUtils.FOR+"/orderDetail.jsp";
}

业务层处理:

public Orders showDetail(String oid) {
    Orders orders = null;
    try{
        //1.根据oid获取到订单对象
        orders = orderDao.selectOdByOid(oid);
        //2.根据oid获取到详情集合
        List<Item> list = orderDao.selectItemsByOid(oid);
        //3.订单对象中设置详情集合
        orders.setList(list);
    }catch (Exception e){
        e.printStackTrace();
    }
    return orders;
}

DAO层的处理:

@Override
public Orders selectOdByOid(String oid) throws SQLException, InvocationTargetException, IllegalAccessException {
    //查询订单和地址的关联
    String sql = "select * from orders o inner join address a on " +
        "o.a_id=a.a_id and o.o_id=?";
    Map<String, Object> map = runner.query(sql, new MapHandler(), oid);
    Orders o = new Orders();
    BeanUtils.populate(o,map);  //值的注入
    Address a = new Address();
    BeanUtils.populate(a,map);
    o.setAddr(a);  //将地址放入订单对象中
    return o;
}
@Override
public List<Item> selectItemsByOid(String oid) throws SQLException, InvocationTargetException, IllegalAccessException {
    //订单详情与商品的关联
    String sql = "select * from item i inner join product p " +
        "on i.p_id=p.p_id and i.o_id=?";
    List<Map<String, Object>> query = runner.query(sql, new MapListHandler(), oid);
    List<Item> items = new ArrayList<>();
    for(Map<String, Object> map:query){
        Item item = new Item();
        BeanUtils.populate(item,map);
        Product product = new Product();
        BeanUtils.populate(product,map);
        item.setGoods(product);
        items.add(item);
    }
    return items;
}

三、支付

查看”沙箱支付“文档,里面有相关配置说明;

测试案例

根据步骤,下载测试案例,并进行调试测试案例。

做支付功能,需要先在测试案例中完成测试,找出与支付相关的文件

需要根据沙箱中的信息来进行配置:AppID,网关,公钥私钥、回调路径

在config配置文件中进行配置,如下所示:

//在案例支付中进行配置
public class AlipayConfig {
	// 应用ID,您的APPID,收款账号既是您的APPID对应支付宝账号
	public static String app_id = "9021000122699441";
	
	// 商户私钥,您的PKCS8格式RSA2私钥
    public static String merchant_private_key = "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCZUka8yrj4q7jECjhpenZ4eyxc8ivsG3mQ2FmiUkdsUdRiF1wYKo0nej9PUQ3cWIXdZaPdMklO7+aUfGaT0eXNXgpgAwHBKCbqDtZZ/EovvgEpsoS3xFdTHVi3B7va9gLhXvTDm1seDEcZXAIJ3C6Zw0i4lvS5+R3M94PlktsnbsBpOUXPmXOXrqrikKN1f5seJuFQAtDon2N4frfETCLYVb5KhRi62aDTqBevSV55GsPKWUM0UN3mhnxMQrtz8nezfftqUIKSjCyXveWXVUpXCSFCjzhgfcUjho9BqQtUM0y85LVNyon7WDoj9GXw/hTUJmiA4jjl5Mnxnz8D+45RAgMBAAECggEACfAjValuQ/Adkdd3wJ6Hf1e8kGnCHxPI1XKwnKzopETJl3IcLhTUAXMTF3kRhO7X/nnQHU5dIhi6wXUu0PYSBzXJRl/rhTGtFA7SJhMMW/vc528C20aGwoRsc7C0pIS9uw4En4k6ZsA0+5fTKgBzpNPbqtteEY/sNpT0n7TdL7kMYC1Kt3DI4tKFM1x3t5xnlzQIZHHLr+usMs3yUV18UVL81RPE0KGYDbWfH7oslNOw1wnX4X2WypF1pn7rT7ukj7s51Gb2xwrJvhGfQTRqzG/NjD6SK9+DZcN3/vkkTshMhL3st6cshZPTgyNQDtt/ipz4JBmBVGw9yrPgFHSCgQKBgQDIy7++y6ZEJjrpU7ao/230EuTK3uLW1vtOhoGeQUHmSViYhqUzTlC5nDeUQmZ4q9I+2jrquO156TiKyv67fUf4+7hAZKBW8rRwWKbPauhq3wwRmq0KkBiV9s3U1GCUVhSk9cgGfxkvsI1Y4yX7HBPCkPJClhiF8+oLJLy5uNKV/QKBgQDDeTdN12KIan9TSFztMs6v/JOWp3itT2O2iyuOOUoDvcuZ8xXHRJ2XteRpEbB/p6mQWBepRoI6hMMVLwgcAdFJe4WEFYzI6YLWOoxmg/KodPBoHrdd4K95GfzXNM7Gi5UOKcwVKRhFwdo94WtkbvnYZxcOOrgEEH+sizevswTf5QKBgQCId5l41bXJqWXugDurffY/pLukeXkX5IJl6xqa8OUV2xGAkDoktXw9ucM4WyyDpNs+ZlkWf9q+OVh5U99uk4Xf3UxrTzh9/3PMyyOL4q/VOoRcTpB+llJvUY6wsCp3hk1/k59/ctAuTkKyf6anlHyFhrdvs8009QJC0pQFcWyGDQKBgEzmyFoobUxL0ZG7O0vaHDRiQtIXSsOsIwdy0wzd/v9f0NTdLGk71mAUICsx2WUvWec+sPhYk+1fw7v2x9L06BhnrwxaygtUyrNrT0cZjAK4FshvpSYaug4DqlQkI2E7EsYCrZZ5l2ICNND5eR2HB2YakJh5g2Gd+AyyrJLD9Bv9AoGASrwaxb+4D+v4/hkwsuD1DZTT9uZh+57QTsCe1j78Lg+Tem6rU7cd8bc28hjODuF6z/icpRwPogk+APp1N14ViDtgUhrXQfGF7aYQ3H92qDvm0F9t6CxvQCgAUBvA6eFbHduUoZhZ4Jb7gO2YWYl9tZYBfSzA0XjuybuuCeaCqck=";
	
	// 支付宝公钥,查看地址:https://openhome.alipay.com/platform/keyManage.htm 对应APPID下的支付宝公钥。
    public static String alipay_public_key = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAi72K+GD45f4pSN+3tyPKUoMoKNTaTLUDABT4xHbBpIg7iSKW9YmiGo4QRxRZte5mJ0X5t6Az4ccLgmKagcc36Nsil7XUzpRTYc2SfPXlE1Hs2RsbmZoDxnT0Q/vR7/6BECYyYMUKZtnJRqZk7+yrdGtPrD3QXVwNZGntXL60+7pWg08quGOPyRhroeFi13nrYEOB6Mju0CXai6KMYNdk7UUFyDe9sz0TiMTVwK/313sS8PMVHXUin6ZpjHwVy4occ9cjrJ1dUoD6o9GF4K608y8PiINn56F9xFHK5uyMt54F6WXb1X7PlZdw29irt6T+2JB8bgsgOEosVvWHq532HwIDAQAB";

	// 服务器异步通知页面路径  需http://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问
	public static String notify_url = "http://localhost:8080/notify_url.jsp";

	// 页面跳转同步通知页面路径 需http://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问
	public static String return_url = "http://localhost:8080/return_url.jsp";

	// 签名方式
	public static String sign_type = "RSA2";
	
	// 字符编码格式
	public static String charset = "utf-8";
	
	// 支付宝网关
	public static String gatewayUrl = "https://openapi-sandbox.dl.alipaydev.com/gateway.do";
}

项目引入支付

导入测试案例中的依赖包,将config配置文件,return_url.jsp,notify_url.jsp拷贝到商城项目中,以及将支付功能页面放到订单控制层,如下所示:

//阿里支付
public String pay(HttpServletRequest request, HttpServletResponse response) throws AlipayApiException, UnsupportedEncodingException {
    //获得初始化的AlipayClient
    AlipayClient alipayClient = new DefaultAlipayClient(AlipayConfig.gatewayUrl, AlipayConfig.app_id, AlipayConfig.merchant_private_key, "json", AlipayConfig.charset, AlipayConfig.alipay_public_key, AlipayConfig.sign_type);

    //设置请求参数
    AlipayTradePagePayRequest alipayRequest = new AlipayTradePagePayRequest();
    alipayRequest.setReturnUrl(AlipayConfig.return_url);
    alipayRequest.setNotifyUrl(AlipayConfig.notify_url);

    //商户订单号,商户网站订单系统中唯一订单号,必填
    String out_trade_no = new String(request.getParameter("WIDout_trade_no").getBytes("ISO-8859-1"),"UTF-8");
    //付款金额,必填
    String total_amount = new String(request.getParameter("WIDtotal_amount").getBytes("ISO-8859-1"),"UTF-8");
    //订单名称,必填
    String subject = new String(request.getParameter("WIDsubject").getBytes("ISO-8859-1"),"UTF-8");
    //商品描述,可空
    String body = new String(request.getParameter("WIDbody").getBytes("ISO-8859-1"),"UTF-8");

    alipayRequest.setBizContent("{\"out_trade_no\":\""+ out_trade_no +"\","
                                + "\"total_amount\":\""+ total_amount +"\","
                                + "\"subject\":\""+ subject +"\","
                                + "\"body\":\""+ body +"\","
                                + "\"product_code\":\"FAST_INSTANT_TRADE_PAY\"}");

    //若想给BizContent增加其他可选请求参数,以增加自定义超时时间参数timeout_express来举例说明
    //alipayRequest.setBizContent("{\"out_trade_no\":\""+ out_trade_no +"\","
    //		+ "\"total_amount\":\""+ total_amount +"\","
    //		+ "\"subject\":\""+ subject +"\","
    //		+ "\"body\":\""+ body +"\","
    //		+ "\"timeout_express\":\"10m\","
    //		+ "\"product_code\":\"FAST_INSTANT_TRADE_PAY\"}");
    //请求参数可查阅【电脑网站支付的API文档-alipay.trade.page.pay-请求参数】章节

    //请求
    String result = alipayClient.pageExecute(alipayRequest).getBody();

    return result;
}

在return_url.jsp文件中进行回调商城项目,并更改订单状态。

//根据订单号,在商城中改变订单状态,重定向到订单列表中
OrderService orderService = new OrderServiceImpl();
int res = orderService.updateOidState(out_trade_no); //修改状态
System.out.println("状态修改:"+res);
response.sendRedirect("order?action=show");  //跳到订单管理中

四、Git

介绍

在单人开发中,需要版本控制,方便进入不同的提交版本

多人开发中,需要版本控制,进行协同配合开发,及项目的整合

Git是一个分布式的版本控制系统(推荐),而svn则是集中式版本控制系统

Git 是 Linus Torvalds 为了帮助管理 Linux 内核开发而开发的一个开放源码的版本控制软件。

git安装

下载git版本后,直接下一步安装。安装完成后,只需要DOS指令进行操作即可

git version    #查看版本

#配置用户标记
git config --global user.name "lhp"  #用户名
git config --global user.email "[email protected]"  #邮箱 无需校验
# 查看信息
git config -l 

#------本地库操作-----
#创建指定目录  例如d盘下的gitDemo,并进入目录中
git init    #将gitDemo变为工作区,里面可存放文件
git add .   #将工作区内容放到暂缓区
git commit -m "ont commit"  #提交  将暂缓区内容放入版本库
git status  #每一步操作都可使用该指令查看状态

远程仓库

目前较为常用的远程仓库有码云、github;推荐使用码云,服务器在国内,性能好,且中文版本

注册后,即可使用账户进行登录,并创建仓库,例如创建gitDemo仓库(建议和本地库名一致)

创建完成后,即可将客户端的提交点推送到远程仓库:

真实场景环境如下:

项目经理推送项目架构; 所有程序员克隆一份完整架构;然后程序员们进行更改后,即可推送到远端,其他程序员都可进行拉取或推送。

#关联远程仓库   标记名为origin
git remote add origin https://gitee.com/lihongping1015/git-demo.git 
#查看关联的远程仓库内容
git remote -v
#推送内容到远程仓库 orign是链接标记   master是主分支(默认) 
git push origin master

#另一个客户端即可克隆一份完整架构(第一次使用克隆,后面都是拉取)
git clone https://gitee.com/lihongping1015/git-demo.git
#同时也可提交并推送一份更改的内容
git push origin master
#其他用户也可拉取该提交内容
git pull origin master

五、总结与作业

总结

1.后端模块梳理
后台登录、展示用户信息,删除与搜索(搜索判断)、权限关联(过滤器)
2.订单详情
前端处理-查看订单详情页面需要的内容;后端处理-实体类加属性,DAO层关联查询
3.支付(重点)
根据支付文档下载demo,然后使用沙箱支付
通过测试案例来测试支付;完成后,再移到商城项目
4.git
介绍、git安装、远程仓库

作业

1. 请简述git本地仓库存文件的流程
2. 远程仓库的工作模式, 请描述清楚
4. 请描述支付宝的支付流程

截屏2023-09-26 09.02.07

晨考

6个git指令
git version
git config -l
git add .
git init
git commit -m "xx"
git remote add origin "路径"