mvc:四
回顾:
我的订单
需求:在任意页面上(当然前提是已经登录了,没登录过滤了访问不到)点击我的订单,将当前用户的订单(包含订单项列表)分页展示出来
步骤分析:
1.修改head.jsp上面订单链接/store/order?method=findMyOrderByPage&pageNumber=1$获取session确定是哪个用户(页面获取和后台获取一样,这里放在后台获取)
2.在orderservlet中编写findMyOrderByPage
获取pagenumber 设置pagesize,获取当前用户的id
调用service完成分页查询操作:返回pagebean
将pagebean放入request域中,请求转发order_list.jsp
3.service中操作
创建pagebean
设置总条数
设置当前页数据
4.dao操作
获取当前页订单数据 select * from orders where uid=? order by ordertimr desc limit ?,?(只能查询订单的基本信息,不能查询订单项)
执行完上面的sql返回的是一个list<order>集合,里面是订单项
遍历orderlist集合,获取到每一个订单,关联查询订单项和商品表,将该订单下的所有信息查询出来, 封装 成orderItem,将每一个orderItem放入当前order的订单项列表中
查询订单项 select * from orderitem oi,product p where oi.pid=p.pid AND oi.oid='afagagafdadf随机uid';
上面的结果用什么封装???BeanHandler不合适,BeanListHandler不行,ArrayHandler只能封装结果的第一条不行ArrayListHandler可以,有角标,但是分析后不好。
最后将order_list返回
后台的查询操作已经完成,下面写前台将返回的list中的数据显示到页面中order_list.jsp
页面显示规律,有多个订单一个订单占一个框,所以循环外框 一个订单里面有多个订单项所以循环内框
订单详情
需求:在order_list.jsp页面上点击去付款要展示出当前订单的详情
步骤:省略一次,看代码
在线支付
需求:在详情页面上 输入收货人信息,选择支付的银行,点击确认订单,保存收获人信息,跳转到银行页面,输入用户名(卡号),点击支付 最后跳转到商城,提示 订单支付成功,(修改订单的状态)
技术分析:在线支付方式
对银行:钱直接给银行打过去
需要和每家银行沟通,银行需要什么数据就要传什么数据,万一银行要求改动了,本地的代码也要改动,开发工作量大,维护成本高。商城是自己的,用户的钱直接打到自己的商城账号上,资金周转快
对第三方:钱先给第三方,在第三方中暂时保存
只需要和第三方沟通,用户需要将钱打到自己的第三方账户上就行了,和银行沟通的事交给第三方,某个银行的接口变了不需要我们管。第三方是收费的,用户给了支付虽然没收我们用户的,但是收了商家的。好比自己的钱存支付宝也收费此时自己就是商家(京东刚开始公司小,依赖支付宝,支持支付宝支付,后来有了自己的京东金融)。第三方小公司用的多,对于大公司都是直接对银行(例如支付宝公司就直接对银行),资金会笼慢(用户先给钱给第三方,第三方通知收货,只有用户确认收货了自己才能收到钱)
在线支付流程
淘宝买东西先看中自己心仪的商品---------选中点去付款(发现页面由淘宝跳到了支付宝(淘宝、支付宝不是一家公司))----------不选余额或余额宝支付选银行卡(发现页面由支付宝跳到了银行页面)
支付进入支付公司 选银行进入银行系统(先登录)。。。。。。。见下图
用户到支付公司需要参数(钱,)
在线支付注意问题: 其实就是让数据由商城到第三方不能被篡改
1、给第三方支付哪些数据和第三方要返回哪些数据给用户和商城(开发中有接口文档)
2、如何保证数据的有效性(保证数据没有被篡改过,电子签名(单向加密(假如我有两张纸,一张是用户要给第三方的数据,第三方会给一个秘钥---字符串,),原则不可逆解密)-------就是给数据贴一个 封条 ,如果数据没有被改,封条就不会变,到达目的地看封条有没有被修改)
商城将发给第三方的数据经过算法和密钥进行加密(不可逆),生成一个字符串,将原始的数据和加密后生成的字符串一并发送给第三方.
第三方拿到数据之后,将原来的数据使用同样的算法和密码重新生成一个字符串,
将其和商城发送过来的加密后的字符串进行比对,若数据是一样的,则证明数据没有被篡改过.
商城开户:商家在第三方中的账号
用户编码
秘钥(会在第三方和商城(用户)都存一份)
算法
支付步骤分析:
1.在订单详情页面上 填写收货人信息, 选择支付银行,点击"确认订单",向商城发送请求
表单提交
收货人信息
支付银行
订单号
路径: /store/order?method=pay
2.在orderservlet中 编写pay方法
接受收货人信息 订单号
调用service获取订单,
设置收货人信息
更新订单
拼接重定向的字符串
//在线支付 public String pay(HttpServletRequest request, HttpServletResponse response) throws IOException { //1.获取收货人信息,获取oid,获取银行 //2.调用service获取订单 修改收货人信息,更新订单 //3.拼接第三方的url(上面两步都简单,这个要一个一个拼接字符串,麻烦吃力不讨好的事,并且不能犯错) //4.重定向 //接受参数(四个参数都获取到了,唯一没有获取到银行) try { String address=request.getParameter("address"); String name=request.getParameter("name"); String telephone=request.getParameter("telephone"); String oid=request.getParameter("oid"); //通过id获取order OrderService s=(OrderService) BeanFactory.getBean("OrderService"); Order order = s.getById(oid); //获取订单信息,这个方法做过 order.setAddress(address); //可以在数据表中看到还没有地址 姓名 电话等信息 order.setName(name); order.setTelephone(telephone); //更新order s.updateOrder(order); //支付信息一个一个获取 // 组织发送支付公司需要哪些数据 String pd_FrpId = request.getParameter("pd_FrpId"); //哪个银行,银行通道 String p0_Cmd = "Buy"; //业务类型 //商户编号 要想完成这个事情首先得开个户 //今天有merchantInfo.properties这个文件,拿过来放到src目录下 //获取这个编号先new一个properties prop = new pro... //然后prop.getproperties() 然后 .node()获取即可,这里用了另外一种东西叫ResourceBundle //这个是jdk提供好的 ctrl shift o 导入,直接.getBundle("文件名称,不带后缀名").getString("放key的值") String p1_MerId = ResourceBundle.getBundle("merchantInfo").getString("p1_MerId"); String p2_Order = oid; //商户订单号 String p3_Amt = "0.01"; //支付金额 按理说这里order.getTotal知道要多少钱 String p4_Cur = "CNY"; //交易币种 cny人民币 String p5_Pid = ""; //商品名称 String p6_Pcat = ""; //商品种类 String p7_Pdesc = ""; //商品描述 // 支付成功回调地址 ---- 第三方支付公司会访问、用户访问 支付成功后由第三方通知商城的地址key=responseURL这个地址暂时没有编写 // 第三方支付可以访问网址,由于我们的地址是localhost是本地地址,而由支付公司在外网 //由外网告诉本地商家修改订单状态收不到,但是由支付公司让我们浏览器重定向可以收到(告诉我自己请求我自己的商城) String p8_Url = ResourceBundle.getBundle("merchantInfo").getString("responseURL"); String p9_SAF = ""; //送货地址 String pa_MP = ""; //商户扩展信息 String pr_NeedResponse = "1"; //应答机制 // 加密hmac 需要密钥 将PaymentUtil复制导入到util包中 String keyValue = ResourceBundle.getBundle("merchantInfo").getString("keyValue"); String hmac = PaymentUtil.buildHmac(p0_Cmd, p1_MerId, p2_Order, p3_Amt, p4_Cur, p5_Pid, p6_Pcat, p7_Pdesc, p8_Url, p9_SAF, pa_MP, pd_FrpId, pr_NeedResponse, keyValue); //发送给第三方 StringBuffer sb = new StringBuffer("https://www.yeepay.com/app-merchant-proxy/node?"); sb.append("p0_Cmd=").append(p0_Cmd).append("&"); sb.append("p1_MerId=").append(p1_MerId).append("&"); sb.append("p2_Order=").append(p2_Order).append("&"); sb.append("p3_Amt=").append(p3_Amt).append("&"); sb.append("p4_Cur=").append(p4_Cur).append("&"); sb.append("p5_Pid=").append(p5_Pid).append("&"); sb.append("p6_Pcat=").append(p6_Pcat).append("&"); sb.append("p7_Pdesc=").append(p7_Pdesc).append("&"); sb.append("p8_Url=").append(p8_Url).append("&"); sb.append("p9_SAF=").append(p9_SAF).append("&"); sb.append("pa_MP=").append(pa_MP).append("&"); sb.append("pd_FrpId=").append(pd_FrpId).append("&"); sb.append("pr_NeedResponse=").append(pr_NeedResponse).append("&"); sb.append("hmac=").append(hmac); //将这些参数一个一个往上面sb追加形成一个地址,然后重定向 我们要做更新订单,收货人信息,上面的s.updateOrder(order)方法要实现 response.sendRedirect(sb.toString()); } catch (Exception e) { e.printStackTrace(); request.setAttribute("msg","支付失败"); return "/jsp/msg.jsp"; } return null; }
支付成功之后的步骤分析:
编写callback方法(这个方法是支付成功了由第三方要跳转到本商城的路径的参数responseURL=http://localhost/store/order?method=callback)
获取第三方发送过来的数据(order_id)
通过id获取订单
修改订单的状态 =1
更新订单
下面在orderservlet中直接编写callback方法实现上面操作
//支付成功的回调 public String callback(HttpServletRequest request, HttpServletResponse response) throws IOException { //1.获取第三方发送过来的数据 //2.获取订单 修改订单状态 //3.更新订单 try { String p1_MerId = request.getParameter("p1_MerId"); String r0_Cmd = request.getParameter("r0_Cmd"); String r1_Code = request.getParameter("r1_Code"); String r2_TrxId = request.getParameter("r2_TrxId"); String r3_Amt = request.getParameter("r3_Amt"); String r4_Cur = request.getParameter("r4_Cur"); String r5_Pid = request.getParameter("r5_Pid"); String r6_Order = request.getParameter("r6_Order"); String r7_Uid = request.getParameter("r7_Uid"); String r8_MP = request.getParameter("r8_MP"); String r9_BType = request.getParameter("r9_BType"); String rb_BankId = request.getParameter("rb_BankId"); String ro_BankOrderId = request.getParameter("ro_BankOrderId"); String rp_PayDate = request.getParameter("rp_PayDate"); String rq_CardNo = request.getParameter("rq_CardNo"); String ru_Trxtime = request.getParameter("ru_Trxtime"); // 身份校验 --- 判断是不是支付公司通知你 String hmac = request.getParameter("hmac"); //获取hmac秘钥 String keyValue = ResourceBundle.getBundle("merchantInfo").getString( "keyValue"); // 自己对上面数据进行加密 --- 比较支付公司发过来hamc verifyCallback进行两个字符串的比较 boolean isValid = PaymentUtil.verifyCallback(hmac, p1_MerId, r0_Cmd, r1_Code, r2_TrxId, r3_Amt, r4_Cur, r5_Pid, r6_Order, r7_Uid, r8_MP, r9_BType, keyValue); if (isValid) { //如果两者相等的话,里面有两个判断,都会执行,用户看到的浏览器会重定向显示到支付成功页面 // 响应数据有效 if (r9_BType.equals("1")) { // 浏览器重定向 System.out.println("111"); request.setAttribute("msg", "您的订单号为:"+r6_Order+",金额为:"+r3_Amt+"已经支付成功,等待发货~~"); } else if (r9_BType.equals("2")) { // 服务器点对点 --- 支付公司通知你 System.out.println("付款成功!222"); // 修改订单状态 为已付款 // 回复支付公司 response.getWriter().print("success"); } //由于我们这里获取不到外网,所以无论哪种方式,我们这里都手动进入到数据库中去修改状态,默认就是支付成功 //修改订单状态 OrderService s=(OrderService) BeanFactory.getBean("OrderService"); Order order = s.getById(r6_Order); //获取哪个订单的编号然后修改状态 order.setState(Constant.ORDER_YIFUKUAN); s.update(order); } else { //秘钥前前端传递与校验的不相同,说明数据被修改了 System.out.println("数据被篡改!"); } } catch (Exception e) { e.printStackTrace(); request.setAttribute("msg", "支付失败"); } return "/jsp/msg.jsp"; } }
权限过滤soeasy
访问淘宝时,要想把商品加入购物车必须首先登陆;但是京东不同,没有登录可以加,一旦登录就会把购物车中的信息放入数据库中,所以在手机上创建的购物车在电脑上也可以访问就是写到了数据库中
需求:模拟淘宝类似功能,访问购物车的时候,需要判断用户是否登录,若没有登录,则提示
技术分析:filter
过滤器编写步骤:
1.编写一个类 PrivilegeFilter (privileger----特权)
实现filter接口
重写方法(主要doFilter)
2.编写配置文件
filter
filter-mapping
步骤分析:
doFilter方法中的逻辑
从session中获取用户,
判断用户是否为空
若为空:提示"请先登录",请求转发到 /jsp/msg.jsp return 若登录了不用管直接dofilter了,编写filter分三步1.强转2.写逻辑3放行
今日总结
查询我的订单
查询订单是要将订单列表查询出来
orders里面只有基本信息 需要关联oderitem和product表去查询数据 用MapListHandler封装 加入到order中
订单详情
在线支付
要明白流程,知道流程怎么走(爱生活爱拉芳爱java爱代码),支付方式有两种,对银行对第三方,优缺点
权限过滤