品优购项目记录:day17

今日目标:

(1)掌握跨域请求CORS解决方案

(2)完成结算页收货人地址选择功能

(3)完成结算页支付方式选择

(4)完成结算页商品清单功能

(5)完成保存订单功能

 

目录

1、商品详细页跨域请求(购物车对接商品详细页)

1.1 需求分析

1.2 跨域调用测试

1.3 跨域解决方案CORS

2、结算页-收件人地址选择

2.1 需求分析

2.2 工程搭建

2.3 展示收货地址列表

2.4 选中收货地址

3、支付方式选择

3.1 需求分析

3.2 前端

4、送货清单与金额显示

4.1 需求分析

4.2 显示商品清单

4.3 显示总金额

5、保存订单

5.1 需求分析

5.2 分布式ID生成算法

5.3 保存订单


 

1、商品详细页跨域请求(购物车对接商品详细页)

 

1.1 需求分析

从商品详细页点击“加入购物车”按钮,将当前商品加入购物车,并跳转到购物车页面。

 

1.2 跨域调用测试

(1)修改freemarker静态资源中的itemController.js中的addToCart方法

	// 加入商品到购物车
	$scope.addToCart = function() {
		// alert("SKU:" + $scope.sku.id + "加入购物车成功,购买数量为:" + $scope.num);
		$http.get('http://localhost:9106/cart/addGoodsToCartList.do?itemId=' + $scope.sku.id + '&num=' + $scope.num).success(
			function(rtn) {
				if (rtn.success) {
					// 新增购物车成功,跳转到购物车页面
					location.href = 'http://localhost:9106/cart.html';
				} else {
					// 打印提示信息
					alert(rtn.message);
				}
			}
		);
	}

(2)调用测试

品优购项目记录:day17_第1张图片

 

1.3 跨域解决方案CORS

(1)什么是CORS?

CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing)。CORS需要浏览器和服务器同时支持。目前,所有浏览器都支持该功能,IE浏览器不能低于IE10。

它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。整个CORS通信过程,都是浏览器自动完成,不需要用户参与。对于开发者来说,CORS通信与同源的AJAX通信没有差别,代码完全一样。浏览器一旦发现AJAX请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感觉。因此,实现CORS通信的关键是服务器。只要服务器实现了CORS接口,就可以跨源通信。

(2)请求过程

品优购项目记录:day17_第2张图片

Preflight Request

品优购项目记录:day17_第3张图片

然后服务器端给我们返回一个Preflight Response

品优购项目记录:day17_第4张图片

(3)实现跨域

控制层(cart-web),在addGoodsToCartList添加设置头信息代码(实现跨域)

        response.setHeader("Access-Control-Allow-Origin", "http://localhost");
        response.setHeader("Access-Control-Allow-Credentials", "true");

控制层(cart-web),在addGoodsToCartList方法上加入注解

@CrossOrigin(origins = "http://localhost",allowCredentials = "true")

注意:请求参数也需要修改,在itemController的addToCart提交请求的参数列表中加入:{'withCredentials':true},用逗号和前面的参数分隔

 

 

 

2、结算页-收件人地址选择

 

 

2.1 需求分析

在结算页实现收件人地址选择功能

 

2.2 工程搭建

(1)复制代码生成器生成的服务层代码到 user 模块中,复制控制层代码以及静态页面到 cart 模块中

 

2.3 展示收货地址列表

(1)后端:服务层接口(address-interface),在AddressService新增方法

	/**
	 * 获取指定用户的收货地址列表
	 *
	 * @param userId 用户ID
	 * @return java.util.List
	 */
	List findListByLoginUser(String userId);

(2)后端:服务层实现(address-service),在AddressServiceImpl新增实现

	@Override
	public List findListByLoginUser(String userId) {
		// 创建查询条件对象
		TbAddressExample example = new TbAddressExample();
		example.createCriteria().andUserIdEqualTo(userId);
		// 执行查询
		return addressMapper.selectByExample(example);
	}

(3)后端:控制层(cart-web),在AddressController中新增方法

    /**
     * 获取当前用户的收货地址列表
     * 
     * @return java.util.List
     */
    @RequestMapping("/findListByLoginUser")
    public List findListByLoginUser() {
        // 获取当前登录用户
        String loginUser = SecurityContextHolder.getContext().getAuthentication().getName();
        return addressService.findListByLoginUser(loginUser);
    }

(4)前端:在cartService.js中新增方法

    // 获取当前登录用户的收货地址列表
    this.findListByLoginUser = function () {
        return $http.get('address/findListByLoginUser.do');
    }

(5)前端:在cartController.js中新增方法

    // 获取当前用户的收货地址列表
    $scope.findListByLoginUser = function () {
        cartService.findListByLoginUser().success(
            function (rtn) {
                $scope.addressList = rtn;
            }
        );
    }

(6)前端:页面引入JS文件和基础指令

品优购项目记录:day17_第5张图片

(7)页面循环展示收货地址列表

 

 

2.4 选中收货地址

(1)前端:在cartController.js中新增方法

    // 选择收货地址
    $scope.selectAddress = function (address) {
        $scope.address = address;
    }

    // 判断当前收货地址是否是被选中地址
    $scope.isSelectedAddress = function (address) {
        if ($scope.address == address) {
            return true;
        }
        return false;
    }

(2)前端:页面绑定方法

(3)展示默认选中的地址,在findListByLoginUser新增逻辑

品优购项目记录:day17_第6张图片

品优购项目记录:day17_第7张图片

 

 

 

 

 

3、支付方式选择

 

3.1 需求分析

实现支付方式的选择,品优购支持两种支付方式:微信支付和货到付款

 

3.2 前端

(1)在cartController.js 中新增方法

    // 选择付款方式
    $scope.order = {paymentType:'1'};
    $scope.selectPayment = function (type) {
        $scope.order.paymentType = type;
    }

(2)页面绑定单击事件(其中1为在线支付,2为货到付款)

 

 

 

4、送货清单与金额显示

 

4.1 需求分析

显示购物车中的商品清单以及合计数量、金额

 

4.2 显示商品清单

(1)初始化调用findCartList方法

(2)页面循环展示购物车列表

品优购项目记录:day17_第8张图片

 

4.3 显示总金额

(1)绑定变量即可

 

 

 

 

5、保存订单

 

5.1 需求分析

(1)需求

点击订单结算页的提交订单 ,将购物车保存到订单表和订单明细表中,并将购物车数据清除.

(2)工程搭建

参看其他的服务层工程,注意web层还是在cart-web中,需要将order的控制层代码复制到cart-web的controller包下

 

5.2 分布式ID生成算法

我们采用的是开源的twitter(  非官方中文惯称:推特.是国外的一个网站,是一个社交网络及微博客服务)  的snowflake算法。

品优购项目记录:day17_第9张图片

结构(64位2进制数):

时间戳(41bit):精确到毫秒

工作机器id(10bit):5位 数据中心ID  5位 机器ID

 

 

5.3 保存订单

(1)后端:在spring的配置文件中配置雪花算法的工具类bean(order-service)

	
	
		
		
	

(2)后端:服务层实现(order-service),修改OrderServiceImpl中的add方法的逻辑

	/**
	 * 增加
	 */
	@Override
	public void add(TbOrder order) {
		// 1.从redis中提取购物车列表
		List cartList = (List) redisTemplate.boundHashOps("cartList").get(order.getUserId());

		// 2.循环购物车保存订单
		for (Cart cart : cartList) {
			// 生成订单对象
			TbOrder tbOrder = buildOrder(order);
			// 设置商家ID
			tbOrder.setSellerId(cart.getSellerId());
			// 合计金额
			double money = 0;

			// 循环购物车明细
			for (TbOrderItem orderItem : cart.getOrderItemList()) {
				// 补全订单明细数据
				orderItem.setOrderId(tbOrder.getOrderId());
				orderItem.setSellerId(cart.getSellerId());
				orderItem.setId(idWorker.nextId());
				// 保存
				orderItemMapper.insert(orderItem);

				// 累加合计金额
				money += orderItem.getTotalFee().doubleValue();
			}
			// 设置合计金额到订单
			tbOrder.setPayment(BigDecimal.valueOf(money));
			// 保存
			orderMapper.insert(tbOrder);
		}

		// 3.清除购物车中的数据
		redisTemplate.boundHashOps("cartList").delete(order.getUserId());
	}

	/**
	 * 构建订单对象
	 *
	 * @param order 订单部分数据
	 * @return com.pinyougou.pojo.TbOrder
	 */
	private TbOrder buildOrder(TbOrder order) {
		TbOrder tbOrder = new TbOrder();
		tbOrder.setOrderId(idWorker.nextId());
		tbOrder.setPaymentType(order.getPaymentType());
		tbOrder.setStatus(TbOrder.STATUS_NOT_PAY);
		tbOrder.setCreateTime(new Date());
		tbOrder.setUpdateTime(new Date());
		tbOrder.setUserId(order.getUserId());
		tbOrder.setReceiverAreaName(order.getReceiverAreaName());
		tbOrder.setReceiverMobile(order.getReceiverMobile());
		tbOrder.setReceiver(order.getReceiver());
		tbOrder.setSourceType(order.getSourceType());

		return tbOrder;
	}

(3)后端:控制层新增方法

	/**
	 * 增加
	 * @param order
	 * @return
	 */
	@RequestMapping("/add")
	public Result add(@RequestBody TbOrder order){
		try {
			order.setUserId(SecurityContextHolder.getContext().getAuthentication().getName());
			// 设置订单来源:PC端
			order.setSourceType("2");
			orderService.add(order);
			return new Result(true, "增加成功");
		} catch (Exception e) {
			e.printStackTrace();
			return new Result(false, "增加失败");
		}
	}

(4)前端:在cartService.js中新增方法

    // 提交订单
    this.submitOrder = function (order) {
        return $http.post('order/add.do', order);
    }

(5)前端:在cartController.js中新增方法

    // 提交订单
    $scope.submitOrder = function () {
        // 封装数据
        $scope.order.receiverAreaName = $scope.address.address;// 地址
        $scope.order.receiverMobile = $scope.address.mobile;// 手机
        $scope.order.receiver = $scope.address.contact;// 联系人

        cartService.submitOrder($scope.order).success(
            function (rtn) {
                if (rtn.success) {
                    // 提交订单成功,跳转到支付页面
                    if ($scope.order.paymentType == "1") {// 微信支付 跳转到支付页面
                        location.href = 'pay.html';
                    } else {// 货到付款 跳转到提示页面
                        location.href = 'paysuccess.html';
                    }
                } else {
                    alert(rtn.message);
                }
            }
        );
    }

(6)前端:提交订单按钮绑定单击事件

 

你可能感兴趣的:(个人成长,实战项目,品优购)