博客地址: https://blog.csdn.net/2303_76227485/article/details/152253986
视频演示: https://www.bilibili.com/video/BV1zMntzVEhH/
毕业设计所有选题地址: https://github.com/codegitpro/allProject
本项目前后端分离,分为用户、商家、管理员三种角色(角色和菜单可自定义)。
- 注册、登录、门票购买、推文查看、我的订单、取消订单、支付宝沙箱支付、个人中心、密码修改
- 数据报表、演唱会管理、票务管理、订单管理
- 数据报表、演唱会管理、票务管理、订单管理、会馆管理、推文管理、用户管理、菜单管理、角色管理、文件管理
后端技术栈:
- Springboot
- mybatisPlus
- redis
- Mysql
- Maven
前端技术栈:
- Vue
- Vue-router
- axios
- elementui
- echarts
基础环境 :IDEA/eclipse, JDK1.8, Mysql5.7及以上, Maven3.6, node14, navicat, 支付宝沙箱账号, ngrok内网穿透
所有项目以及源代码本人均调试运行无问题 可支持远程调试运行
前台访问地址:http://localhost:8080
用户账号密码:zhangsan/123456
管理员账号密码:admin/123456
卖家账号密码:liqiang/123456
-
使用Navicat或者其它工具,在mysql中创建对应名称的数据库,并执行项目的sql文件
-
使用IDEA/Eclipse导入music-ticket-springboot项目,若为maven项目请选择maven,等待依赖下载完成
-
修改application.yml里面的数据库配置和redis配置,src/main/java/com/SpringbootSchemaApplication.java启动后端项目
-
vscode或idea打开music-ticket-vue项目
-
在编译器中打开terminal,执行npm install 依赖下载完成后执行 npm run serve,执行成功后会显示后台访问地址
1、使用支付宝沙箱完全模拟真实支付流程,保障功能完整性。简化调试流程,提升开发效率。
@RestController
@RequestMapping("/alipay")
public class PayController {
private static final String GATEWAY_URL = "https://openapi-sandbox.dl.alipaydev.com/gateway.do";
private static final String FORMAT = "JSON";
private static final String CHARSET = "UTF-8";
//签名方式
private static final String SIGN_TYPE = "RSA2";
@Resource
private AliPayConfig aliPayConfig;
@Resource
private OrderMapper orderMapper;
@Resource
private TicketMapper ticketMapper;
@Resource
private ConcertMapper concertMapper;
private Map<String, Timeout> timeoutMap; // 保存订单号与定时任务的映射关系
@Autowired
public PayController() {
timeoutMap = new HashMap<>();
}
private HashedWheelTimer timer; // HashedWheelTimer实例
@PostConstruct
public void init() {
timer = new HashedWheelTimer(); // 在初始化时创建 HashedWheelTimer 实例
}
@GetMapping("/pay") // &subject=xxx&traceNo=xxx&totalAmount=xxx
public void pay(AliPay aliPay, HttpServletResponse httpResponse) throws Exception {
// 1. 创建Client,通用SDK提供的Client,负责调用支付宝的API
AlipayClient alipayClient = new DefaultAlipayClient(GATEWAY_URL, aliPayConfig.getAppId(),
aliPayConfig.getAppPrivateKey(), FORMAT, CHARSET, aliPayConfig.getAlipayPublicKey(), SIGN_TYPE);
// 2. 创建 Request并设置Request参数
AlipayTradePagePayRequest request = new AlipayTradePagePayRequest(); // 发送请求的 Request类
request.setNotifyUrl(aliPayConfig.getNotifyUrl());
request.setReturnUrl(aliPayConfig.getReturnUrl());
JSONObject bizContent = new JSONObject();
bizContent.set("out_trade_no", aliPay.getTraceNo()); // 我们自己生成的订单编号
bizContent.set("total_amount", aliPay.getTotalAmount()); // 订单的总金额
bizContent.set("subject", aliPay.getSubject()); // 支付的名称
bizContent.set("product_code", "FAST_INSTANT_TRADE_PAY"); // 固定配置
request.setBizContent(bizContent.toString());
// 执行请求,拿到响应的结果,返回给浏览器
String form = "";
try {
form = alipayClient.pageExecute(request).getBody(); // 调用SDK生成表单
} catch (AlipayApiException e) {
e.printStackTrace();
}
httpResponse.setContentType("text/html;charset=" + CHARSET);
httpResponse.getWriter().write(form);// 直接将完整的表单html输出到页面
httpResponse.getWriter().flush();
httpResponse.getWriter().close();
}
@PostMapping("/notify") // 注意这里必须是POST接口
public String payNotify(HttpServletRequest request) throws Exception {
if (request.getParameter("trade_status").equals("TRADE_SUCCESS")) {
System.out.println("=========支付宝异步回调========");
Map<String, String> params = new HashMap<>();
Map<String, String[]> requestParams = request.getParameterMap();
for (String name : requestParams.keySet()) {
params.put(name, request.getParameter(name));
// System.out.println(name + " = " + request.getParameter(name));
}
String outTradeNo = params.get("out_trade_no");
String gmtPayment = params.get("gmt_payment");
String alipayTradeNo = params.get("trade_no");
String sign = params.get("sign");
String content = AlipaySignature.getSignCheckContentV1(params);
boolean checkSignature = AlipaySignature.rsa256CheckContent(content, sign, aliPayConfig.getAlipayPublicKey(), "UTF-8"); // 验证签名
// 支付宝验签
if (checkSignature) {
// 验签通过
System.out.println("交易名称: " + params.get("subject"));
System.out.println("交易状态: " + params.get("trade_status"));
System.out.println("支付宝交易凭证号: " + params.get("trade_no"));
System.out.println("商户订单号: " + params.get("out_trade_no"));
System.out.println("交易金额: " + params.get("total_amount"));
System.out.println("买家在支付宝唯一id: " + params.get("buyer_id"));
System.out.println("买家付款时间: " + params.get("gmt_payment"));
System.out.println("买家付款金额: " + params.get("buyer_pay_amount"));
// 支付成功,关闭订单定时任务
Timeout timeout = timeoutMap.get(outTradeNo); // 根据订单号获取之前的定时任务
if (timeout != null) {
timeout.cancel(); // 取消之前的定时任务
}
// 查询订单
QueryWrapper<Order> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("order_no", outTradeNo);
Order order = orderMapper.selectOne(queryWrapper);
if (order != null) {
LocalDateTime now = LocalDateTime.now();
order.setAlipayNo(alipayTradeNo);
order.setPayTime(now);
order.setStatus("2");
orderMapper.updateById(order);
// 票的数量减一
Integer ticketId = order.getTicketId();
if (ticketId != null) {
Ticket ticket = ticketMapper.selectById(ticketId);
Integer concertId = ticket.getConcertId();
if (concertId != null) {
Concert concert = concertMapper.selectById(concertId);
Integer total = concert.getConcertTotal();
concert.setConcertTotal(total - order.getTicketTotal());
concertMapper.updateById(concert);
}
}
}
}
}
return "success";
}
@GetMapping(value = "/paySuccess")
@ApiOperation("支付成功同步回调接口")
public void success(@RequestParam Map<String, String> map, HttpServletResponse response) throws IOException {
response.sendRedirect(aliPayConfig.getSuccessUrl());
}
}