订单模块

编程入门 行业动态 更新时间:2024-10-27 05:21:44

订单<a href=https://www.elefans.com/category/jswz/34/1771428.html style=模块"/>

订单模块

抽取订单模型

分析订单组成

会员ID:
流水号:
交易事件:
商品名称 商品价格 商品数量 小计
.
.
.
总金额:

设计表,存储小票上的数据

  1. 创建订单表
CREATE TABLE `orders` (`oid` VARCHAR(32) NOT NULL,`ordertime` DATETIME DEFAULT NULL,		#下单时间`total` DOUBLE DEFAULT NULL,				#总价`state` INT(11) DEFAULT NULL,				#订单状态:1=未付款;2=已付款,未发货;3=已发货,没收货;4=收货,订单结束`address` VARCHAR(30) DEFAULT NULL,		#收获地址`name` VARCHAR(20) DEFAULT NULL,			#收获人`telephone` VARCHAR(20) DEFAULT NULL,		#收货人电话`uid` VARCHAR(32) DEFAULT NULL,PRIMARY KEY (`oid`),KEY `order_fk_0001` (`uid`),CONSTRAINT `order_fk_0001` FOREIGN KEY (`uid`) REFERENCES `user` (`uid`)
) ENGINE=INNODB DEFAULT CHARSET=utf8;
  1. 创建订单项表
CREATE TABLE `orderitem` (`itemid` VARCHAR(32) NOT NULL,`quantity` INT(11) DEFAULT NULL,			#购买数量`total` DOUBLE DEFAULT NULL,			#小计`pid` VARCHAR(32) DEFAULT NULL,		#购买商品的id`oid` VARCHAR(32) DEFAULT NULL,		#订单项所在订单idPRIMARY KEY (`itemid`),KEY `order_item_fk_0001` (`pid`),KEY `order_item_fk_0002` (`oid`),CONSTRAINT `order_item_fk_0001` FOREIGN KEY (`pid`) REFERENCES `product` (`pid`),CONSTRAINT `order_item_fk_0002` FOREIGN KEY (`oid`) REFERENCES `orders` (`oid`)
) ENGINE=INNODB DEFAULT CHARSET=utf8;

提交订单

需求

用户点击提交订单,将购物车中的数据以订单/订单项形式保存下来,清空购物车
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bdivx073-1607676523969)(提交订单开发流程.png)]

  1. 保存订单:为订单表中插入一行数据,描述本次交易,这行数据部分数据是通过程序赋予,部分数据来自购物车的,部分数据来自session中的用户。

     oid:UUIDUtilsoderTime:new Date();total:从购物车中获取state:1address:nullname:nulltelephone:nulluid:从session中的用户获取
    
  2. 保存订单项:向订单项表中插入数据,描述当前订单的详细的购买信息,部分数据来自购物车,部分数据需要通过程序赋予。

     itemid:UUIDUtilsquantity:来自于订单中的购物项total:来自于购物车中的购物项pid:来自于购物车上的购物项下商品对象pidoid:来自于当前订单的id
    

提交订单时,订单以及订单项必须同时成功(事务)

创建订单对象

  1. 创建一个user对象而不是user对象的属性uid。
    1. 程序对象和对象发生关系,而不是对象和对象的属性发生关系
    2. 设计Order目的:让order携带订单上的数据向service,dao传递,user对象是可以携带更多的数据
  2. private List list = new ArrayList();程序中体现订单对象和订单项之间关系,我们再项目中的部分功能中有类似的需求:查询订单的同时还需要获取订单下所有的订单项
public class Order {private String oid; //订单编号private Date ordertime; //下单时间private double total; //总计private int state; //状态private String address; //收货人地址private String name; //收货人姓名private String telephone; //收货人电话// private String uid;// 1_程序对象和对象发生关系,而不是对象和对象的属性发生关系// 2_设计Order目的:让order携带订单上的数据向service,dao传递,user对象是可以携带更多的数据private User user;// 程序中体现订单对象和订单项之间关系,我们再项目中的部分功能中有类似的需求:查询订单的同时还需要获取订单下所有的订单项private List<OrderItem> list = new ArrayList<OrderItem>();public String getOid() {return oid;}public void setOid(String oid) {this.oid = oid;}public Date getOrdertime() {return ordertime;}public void setOrdertime(Date ordertime) {this.ordertime = ordertime;}public double getTotal() {return total;}public void setTotal(double total) {this.total = total;}public int getState() {return state;}public void setState(int state) {this.state = state;}public String getAddress() {return address;}public void setAddress(String address) {this.address = address;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getTelephone() {return telephone;}public void setTelephone(String telephone) {this.telephone = telephone;}public User getUser() {return user;}public void setUser(User user) {this.user = user;}public List<OrderItem> getList() {return list;}public void setList(List<OrderItem> list) {this.list = list;}}

创建订单项对象

创建一个product对象而不是product对象的属性pid;
创建一个order对象而不是product对象的属性oid。

  1. 对象对应对象
  2. product,order携带更多的数据
public class OrderItem {private String itemid; //idprivate int quantity; //数量private double total; //小计//1_对象对应对象//2_product,order携带更多的数据private Product product;private Order order;	public String getItemid() {return itemid;}public void setItemid(String itemid) {this.itemid = itemid;}public int getQuantity() {return quantity;}public void setQuantity(int quantity) {this.quantity = quantity;}public double getTotal() {return total;}public void setTotal(double total) {this.total = total;}public Product getProduct() {return product;}public void setProduct(Product product) {this.product = product;}public Order getOrder() {return order;}public void setOrder(Order order) {this.order = order;}}

保存订单

  1. 客户端点击提交订单,向服务器发起请求
<a href="${pageContext.request.contextPath}/orderServlet?method=saveOrder"><%--提交表单 --%><input type="button" width="100" value="提交订单" name="submit" border="0"style="background: url('${pageContext.request.contextPath}/img/register.gif') no-repeat scroll 0 0 rgba(0, 0, 0, 0);height:35px;width:100px;color:white;">
</a>
  1. OrderServlet下编写saveOrder方法
public String saveOrder(HttpServletRequest req, HttpServletResponse resp) throws Exception {//确认用户登录状态User user = (User) req.getSession().getAttribute("loginUser");if (user == null) {req.setAttribute("msg", "请登陆后再下单");return "/jsp/info.jsp";}//获取购物车Cart cart = (Cart) req.getSession().getAttribute("cart");//创建订单对象,为订单对象赋值Order order = new Order();order.setOid(UUIDUtils.getCode());order.setOrdertime(new Date());order.setTotal(cart.getTotal());order.setState(1);order.setUser(user);//遍历购物项的同时,创建订单项for (CartItem item : cart.getCartItems()) {OrderItem orderItem = new OrderItem();orderItem.setItemid(UUIDUtils.getCode());orderItem.setQuantity(item.getNum());orderItem.setTotal(item.getSubTotal());orderItem.setProduct(item.getProduct());//设置当前的订单项属于哪个订单:订单项和订单的对应关系orderItem.setOrder(order);order.getList().add(orderItem);}//调用业务层功能OrderService orderService = new OrderServiceImp();//将订单数据,用户的数据,订单下所有的订单项都传递到了service层orderService.saveOrder(order);//清空购物车cart.clearCart();//将订单放入requestreq.setAttribute("order",order);//转发/jsp/order_info.jspreturn "/jsp/order_info.jsp";
}
  1. 编写业务层,保存订单功能
public void saveOrder(Order order) throws SQLException {//保存订单和订单下所有的订单项(同时成功,失败)/*try {JDBCUtils.startTransaction();OrderDao orderDao=new OrderDaoImp();orderDao.saveOrder(order);for(OrderItem item:order.getList()){orderDao.saveOrderItem(item);}JDBCUtilsmitAndClose();} catch (Exception e) {JDBCUtils.rollbackAndClose();}*/Connection conn = null;try {//获取连接conn = JDBCUtils.getConnection();//开启事务conn.setAutoCommit(false);//保存订单orderDao.saveOrder(conn, order);//保存订单项for (OrderItem item : order.getList()) {orderDao.saveOrderItem(conn, item);}//提交connmit();} catch (Exception e) {//回滚conn.rollback();}
}
  1. 编写dao层,插入数据到订单表和订单项表
@Override
public void saveOrder(Connection conn, Order order) {String sql="INSERT INTO orders VALUES(?,?,?,?,?,?,?,?)";Object[] params={order.getOid(),order.getOrdertime(),order.getTotal(),order.getState(),order.getAddress(),order.getName(),order.getTelephone(),order.getUser().getUid()};template.update(sql,params);
}
@Override
public void saveOrderItem(Connection conn, OrderItem item) {String sql="INSERT INTO orderitem VALUES(?,?,?,?,?)";Object[] params={item.getItemid(),item.getQuantity(),item.getTotal(),item.getProduct().getPid(),item.getOrder().getOid()};template.update(sql,params);
}
  1. 编写订单详情页面order_info.jsp
<div class="row"><div style="margin:0 auto;margin-top:10px;width:950px;"><strong>订单详情</strong><table class="table table-bordered"><tbody><tr class="warning"><th colspan="5">订单编号:${order.oid}</th></tr><tr class="warning"><th>图片</th><th>商品</th><th>价格</th><th>数量</th><th>小计</th></tr><c:forEach items="${order.list}" var="orderItem"><tr class="active"><td width="60" width="40%"><input type="hidden" name="id" value="22"><img src="${pageContext.request.contextPath}/${orderItem.product.pimage}" width="70"height="60"></td><td width="30%"><a target="_blank">${orderItem.product.pname}</a></td><td width="20%">¥${orderItem.product.shop_price}</td><td width="10%">${orderItem.quantity}</td><td width="15%"><span class="subtotal">¥${orderItem.total}</span></td></tr></c:forEach></tbody></table></div><div style="text-align:right;margin-right:120px;">商品金额: <strong style="color:#ff6600;">¥${order.total}元</strong></div></div>

查询我的订单

### 编写findMyOrdersWithPage方法
首先获取用户信息,调用业务层功能查询当前用户的订单信息

public String findMyOrdersWithPage(HttpServletRequest req, HttpServletResponse resp) throws Exception {//获取用户信息User user = (User) req.getSession().getAttribute("loginUser");//获取当前页int curNum = Integer.parseInt(req.getParameter("num"));//调用业务层功能:查询当前用户订单信息,返回PageModelOrderService orderService = new OrderServiceImp();//SELECT * FROM orders WHERE uid=? limit ? , ?//PageModel:1_分页参数 2_url  3_当前用户的当前页的订单(集合) ,每笔订单上对应的订单项,以及订单项对应的商品信息PageModel pm = orderService.findMyOrdersWithPage(user, curNum);//将PageModel放入requestreq.setAttribute("page", pm);//转发到/jsp/order_list.jspreturn "/jsp/order_list.jsp";}

编写业务层

public PageModel findMyOrdersWithPage(User user, int curNum) throws Exception {//1_创建PageModel对象,目的:计算并且携带分页参数//select count(*) from orders where uid=?int totalRecords = orderDao.getTotalRecords(user);PageModel pm = new PageModel(curNum, totalRecords, 3);//2_关联集合  select * from orders where uid=? limit ? ,?List list = orderDao.findMyOrdersWithPage(user, pm.getStartIndex(), pm.getPageSize());pm.setList(list);//3_关联urlpm.setUrl("orderServlet?method=findMyOrdersWithPage");return pm;
}

编写dao层,查询数据库

遍历所有订单,并获取每笔订单下的订单项

public List findMyOrdersWithPage(User user, int startIndex, int pageSize) throws Exception {String sql = "select * from orders where uid=? limit ? , ?";List<Order> list = template.query(sql, new BeanPropertyRowMapper<>(Order.class), user.getUid(), startIndex, pageSize);//遍历所有订单for (Order order : list) {//获取到每笔订单oid   查询每笔订单下的订单项以及订单项对应的商品信息String oid = order.getOid();sql = "select * from orderItem o ,product p where o.pid=p.pid and oid=?";List<Map<String, Object>> list01 = template.queryForList(sql, oid);//遍历listfor (Map<String, Object> map : list01) {OrderItem orderItem = new OrderItem();Product product = new Product();// 由于BeanUtils将字符串"1992-3-3"向user对象的setBithday();方法传递参数有问题,手动向BeanUtils注册一个时间类型转换器// 1_创建时间类型的转换器DateConverter dt = new DateConverter();// 2_设置转换的格式dt.setPattern("yyyy-MM-dd");// 3_注册转换器ConvertUtils.register(dt, java.util.Date.class);//将map中属于orderItem的数据自动填充到orderItem对象上BeanUtils.populate(orderItem, map);//将map中属于product的数据自动填充到product对象上BeanUtils.populate(product, map);//让每个订单项和商品发生关联关系orderItem.setProduct(product);//将每个订单项存入订单下的集合中order.getList().add(orderItem);}}return list;
}

### 编写订单列表页面/jsp/order_list.jsp

<div class="container"><c:if test="${empty page.list}"><div>暂无数据</div></c:if><c:if test="${not empty page.list }"><div class="row"><div style="margin:0 auto; margin-top:10px;width:950px;"><strong>我的订单</strong><table class="table table-bordered"><c:forEach items="${page.list}" var="order"><tbody><tr class="success"><th colspan="5">订单编号:${order.oid} 金额:${order.total}<c:if test="${order.state==1}"><a href="${pageContext.request.contextPath}/orderServlet?method=findOrderByOid&oid=${order.oid}">付款</a></c:if><c:if test="${order.state==2}">待发货</c:if><c:if test="${order.state==3}">在路上</c:if><c:if test="${order.state==4}">结束</c:if></th></tr><tr class="warning"><th>图片</th><th>商品</th><th>价格</th><th>数量</th><th>小计</th></tr><c:forEach items="${order.list}" var="orderItem"><tr class="active"><td width="60" width="40%"><input type="hidden" name="id" value="22"><img src="${pageContext.request.contextPath}/${orderItem.product.pimage}" width="70"height="60"></td><td width="30%"><a target="_blank">${orderItem.product.pname}</a></td><td width="20%">¥${orderItem.product.shop_price}</td><td width="10%">${orderItem.quantity}</td><td width="15%"><span class="subtotal">¥${orderItem.total}</span></td></tr></c:forEach></tbody></c:forEach></table></div></div><%@ include file="/jsp/pageFile.jsp" %></c:if>
</div>

订单详情

客户端点击付款,跳转至订单详情页面

编写findOrderByOid方法

public String findOrderByOid(HttpServletRequest req, HttpServletResponse resp) throws Exception {//获取到订单oidString oid = req.getParameter("oid");//调用业务层功能:根据订单编号查询订单信息OrderService OrderService = new OrderServiceImp();Order order = OrderService.findOrderByOid(oid);// 将订单放入requestreq.setAttribute("order", order);// 转发到/jsp/order_info.jspreturn "/jsp/order_info.jsp";
}

编写业务层

根据订单编号查询订单信息

public Order findOrderByOid(String oid) throws Exception {return orderDao.findOrderByOid(oid);
}

编写dao层

public Order findOrderByOid(String oid) throws Exception {String sql = "select * from orders where oid= ?";Order order = (Order) template.queryForObject(sql, new BeanPropertyRowMapper<>(Order.class), oid);//根据订单id查询订单下所有的订单项以及订单项对应的商品信息sql = "select * from orderitem o, product p where o.pid=p.pid and oid=?";List<Map<String, Object>> list02 = template.queryForList(sql, oid);//遍历listfor (Map<String, Object> map : list02) {OrderItem orderItem = new OrderItem();Product product = new Product();// 由于BeanUtils将字符串"1992-3-3"向user对象的setBithday();方法传递参数有问题,手动向BeanUtils注册一个时间类型转换器// 1_创建时间类型的转换器DateConverter dt = new DateConverter();// 2_设置转换的格式dt.setPattern("yyyy-MM-dd");// 3_注册转换器ConvertUtils.register(dt, java.util.Date.class);//将map中属于orderItem的数据自动填充到orderItem对象上BeanUtils.populate(orderItem, map);//将map中属于product的数据自动填充到product对象上BeanUtils.populate(product, map);//让每个订单项和商品发生关联关系orderItem.setProduct(product);//将每个订单项存入订单下的集合中order.getList().add(orderItem);}return order;
}

支付功能

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Tq6f1Hro-1607676523973)(支付开发流程.png)]

准备工作 /jsp/order_info.jsp

设置form表单(method,action,id)

<form class="form-horizontal" style="margin-top:5px;margin-left:150px;" id="orderForm" method="post"action="${pageContext.request.contextPath}/orderServlet?method=payOrder"><a href="javascript:document.getElementById('orderForm').submit();"><img src="${pageContext.request.contextPath}/img/finalbutton.gif" width="204" height="51" border="0"/></a>
</form>   

设置form表单input标签,设置隐藏域,传递订单oid。

<div class="form-group"><label for="username" class="col-sm-1 control-label">地址</label><div class="col-sm-5"><input type="text" class="form-control" id="username" placeholder="请输入收货地址" name="address"></div>
</div>
<div class="form-group"><label for="inputPassword3" class="col-sm-1 control-label">收货人</label><div class="col-sm-5"><input type="text" class="form-control" id="inputPassword3" placeholder="请输收货人" name="name"></div>
</div>
<div class="form-group"><label for="confirmpwd" class="col-sm-1 control-label">电话</label><div class="col-sm-5"><input type="text" class="form-control" id="confirmpwd" placeholder="请输入联系方式" name="telephone"><input type="hidden" name="oid" value="${order.oid }"/></div>
</div>

编写OrderServlet下的payOrder方法

获取订单oid,收货人地址,姓名电话
更新订单上的收货人地址,姓名电话
向支付宝发送参数

public String payOrder(HttpServletRequest req, HttpServletResponse resp) throws Exception {//获取订单oid,收货人地址,姓名,电话,银行String oid=req.getParameter("oid");String address=req.getParameter("address");String name=req.getParameter("name");String telephone=req.getParameter("telephone");String pd_FrpId=req.getParameter("pd_FrpId");//更新订单上收货人的地址,姓名,电话OrderService OrderService=new OrderServiceImp();Order order=OrderService.findOrderByOid(oid);order.setName(name);order.setTelephone(telephone);order.setAddress(address);OrderService.updateOrder(order);//向易宝支付发送参数// 把付款所需要的参数准备好:String p0_Cmd = "Buy";//商户编号String p1_MerId = "10001126856";//订单编号String p2_Order = oid;//金额String p3_Amt = "0.01";String p4_Cur = "CNY";String p5_Pid = "";String p6_Pcat = "";String p7_Pdesc = "";//接受响应参数的ServletString p8_Url = "http://localhost:8080/store_v5/OrderServlet?method=callBack";String p9_SAF = "";String pa_MP = "";String pr_NeedResponse = "1";//公司的秘钥String keyValue = "69cl522AV6q613Ii4W6u8K6XuW8vM1N6bFgyv769220IuYe9u37N4y7rI4Pl";//调用易宝的加密算法,对所有数据进行加密,返回电子签名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("?");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);System.out.println(sb.toString());//// 使用重定向:resp.sendRedirect(sb.toString());return null;
}

编写OrderServlet下的callBack方法

接收易宝支付的数据
验证请求来源和数据有效性
阅读支付结果参数说明

public String callBack(HttpServletRequest request, HttpServletResponse resp) throws Exception {//接收易宝支付的数据// 验证请求来源和数据有效性// 阅读支付结果参数说明// System.out.println("==============================================");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");// hmacString hmac = request.getParameter("hmac");// 利用本地密钥和加密算法 加密数据String keyValue = "69cl522AV6q613Ii4W6u8K6XuW8vM1N6bFgyv769220IuYe9u37N4y7rI4Pl";//保证数据合法性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")) {// 浏览器重定向//如果支付成功,更新订单状态OrderService OrderService=new OrderServiceImp();Order order=OrderService.findOrderByOid(r6_Order);order.setState(2);OrderService.updateOrder(order);//向request放入提示信息request.setAttribute("msg", "支付成功!订单号:" + r6_Order + "金额:" + r3_Amt);//转发到/jsp/info.jspreturn "/jsp/info.jsp";} else if (r9_BType.equals("2")) {// 修改订单状态:// 服务器点对点,来自于易宝的通知System.out.println("收到易宝通知,修改订单状态!");//// 回复给易宝success,如果不回复,易宝会一直通知resp.getWriter().print("success");}} else {throw new RuntimeException("数据被篡改!");}return null;}

权限过滤器

某些功能需要登录才可访问。

public class PriviledgeFilter implements Filter {public PriviledgeFilter() {}public void destroy() {}public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {HttpServletRequest myReq = (HttpServletRequest)request;//判断当前的session中是否存在已经登录成功的用户User user = (User)myReq.getSession().getAttribute("loginUser");if(null!=user){//如果存在,放行chain.doFilter(request, response);}else{//如果不存在,转入到提示页面myReq.setAttribute("msg", "请用户登录之后再去访问");//转入到提示页面myReq.getRequestDispatcher("/jsp/info.jsp").forward(request, response);}	}public void init(FilterConfig fConfig) throws ServletException {}}

配置过滤器路径

<filter><display-name>PriviledgeFilter</display-name><filter-name>PriviledgeFilter</filter-name><filter-class>web.filter.PriviledgeFilter</filter-class>
</filter>
<filter-mapping><filter-name>PriviledgeFilter</filter-name><url-pattern>/jsp/cart.jsp</url-pattern><url-pattern>/jsp/order_info.jsp</url-pattern><url-pattern>/jsp/order_list.jsp</url-pattern>
</filter-mapping>

更多推荐

订单模块

本文发布于:2024-02-25 02:37:06,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1697503.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:模块   订单

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!