目录

一、购物车结算前端功能实现

1.购物车页面实现结算功能,主要是拿到传入后台的gids

二、购物车结算后端功能实现

1.跳转订单页后台,主要是拿到订单页展示数据

2.订单页前台展示

三、生成订单

1.结算页的下单前端

2.结算下单后台实现

四、沙箱支付简介

1.配置沙箱支付

五、沙箱支付应用

1.完成支付宝沙箱支付功能接入

六、支付成功后变更订单状态


一、购物车结算前端功能实现

实现思路

1.购物车页面实现结算功能,主要是拿到传入后台的gids

2.跳转订单页后台,主要是拿到订单页展示数据

3.订单页前台数据展示

1.购物车页面实现结算功能,主要是拿到传入后台的gids

注:使用jquery动态实现结算功能,必须勾选购物车中的商品进行结算,没有勾选无法完成结算功能!!!

测试效果如下:

关于结算按钮的绑定事件

//计算总共几件商品
function zg(){var zsl = 0;var index = $(".th input[type='checkbox']:checked").parents(".th").find(".num span");var len =index.length;if(len==0){$("#sl").text(0);}else{index.each(function(){zsl+=parseInt($(this).text());$("#sl").text(zsl);})}if($("#sl").text()>0){$(".count").css("background","#c10000");//    TODO    绑定结算事件$(".count").bind("click",function () {alert("绑定结算事件");})}else{$(".count").css("background","#8e8e8e");$(".count").unbind("click");}
}

cart.js进行整改     计算总共几件商品

$(function(){/**************数量加减***************/$(".num .sub").click(function(){var num = parseInt($(this).siblings("span").text());if(num<=1){$(this).attr("disabled","disabled");}else{num--;$(this).siblings("span").text(num);//获取除了货币符号以外的数字var price = $(this).parents(".number").prev().text().substring(1);//单价和数量相乘并保留两位小数$(this).parents(".th").find(".sAll").text('¥'+(num*price).toFixed(2));jisuan();zg();//TODO 获取当前行的行索引let index = $(this).parents(".th").index()-1;//获取当前的checkbox中设置的隐藏域(包含了商品ID)let gid=$(".th").eq(index).find('div:eq(0) input[type=hidden]').val();update(num,gid);}});$(".num .add").click(function(){var num = parseInt($(this).siblings("span").text());if(num>=5){confirm("限购5件");}else{num++;$(this).siblings("span").text(num);var price = $(this).parents(".number").prev().text().substring(1);$(this).parents(".th").find(".sAll").text('¥'+(num*price).toFixed(2));jisuan();zg();//TODO 获取当前行的行索引let index = $(this).parents(".th").index()-1;//获取当前的checkbox中设置的隐藏域(包含了商品ID)let gid=$(".th").eq(index).find('div:eq(0) input[type=hidden]').val();update(num,gid);}});//计算总价function jisuan(){var all=0;var len =$(".th input[type='checkbox']:checked").length;if(len==0){$("#all").text('¥'+parseFloat(0).toFixed(2));}else{$(".th input[type='checkbox']:checked").each(function(){//获取小计里的数值var sAll = $(this).parents(".pro").siblings('.sAll').text().substring(1);//累加all+=parseFloat(sAll);//赋值$("#all").text('¥'+all.toFixed(2));})}}//计算总共几件商品function zg(){let gids = "";var zsl = 0;var index = $(".th input[type='checkbox']:checked").parents(".th").find(".num span");var len =index.length;if(len==0){$("#sl").text(0);}else{let gidarr = new Array();index.each(function(){zsl+=parseInt($(this).text());$("#sl").text(zsl);//TODO  获取当前行的索引let idx = $(this).parents(".th").index()-1;console.log(idx);//在这里需要获取当前行商品的商品IDgidarr.push($(".th").eq(idx).find("div:eq(0) input[type='hidden']").val());});gids = gidarr.join(",");}if($("#sl").text()>0){$(".count").css("background","#c10000");$(".count").bind("click",function () {//拿到gidslocation.href='/order/toOrder?gids='+gids});}else{$(".count").css("background","#8e8e8e");$(".count").unbind("click");}}/*****************商品全选***********************/$("input[type='checkbox']").on('click',function(){var sf = $(this).is(":checked");var sc= $(this).hasClass("checkAll");if(sf){if(sc){$("input[type='checkbox']").each(function(){  this.checked=true;  }); zg();jisuan();}else{$(this).checked=true; var len = $("input[type='checkbox']:checked").length;var len1 = $("input").length-1;if(len==len1){$("input[type='checkbox']").each(function(){  this.checked=true;  }); }zg();jisuan();}}else{if(sc){$("input[type='checkbox']").each(function(){  this.checked=false;  }); zg();jisuan();}else{$(this).checked=false;var len = $(".th input[type='checkbox']:checked").length;var len1 = $("input").length-1;if(len<len1){$('.checkAll').attr("checked",false);}zg();jisuan();}}});/****************************proDetail 加入购物车*******************************/$(".btns .cart").click(function(){if($(".categ p").hasClass("on")){var num = parseInt($(".num span").text());var num1 = parseInt($(".goCart span").text());$(".goCart span").text(num+num1);}});//删除购物车商品$('.del').click(function(){//定义商品id 比如:1,2,3,4,5let gids = "";//单个删除if($(this).parent().parent().hasClass("th")){$(".mask").show();$(".tipDel").show();index = $(this).parents(".th").index()-1;//TODO 获取当前的checkbox中设置的隐藏域(包含了商品ID)gids=$(".th").eq(index).find('div:eq(0) input[type=hidden]').val();console.log(gids);$('.cer').click(function(){$(".mask").hide();$(".tipDel").hide();$(".th").eq(index).remove();$('.cer').off('click');if($(".th").length==0){$(".table .goOn").show();}del(gids);})}else{//选中多个一起删除if($(".th input[type='checkbox']:checked").length==0){$(".mask").show();$(".pleaseC").show();}else{$(".mask").show();$(".tipDel").show();//TODO 先获取所有即将被删除的商品IDlet gidarr = new Array();$(".th input[type='checkbox']:checked").each(function(j){gidarr.push($(".th").eq(index).find('div:eq(0) input[type=hidden]').val());// gids += $(".th").eq(index).find('div:eq(0) input[type=hidden]').val();  很容易报数据下标越界异常});gids = gidarr.join(",");$('.cer').click(function(){$(".th input[type='checkbox']:checked").each(function(j){index = $(this).parents('.th').index()-1;$(".th").eq(index).remove();if($(".th").length==0){$(".table .goOn").show();}})$(".mask").hide();$(".tipDel").hide();zg();jisuan();del(gids);})}}})$('.cancel').click(function(){$(".mask").hide();$(".tipDel").hide();})//改变商品规格
//  $(".pro dd").hover(function(){
//      var html='';
//      html='<span class="edit">修改</span>';
//      $(this).addClass("on").append(html).parents(".th").siblings(".th").find(".pro dd").removeClass("on").find('.edit').remove();
//      $(".edit").each(function(i){
//          $(this).attr("id",'edit'+i);
//          $("#edit"+i).click(function(){
//              $(".proDets").show();
//              $(".mask").show();
//              $(".changeBtn .buy").attr("data-id",i);
//          })
//      })
//  },function(){
//      $(this).removeClass("on");
//  })
//  $(".changeBtn .buy").click(function(){
//      var index = $(this).attr("data-id");
//      var result = $(".smallImg .on").find("img").attr("alt");
//      $("#edit"+index).prev().text(result);
//      $(".proDets").hide();
//      $(".mask").hide();
//      $("#edit"+index).parent("dd").removeClass("on").find(".edit").remove();
//  });
//  $(".changeBtn .cart").click(function(){
//      $(".proDets").hide();
//      $(".mask").hide();
//  })
})
//删除商品
function del(gids) {$.post('/shopCar/delete',{'gids':gids},function(rs){if(rs.code!=200)alert(rs.msg);elselocation.href='/shopCar/queryShopCar';},'json');
}//修改商品数量
function update(num,gid){$.post('/shopCar/update',{'gid':gid,'quantity':num},function(rs){if(rs.code!=200)alert(rs.msg);elselocation.href='/shopCar/queryShopCar';},'json');
}

测试结果如下:

二、购物车结算后端功能实现

在点击结算的事件下,添加上跳转地址:

if($("#sl").text()>0){$(".count").css("background","#c10000");$(".count").bind("click",function () {//拿到gidslocation.href='/order/toOrder?gids='+gids});
}else{$(".count").css("background","#8e8e8e");$(".count").unbind("click");
}

先生成订单表,订单信息表 t_order 、t_order_item

打开CodeGenerator.java运行里面的main方法

package com.jwj.spbootpro.generator;import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.InjectionConfig;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;public class CodeGenerator {/*** <p>* 读取控制台内容* </p>*/public static String scanner(String tip) {Scanner scanner = new Scanner(System.in);StringBuilder help = new StringBuilder();help.append("请输入" + tip + ":");System.out.println(help.toString());if (scanner.hasNext()) {String ipt = scanner.next();if (StringUtils.isNotBlank(ipt)) {return ipt;}}throw new MybatisPlusException("请输入正确的" + tip + "!");}public static void main(String[] args) {// 代码生成器AutoGenerator mpg = new AutoGenerator();// 全局配置GlobalConfig gc = new GlobalConfig();String projectPath = System.getProperty("user.dir") + "/spbootpro";gc.setOutputDir(projectPath + "/src/main/java");gc.setAuthor("jwj");gc.setOpen(false);gc.setBaseColumnList(true);gc.setBaseResultMap(true);// gc.setSwagger2(true); 实体属性 Swagger2 注解mpg.setGlobalConfig(gc);// 数据源配置DataSourceConfig dsc = new DataSourceConfig();dsc.setUrl("jdbc:mysql://localhost:3306/spbootpro?useUnicode=true&useSSL=false&characterEncoding=utf8");// dsc.setSchemaName("public");dsc.setDriverName("com.mysql.jdbc.Driver");dsc.setUsername("root");dsc.setPassword("123456");mpg.setDataSource(dsc);// 包配置PackageConfig pc = new PackageConfig();//pc.setModuleName(scanner("模块名"));pc.setParent("com.jwj.spbootpro");//设置包名pc.setEntity("model");mpg.setPackageInfo(pc);// 自定义配置InjectionConfig cfg = new InjectionConfig() {@Overridepublic void initMap() {// to do nothing}};// 如果模板引擎是 freemarkerString templatePath = "/templates/mybatis-generator/mapper2.xml.ftl";// 如果模板引擎是 velocity// String templatePath = "/templates/mapper.xml.vm";// 自定义输出配置List<FileOutConfig> focList = new ArrayList<>();// 自定义配置会被优先输出focList.add(new FileOutConfig(templatePath) {@Overridepublic String outputFile(TableInfo tableInfo) {// 自定义输出文件名 , 如果你 Entity 设置了前后缀、此处注意 xml 的名称会跟着发生变化!!return projectPath + "/src/main/resources/mapper/" + pc.getModuleName()+ "/" + tableInfo.getEntityName() + "Mapper" + StringPool.DOT_XML;}});/*cfg.setFileCreate(new IFileCreate() {@Overridepublic boolean isCreate(ConfigBuilder configBuilder, FileType fileType, String filePath) {// 判断自定义文件夹是否需要创建checkDir("调用默认方法创建的目录,自定义目录用");if (fileType == FileType.MAPPER) {// 已经生成 mapper 文件判断存在,不想重新生成返回 falsereturn !new File(filePath).exists();}// 允许生成模板文件return true;}});*/cfg.setFileOutConfigList(focList);mpg.setCfg(cfg);// 配置模板TemplateConfig templateConfig = new TemplateConfig();// 配置自定义输出模板//指定自定义模板路径,注意不要带上.ftl/.vm, 会根据使用的模板引擎自动识别templateConfig.setMapper("templates/mybatis-generator/mapper2.java");templateConfig.setEntity("templates/mybatis-generator/entity2.java");templateConfig.setService("templates/mybatis-generator/service2.java");templateConfig.setServiceImpl("templates/mybatis-generator/serviceImpl2.java");templateConfig.setController("templates/mybatis-generator/controller2.java");templateConfig.setXml(null);mpg.setTemplate(templateConfig);// 策略配置StrategyConfig strategy = new StrategyConfig();strategy.setNaming(NamingStrategy.underline_to_camel);strategy.setColumnNaming(NamingStrategy.underline_to_camel);//strategy.setSuperEntityClass("你自己的父类实体,没有就不用设置!");strategy.setEntityLombokModel(true);strategy.setRestControllerStyle(true);strategy.setEntitySerialVersionUID(false);// 公共父类//strategy.setSuperControllerClass("你自己的父类控制器,没有就不用设置!");// 写于父类中的公共字段strategy.setSuperEntityColumns("id");strategy.setInclude(scanner("表名,多个英文逗号分割").split(","));strategy.setControllerMappingHyphenStyle(true);strategy.setTablePrefix("t_");mpg.setStrategy(strategy);mpg.setTemplateEngine(new FreemarkerTemplateEngine());mpg.execute();}
}

如下图所示:

生成成功后如果有时间问题都改为Date,因为我们上一次的错误就又出现这样的情况,凡是有带时间的都改过来,就比如生成这个Order.java

1.跳转订单页后台,主要是拿到订单页展示数据

思路

1.从session中获取购物车对象

2.筛选出要结算的订单项列表集合

OrderController.java

package com.jwj.spbootpro.controller;import com.jwj.spbootpro.model.Goods;
import com.jwj.spbootpro.model.User;
import com.jwj.spbootpro.model.vo.ShopCar;
import com.jwj.spbootpro.model.vo.ShopCarItem;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.ModelAndView;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;/*** <p>* 订单信息表 前端控制器* </p>** @author jwj* @since 2022-11-10** @Controller:因为我们最终是要跳转到页面*/
@Controller
@RequestMapping("/order")
public class OrderController {/*** 根据勾选结算的商品跳转到订单页面* @param user* @param gids* @param request* @return*/@RequestMapping("/toOrder")public ModelAndView toOrder(User user,String gids, HttpServletRequest request){ModelAndView mv = new ModelAndView();
//        拿到购物车中的所有商品ShopCar shopCar = getShopCar(user, request);
//        通过gids从购物车中筛选出指定的商品List<ShopCarItem> list = getGoods(shopCar,gids);mv.addObject("goods",list);mv.setViewName("order.html");return mv;}/*** 由于用户结算商品时,不一定是将购物车中所有商品进行结算,有可能只有部分商品* 必须根据前端页面用户勾选的商品ID从购物车中找到对应需要结算的商品并存入* @param shopCar* @param gids* @return*/
//    通过gids从购物车中筛选出指定的商品private List<ShopCarItem> getGoods(ShopCar shopCar, String gids) {//根据逗号分割商品gidsList<String> gidList = Arrays.asList(gids.split(","));//代表购物车中已有的商品集合List<ShopCarItem> items = shopCar.getItems();   //3个    购物车里的商品//定义结算商品集合List<ShopCarItem> itemsNew = new ArrayList<>();//2个    购物车要结算的商品//循环遍历购物车中的商品并与勾选结算的商品ID进行比较for (ShopCarItem item : items) {//判断购物车中的商品与勾选结算的商品ID是否一致if(gidList.contains(item.getGid()+"")){itemsNew.add(item);}}return itemsNew;}//    从session中获取购物车对象private ShopCar getShopCar(User user, HttpServletRequest request){//获取sessionHttpSession session = request.getSession();//从session中获取购物车对象ShopCar shopCar = (ShopCar)session.getAttribute(user.getId() + "_shopCar");//判断shopCar是否为空if(shopCar == null){//初始化购物车对象shopCar = new ShopCar();//将初始化完成的购物车对象根据用户id报错到session中session.setAttribute(user.getId()+"_shopCar",shopCar);}return shopCar;}}

2.订单页前台展示

order.html

<!DOCTYPE html>
<html><head lang="en"><#include "common/head.html"><link rel="stylesheet" type="text/css" href="css/public.css"/><link rel="stylesheet" type="text/css" href="css/proList.css" /><link rel="stylesheet" type="text/css" href="css/mygxin.css" /></head><body><!----------------------------------------order------------------><div class="head ding"><div class="wrapper clearfix"><div class="clearfix" id="top"><h1 class="fl"><a href="${ctx}/"><img src="img/logo.png"/></a></h1><div class="fr clearfix" id="top1"><form action="#" method="get" class="fl"><input type="text" placeholder="搜索" /><input type="button" /></form></div></div></div></div><!-----------------site-------------------><div class="order cart mt"><div class="site"><p class="wrapper clearfix"><span class="fl">订单确认</span><img class="top" src="img/temp/cartTop02.png"></p></div><!-----------------orderCon-------------------><div class="orderCon wrapper clearfix"><div class="orderL fl"><!--------h3----------------><h3>收件信息<a href="#" class="fr">新增地址</a></h3><!--------addres----------------><div class="addres clearfix"><div class="addre fl on"><div class="tit clearfix"><p class="fl">张三1<span class="default">[默认地址]</span></p><p class="fr"><a href="#">删除</a><span>|</span><a href="#" class="edit">编辑</a></p></div><div class="addCon"><p>河北省&nbsp;唐山市&nbsp;路北区&nbsp;大学生公寓村</p><p>15732570937</p></div></div><div class="addre fl"><div class="tit clearfix"><p class="fl">张三2</p><p class="fr"><a href="#" class="setDefault">设为默认</a><span>|</span><a href="#">删除</a><span>|</span><a href="#" class="edit">编辑</a></p></div><div class="addCon"><p>河北省&nbsp;唐山市&nbsp;路北区&nbsp;大学生公寓村</p><p>15732570937</p></div></div><div class="addre fl"><div class="tit clearfix"><p class="fl">张三3</p><p class="fr"><a href="#" class="setDefault">设为默认</a><span>|</span><a href="#">删除</a><span>|</span><a href="#" class="edit">编辑</a></p></div><div class="addCon"><p>河北省&nbsp;唐山市&nbsp;路北区&nbsp;大学生公寓村</p><p>15732570937</p></div></div></div><h3>支付方式</h3><!--------way----------------><div class="way clearfix"><img class="on" value="0" src="img/temp/way01.jpg"><img value="1" src="img/temp/way02.jpg"><img value="2" src="img/temp/way03.jpg"><img value="3" src="img/temp/way04.jpg"></div><h3>选择快递</h3><!--------dis----------------><div class="dis clearfix"><span class="on">顺风快递</span><span>百世汇通</span><span>圆通快递</span><span>中通快递</span></div></div> <div class="orderR fr"><div class="msg"><h3>订单内容<a href="${ctx}/shopCar/queryShopCar" class="fr">返回购物车</a></h3><#if goods??><#list goods as g><ul class="clearfix"><li class="fl"><img style="height: 87px;width: 87px;" src="${g.goodsImg}"></li><li class="fl"><p>${g.goodsName}</p><p>颜色分类:烟灰色玻璃瓶</p><p>数量:${g.quantity}</p></li><li class="fr">¥${g.goodsPrice}</li></ul></#list></#if></div><!--------tips----------------><div class="tips"><p><span class="fl">商品金额:</span><span class="fr">¥139.8</span></p><p><span class="fl">优惠金额:</span><span class="fr">¥0.00</span></p><p><span class="fl">运费:</span><span class="fr">免运费</span></p></div><!--------tips count----------------><div class="count tips"><p><span class="fl">合计:</span><span class="fr">¥139.8</span></p></div><!--<input type="button" name="" value="去支付"> --><a href="javascript:void(0);" class="pay">去支付</a></div></div></div><!--编辑弹框--><!--遮罩--><div class="mask"></div><div class="adddz editAddre"><form action="#" method="get"><input type="text" placeholder="姓名" class="on" /><input type="text" placeholder="手机号" /><div class="city"><select name=""><option value="省份/自治区">省份/自治区</option></select><select><option value="城市/地区">城市/地区</option></select><select><option value="区/县">区/县</option></select><select><option value="配送区域">配送区域</option></select></div><textarea name="" rows="" cols="" placeholder="详细地址"></textarea><input type="text" placeholder="邮政编码" /><div class="bc"><input type="button" value="保存" /><input type="button" value="取消" /></div></form></div><!--返回顶部--><input type="hidden" id="gids" value="${RequestParameters['gids']!}"/><#include "common/footer.html"><script src="js/others/order.js" type="text/javascript" charset="utf-8"></script><script src="js/public.js" type="text/javascript" charset="utf-8"></script><script src="js/pro.js" type="text/javascript" charset="utf-8"></script><script src="js/user.js" type="text/javascript" charset="utf-8"></script></body>
</html>

展示结果如下:

结算如下所示:

三、生成订单

实现思路

1.前台订单相关数据获取

2.后台进行下单操作

1.结算页的下单前端

前端相关处理

1.获取收货地址、收货人以及联系电话

2.获取支付方式

获取快递方式


在Order.html添加Order.js

Order.js代码如下:

$(function () {$(".pay").click(function () {// 1)获取收货地址、收货人以及联系电话let name=$('.addres').find('div.on div:eq(0)>p:eq(0)').text().trim();let address=$('.addres').find('div.on div:eq(1)>p:eq(0)').text();let phone=$('.addres').find('div.on div:eq(1)>p:eq(1)').text();console.log("name=%s,address=%s,phone=%s",name,address,phone);// 2)获取支付方式let pay=$('.way').find('img.on').attr('value');console.log(pay);// 3)获取快递方式let dis=$('.dis').find('span.on').text();console.log(dis);//获取勾选结算的商品IDlet gids=$('#gids').val();//拼接请求参数let params={gids:gids,address:address,person:name,telephone:phone,pay:pay,mail:dis};console.log(params);$.post('/order/addOrder',params,function(rs){if(rs.code==200){location.href='/page/ok.html';}else{alert(rs.msg);}},'json');});
});

2.结算下单后台实现

建一个OrderDto.java为了处理在order.js里去写大量的js代码

OrderDto.java

package com.jwj.spbootpro.model.dto;import com.jwj.spbootpro.model.Order;
import lombok.Data;/*** @author 敢敢* @site www.javajwj.com* @company xxx公司* @create  2022-11-10 18:23*/
@Data
public class OrderDto extends Order {private String gids;
}

OrderController.java

package com.jwj.spbootpro.controller;import com.jwj.spbootpro.model.Goods;
import com.jwj.spbootpro.model.User;
import com.jwj.spbootpro.model.dto.OrderDto;
import com.jwj.spbootpro.model.vo.ShopCar;
import com.jwj.spbootpro.model.vo.ShopCarItem;
import com.jwj.spbootpro.service.IOrderService;
import com.jwj.spbootpro.utils.JsonResponseBody;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.ModelAndView;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;/*** <p>* 订单信息表 前端控制器* </p>** @author jwj* @since 2022-11-10** @Controller:因为我们最终是要跳转到页面*/
@Controller
@RequestMapping("/order")
public class OrderController {/*** 根据勾选结算的商品跳转到订单页面* @param user* @param gids* @param request* @return*/@RequestMapping("/toOrder")public ModelAndView toOrder(User user,String gids, HttpServletRequest request){ModelAndView mv = new ModelAndView();
//        拿到购物车中的所有商品ShopCar shopCar = getShopCar(user, request);
//        通过gids从购物车中筛选出指定的商品List<ShopCarItem> list = getGoods(shopCar,gids);mv.addObject("goods",list);mv.setViewName("order.html");return mv;}/*** 由于用户结算商品时,不一定是将购物车中所有商品进行结算,有可能只有部分商品* 必须根据前端页面用户勾选的商品ID从购物车中找到对应需要结算的商品并存入* @param shopCar* @param gids* @return*/
//    通过gids从购物车中筛选出指定的商品private List<ShopCarItem> getGoods(ShopCar shopCar, String gids) {//根据逗号分割商品gidsList<String> gidList = Arrays.asList(gids.split(","));//代表购物车中已有的商品集合List<ShopCarItem> items = shopCar.getItems();   //3个    购物车里的商品//定义结算商品集合List<ShopCarItem> itemsNew = new ArrayList<>();//2个    购物车要结算的商品//循环遍历购物车中的商品并与勾选结算的商品ID进行比较for (ShopCarItem item : items) {//判断购物车中的商品与勾选结算的商品ID是否一致if(gidList.contains(item.getGid()+"")){itemsNew.add(item);}}return itemsNew;}//    从session中获取购物车对象private ShopCar getShopCar(User user, HttpServletRequest request){//获取sessionHttpSession session = request.getSession();//从session中获取购物车对象ShopCar shopCar = (ShopCar)session.getAttribute(user.getId() + "_shopCar");//判断shopCar是否为空if(shopCar == null){//初始化购物车对象shopCar = new ShopCar();//将初始化完成的购物车对象根据用户id报错到session中session.setAttribute(user.getId()+"_shopCar",shopCar);}return shopCar;}  @Autowiredprivate IOrderService orderService;@ResponseBody@RequestMapping("/addOrder")//非ajax返回的ModelAndView,ajax返回的是JsonResponseBodypublic JsonResponseBody addOrder(User user, OrderDto orderDto,HttpServletRequest request){// 1.拿到购物车 2.通过orderDto拿到gids,再拿到要结算的商品 3.数据要入订单表 4.数据要入订单项表//获取购物车ShopCar shopCar = this.getShopCar(user, request);//获取结算商品集合List<ShopCarItem> shopCarItems = this.getGoods(shopCar, orderDto.getGids());//生成订单及订单项orderDto.setUserId(user.getId());orderService.addOrder(orderDto,shopCarItems);//从购物车中删除已结算的商品shopCar.delete(orderDto.getGids());//跳转支付页面return new JsonResponseBody();}
}

IOrderService.java创建addOrder方法

package com.jwj.spbootpro.service;import com.jwj.spbootpro.model.Order;
import com.baomidou.mybatisplus.extension.service.IService;
import com.jwj.spbootpro.model.dto.OrderDto;
import com.jwj.spbootpro.model.vo.ShopCarItem;import java.util.List;/*** <p>* 订单信息表 服务类* </p>** @author jwj* @since 2022-11-10*/
public interface IOrderService extends IService<Order> {void addOrder(OrderDto orderDto, List<ShopCarItem> shopCarItems);
}

在我们的实现类也要实现addOrder方法

OrderServiceImpl.java

package com.jwj.spbootpro.service.impl;import com.jwj.spbootpro.model.Order;
import com.jwj.spbootpro.mapper.OrderMapper;
import com.jwj.spbootpro.model.OrderItem;
import com.jwj.spbootpro.model.dto.OrderDto;
import com.jwj.spbootpro.model.vo.ShopCarItem;
import com.jwj.spbootpro.service.IOrderItemService;
import com.jwj.spbootpro.service.IOrderService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jwj.spbootpro.utils.SnowFlake;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;/*** <p>* 订单信息表 服务实现类* </p>** @author jwj* @since 2022-11-10*/
@Service
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements IOrderService {@Autowiredprivate OrderMapper orderMapper;@Autowiredprivate IOrderItemService orderItemService;//    @Transactional注解:以下的方法因为同时设置到两张表的增删改的操作,要么同时成功,要么同时失败@Transactional@Overridepublic void addOrder(OrderDto orderDto, List<ShopCarItem> shopCarItems) {
//        订单表以及订单项表的数据录入//1) 生成订单ID     SnowFlake生成雪花ID,它的作用,生成一个随机的long类型的数字;
//        相比较于UUID的优点在于,雪花ID可以排序SnowFlake snowFlake = new SnowFlake(2, 3);Long orderId=snowFlake.nextId();orderDto.setOid(orderId);//2) 循环勾选的商品集合计算商品总价、获取商品详情集合//总价BigDecimal total=BigDecimal.valueOf(0);//定义商品详情集合List<OrderItem> orderItems=new ArrayList<>();OrderItem it=null;for (ShopCarItem shopCarItem : shopCarItems) {//累加小计等于总价total=total.add(shopCarItem.smalltotal());//初始化OrderItem商品详情对象it=new OrderItem();
//          订单项表的ooid为自增,所以不需要设置it.setOid(orderId);it.setGid(shopCarItem.getGid());it.setGoodsName(shopCarItem.getGoodsName());it.setGoodsPrice(shopCarItem.getGoodsPrice());it.setQuantity(shopCarItem.getQuantity());orderItems.add(it);}orderDto.setTotal(total);//1.保存订单orderMapper.insert(orderDto);//2.保存订单对应的订单项orderItemService.saveBatch(orderItems);}
}

给我们OrderMapper添加注解@repository,

同时还要OrderItemMapper也要添加注解@repository

SnowFlake.java 放到我们的util里面去

这是我们的雪花算法,把我们的id转成一个long类型的随机的一个数字

想比较于UUID的优点在于,雪花ID可以排序 

package com.jwj.spbootpro.utils;public class SnowFlake {/*** 起始的时间戳*/private final static long START_STMP = 1480166465631L;/*** 每一部分占用的位数*/private final static long SEQUENCE_BIT = 12; //序列号占用的位数private final static long MACHINE_BIT = 5;   //机器标识占用的位数private final static long DATACENTER_BIT = 5;//数据中心占用的位数/*** 每一部分的最大值*/private final static long MAX_DATACENTER_NUM = -1L ^ (-1L << DATACENTER_BIT);private final static long MAX_MACHINE_NUM = -1L ^ (-1L << MACHINE_BIT);private final static long MAX_SEQUENCE = -1L ^ (-1L << SEQUENCE_BIT);/*** 每一部分向左的位移*/private final static long MACHINE_LEFT = SEQUENCE_BIT;private final static long DATACENTER_LEFT = SEQUENCE_BIT + MACHINE_BIT;private final static long TIMESTMP_LEFT = DATACENTER_LEFT + DATACENTER_BIT;private long datacenterId;  //数据中心private long machineId;     //机器标识private long sequence = 0L; //序列号private long lastStmp = -1L;//上一次时间戳public SnowFlake(long datacenterId, long machineId) {if (datacenterId > MAX_DATACENTER_NUM || datacenterId < 0) {throw new IllegalArgumentException("datacenterId can't be greater than MAX_DATACENTER_NUM or less than 0");}if (machineId > MAX_MACHINE_NUM || machineId < 0) {throw new IllegalArgumentException("machineId can't be greater than MAX_MACHINE_NUM or less than 0");}this.datacenterId = datacenterId;this.machineId = machineId;}/*** 产生下一个ID** @return*/public synchronized long nextId() {long currStmp = getNewstmp();if (currStmp < lastStmp) {throw new RuntimeException("Clock moved backwards.  Refusing to generate id");}if (currStmp == lastStmp) {//相同毫秒内,序列号自增sequence = (sequence + 1) & MAX_SEQUENCE;//同一毫秒的序列数已经达到最大if (sequence == 0L) {currStmp = getNextMill();}} else {//不同毫秒内,序列号置为0sequence = 0L;}lastStmp = currStmp;return (currStmp - START_STMP) << TIMESTMP_LEFT //时间戳部分| datacenterId << DATACENTER_LEFT       //数据中心部分| machineId << MACHINE_LEFT             //机器标识部分| sequence;                             //序列号部分}private long getNextMill() {long mill = getNewstmp();while (mill <= lastStmp) {mill = getNewstmp();}return mill;}private long getNewstmp() {return System.currentTimeMillis();}public static void main(String[] args) {SnowFlake snowFlake = new SnowFlake(2, 3);long start = System.currentTimeMillis();for (int i = 0; i < 1000000; i++) {System.out.println(snowFlake.nextId());}System.out.println(System.currentTimeMillis() - start);}
}

测试效果如下图所示:

我们数据库里目前是没有数据的,如下所示:

注意:这里的数据库里面要自动增长,如果没有很可能会出错。

最终跳转到结算成功页面,5s后自动跳转到订单展示页面,如下图所示:

在看一下我们数据库有没有数据,如下所示:

四、沙箱支付简介

1.配置沙箱支付

第一步:

1)登陆支付宝:https://open.alipay.com/

点击登录:扫码登录

2)首页找到进入管理中心 ---》开发工具推荐选择【沙箱】

3)下载安装支付宝开放平台开发助手:

密钥工具简介 | 开放平台

下载好之后就是这样的,我下载的安卓的

4)打开本地支付宝开放平台助手---》密钥工具---》生成密钥---》以默认的方式(RSA2和KCS8)生成应用私钥和应用公钥

注意:密钥是留给自己用的 ,公钥是copy出去的

5)在沙箱应用的开发信息中选择自定义密钥生成支付宝公钥(基于应用公钥生成支付宝公钥)

第二步:配置沙箱账号(买家)并完成手动充值

登录 - 支付宝

第三步:下载沙箱支付宝(只支持安卓)

沙箱工具---》支付宝客户端沙箱版---》请使用浏览器中的扫码功能扫码下载

注:请使用Android手机扫码下载支付宝客户端沙箱版;如需登录,请访问沙箱账号,在商家信息中获取账密

通过这个扫码它就会自动下载,下载沙箱支付宝APP的安装包,下载好了之后,这里面默认会有100万块钱或者其他,可以通过下面这种方式,进行充值。

五、沙箱支付应用

实现思路

1.完成支付宝沙箱支付功能接入

2.支付成功后变更订单状态

1.完成支付宝沙箱支付功能接入

根据官方网站开发文档进行支付宝接入

Easy 版 | 开放平台

先在支付宝开放平台密钥工具,生成密钥,把我们的 应用公钥复制到

注意:上面的支付宝公钥复制了之后要记得点击确定。

把我们的支付宝公钥复制到我们的代码里面AlipayConfig类里的支付宝公钥

那么下面这里我封装了一版,封装类版,配置类

AlipayConfig.java

package com.jwj.spbootpro.config;import com.alipay.easysdk.factory.Factory;
import com.alipay.easysdk.kernel.Config;
import com.alipay.easysdk.payment.page.models.AlipayTradePagePayResponse;
import com.jwj.spbootpro.model.dto.OrderDto;/*** 支付宝沙箱支付*/
public class AlipayConfig {public String goAlipay(OrderDto orderDto){try {// 1. 设置参数(全局只需设置一次)Factory.setOptions(aliconfig());// 2. 发起API调用(subject商品标题、outTradeNo订单编号、totalAmount总金额、returnUrl异步通知地址)AlipayTradePagePayResponse response = Factory.Payment.Page().pay(orderDto.getOid()+"",orderDto.getOid()+"",orderDto.getTotal().toString(),"http://localhost:8081/page/ok.html");  //支付成功之后的异步通知(跳出到自己系统的哪个位置)System.out.println(response.body);return response.body;}  catch (Exception e) {e.printStackTrace();throw new RuntimeException(e);}}private Config aliconfig(){Config config=new Config();//沙箱支付宝地址config.gatewayHost="openapi.alipaydev.com";//协议httpsconfig.protocol="https";//应用ID,您的APPID,收款账号既是您的APPID对应支付宝账号config.appId="2021000121687583";//支付宝公钥config.alipayPublicKey="MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsc74PulHrpMlGXt53c1CYfBziNjY9W299fXA5aU3f+eKKNnjc9fmUXYusGms0MgSSYgji4SuAfl1LxtRJEwqz8L7zxOxq0JB6Y5+XFXiSpdys4f6wMJXoaRWamEzfaSkpgoJ6vO+VqJa+j77Brc//mxRtHjrcS3xW5doUBOsAAdofjwaaWgcT2cmzb3r/QEXu4vfrOdV4uuXD5GWJ7bIYTDuRsRBL8iBPtqv1OkB6184f2t0Qch0g6Pyti/cg10BB5s/i9uUCqHCtHl5CQrpubQc6hYb4mmp8ZXLvqfPAmq0fgABDQklCPdww7qML6cATsv+WZF+f5NsxVPOgYPeQwIDAQAB";//签名方式config.signType="RSA2";//商户私钥(应用私钥),您的PKCS8格式RSA2私钥config.merchantPrivateKey="MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCG0psRs7/OH5gLmjpvlINXDMPOMIlLk8oqP1KdeKBHTOejsk01PyN6zqS0rzqmYHRNMCFsZnX1JvpqvZ8F0Vcw8FSzTGXGLyvAufqic5dIASb91qcF/4QSnoFzNVhIp6KSUsWlpY87bHkRZlLY3sseHu8M4HWOJmr1XidvIFpozxDmc5EgA0tHqogcth6ncW3uGXtNtKg840hejawhpEryCXNPbPK0pq1P95iWpmV+YtxTUWSfFTgjc88JPCaNSfhpPx11Up3oDHsMa+RlsKD1xaetLzjfPwoU73ymPVo0ii88z/KrzdNKfTE0Mkm4GQbID31GJ4yhYW/jsLNUQs+vAgMBAAECggEAN8TEOjVVQMkW1q3MQD15eregAxlWoXmXpZQd819jRTsNkkv93empHnJ99POK2imJ0if3m2RipK6j5SVcs0Zdv7OaBbSzYKBAg+8qOqp/yFwZqeRxoGyKUD1apLJLO3qEJ+yvLw7lyZncFpNx751w/ZukHHp4hf1kPuzceP40B6gH8h8BIJTpYItP3fVYrECjJ94Yr68OAQZ1pvlwK68b1HD68MIInHZIeZ9QYpzfMoCk/6wNYE31yYuoUpkmoENuCrA2r/G2xOQBVwgIO8pPyJ7WQCC5/jtFu8pbob8HBb2QHAUfvYj+MXtxglC8cHZmXECW7+mc61YRFCS7AlnmkQKBgQD0prghOEQdp1zCw0y2yfhmLhwfARyZUFZbOe4yuKuWitsuG3c7t8JCPiT3ifXzRnyoG3ticQxctFtfsBmGFzNxk+Y7fyexzN5EMcwD6wGIstemxumF76ts4Ycj4iiuotxbqJ/gw/xPHcL03AZTMokO1+HR78xjHLXjl0LshgK9pwKBgQCNE6arORAsnvJnC5scDsE2IYcbB13+eRKed2I5KAIMfEnXYRIscI413dujU3vR85s6ed91+vifh6wchwtdngX/eJ7V5Diz7m46hvGDH7YAe9RbSD9QaedDf2z/kotKV6m16Wlwy64DCEUlyVkaw3I7qOjrezfATQLWqbsimCZuuQKBgGvEyRVxGKhLYhQ1PaTDYVV5eE+8CKIMfo3e/et/563/6r7rwGEg+ER/5X7ZWetZIG5Y9MgPblej5yBGjWfA7ptYgDGzOIQc78fwe6M6MUnLJi3EL3gddFEZI5ON+0e6XAFQTWUQUCN1w7xi87JQb4mHVWVKEamTKxhfOE7CVZC/AoGAHA2UTugB912EBkmghmvIr+Lq4s0MO9YHhctnlMYH4kO0y0daPcwD+2Iqkse/D3jJnU8uyF8noVFxQBr6f5s0xiBONWo0fFMlSC4dSF2960q0Z5JuRKdKfXmRSyDw4c+cx7eqZ+uYprG2TlVDirbiuEpWRr0x0ON/dQA7Xh2zRsECgYEAj4iagNb8hBqJOPLBLzca3qLbUmdrGMVSEbXxyJaR6RP9C4SFeuJTh09LqVcFuss+jw7GaCJ74j1a2xQuKDF1xlfO7krb32EV0KGnrMtVwTCyT7LVcugPw+rsd97pros85jZhigARiSUA3vKpQf0bA7BEfq2RFSVKZ9fdHVsUSAM=";return config;}
}

我们支付成功之后就要跳转到最终的那个页面了,然而我们之前是直接跳转到最终页面了,现在就不可以了。

order.js 就要变更如下:        支付会引发页面跳转,所以要经ajax请求换成页面跳转的方式

$(function(){$('.pay').click(function(){alert("11");//获取收货地址、联系人、联系电话let name=$('.addres').find('div.on div:eq(0)>p:eq(0)').text().trim();let address=$('.addres').find('div.on div:eq(1)>p:eq(0)').text();let phone=$('.addres').find('div.on div:eq(1)>p:eq(1)').text();console.log("name=%s,address=%s,phone=%s",name,address,phone);//获取支付方式let pay=$('.way').find('img.on').attr('value');console.log(pay);//获取快递方式let dis=$('.dis').find('span.on').text();console.log(dis);//获取勾选结算的商品IDlet gids=$('#gids').val();//拼接请求参数let params={gids:gids,address:address,person:name,telephone:phone,pay:pay,mail:dis};console.log(params);// $.post('/order/addOrder',params,function(rs){//     if(rs.code==200){//         location.href='/page/ok.html';//     }else{//         alert(rs.msg);//     }// },'json');//一般的支付成功网址都是很长就列如:http://localhost:8080/order/addOrder?gids=sjdksjljfdsjw&djfsj&name=jssjdj location.href="/order/addOrder?"+parseParams(params);
});
});/*** JSON转URL参数* @param data* @returns {string}*/
function parseParams(data) {try {var tempArr = [];for (var i in data) {var key = encodeURIComponent(i);var value = encodeURIComponent(data[i]);tempArr.push(key + '=' + value);}var urlParamsStr = tempArr.join('&');return urlParamsStr;} catch (err) {return '';}
}

OrderController.java代码也要变更如下:

@Autowired
private IOrderService orderService;@RequestMapping("/addOrder")
@ResponseBody
//非ajax返回的ModelAndView,ajax返回的是JsonResponseBody
public String addOrder(User user, OrderDto orderDto,HttpServletRequest request){// 1.拿到购物车 2.通过orderDto拿到gids,再拿到要结算的商品 3.数据要入订单表 4.数据要入订单项表//获取购物车ShopCar shopCar = this.getShopCar(user, request);//获取结算商品集合List<ShopCarItem> shopCarItems = this.getGoods(shopCar, orderDto.getGids());//生成订单及订单项orderDto.setUserId(user.getId());orderService.addOrder(orderDto,shopCarItems);//从购物车中删除已结算的商品shopCar.delete(orderDto.getGids());//跳转支付页面 AlipayConfig alipayConfig = new AlipayConfig();return alipayConfig.goAlipay(orderDto);
}

测试如下:为了方便我们测试,我又把数据清空掉了


成功了

来看一下我们买家的金额

看一下我们的数据库里有没有数据

六、支付成功后变更订单状态

OrderController.java 代码新增如下:

/*** 支付成功后回调处理订单状态,完成整个下单流程的链路* @param param* @return*/
@RequestMapping("/orderFinish")
public String orderFinish(@RequestParam Map<String, String> param){System.out.println("异步回调开始。。。。。。");Boolean signVerified=false;try {System.out.println(param);signVerified = Factory.Payment.Common().verifyNotify(param);System.out.println(signVerified);System.out.println("out_trade_no:"+param.get("out_trade_no"));System.out.println("total_amount:"+param.get("total_amount"));System.out.println("trade_no:"+param.get("trade_no"));if(signVerified){//支付成功//根据订单编号修改订单状态//update t_xxx set xx=?,tt=? where id=?orderService.update(new UpdateWrapper<Order>().set("status",1).setSql("pay_date=now()").eq("oid",param.get("out_trade_no")));//跳转到支付成功页面}else{//支付失败}} catch (Exception e) {e.printStackTrace();}return "ok.html";
}

AlipayConfig.java 变更如下:

package com.jwj.spbootpro.config;import com.alipay.easysdk.factory.Factory;
import com.alipay.easysdk.kernel.Config;
import com.alipay.easysdk.payment.page.models.AlipayTradePagePayResponse;
import com.jwj.spbootpro.model.dto.OrderDto;/*** 支付宝沙箱支付*/
public class AlipayConfig {public String goAlipay(OrderDto orderDto){try {// 1. 设置参数(全局只需设置一次)Factory.setOptions(aliconfig());// 2. 发起API调用(subject商品标题、outTradeNo订单编号、totalAmount总金额、returnUrl异步通知地址)AlipayTradePagePayResponse response = Factory.Payment.Page().pay(orderDto.getOid()+"",orderDto.getOid()+"",orderDto.getTotal().toString(),
//                            "http://localhost:8081/page/ok.html");  //支付成功之后的异步通知(跳出到自己系统的哪个位置) "http://localhost:8081/order/orderFinish");  //支付成功之后的异步通知(跳出到自己系统的哪个位置)System.out.println(response.body);return response.body;}  catch (Exception e) {e.printStackTrace();throw new RuntimeException(e);}}private Config aliconfig(){Config config=new Config();//沙箱支付宝地址config.gatewayHost="openapi.alipaydev.com";//协议httpsconfig.protocol="https";//应用ID,您的APPID,收款账号既是您的APPID对应支付宝账号config.appId="2021000121687583";//支付宝公钥config.alipayPublicKey="MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsc74PulHrpMlGXt53c1CYfBziNjY9W299fXA5aU3f+eKKNnjc9fmUXYusGms0MgSSYgji4SuAfl1LxtRJEwqz8L7zxOxq0JB6Y5+XFXiSpdys4f6wMJXoaRWamEzfaSkpgoJ6vO+VqJa+j77Brc//mxRtHjrcS3xW5doUBOsAAdofjwaaWgcT2cmzb3r/QEXu4vfrOdV4uuXD5GWJ7bIYTDuRsRBL8iBPtqv1OkB6184f2t0Qch0g6Pyti/cg10BB5s/i9uUCqHCtHl5CQrpubQc6hYb4mmp8ZXLvqfPAmq0fgABDQklCPdww7qML6cATsv+WZF+f5NsxVPOgYPeQwIDAQAB";//签名方式config.signType="RSA2";//商户私钥(应用私钥),您的PKCS8格式RSA2私钥config.merchantPrivateKey="MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCG0psRs7/OH5gLmjpvlINXDMPOMIlLk8oqP1KdeKBHTOejsk01PyN6zqS0rzqmYHRNMCFsZnX1JvpqvZ8F0Vcw8FSzTGXGLyvAufqic5dIASb91qcF/4QSnoFzNVhIp6KSUsWlpY87bHkRZlLY3sseHu8M4HWOJmr1XidvIFpozxDmc5EgA0tHqogcth6ncW3uGXtNtKg840hejawhpEryCXNPbPK0pq1P95iWpmV+YtxTUWSfFTgjc88JPCaNSfhpPx11Up3oDHsMa+RlsKD1xaetLzjfPwoU73ymPVo0ii88z/KrzdNKfTE0Mkm4GQbID31GJ4yhYW/jsLNUQs+vAgMBAAECggEAN8TEOjVVQMkW1q3MQD15eregAxlWoXmXpZQd819jRTsNkkv93empHnJ99POK2imJ0if3m2RipK6j5SVcs0Zdv7OaBbSzYKBAg+8qOqp/yFwZqeRxoGyKUD1apLJLO3qEJ+yvLw7lyZncFpNx751w/ZukHHp4hf1kPuzceP40B6gH8h8BIJTpYItP3fVYrECjJ94Yr68OAQZ1pvlwK68b1HD68MIInHZIeZ9QYpzfMoCk/6wNYE31yYuoUpkmoENuCrA2r/G2xOQBVwgIO8pPyJ7WQCC5/jtFu8pbob8HBb2QHAUfvYj+MXtxglC8cHZmXECW7+mc61YRFCS7AlnmkQKBgQD0prghOEQdp1zCw0y2yfhmLhwfARyZUFZbOe4yuKuWitsuG3c7t8JCPiT3ifXzRnyoG3ticQxctFtfsBmGFzNxk+Y7fyexzN5EMcwD6wGIstemxumF76ts4Ycj4iiuotxbqJ/gw/xPHcL03AZTMokO1+HR78xjHLXjl0LshgK9pwKBgQCNE6arORAsnvJnC5scDsE2IYcbB13+eRKed2I5KAIMfEnXYRIscI413dujU3vR85s6ed91+vifh6wchwtdngX/eJ7V5Diz7m46hvGDH7YAe9RbSD9QaedDf2z/kotKV6m16Wlwy64DCEUlyVkaw3I7qOjrezfATQLWqbsimCZuuQKBgGvEyRVxGKhLYhQ1PaTDYVV5eE+8CKIMfo3e/et/563/6r7rwGEg+ER/5X7ZWetZIG5Y9MgPblej5yBGjWfA7ptYgDGzOIQc78fwe6M6MUnLJi3EL3gddFEZI5ON+0e6XAFQTWUQUCN1w7xi87JQb4mHVWVKEamTKxhfOE7CVZC/AoGAHA2UTugB912EBkmghmvIr+Lq4s0MO9YHhctnlMYH4kO0y0daPcwD+2Iqkse/D3jJnU8uyF8noVFxQBr6f5s0xiBONWo0fFMlSC4dSF2960q0Z5JuRKdKfXmRSyDw4c+cx7eqZ+uYprG2TlVDirbiuEpWRr0x0ON/dQA7Xh2zRsECgYEAj4iagNb8hBqJOPLBLzca3qLbUmdrGMVSEbXxyJaR6RP9C4SFeuJTh09LqVcFuss+jw7GaCJ74j1a2xQuKDF1xlfO7krb32EV0KGnrMtVwTCyT7LVcugPw+rsd97pros85jZhigARiSUA3vKpQf0bA7BEfq2RFSVKZ9fdHVsUSAM=";return config;}
}

测试如下:

看看我们的数据库时间有没有,状态发生改变没有如下:

网上商城项目(购物车下单、支付)相关推荐

  1. 【SSH网上商城项目实战21】从Demo中看易宝支付的流程

    这一节我们先写一个简单点的Demo来测试易宝支付的流程,熟悉这个流程后,再做实际的开发,因为是一个Demo,所以我没有考虑一些设计模式的东西,就是直接实现支付功能.实现支付功能需要易宝给我们提供的AP ...

  2. Django框架学习之网上商城项目一(后端设计)

    目录 一.项目需求分析 1.项目介绍 1.技术难点 2.系统功能 3.项目环境 4.后台管理页面 二.数据库模型设计 一.准备工作 二.用户认证数据库模型设计 1. app/users/models. ...

  3. 十七、网上商城项目(1)

    本章概要 脚手架项目搭建 安装与配置 axios 首页 页面头部组件 头部搜索框组件 头部购物车组件 头部组件 本章结合前面所学知识,开发一个网上商城项目. 成品如下 17.1 脚手架项目搭建 选择好 ...

  4. 【SSH网上商城项目实战16】Hibernate的二级缓存处理首页的热门显示

    转自:https://blog.csdn.net/eson_15/article/details/51405911 网上商城首页都有热门商品,那么这些商品的点击率是很高的,当用户点击某个热门商品后需要 ...

  5. java web网上商城项目实战与源码

    java web网上商城项目实战与源码 点击这里,轻松完成毕设https://x-x.fun/i/AAbf595445aBT

  6. 商城项目购物车的实现

    商城项目购物车的实现 一,新建购物车的实体类Cart 二,在选择商品类型页面进行页面跳转 三,在controller进行添加商品对象并记入session 四,购物车页面接收购物车信息并展示 五,补充说 ...

  7. 商城项目中信息的集合怎么存储_网上商城项目_数据库设计说明书.doc

    秘密 第 PAGE 2 页 共 NUMPAGES 10 页 信用卡网上商城项目 数据库设计说明书 文件修订历史 修订时间 修订说明 作者 审核 2010.08.05 编写数据字典 谭星佑 曾玉贞 20 ...

  8. 【SSH网上商城项目实战】之环境搭建填坑

    此篇主要是记录我在从零开始走一遍倪升武大神的[SSH网上商城项目实战]过程中遇到的一些坑并记录解决方法.关于这个项目,大家可以去倪升武的博客学习了解,SSH网上商城项目实战请戳倪升武的项目实战专题. ...

  9. 【SSH网上商城项目实战20】在线支付平台的介绍

    之前已经完成了首页的显示,用户添加购物车,确认订单等功能,下面就是支付功能的开发了.用户确认了订单后会直接跳转到支付页面进行在线支付,在线支付需要第三方的接口,这一节主要介绍一些关于第三方支付的内容, ...

  10. 【SSH网上商城项目实战23】完成在线支付功能

    转自:https://blog.csdn.net/eson_15/article/details/51464415 上一节我们做好了支付页面的显示,从上一节支付页面显示的jsp代码中可以看出,当用户点 ...

最新文章

  1. 采摘工人月薪十万却无人应聘,英澳农场求助 AI
  2. WEB学习-CSS盒模型
  3. python 內建数据类型
  4. JdbcTemplate+PageImpl实现多表分页查询
  5. java map 数组_java技术Spring集合属性
  6. 用jQuery实现一些导航条切换,显示隐藏
  7. iOS面试中经常问的点 - RunTime
  8. oracle not like优化,Oracle中的like优化
  9. mysql 取汉字笔划数_PHP获取汉字笔画数功能【测试可用】
  10. oppo手机解锁_oppo手机密码解锁大全【图文】
  11. 两次碰到编译错误: crosses initialization of...
  12. 【php环境搭建/wamp/解释器/下载】
  13. 吐血总结:国内外App制作平台大集合,总有一款适合你
  14. 跟领导汇报工作时,这句话建议你不要说
  15. Microsoft Edge浏览器一款不同于传统IE的浏览器
  16. 易基因|3文聚焦:宏病毒组测序在肠病中的应用研究
  17. python的字节码(ByteCode)
  18. 贯珠者说—一切荣誉归老板
  19. Python学习 matplotlib库 霍兰德人格分析雷达图
  20. 如何设计出更好的 API ?

热门文章

  1. AD_Copy Room
  2. 手机银行APP评测系列:天津银行持续优化手机银行用户体验,但仍需加强细节提升
  3. var foo = 11+2+1; console.log(foo); //1121 好多文章答案写错了,我发下给初学的朋友看到,以免一开始就学错了...
  4. 生成式对抗网络(GAN)实战——书法字体生成练习赛
  5. 小白学习MySQL - 不同版本创建用户的些许区别
  6. java实验报告6:异常处理程序设计
  7. bzoj1724【Usaco2006 Nov】Fence Repair 切割木板
  8. 搭建Prometheus监控报警
  9. 【C语言】求Sn=a+aa+aaa+aaaa+aaaaa的前5项之和,其中a是一个数字
  10. IEEE754标准转换