• 网上商城项目(购物车下单、支付)


    目录

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

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

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

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

    2.订单页前台展示 

    三、生成订单

    1.结算页的下单前端

     2.结算下单后台实现

     四、沙箱支付简介

    1.配置沙箱支付

     五、沙箱支付应用

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

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


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

     实现思路

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

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

    3.订单页前台数据展示

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

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

    测试效果如下:

    关于结算按钮的绑定事件

    1. //计算总共几件商品
    2. function zg(){
    3. var zsl = 0;
    4. var index = $(".th input[type='checkbox']:checked").parents(".th").find(".num span");
    5. var len =index.length;
    6. if(len==0){
    7. $("#sl").text(0);
    8. }else{
    9. index.each(function(){
    10. zsl+=parseInt($(this).text());
    11. $("#sl").text(zsl);
    12. })
    13. }
    14. if($("#sl").text()>0){
    15. $(".count").css("background","#c10000");
    16. // TODO 绑定结算事件
    17. $(".count").bind("click",function () {
    18. alert("绑定结算事件");
    19. })
    20. }else{
    21. $(".count").css("background","#8e8e8e");
    22. $(".count").unbind("click");
    23. }
    24. }

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

    1. $(function(){
    2. /**************数量加减***************/
    3. $(".num .sub").click(function(){
    4. var num = parseInt($(this).siblings("span").text());
    5. if(num<=1){
    6. $(this).attr("disabled","disabled");
    7. }else{
    8. num--;
    9. $(this).siblings("span").text(num);
    10. //获取除了货币符号以外的数字
    11. var price = $(this).parents(".number").prev().text().substring(1);
    12. //单价和数量相乘并保留两位小数
    13. $(this).parents(".th").find(".sAll").text('¥'+(num*price).toFixed(2));
    14. jisuan();
    15. zg();
    16. //TODO 获取当前行的行索引
    17. let index = $(this).parents(".th").index()-1;
    18. //获取当前的checkbox中设置的隐藏域(包含了商品ID)
    19. let gid=$(".th").eq(index).find('div:eq(0) input[type=hidden]').val();
    20. update(num,gid);
    21. }
    22. });
    23. $(".num .add").click(function(){
    24. var num = parseInt($(this).siblings("span").text());
    25. if(num>=5){
    26. confirm("限购5件");
    27. }else{
    28. num++;
    29. $(this).siblings("span").text(num);
    30. var price = $(this).parents(".number").prev().text().substring(1);
    31. $(this).parents(".th").find(".sAll").text('¥'+(num*price).toFixed(2));
    32. jisuan();
    33. zg();
    34. //TODO 获取当前行的行索引
    35. let index = $(this).parents(".th").index()-1;
    36. //获取当前的checkbox中设置的隐藏域(包含了商品ID)
    37. let gid=$(".th").eq(index).find('div:eq(0) input[type=hidden]').val();
    38. update(num,gid);
    39. }
    40. });
    41. //计算总价
    42. function jisuan(){
    43. var all=0;
    44. var len =$(".th input[type='checkbox']:checked").length;
    45. if(len==0){
    46. $("#all").text('¥'+parseFloat(0).toFixed(2));
    47. }else{
    48. $(".th input[type='checkbox']:checked").each(function(){
    49. //获取小计里的数值
    50. var sAll = $(this).parents(".pro").siblings('.sAll').text().substring(1);
    51. //累加
    52. all+=parseFloat(sAll);
    53. //赋值
    54. $("#all").text('¥'+all.toFixed(2));
    55. })
    56. }
    57. }
    58. //计算总共几件商品
    59. function zg(){
    60. let gids = "";
    61. var zsl = 0;
    62. var index = $(".th input[type='checkbox']:checked").parents(".th").find(".num span");
    63. var len =index.length;
    64. if(len==0){
    65. $("#sl").text(0);
    66. }else{
    67. let gidarr = new Array();
    68. index.each(function(){
    69. zsl+=parseInt($(this).text());
    70. $("#sl").text(zsl);
    71. //TODO 获取当前行的索引
    72. let idx = $(this).parents(".th").index()-1;
    73. console.log(idx);
    74. //在这里需要获取当前行商品的商品ID
    75. gidarr.push($(".th").eq(idx).find("div:eq(0) input[type='hidden']").val());
    76. });
    77. gids = gidarr.join(",");
    78. }
    79. if($("#sl").text()>0){
    80. $(".count").css("background","#c10000");
    81. $(".count").bind("click",function () {
    82. //拿到gids
    83. location.href='/order/toOrder?gids='+gids
    84. });
    85. }else{
    86. $(".count").css("background","#8e8e8e");
    87. $(".count").unbind("click");
    88. }
    89. }
    90. /*****************商品全选***********************/
    91. $("input[type='checkbox']").on('click',function(){
    92. var sf = $(this).is(":checked");
    93. var sc= $(this).hasClass("checkAll");
    94. if(sf){
    95. if(sc){
    96. $("input[type='checkbox']").each(function(){
    97. this.checked=true;
    98. });
    99. zg();
    100. jisuan();
    101. }else{
    102. $(this).checked=true;
    103. var len = $("input[type='checkbox']:checked").length;
    104. var len1 = $("input").length-1;
    105. if(len==len1){
    106. $("input[type='checkbox']").each(function(){
    107. this.checked=true;
    108. });
    109. }
    110. zg();
    111. jisuan();
    112. }
    113. }else{
    114. if(sc){
    115. $("input[type='checkbox']").each(function(){
    116. this.checked=false;
    117. });
    118. zg();
    119. jisuan();
    120. }else{
    121. $(this).checked=false;
    122. var len = $(".th input[type='checkbox']:checked").length;
    123. var len1 = $("input").length-1;
    124. if(len<len1){
    125. $('.checkAll').attr("checked",false);
    126. }
    127. zg();
    128. jisuan();
    129. }
    130. }
    131. });
    132. /****************************proDetail 加入购物车*******************************/
    133. $(".btns .cart").click(function(){
    134. if($(".categ p").hasClass("on")){
    135. var num = parseInt($(".num span").text());
    136. var num1 = parseInt($(".goCart span").text());
    137. $(".goCart span").text(num+num1);
    138. }
    139. });
    140. //删除购物车商品
    141. $('.del').click(function(){
    142. //定义商品id 比如:1,2,3,4,5
    143. let gids = "";
    144. //单个删除
    145. if($(this).parent().parent().hasClass("th")){
    146. $(".mask").show();
    147. $(".tipDel").show();
    148. index = $(this).parents(".th").index()-1;
    149. //TODO 获取当前的checkbox中设置的隐藏域(包含了商品ID)
    150. gids=$(".th").eq(index).find('div:eq(0) input[type=hidden]').val();
    151. console.log(gids);
    152. $('.cer').click(function(){
    153. $(".mask").hide();
    154. $(".tipDel").hide();
    155. $(".th").eq(index).remove();
    156. $('.cer').off('click');
    157. if($(".th").length==0){
    158. $(".table .goOn").show();
    159. }
    160. del(gids);
    161. })
    162. }else{
    163. //选中多个一起删除
    164. if($(".th input[type='checkbox']:checked").length==0){
    165. $(".mask").show();
    166. $(".pleaseC").show();
    167. }
    168. else{
    169. $(".mask").show();
    170. $(".tipDel").show();
    171. //TODO 先获取所有即将被删除的商品ID
    172. let gidarr = new Array();
    173. $(".th input[type='checkbox']:checked").each(function(j){
    174. gidarr.push($(".th").eq(index).find('div:eq(0) input[type=hidden]').val());
    175. // gids += $(".th").eq(index).find('div:eq(0) input[type=hidden]').val(); 很容易报数据下标越界异常
    176. });
    177. gids = gidarr.join(",");
    178. $('.cer').click(function(){
    179. $(".th input[type='checkbox']:checked").each(function(j){
    180. index = $(this).parents('.th').index()-1;
    181. $(".th").eq(index).remove();
    182. if($(".th").length==0){
    183. $(".table .goOn").show();
    184. }
    185. })
    186. $(".mask").hide();
    187. $(".tipDel").hide();
    188. zg();
    189. jisuan();
    190. del(gids);
    191. })
    192. }
    193. }
    194. })
    195. $('.cancel').click(function(){
    196. $(".mask").hide();
    197. $(".tipDel").hide();
    198. })
    199. //改变商品规格
    200. // $(".pro dd").hover(function(){
    201. // var html='';
    202. // html='修改';
    203. // $(this).addClass("on").append(html).parents(".th").siblings(".th").find(".pro dd").removeClass("on").find('.edit').remove();
    204. // $(".edit").each(function(i){
    205. // $(this).attr("id",'edit'+i);
    206. // $("#edit"+i).click(function(){
    207. // $(".proDets").show();
    208. // $(".mask").show();
    209. // $(".changeBtn .buy").attr("data-id",i);
    210. // })
    211. // })
    212. // },function(){
    213. // $(this).removeClass("on");
    214. // })
    215. // $(".changeBtn .buy").click(function(){
    216. // var index = $(this).attr("data-id");
    217. // var result = $(".smallImg .on").find("img").attr("alt");
    218. // $("#edit"+index).prev().text(result);
    219. // $(".proDets").hide();
    220. // $(".mask").hide();
    221. // $("#edit"+index).parent("dd").removeClass("on").find(".edit").remove();
    222. // });
    223. // $(".changeBtn .cart").click(function(){
    224. // $(".proDets").hide();
    225. // $(".mask").hide();
    226. // })
    227. })
    228. //删除商品
    229. function del(gids) {
    230. $.post('/shopCar/delete',{
    231. 'gids':gids
    232. },function(rs){
    233. if(rs.code!=200)
    234. alert(rs.msg);
    235. else
    236. location.href='/shopCar/queryShopCar';
    237. },'json');
    238. }
    239. //修改商品数量
    240. function update(num,gid){
    241. $.post('/shopCar/update',{
    242. 'gid':gid,
    243. 'quantity':num
    244. },function(rs){
    245. if(rs.code!=200)
    246. alert(rs.msg);
    247. else
    248. location.href='/shopCar/queryShopCar';
    249. },'json');
    250. }

    测试结果如下:

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

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

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

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

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

    1. package com.jwj.spbootpro.generator;
    2. import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException;
    3. import com.baomidou.mybatisplus.core.toolkit.StringPool;
    4. import com.baomidou.mybatisplus.core.toolkit.StringUtils;
    5. import com.baomidou.mybatisplus.generator.AutoGenerator;
    6. import com.baomidou.mybatisplus.generator.InjectionConfig;
    7. import com.baomidou.mybatisplus.generator.config.*;
    8. import com.baomidou.mybatisplus.generator.config.po.TableInfo;
    9. import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
    10. import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
    11. import java.util.ArrayList;
    12. import java.util.List;
    13. import java.util.Scanner;
    14. public class CodeGenerator {
    15. /**
    16. *

    17. * 读取控制台内容
    18. *

    19. */
    20. public static String scanner(String tip) {
    21. Scanner scanner = new Scanner(System.in);
    22. StringBuilder help = new StringBuilder();
    23. help.append("请输入" + tip + ":");
    24. System.out.println(help.toString());
    25. if (scanner.hasNext()) {
    26. String ipt = scanner.next();
    27. if (StringUtils.isNotBlank(ipt)) {
    28. return ipt;
    29. }
    30. }
    31. throw new MybatisPlusException("请输入正确的" + tip + "!");
    32. }
    33. public static void main(String[] args) {
    34. // 代码生成器
    35. AutoGenerator mpg = new AutoGenerator();
    36. // 全局配置
    37. GlobalConfig gc = new GlobalConfig();
    38. String projectPath = System.getProperty("user.dir") + "/spbootpro";
    39. gc.setOutputDir(projectPath + "/src/main/java");
    40. gc.setAuthor("jwj");
    41. gc.setOpen(false);
    42. gc.setBaseColumnList(true);
    43. gc.setBaseResultMap(true);
    44. // gc.setSwagger2(true); 实体属性 Swagger2 注解
    45. mpg.setGlobalConfig(gc);
    46. // 数据源配置
    47. DataSourceConfig dsc = new DataSourceConfig();
    48. dsc.setUrl("jdbc:mysql://localhost:3306/spbootpro?useUnicode=true&useSSL=false&characterEncoding=utf8");
    49. // dsc.setSchemaName("public");
    50. dsc.setDriverName("com.mysql.jdbc.Driver");
    51. dsc.setUsername("root");
    52. dsc.setPassword("123456");
    53. mpg.setDataSource(dsc);
    54. // 包配置
    55. PackageConfig pc = new PackageConfig();
    56. //pc.setModuleName(scanner("模块名"));
    57. pc.setParent("com.jwj.spbootpro");
    58. //设置包名
    59. pc.setEntity("model");
    60. mpg.setPackageInfo(pc);
    61. // 自定义配置
    62. InjectionConfig cfg = new InjectionConfig() {
    63. @Override
    64. public void initMap() {
    65. // to do nothing
    66. }
    67. };
    68. // 如果模板引擎是 freemarker
    69. String templatePath = "/templates/mybatis-generator/mapper2.xml.ftl";
    70. // 如果模板引擎是 velocity
    71. // String templatePath = "/templates/mapper.xml.vm";
    72. // 自定义输出配置
    73. List<FileOutConfig> focList = new ArrayList<>();
    74. // 自定义配置会被优先输出
    75. focList.add(new FileOutConfig(templatePath) {
    76. @Override
    77. public String outputFile(TableInfo tableInfo) {
    78. // 自定义输出文件名 , 如果你 Entity 设置了前后缀、此处注意 xml 的名称会跟着发生变化!!
    79. return projectPath + "/src/main/resources/mapper/" + pc.getModuleName()
    80. + "/" + tableInfo.getEntityName() + "Mapper" + StringPool.DOT_XML;
    81. }
    82. });
    83. /*
    84. cfg.setFileCreate(new IFileCreate() {
    85. @Override
    86. public boolean isCreate(ConfigBuilder configBuilder, FileType fileType, String filePath) {
    87. // 判断自定义文件夹是否需要创建
    88. checkDir("调用默认方法创建的目录,自定义目录用");
    89. if (fileType == FileType.MAPPER) {
    90. // 已经生成 mapper 文件判断存在,不想重新生成返回 false
    91. return !new File(filePath).exists();
    92. }
    93. // 允许生成模板文件
    94. return true;
    95. }
    96. });
    97. */
    98. cfg.setFileOutConfigList(focList);
    99. mpg.setCfg(cfg);
    100. // 配置模板
    101. TemplateConfig templateConfig = new TemplateConfig();
    102. // 配置自定义输出模板
    103. //指定自定义模板路径,注意不要带上.ftl/.vm, 会根据使用的模板引擎自动识别
    104. templateConfig.setMapper("templates/mybatis-generator/mapper2.java");
    105. templateConfig.setEntity("templates/mybatis-generator/entity2.java");
    106. templateConfig.setService("templates/mybatis-generator/service2.java");
    107. templateConfig.setServiceImpl("templates/mybatis-generator/serviceImpl2.java");
    108. templateConfig.setController("templates/mybatis-generator/controller2.java");
    109. templateConfig.setXml(null);
    110. mpg.setTemplate(templateConfig);
    111. // 策略配置
    112. StrategyConfig strategy = new StrategyConfig();
    113. strategy.setNaming(NamingStrategy.underline_to_camel);
    114. strategy.setColumnNaming(NamingStrategy.underline_to_camel);
    115. //strategy.setSuperEntityClass("你自己的父类实体,没有就不用设置!");
    116. strategy.setEntityLombokModel(true);
    117. strategy.setRestControllerStyle(true);
    118. strategy.setEntitySerialVersionUID(false);
    119. // 公共父类
    120. //strategy.setSuperControllerClass("你自己的父类控制器,没有就不用设置!");
    121. // 写于父类中的公共字段
    122. strategy.setSuperEntityColumns("id");
    123. strategy.setInclude(scanner("表名,多个英文逗号分割").split(","));
    124. strategy.setControllerMappingHyphenStyle(true);
    125. strategy.setTablePrefix("t_");
    126. mpg.setStrategy(strategy);
    127. mpg.setTemplateEngine(new FreemarkerTemplateEngine());
    128. mpg.execute();
    129. }
    130. }

    如下图所示:

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

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

    思路

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

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

    OrderController.java

    1. package com.jwj.spbootpro.controller;
    2. import com.jwj.spbootpro.model.Goods;
    3. import com.jwj.spbootpro.model.User;
    4. import com.jwj.spbootpro.model.vo.ShopCar;
    5. import com.jwj.spbootpro.model.vo.ShopCarItem;
    6. import org.springframework.stereotype.Controller;
    7. import org.springframework.web.bind.annotation.RequestMapping;
    8. import org.springframework.web.bind.annotation.RestController;
    9. import org.springframework.web.servlet.ModelAndView;
    10. import javax.servlet.http.HttpServletRequest;
    11. import javax.servlet.http.HttpSession;
    12. import java.util.ArrayList;
    13. import java.util.Arrays;
    14. import java.util.List;
    15. /**
    16. *

    17. * 订单信息表 前端控制器
    18. *

    19. *
    20. * @author jwj
    21. * @since 2022-11-10
    22. *
    23. * @Controller:因为我们最终是要跳转到页面
    24. */
    25. @Controller
    26. @RequestMapping("/order")
    27. public class OrderController {
    28. /**
    29. * 根据勾选结算的商品跳转到订单页面
    30. * @param user
    31. * @param gids
    32. * @param request
    33. * @return
    34. */
    35. @RequestMapping("/toOrder")
    36. public ModelAndView toOrder(User user,String gids, HttpServletRequest request){
    37. ModelAndView mv = new ModelAndView();
    38. // 拿到购物车中的所有商品
    39. ShopCar shopCar = getShopCar(user, request);
    40. // 通过gids从购物车中筛选出指定的商品
    41. List<ShopCarItem> list = getGoods(shopCar,gids);
    42. mv.addObject("goods",list);
    43. mv.setViewName("order.html");
    44. return mv;
    45. }
    46. /**
    47. * 由于用户结算商品时,不一定是将购物车中所有商品进行结算,有可能只有部分商品
    48. * 必须根据前端页面用户勾选的商品ID从购物车中找到对应需要结算的商品并存入
    49. * @param shopCar
    50. * @param gids
    51. * @return
    52. */
    53. // 通过gids从购物车中筛选出指定的商品
    54. private List<ShopCarItem> getGoods(ShopCar shopCar, String gids) {
    55. //根据逗号分割商品gids
    56. List<String> gidList = Arrays.asList(gids.split(","));
    57. //代表购物车中已有的商品集合
    58. List<ShopCarItem> items = shopCar.getItems(); //3个 购物车里的商品
    59. //定义结算商品集合
    60. List<ShopCarItem> itemsNew = new ArrayList<>();//2个 购物车要结算的商品
    61. //循环遍历购物车中的商品并与勾选结算的商品ID进行比较
    62. for (ShopCarItem item : items) {
    63. //判断购物车中的商品与勾选结算的商品ID是否一致
    64. if(gidList.contains(item.getGid()+"")){
    65. itemsNew.add(item);
    66. }
    67. }
    68. return itemsNew;
    69. }
    70. // 从session中获取购物车对象
    71. private ShopCar getShopCar(User user, HttpServletRequest request){
    72. //获取session
    73. HttpSession session = request.getSession();
    74. //从session中获取购物车对象
    75. ShopCar shopCar = (ShopCar)session.getAttribute(user.getId() + "_shopCar");
    76. //判断shopCar是否为空
    77. if(shopCar == null){
    78. //初始化购物车对象
    79. shopCar = new ShopCar();
    80. //将初始化完成的购物车对象根据用户id报错到session中
    81. session.setAttribute(user.getId()+"_shopCar",shopCar);
    82. }
    83. return shopCar;
    84. }
    85. }

    2.订单页前台展示 

    order.html

    
    
       
          <#include "common/head.html">
          
          
          
       
       
          
          

    订单确认

    收件信息新增地址

    张三1 [默认地址]

    删除 | 编辑

    河北省 唐山市 路北区 大学生公寓村

    15732570937

    张三2

    设为默认 | 删除 | 编辑

    河北省 唐山市 路北区 大学生公寓村

    15732570937

    张三3

    设为默认 | 删除 | 编辑

    河北省 唐山市 路北区 大学生公寓村

    15732570937

    支付方式

    选择快递

    顺风快递 百世汇通 圆通快递 中通快递

    订单内容返回购物车

    <#if goods??> <#list goods as g>
    • ${g.goodsName}

      颜色分类:烟灰色玻璃瓶

      数量:${g.quantity}

    • ¥${g.goodsPrice}

    商品金额:¥139.8

    优惠金额:¥0.00

    运费:免运费

    合计:¥139.8

    去支付
    <#include "common/footer.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);
            //获取勾选结算的商品ID
            let 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

    1. package com.jwj.spbootpro.model.dto;
    2. import com.jwj.spbootpro.model.Order;
    3. import lombok.Data;
    4. /**
    5. * @author 敢敢
    6. * @site www.javajwj.com
    7. * @company xxx公司
    8. * @create  2022-11-10 18:23
    9. */
    10. @Data
    11. public class OrderDto extends Order {
    12. private String gids;
    13. }

    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;
    
    /**
     * 

    * 订单信息表 前端控制器 *

    * * @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 list = getGoods(shopCar,gids); mv.addObject("goods",list); mv.setViewName("order.html"); return mv; } /** * 由于用户结算商品时,不一定是将购物车中所有商品进行结算,有可能只有部分商品 * 必须根据前端页面用户勾选的商品ID从购物车中找到对应需要结算的商品并存入 * @param shopCar * @param gids * @return */ // 通过gids从购物车中筛选出指定的商品 private List getGoods(ShopCar shopCar, String gids) { //根据逗号分割商品gids List gidList = Arrays.asList(gids.split(",")); //代表购物车中已有的商品集合 List items = shopCar.getItems(); //3个 购物车里的商品 //定义结算商品集合 List 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){ //获取session HttpSession 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; } @Autowired private IOrderService orderService; @ResponseBody @RequestMapping("/addOrder") //非ajax返回的ModelAndView,ajax返回的是JsonResponseBody public JsonResponseBody addOrder(User user, OrderDto orderDto,HttpServletRequest request){ // 1.拿到购物车 2.通过orderDto拿到gids,再拿到要结算的商品 3.数据要入订单表 4.数据要入订单项表 //获取购物车 ShopCar shopCar = this.getShopCar(user, request); //获取结算商品集合 List shopCarItems = this.getGoods(shopCar, orderDto.getGids()); //生成订单及订单项 orderDto.setUserId(user.getId()); orderService.addOrder(orderDto,shopCarItems); //从购物车中删除已结算的商品 shopCar.delete(orderDto.getGids()); //跳转支付页面 return new JsonResponseBody(); } }

     IOrderService.java创建addOrder方法

    1. package com.jwj.spbootpro.service;
    2. import com.jwj.spbootpro.model.Order;
    3. import com.baomidou.mybatisplus.extension.service.IService;
    4. import com.jwj.spbootpro.model.dto.OrderDto;
    5. import com.jwj.spbootpro.model.vo.ShopCarItem;
    6. import java.util.List;
    7. /**
    8. *

    9. * 订单信息表 服务类
    10. *

    11. *
    12. * @author jwj
    13. * @since 2022-11-10
    14. */
    15. public interface IOrderService extends IService<Order> {
    16. void addOrder(OrderDto orderDto, List<ShopCarItem> shopCarItems);
    17. }

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

    OrderServiceImpl.java

    1. package com.jwj.spbootpro.service.impl;
    2. import com.jwj.spbootpro.model.Order;
    3. import com.jwj.spbootpro.mapper.OrderMapper;
    4. import com.jwj.spbootpro.model.OrderItem;
    5. import com.jwj.spbootpro.model.dto.OrderDto;
    6. import com.jwj.spbootpro.model.vo.ShopCarItem;
    7. import com.jwj.spbootpro.service.IOrderItemService;
    8. import com.jwj.spbootpro.service.IOrderService;
    9. import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
    10. import com.jwj.spbootpro.utils.SnowFlake;
    11. import org.springframework.beans.factory.annotation.Autowired;
    12. import org.springframework.stereotype.Service;
    13. import org.springframework.transaction.annotation.Transactional;
    14. import java.math.BigDecimal;
    15. import java.util.ArrayList;
    16. import java.util.List;
    17. /**
    18. *

    19. * 订单信息表 服务实现类
    20. *

    21. *
    22. * @author jwj
    23. * @since 2022-11-10
    24. */
    25. @Service
    26. public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements IOrderService {
    27. @Autowired
    28. private OrderMapper orderMapper;
    29. @Autowired
    30. private IOrderItemService orderItemService;
    31. // @Transactional注解:以下的方法因为同时设置到两张表的增删改的操作,要么同时成功,要么同时失败
    32. @Transactional
    33. @Override
    34. public void addOrder(OrderDto orderDto, List<ShopCarItem> shopCarItems) {
    35. // 订单表以及订单项表的数据录入
    36. //1) 生成订单ID SnowFlake生成雪花ID,它的作用,生成一个随机的long类型的数字;
    37. // 相比较于UUID的优点在于,雪花ID可以排序
    38. SnowFlake snowFlake = new SnowFlake(2, 3);
    39. Long orderId=snowFlake.nextId();
    40. orderDto.setOid(orderId);
    41. //2) 循环勾选的商品集合计算商品总价、获取商品详情集合
    42. //总价
    43. BigDecimal total=BigDecimal.valueOf(0);
    44. //定义商品详情集合
    45. List<OrderItem> orderItems=new ArrayList<>();
    46. OrderItem it=null;
    47. for (ShopCarItem shopCarItem : shopCarItems) {
    48. //累加小计等于总价
    49. total=total.add(shopCarItem.smalltotal());
    50. //初始化OrderItem商品详情对象
    51. it=new OrderItem();
    52. // 订单项表的ooid为自增,所以不需要设置
    53. it.setOid(orderId);
    54. it.setGid(shopCarItem.getGid());
    55. it.setGoodsName(shopCarItem.getGoodsName());
    56. it.setGoodsPrice(shopCarItem.getGoodsPrice());
    57. it.setQuantity(shopCarItem.getQuantity());
    58. orderItems.add(it);
    59. }
    60. orderDto.setTotal(total);
    61. //1.保存订单
    62. orderMapper.insert(orderDto);
    63. //2.保存订单对应的订单项
    64. orderItemService.saveBatch(orderItems);
    65. }
    66. }

    给我们OrderMapper添加注解@repository,

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

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

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

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

    1. package com.jwj.spbootpro.utils;
    2. public class SnowFlake {
    3. /**
    4. * 起始的时间戳
    5. */
    6. private final static long START_STMP = 1480166465631L;
    7. /**
    8. * 每一部分占用的位数
    9. */
    10. private final static long SEQUENCE_BIT = 12; //序列号占用的位数
    11. private final static long MACHINE_BIT = 5; //机器标识占用的位数
    12. private final static long DATACENTER_BIT = 5;//数据中心占用的位数
    13. /**
    14. * 每一部分的最大值
    15. */
    16. private final static long MAX_DATACENTER_NUM = -1L ^ (-1L << DATACENTER_BIT);
    17. private final static long MAX_MACHINE_NUM = -1L ^ (-1L << MACHINE_BIT);
    18. private final static long MAX_SEQUENCE = -1L ^ (-1L << SEQUENCE_BIT);
    19. /**
    20. * 每一部分向左的位移
    21. */
    22. private final static long MACHINE_LEFT = SEQUENCE_BIT;
    23. private final static long DATACENTER_LEFT = SEQUENCE_BIT + MACHINE_BIT;
    24. private final static long TIMESTMP_LEFT = DATACENTER_LEFT + DATACENTER_BIT;
    25. private long datacenterId; //数据中心
    26. private long machineId; //机器标识
    27. private long sequence = 0L; //序列号
    28. private long lastStmp = -1L;//上一次时间戳
    29. public SnowFlake(long datacenterId, long machineId) {
    30. if (datacenterId > MAX_DATACENTER_NUM || datacenterId < 0) {
    31. throw new IllegalArgumentException("datacenterId can't be greater than MAX_DATACENTER_NUM or less than 0");
    32. }
    33. if (machineId > MAX_MACHINE_NUM || machineId < 0) {
    34. throw new IllegalArgumentException("machineId can't be greater than MAX_MACHINE_NUM or less than 0");
    35. }
    36. this.datacenterId = datacenterId;
    37. this.machineId = machineId;
    38. }
    39. /**
    40. * 产生下一个ID
    41. *
    42. * @return
    43. */
    44. public synchronized long nextId() {
    45. long currStmp = getNewstmp();
    46. if (currStmp < lastStmp) {
    47. throw new RuntimeException("Clock moved backwards. Refusing to generate id");
    48. }
    49. if (currStmp == lastStmp) {
    50. //相同毫秒内,序列号自增
    51. sequence = (sequence + 1) & MAX_SEQUENCE;
    52. //同一毫秒的序列数已经达到最大
    53. if (sequence == 0L) {
    54. currStmp = getNextMill();
    55. }
    56. } else {
    57. //不同毫秒内,序列号置为0
    58. sequence = 0L;
    59. }
    60. lastStmp = currStmp;
    61. return (currStmp - START_STMP) << TIMESTMP_LEFT //时间戳部分
    62. | datacenterId << DATACENTER_LEFT //数据中心部分
    63. | machineId << MACHINE_LEFT //机器标识部分
    64. | sequence; //序列号部分
    65. }
    66. private long getNextMill() {
    67. long mill = getNewstmp();
    68. while (mill <= lastStmp) {
    69. mill = getNewstmp();
    70. }
    71. return mill;
    72. }
    73. private long getNewstmp() {
    74. return System.currentTimeMillis();
    75. }
    76. public static void main(String[] args) {
    77. SnowFlake snowFlake = new SnowFlake(2, 3);
    78. long start = System.currentTimeMillis();
    79. for (int i = 0; i < 1000000; i++) {
    80. System.out.println(snowFlake.nextId());
    81. }
    82. System.out.println(System.currentTimeMillis() - start);
    83. }
    84. }

    测试效果如下图所示:

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

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

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

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

     四、沙箱支付简介

    1.配置沙箱支付

    第一步:

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

    点击登录:扫码登录

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

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

    密钥工具简介 | 开放平台

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

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

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

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

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

    登录 - 支付宝

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

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

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

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

     五、沙箱支付应用

    实现思路

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

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

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

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

    Easy 版 | 开放平台

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

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

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

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

    AlipayConfig.java

    1. package com.jwj.spbootpro.config;
    2. import com.alipay.easysdk.factory.Factory;
    3. import com.alipay.easysdk.kernel.Config;
    4. import com.alipay.easysdk.payment.page.models.AlipayTradePagePayResponse;
    5. import com.jwj.spbootpro.model.dto.OrderDto;
    6. /**
    7. * 支付宝沙箱支付
    8. */
    9. public class AlipayConfig {
    10. public String goAlipay(OrderDto orderDto){
    11. try {
    12. // 1. 设置参数(全局只需设置一次)
    13. Factory.setOptions(aliconfig());
    14. // 2. 发起API调用(subject商品标题、outTradeNo订单编号、totalAmount总金额、returnUrl异步通知地址)
    15. AlipayTradePagePayResponse response = Factory.Payment.Page()
    16. .pay(orderDto.getOid()+"",
    17. orderDto.getOid()+"",
    18. orderDto.getTotal().toString(),
    19. "http://localhost:8081/page/ok.html"); //支付成功之后的异步通知(跳出到自己系统的哪个位置)
    20. System.out.println(response.body);
    21. return response.body;
    22. } catch (Exception e) {
    23. e.printStackTrace();
    24. throw new RuntimeException(e);
    25. }
    26. }
    27. private Config aliconfig(){
    28. Config config=new Config();
    29. //沙箱支付宝地址
    30. config.gatewayHost="openapi.alipaydev.com";
    31. //协议https
    32. config.protocol="https";
    33. //应用ID,您的APPID,收款账号既是您的APPID对应支付宝账号
    34. config.appId="2021000121687583";
    35. //支付宝公钥
    36. config.alipayPublicKey="MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsc74PulHrpMlGXt53c1CYfBziNjY9W299fXA5aU3f+eKKNnjc9fmUXYusGms0MgSSYgji4SuAfl1LxtRJEwqz8L7zxOxq0JB6Y5+XFXiSpdys4f6wMJXoaRWamEzfaSkpgoJ6vO+VqJa+j77Brc//mxRtHjrcS3xW5doUBOsAAdofjwaaWgcT2cmzb3r/QEXu4vfrOdV4uuXD5GWJ7bIYTDuRsRBL8iBPtqv1OkB6184f2t0Qch0g6Pyti/cg10BB5s/i9uUCqHCtHl5CQrpubQc6hYb4mmp8ZXLvqfPAmq0fgABDQklCPdww7qML6cATsv+WZF+f5NsxVPOgYPeQwIDAQAB";
    37. //签名方式
    38. config.signType="RSA2";
    39. //商户私钥(应用私钥),您的PKCS8格式RSA2私钥
    40. 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=";
    41. return config;
    42. }
    43. }

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

    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);
            //获取勾选结算的商品ID
            let 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 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 代码新增如下:

    1. /**
    2. * 支付成功后回调处理订单状态,完成整个下单流程的链路
    3. * @param param
    4. * @return
    5. */
    6. @RequestMapping("/orderFinish")
    7. public String orderFinish(@RequestParam Map<String, String> param){
    8. System.out.println("异步回调开始。。。。。。");
    9. Boolean signVerified=false;
    10. try {
    11. System.out.println(param);
    12. signVerified = Factory.Payment.Common().verifyNotify(param);
    13. System.out.println(signVerified);
    14. System.out.println("out_trade_no:"+param.get("out_trade_no"));
    15. System.out.println("total_amount:"+param.get("total_amount"));
    16. System.out.println("trade_no:"+param.get("trade_no"));
    17. if(signVerified){
    18. //支付成功
    19. //根据订单编号修改订单状态
    20. //update t_xxx set xx=?,tt=? where id=?
    21. orderService.update(new UpdateWrapper<Order>()
    22. .set("status",1)
    23. .setSql("pay_date=now()")
    24. .eq("oid",param.get("out_trade_no")));
    25. //跳转到支付成功页面
    26. }else{
    27. //支付失败
    28. }
    29. } catch (Exception e) {
    30. e.printStackTrace();
    31. }
    32. return "ok.html";
    33. }

     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";
            //协议https
            config.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;
        }
    }
    

    测试如下:

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

  • 相关阅读:
    基于灰狼算法(GWO)优化的VMD参数(GWO-VMD)
    Unity3D Entity_CacheService实现详解
    基于springboot实现班级综合测评管理系统项目【项目源码+论文说明】
    六、Docker仓库之Harbor搭建(三)
    java计算机毕业设计基于springboot+vue+elementUI的在线彩妆化妆品销售店铺商城(前后端分离)
    企业级-精度计算
    基于华为云服务器Docker nginx安装和配置挂载
    深入浅出DAX:数据分析
    本地FTP YUM源报错处理
    Con A-PEG-Indocyanine green 刀豆球蛋白A-聚乙二醇-吲哚菁绿,Concanavalin A-ICG
  • 原文地址:https://blog.csdn.net/weixin_67465673/article/details/127775386