目录
一.购物车结算前端功能实现
cart.js
//计算总共几件商品
function zg(){
var zsl = 0;
var index = $(".th input[type='checkbox']:checked").parents(".th").find(".num span");
var len =index.length;
let gids="";
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);
//在这里需要获取当前行商品的商品ID
gidArr.push($(".th").eq(idx).find("div:eq(0) input[type='hidden']").val());
})
gids = gidArr.join(",");
}
if($("#sl").text()>0){
$(".count").css("background","#c10000");
// TODO 绑定结算事件
$(".count").bind("click",function () {
// alert("绑定结算事件");
location.href='/order/toOrder?gids='+gids
})
}else{
$(".count").css("background","#8e8e8e");
$(".count").unbind("click");
}
}
生成代码:
package com.zking.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("zking"); 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.zking.spbootpro"); //设置包名 pc.setEntity("model"); mpg.setPackageInfo(pc); // 自定义配置 InjectionConfig cfg = new InjectionConfig() { @Override public void initMap() { // to do nothing } }; // 如果模板引擎是 freemarker String templatePath = "/templates/mybatis-generator/mapper2.xml.ftl"; // 如果模板引擎是 velocity // String templatePath = "/templates/mapper.xml.vm"; // 自定义输出配置 List<FileOutConfig> focList = new ArrayList<>(); // 自定义配置会被优先输出 focList.add(new FileOutConfig(templatePath) { @Override public String outputFile(TableInfo tableInfo) { // 自定义输出文件名 , 如果你 Entity 设置了前后缀、此处注意 xml 的名称会跟着发生变化!! return projectPath + "/src/main/resources/mapper/" + pc.getModuleName() + "/" + tableInfo.getEntityName() + "Mapper" + StringPool.DOT_XML; } }); /* cfg.setFileCreate(new IFileCreate() { @Override public boolean isCreate(ConfigBuilder configBuilder, FileType fileType, String filePath) { // 判断自定义文件夹是否需要创建 checkDir("调用默认方法创建的目录,自定义目录用"); if (fileType == FileType.MAPPER) { // 已经生成 mapper 文件判断存在,不想重新生成返回 false return !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(); } }
实现可跳转功能
二、.购物车结算后端功能实现
OrderCotroller 后台代码
package com.zking.spbootpro.Controller;
import com.zking.spbootpro.model.Goods;
import com.zking.spbootpro.model.User;
import com.zking.spbootpro.model.vo.ShopCar;
import com.zking.spbootpro.model.vo.ShopCarItem;
import com.zking.spbootpro.utils.JsonResponseBody;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* @author 锦鲤
* @site www.lucy.com
* @company xxx公司
* @create 2022-11-08 15:21
*/
@Controller
@RequestMapping("/order")
public class OrderCotroller {
/**
* 根据勾选结算的商品跳转到订单页面
* @param user
* @param req
* @param gids
* @return
*/
@RequestMapping("/toOrder")
public ModelAndView toOrder(User user,
HttpServletRequest req,
String gids){
ModelAndView mv=new ModelAndView();
//根据用户ID获取session中对应的购物车
ShopCar shopCar = getShopCar(user, req);
//从购物车中获取勾选结算的商品集合
List<ShopCarItem> list=getgoods(shopCar,gids);
mv.addObject("goods",list);
mv.setViewName("order.html");
return mv;
}
//筛选指定商品
private List<ShopCarItem> getgoods(ShopCar shopCar, String gids) {
List<String> gidlist= Arrays.asList(gids.split(","));
List<Goods> goods=new ArrayList<>();
List<ShopCarItem> items=shopCar.getItems();//购物车全部商品
List<ShopCarItem> itemsnew=new ArrayList<>();//购物车中选中要买的商品
for (ShopCarItem item : items) {
if(gidlist.contains(item.getGid()+"")){
itemsnew.add(item);
}
}
return itemsnew;
}
// 从session中获取购物车对象
private ShopCar getShopCar(User user, HttpServletRequest request) {
HttpSession session = request.getSession();
ShopCar shopCar = (ShopCar) session.getAttribute(user.getId() + "_shopCar");
if (shopCar == null) {
shopCar = new ShopCar();
session.setAttribute(user.getId() + "_shopCar", shopCar);
}
return shopCar;
}
}
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</p>
<span class="default">[默认地址]</span>
<p class="fr">
<a href="#">删除</a>
<span>|</span>
<a href="#" class="edit">编辑</a>
</p>
</div>
<div class="addCon">
<p>河北省 唐山市 路北区 大学生公寓村</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>河北省 唐山市 路北区 大学生公寓村</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>河北省 唐山市 路北区 大学生公寓村</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>
<#assign total=0>
<#--判断结算商品集合是否为空-->
<#if goods??>
<#--循环遍历结算商品-->
<#list goods.items as g>
<#--在循环里累加小计的和就是总价-->
<#assign total=total+g.smalltotal()>
<ul class="clearfix">
<li class="fl">
<img style="width: 87px;height: 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">¥${total}</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">¥${total}</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/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>
<script src="js/user/order.js" type="text/javascript" charset="utf-8"></script>
</body>
</html>
订单效果图
三、结算页的下单前端、后端
前端:js
$(function(){ $('.pay').click(function(){ //获取收货地址、联系人、联系电话 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'); }); });
后端
SnowFlake 雪花id
package com.zking.spbootpro.utils;
/*
*
* 雪花id特点;可以排序
* uuid特点:随机id,不可排序
*
* */
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 {
//不同毫秒内,序列号置为0
sequence = 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);
}
}
OrderServiceImpl
package com.zking.spbootpro.service.impl;
import com.zking.spbootpro.model.Dto.OrderDto;
import com.zking.spbootpro.model.Order;
import com.zking.spbootpro.mapper.OrderMapper;
import com.zking.spbootpro.model.OrderItem;
import com.zking.spbootpro.model.vo.ShopCarItem;
import com.zking.spbootpro.service.IOrderItemService;
import com.zking.spbootpro.service.IOrderService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zking.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 zking
* @since 2022-11-08
*/
@Service
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements IOrderService {
@Autowired
private OrderMapper orderMapper;
@Autowired
private IOrderItemService iOrderItemService;
@Transactional
@Override
public void addOrder(OrderDto orderDto, List<ShopCarItem> shopCarItems) {
//1) 生成订单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.保存订单对应的订单项
iOrderItemService.saveBatch(orderItems);
}
}
OrderDto-->获得gid
package com.zking.spbootpro.model.Dto; import com.zking.spbootpro.model.Order; import lombok.Data; /** * @author 锦鲤 * @site www.lucy.com * @company xxx公司 * @create 2022-11-08 18:43 */ @Data public class OrderDto extends Order { private String gids; }
IOrderItemService
package com.zking.spbootpro.service; import com.zking.spbootpro.model.OrderItem; import com.baomidou.mybatisplus.extension.service.IService; import org.springframework.stereotype.Repository; /** * <p> * 服务类 * </p> * * @author zking * @since 2022-11-08 */ public interface IOrderItemService extends IService<OrderItem> { }
’
OrderMapper
package com.zking.spbootpro.mapper; import com.zking.spbootpro.model.Order; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import org.springframework.stereotype.Repository; /** * <p> * 订单信息表 Mapper 接口 * </p> * * @author zking * @since 2022-11-08 */ @Repository public interface OrderMapper extends BaseMapper<Order> { }
OrderItemMapper
package com.zking.spbootpro.mapper; import com.zking.spbootpro.model.OrderItem; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import org.springframework.stereotype.Repository; /** * <p> * Mapper 接口 * </p> * * @author zking * @since 2022-11-08 */ @Repository public interface OrderItemMapper extends BaseMapper<OrderItem> { }
四、沙箱支付简介及初步接入
简介:
第一步:
1)登陆支付宝:https://open.alipay.com/
2)首页找到进入管理中心 -> 开发工具推荐选择【沙箱】
3)下载安装支付宝开放平台开发助手:
https://opendocs.alipay.com/common/02kipk
4)打开本地支付宝开放平台助手 -> 密钥工具 -> 生成密钥 -> 以默认方式(RSA2和PKCS8)生成应用私钥和应用公钥
5)在沙箱应用的开发信息中选择自定义密钥生成支付宝公钥(基于应用公钥生成支付宝公钥)第二步:配置沙箱账号(买家)并完成手动充值
https://open.alipay.com/develop/sandbox/account第三步:下载沙箱支付宝(只支持安卓)
https://open.alipay.com/develop/sandbox/tool/alipayclint沙箱工具 -> 支付宝客户端沙箱版 -> 请使用浏览器中的扫码功能扫描下载
注:请使用Android手机扫码下载支付宝客户端沙箱版;如需登录,请访问沙箱账号,在商家信息中获取帐密
登陆支付宝:https://open.alipay.com/
手机支付宝扫码注册账户
电脑安装密钥工具
作用:生成密钥
下载沙箱支付宝(只支持安卓)
手机安卓版安装沙箱版支付宝
手机登录后清除清(支付宝开放平台)缓存
随之充值(最高限额1000000元)
设置密钥
设置支付宝公钥
再将公钥放到 代码里
//支付宝公钥
config.alipayPublicKey="MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmUifAAtXclpNk2ezFnuM/Em1nYyBD2yEnHaanfUwh6TFyhqcQKbcHxYpurlyFyjHsBcBFhYmtUkpVWrNDqsIL4AmxKpNHQ5HGW7pKDOy+4ovoI3JcCzYeXuxti4L4yyd5Afuf3xUDcfRacriOf5FXlH6dSE6NvkShF0f7mPMOhtiVDnKyvuHcxH/qwjcqxZ6WilsaPNcOkOua3NEVlaqFll2wDxezukmtMqntUDqlJZ5U5CpOSXUOwAbvo9L+0nAReFE7N1z0huHtTDODyacIHaOATo5UTB8BQZm/niRqRKeTTduxSy6Udd6mTZkwO5KznZGVOuFdZ6F02zqrM9/1wIDAQAB";
设置应用密钥
设置appId
AlipayConfig
package com.zking.spbootpro.config;
import com.alipay.easysdk.factory.Factory;
import com.alipay.easysdk.kernel.Config;
import com.alipay.easysdk.payment.page.models.AlipayTradePagePayResponse;
import com.zking.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";
//协议https
config.protocol="https";
//应用ID,您的APPID,收款账号既是您的APPID对应支付宝账号
config.appId="2021000121689396";
//支付宝公钥
config.alipayPublicKey="MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmUifAAtXclpNk2ezFnuM/Em1nYyBD2yEnHaanfUwh6TFyhqcQKbcHxYpurlyFyjHsBcBFhYmtUkpVWrNDqsIL4AmxKpNHQ5HGW7pKDOy+4ovoI3JcCzYeXuxti4L4yyd5Afuf3xUDcfRacriOf5FXlH6dSE6NvkShF0f7mPMOhtiVDnKyvuHcxH/qwjcqxZ6WilsaPNcOkOua3NEVlaqFll2wDxezukmtMqntUDqlJZ5U5CpOSXUOwAbvo9L+0nAReFE7N1z0huHtTDODyacIHaOATo5UTB8BQZm/niRqRKeTTduxSy6Udd6mTZkwO5KznZGVOuFdZ6F02zqrM9/1wIDAQAB";
//签名方式
config.signType="RSA2";
//商户私钥(应用私钥),您的PKCS8格式RSA2私钥
config.merchantPrivateKey="自己的应用私钥";
return config;
}
}
实现支付功能
order.js
$(function(){ $('.pay').click(function(){ //获取收货地址、联系人、联系电话 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'); 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 ''; } }
OrderCotroller
package com.zking.spbootpro.Controller;
import com.zking.spbootpro.config.AlipayConfig;
import com.zking.spbootpro.model.Dto.OrderDto;
import com.zking.spbootpro.model.Goods;
import com.zking.spbootpro.model.User;
import com.zking.spbootpro.model.vo.ShopCar;
import com.zking.spbootpro.model.vo.ShopCarItem;
import com.zking.spbootpro.service.IOrderService;
import com.zking.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.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* @author 锦鲤
* @site www.lucy.com
* @company xxx公司
* @create 2022-11-08 15:21
*/
@Controller
@RequestMapping("/order")
public class OrderCotroller {
/**
* 根据勾选结算的商品跳转到订单页面
* @param user
* @param req
* @param gids
* @return
*/
@RequestMapping("/toOrder")
public ModelAndView toOrder(User user,
HttpServletRequest req,
String gids){
ModelAndView mv=new ModelAndView();
//根据用户ID获取session中对应的购物车
ShopCar shopCar = getShopCar(user, req);
//从购物车中获取勾选结算的商品集合
List<ShopCarItem> list=getgoods(shopCar,gids);
mv.addObject("goods",list);
mv.setViewName("order.html");
return mv;
}
//筛选指定商品
private List<ShopCarItem> getgoods(ShopCar shopCar, String gids) {
List<String> gidlist= Arrays.asList(gids.split(","));
List<Goods> goods=new ArrayList<>();
List<ShopCarItem> items=shopCar.getItems();//购物车全部商品
List<ShopCarItem> itemsnew=new ArrayList<>();//购物车中选中要买的商品
for (ShopCarItem item : items) {
if(gidlist.contains(item.getGid()+"")){
itemsnew.add(item);
}
}
return itemsnew;
}
// 从session中获取购物车对象
private ShopCar getShopCar(User user, HttpServletRequest request) {
HttpSession session = request.getSession();
ShopCar shopCar = (ShopCar) session.getAttribute(user.getId() + "_shopCar");
if (shopCar == null) {
shopCar = new ShopCar();
session.setAttribute(user.getId() + "_shopCar", shopCar);
}
return shopCar;
}
/**
*
* @param user 拿到商品信息
* @param request 拿到session
* @param orderDto 拿到gids
* @return
*/
@Autowired
private IOrderService orderService;
@ResponseBody
@RequestMapping("/addOrder")
public String addOrder(User user, HttpServletRequest request, OrderDto orderDto){
//获取购物车
ShopCar shopCar = this.getShopCar(user, request);
//获取结算商品集合
List<ShopCarItem> shopCarItems = getgoods(shopCar, orderDto.getGids());
//生成订单及订单项
// orderDto.setUserId(Long.parseLong(user.getId()));
orderDto.setUserId(user.getId());
orderService.addOrder(orderDto,shopCarItems);
//从购物车中删除已结算的商品
shopCar.delete(orderDto.getGids());
//跳转支付页面
AlipayConfig alipayConfig= new AlipayConfig();
return alipayConfig.goAlipay(orderDto);
}
}
报错了!
拿到自己的app_id
询问客服
解决:
五、支付宝支付回调
代码源于
OrderCotroller更新
package com.zking.spbootpro.Controller; import com.alipay.easysdk.factory.Factory; import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; import com.zking.spbootpro.config.AlipayConfig; import com.zking.spbootpro.model.Dto.OrderDto; import com.zking.spbootpro.model.Goods; import com.zking.spbootpro.model.Order; import com.zking.spbootpro.model.User; import com.zking.spbootpro.model.vo.ShopCar; import com.zking.spbootpro.model.vo.ShopCarItem; import com.zking.spbootpro.service.IOrderService; import com.zking.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.RequestParam; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Map; /** * @author 锦鲤 * @site www.lucy.com * @company xxx公司 * @create 2022-11-08 15:21 */ @Controller @RequestMapping("/order") public class OrderCotroller { /** * 根据勾选结算的商品跳转到订单页面 * @param user * @param req * @param gids * @return */ @RequestMapping("/toOrder") public ModelAndView toOrder(User user, HttpServletRequest req, String gids){ ModelAndView mv=new ModelAndView(); //根据用户ID获取session中对应的购物车 ShopCar shopCar = getShopCar(user, req); //从购物车中获取勾选结算的商品集合 List<ShopCarItem> list=getgoods(shopCar,gids); mv.addObject("goods",list); mv.setViewName("order.html"); return mv; } //筛选指定商品 private List<ShopCarItem> getgoods(ShopCar shopCar, String gids) { List<String> gidlist= Arrays.asList(gids.split(",")); List<Goods> goods=new ArrayList<>(); List<ShopCarItem> items=shopCar.getItems();//购物车全部商品 List<ShopCarItem> itemsnew=new ArrayList<>();//购物车中选中要买的商品 for (ShopCarItem item : items) { if(gidlist.contains(item.getGid()+"")){ itemsnew.add(item); } } return itemsnew; } // 从session中获取购物车对象 private ShopCar getShopCar(User user, HttpServletRequest request) { HttpSession session = request.getSession(); ShopCar shopCar = (ShopCar) session.getAttribute(user.getId() + "_shopCar"); if (shopCar == null) { shopCar = new ShopCar(); session.setAttribute(user.getId() + "_shopCar", shopCar); } return shopCar; } /** * * @param user 拿到商品信息 * @param request 拿到session * @param orderDto 拿到gids * @return */ @Autowired private IOrderService orderService; @ResponseBody @RequestMapping("/addOrder") public String addOrder(User user, HttpServletRequest request, OrderDto orderDto){ //获取购物车 ShopCar shopCar = getShopCar(user, request); //获取结算商品集合 List<ShopCarItem> shopCarItems = getgoods(shopCar, orderDto.getGids()); //生成订单及订单项 orderDto.setUserId(user.getId()); orderService.addOrder(orderDto,shopCarItems); //从购物车中删除已结算的商品 shopCar.delete(orderDto.getGids()); //跳转支付页面(下节课内容) AlipayConfig alipayConfig= new AlipayConfig(); return alipayConfig.goAlipay(orderDto); } /** * 支付成功后回调处理订单状态,完成整个下单流程的链路 * @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更新
package com.zking.spbootpro.config;
import com.alipay.easysdk.factory.Factory;
import com.alipay.easysdk.kernel.Config;
import com.alipay.easysdk.payment.page.models.AlipayTradePagePayResponse;
import com.zking.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="2021000121689396";
//支付宝公钥
config.alipayPublicKey="MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmUifAAtXclpNk2ezFnuM/Em1nYyBD2yEnHaanfUwh6TFyhqcQKbcHxYpurlyFyjHsBcBFhYmtUkpVWrNDqsIL4AmxKpNHQ5HGW7pKDOy+4ovoI3JcCzYeXuxti4L4yyd5Afuf3xUDcfRacriOf5FXlH6dSE6NvkShF0f7mPMOhtiVDnKyvuHcxH/qwjcqxZ6WilsaPNcOkOua3NEVlaqFll2wDxezukmtMqntUDqlJZ5U5CpOSXUOwAbvo9L+0nAReFE7N1z0huHtTDODyacIHaOATo5UTB8BQZm/niRqRKeTTduxSy6Udd6mTZkwO5KznZGVOuFdZ6F02zqrM9/1wIDAQAB";
//签名方式
config.signType="RSA2";
//商户私钥(应用私钥),您的PKCS8格式RSA2私钥
config.merchantPrivateKey="自己的支付宝开放平台私钥";
return config;
}
}
输入沙箱支付宝密码合账户
查看余额
查看数据库数据
账单状态由0变为1