diff --git a/ruoyi-admin/src/main/java/com/ruoyi/system/controller/BsGoodsController.java b/ruoyi-admin/src/main/java/com/ruoyi/system/controller/BsGoodsController.java index 7621fff5..65835ead 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/system/controller/BsGoodsController.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/system/controller/BsGoodsController.java @@ -67,7 +67,7 @@ public class BsGoodsController extends BaseController { /** * 新增商品 */ - @PreAuthorize("@ss.hasPermi('system:goods:add')") +// @PreAuthorize("@ss.hasPermi('system:goods:add')") @Log(title = "商品", businessType = BusinessType.INSERT) @PostMapping public AjaxResult add(@RequestBody BsGoods bsGoods) { diff --git a/ruoyi-admin/src/main/java/com/ruoyi/system/controller/BsOrderController.java b/ruoyi-admin/src/main/java/com/ruoyi/system/controller/BsOrderController.java index 6002bc2b..75eba76d 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/system/controller/BsOrderController.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/system/controller/BsOrderController.java @@ -82,18 +82,20 @@ public class BsOrderController extends BaseController /** * 新增订单 */ - @PreAuthorize("@ss.hasPermi('system:order:add')") +// @PreAuthorize("@ss.hasPermi('system:order:add')") @Log(title = "订单", businessType = BusinessType.INSERT) @PostMapping public AjaxResult add(@RequestBody BsOrder bsOrder) { - return toAjax(bsOrderService.insertBsOrder(bsOrder)); +// return toAjax(bsOrderService.insertBsOrder(bsOrder)); + int result = bsOrderService.insertBsOrder(bsOrder); + return result > 0 ? AjaxResult.success("orderNo", bsOrder.getOrderNo()) : AjaxResult.error("订单新增失败"); } /** * 修改订单 */ - @PreAuthorize("@ss.hasPermi('system:order:edit')") +// @PreAuthorize("@ss.hasPermi('system:order:edit')") @Log(title = "订单", businessType = BusinessType.UPDATE) @PutMapping public AjaxResult edit(@RequestBody BsOrder bsOrder) @@ -111,4 +113,13 @@ public class BsOrderController extends BaseController { return toAjax(bsOrderService.deleteBsOrderByIds(ids)); } + + /** + * 判断是否支付 + */ + @GetMapping("/getPayStatus/{orderNo}") + public AjaxResult getPayStatus(@PathVariable("orderNo") String orderNo) + { + return success(bsOrderService.getPayStatus(orderNo)); + } } diff --git a/ruoyi-admin/src/main/java/com/ruoyi/system/domain/BsOrder.java b/ruoyi-admin/src/main/java/com/ruoyi/system/domain/BsOrder.java index 9a3a5fa5..face386a 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/system/domain/BsOrder.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/system/domain/BsOrder.java @@ -1,5 +1,6 @@ package com.ruoyi.system.domain; +import java.math.BigDecimal; import java.util.Date; import com.fasterxml.jackson.annotation.JsonFormat; import org.apache.commons.lang3.builder.ToStringBuilder; @@ -9,7 +10,7 @@ import com.ruoyi.common.core.domain.BaseEntity; /** * 订单对象 bs_order - * + * * @author ruoyi * @date 2024-10-25 */ @@ -20,19 +21,28 @@ public class BsOrder extends BaseEntity /** 主键 */ private Long id; - /** 订单号 */ - @Excel(name = "订单号") + /** 商户单号 */ + @Excel(name = "商户单号") private String orderNo; + /** 订单号 */ + @Excel(name = "交易流水号") + private String transactionId; + /** 1:微信,2:支付宝 */ @Excel(name = "1:微信,2:支付宝") private Long channel; /** 支付时间 */ - @JsonFormat(pattern = "yyyy-MM-dd") - @Excel(name = "支付时间", width = 30, dateFormat = "yyyy-MM-dd") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @Excel(name = "支付时间", width = 50, dateFormat = "yyyy-MM-dd HH:mm:ss") private Date payTime; + /** 创建时间 */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @Excel(name = "创建时间", width = 50, dateFormat = "yyyy-MM-dd HH:mm:ss") + private Date createTime; + /** 商品名称 */ @Excel(name = "商品名称") private String goodsName; @@ -43,85 +53,127 @@ public class BsOrder extends BaseEntity /** 订单价格 */ @Excel(name = "订单价格") - private String price; + private BigDecimal price; /** 购买人id */ @Excel(name = "购买人id") private String createId; - public void setId(Long id) + /** 支付状态 */ + @Excel(name = "支付状态") + private int payStatus; + + /** 购买人openid */ + @Excel(name = "购买人openid") + private String openid; + + public void setId(Long id) { this.id = id; } - public Long getId() + public Long getId() { return id; } - public void setOrderNo(String orderNo) + public void setOrderNo(String orderNo) { this.orderNo = orderNo; } - public String getOrderNo() + public String getOrderNo() { return orderNo; } - public void setChannel(Long channel) + public void setChannel(Long channel) { this.channel = channel; } - public Long getChannel() + public Long getChannel() { return channel; } - public void setPayTime(Date payTime) + public void setPayTime(Date payTime) { this.payTime = payTime; } - public Date getPayTime() + public Date getPayTime() { return payTime; } - public void setGoodsName(String goodsName) + public void setGoodsName(String goodsName) { this.goodsName = goodsName; } - public String getGoodsName() + public String getGoodsName() { return goodsName; } - public void setGoodsmin(Long goodsmin) + public void setGoodsmin(Long goodsmin) { this.goodsmin = goodsmin; } - public Long getGoodsmin() + public Long getGoodsmin() { return goodsmin; } - public void setPrice(String price) + public void setPrice(BigDecimal price) { this.price = price; } - public String getPrice() + public BigDecimal getPrice() { return price; } - public void setCreateId(String createId) + public void setCreateId(String createId) { this.createId = createId; } - public String getCreateId() + public String getCreateId() { return createId; } + public String getTransactionId() { + return transactionId; + } + + public void setTransactionId(String transactionId) { + this.transactionId = transactionId; + } + + @Override + public Date getCreateTime() { + return createTime; + } + + @Override + public void setCreateTime(Date createTime) { + this.createTime = createTime; + } + + public int getPayStatus() { + return payStatus; + } + + public void setPayStatus(int payStatus) { + this.payStatus = payStatus; + } + + public String getOpenid() { + return openid; + } + + public void setOpenid(String openid) { + this.openid = openid; + } + @Override public String toString() { return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) @@ -134,6 +186,9 @@ public class BsOrder extends BaseEntity .append("price", getPrice()) .append("createId", getCreateId()) .append("createTime", getCreateTime()) + .append("payStatus", getPayStatus()) + .append("openid", getOpenid()) + .append("transactionId", getTransactionId()) .toString(); } } diff --git a/ruoyi-admin/src/main/java/com/ruoyi/system/mapper/BsOrderMapper.java b/ruoyi-admin/src/main/java/com/ruoyi/system/mapper/BsOrderMapper.java index d80f1164..8b4fe079 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/system/mapper/BsOrderMapper.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/system/mapper/BsOrderMapper.java @@ -66,4 +66,12 @@ public interface BsOrderMapper * @return 结果 */ public int deleteBsOrderByIds(Long[] ids); + + /** + * 判断是否支付 + * + * @param orderNo 商家订单号号 + * @return 结果 + */ + public int getPayStatus(String orderNo); } diff --git a/ruoyi-admin/src/main/java/com/ruoyi/system/service/IBsOrderService.java b/ruoyi-admin/src/main/java/com/ruoyi/system/service/IBsOrderService.java index 862ebba4..458dbdef 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/system/service/IBsOrderService.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/system/service/IBsOrderService.java @@ -66,4 +66,12 @@ public interface IBsOrderService * @return 结果 */ public int deleteBsOrderById(Long id); + + /** + * 判断是否支付 + * + * @param orderNo 商家订单号号 + * @return 结果 + */ + public int getPayStatus(String orderNo); } diff --git a/ruoyi-admin/src/main/java/com/ruoyi/system/service/impl/BsOrderServiceImpl.java b/ruoyi-admin/src/main/java/com/ruoyi/system/service/impl/BsOrderServiceImpl.java index 337e28bd..49c054e4 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/system/service/impl/BsOrderServiceImpl.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/system/service/impl/BsOrderServiceImpl.java @@ -106,4 +106,15 @@ public class BsOrderServiceImpl implements IBsOrderService { return bsOrderMapper.deleteBsOrderById(id); } + + /** + * 判断是否支付 + * + * @param orderNo 商家订单号号 + * @return 结果 + */ + @Override + public int getPayStatus(String orderNo) { + return bsOrderMapper.getPayStatus(orderNo); + } } diff --git a/ruoyi-admin/src/main/java/com/ruoyi/wxPay/WechatPayController.java b/ruoyi-admin/src/main/java/com/ruoyi/wxPay/WechatPayController.java index f54d1061..ed617d3c 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/wxPay/WechatPayController.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/wxPay/WechatPayController.java @@ -9,10 +9,13 @@ import com.ruoyi.common.wx.PayService; import com.ruoyi.common.wx.StreamUtils; import com.ruoyi.common.wx.WxPayDTO; import com.ruoyi.common.wx.WxPayProperties; +import com.ruoyi.system.domain.BsOrder; +import com.ruoyi.system.service.IBsOrderService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; @@ -20,6 +23,8 @@ import javax.annotation.Resource; import javax.servlet.ServletInputStream; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import java.math.BigDecimal; +import java.text.SimpleDateFormat; import java.util.Date; import java.util.HashMap; import java.util.Map; @@ -38,18 +43,23 @@ public class WechatPayController { @Resource // 注入WxPayProperties,用于获取微信支付的配置信息 private WxPayProperties wxPayProperties; - @Anonymous + @Autowired + private IBsOrderService bsOrderService; + @Anonymous @ApiOperation(value = "微信native下单,返回支付二维码") // 描述该API的功能 @GetMapping("/nativePay") // 定义GET请求的路径为/pay/nativePay public Object nativePay(@RequestParam("orderNumber") String orderNumber) { - // todo 业务操作-根据订单编号查询订单信息 + //根据订单编号查询订单信息 + BsOrder bsOrder = bsOrderService.selectBsOrderByOrderNo(orderNumber); // 将订单信息中的数据存到WxPayDTO WxPayDTO payDTO = new WxPayDTO(); // 创建WxPayDTO对象用于存储支付信息 - payDTO.setBody("商品描述"); // 设置商品描述 + payDTO.setBody(bsOrder.getGoodsName()); // 设置商品描述 // 订单总金额,单位为分 - payDTO.setTotalFee(1); // 设置订单总金额(1分) + BigDecimal price = bsOrder.getPrice(); + final int total = price.multiply(new BigDecimal("100")).setScale(0, BigDecimal.ROUND_HALF_UP).intValue(); + payDTO.setTotalFee(total); // 设置订单总金额(1分) // 支付回调地址 payDTO.setNotifyUrl(wxPayProperties.getNotifyUrl()); // 设置支付成功后的回调地址 @@ -81,7 +91,7 @@ public class WechatPayController { // todo 业务操作-根据订单编号查询订单信息 // 将订单信息中的数据存到WxPayDTO WxPayDTO payDTO = new WxPayDTO(); // 创建WxPayDTO对象用于存储支付信息 - payDTO.setBody("支付测试"); // 设置商品描述 + payDTO.setBody("支付测试2"); // 设置商品描述 // 订单总金额,单位为分 payDTO.setTotalFee(1); // 设置订单总金额(1分) @@ -117,7 +127,7 @@ public class WechatPayController { // todo 业务操作-根据订单编号查询订单信息 // 将订单信息中的数据存到WxPayDTO WxPayDTO payDTO = new WxPayDTO(); // 创建WxPayDTO对象用于存储支付信息 - payDTO.setBody("商品描述"); // 设置商品描述 + payDTO.setBody("支付测试3"); // 设置商品描述 // 订单总金额,单位为分 payDTO.setTotalFee(1); // 设置订单总金额(1分) @@ -148,10 +158,12 @@ public class WechatPayController { return url; // 返回H5支付链接 } + @Anonymous @ApiOperation(value = "微信支付回调") // 描述该API的功能 @PostMapping("/wxCallback") // 定义POST请求的路径为/pay/wxCallback public Object wxCallback(HttpServletRequest request, HttpServletResponse response) { ServletInputStream inputStream = null; // 定义输入流用于接收请求体 + SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss"); try { inputStream = request.getInputStream(); // 获取请求体的输入流 String notifyXml = StreamUtils.inputStream2String(inputStream, "utf-8"); // 将输入流转换为字符串 @@ -165,6 +177,14 @@ public class WechatPayController { // 判断支付是否成功 if ("SUCCESS".equals(notifyMap.get("result_code"))) { // 如果支付结果为成功 // todo 修改订单状态 + BsOrder order = new BsOrder(); + order.setChannel(1L); + order.setPayStatus(1); + order.setTransactionId(notifyMap.get("transaction_id")); + order.setOpenid(notifyMap.get("openid")); + order.setOrderNo(notifyMap.get("out_trade_no")); + order.setPayTime(sdf.parse(notifyMap.get("time_end"))); + int i = bsOrderService.updateBsOrder(order); // 支付成功:给微信发送我已接收通知的响应 创建响应对象 Map returnMap = new HashMap<>(); // 创建返回的Map @@ -174,9 +194,11 @@ public class WechatPayController { String returnXml = WXPayUtil.mapToXml(returnMap); // 将Map转换为XML格式 response.setContentType("text/xml"); // 设置响应的内容类型为XML log.info("支付成功"); // 打印支付成功日志 + System.out.println("支付成功"); return returnXml; // 返回成功的XML响应 } else { // 保存回调信息,方便排除问题 + System.out.println("支付失败"); } // 创建响应对象:微信接收到校验失败的结果后,会反复的调用当前回调函数 Map returnMap = new HashMap<>(); // 创建返回的Map diff --git a/ruoyi-admin/src/main/resources/mapper/system/BsOrderMapper.xml b/ruoyi-admin/src/main/resources/mapper/system/BsOrderMapper.xml index 7085192a..fc57a9d9 100644 --- a/ruoyi-admin/src/main/resources/mapper/system/BsOrderMapper.xml +++ b/ruoyi-admin/src/main/resources/mapper/system/BsOrderMapper.xml @@ -5,33 +5,51 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" - - - - - - - - - + + + + + + + + + + + + - select id, order_no, channel, pay_time, goods_name, goodsmin, price, create_id, create_time from bs_order - + select + id, + order_no, + channel, + transaction_id, + pay_time, + goods_name, + goodsmin, + price, + create_id, + create_time, + payStatus, + openid + from bs_order + select payStatus from bs_order where + order_no = #{orderNo} + diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java index e9dd98c6..c003a2fb 100644 --- a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java @@ -111,7 +111,7 @@ public class SecurityConfig .authorizeHttpRequests((requests) -> { permitAllUrl.getUrls().forEach(url -> requests.antMatchers(url).permitAll()); // 对于登录login 注册register 验证码captchaImage 允许匿名访问 - requests.antMatchers("/login", "/register", "/captchaImage","/system/goods/**","/system/designType/**","/system/type/**","/system/order/**","/system/note/**").permitAll() + requests.antMatchers("/login", "/register", "/captchaImage","/system/goods/**","/system/designType/**","/system/type/**","/system/order/**","/system/note/**","/pay/**").permitAll() // 静态资源,可匿名访问 .antMatchers(HttpMethod.GET, "/", "/*.html", "/**/*.html", "/**/*.css", "/**/*.js", "/profile/**").permitAll() .antMatchers("/swagger-ui.html", "/swagger-resources/**", "/webjars/**", "/*/api-docs", "/druid/**").permitAll() diff --git a/ruoyi-ui/package.json b/ruoyi-ui/package.json index fafe49c0..5c5a7043 100644 --- a/ruoyi-ui/package.json +++ b/ruoyi-ui/package.json @@ -49,6 +49,7 @@ "js-cookie": "3.0.1", "jsencrypt": "3.0.0-rc.1", "nprogress": "0.2.0", + "qrcode": "^1.5.4", "quill": "2.0.2", "screenfull": "5.0.2", "sortablejs": "1.10.2", @@ -57,6 +58,7 @@ "vue-count-to": "1.0.13", "vue-cropper": "0.5.5", "vue-meta": "2.4.0", + "vue-qr": "^4.0.9", "vue-router": "3.4.9", "vuedraggable": "2.24.3", "vuex": "3.6.0" diff --git a/ruoyi-ui/src/api/system/order.js b/ruoyi-ui/src/api/system/order.js index 84e28f1f..33bfda74 100644 --- a/ruoyi-ui/src/api/system/order.js +++ b/ruoyi-ui/src/api/system/order.js @@ -50,3 +50,18 @@ export function delOrder(id) { method: 'delete' }) } + +//根据订单编号获取支付二维码 +export function orderPay(orderNo) { + return request({ + url: '/pay/nativePay?orderNumber=' + orderNo, + method: 'get' + }) +} + +export function getPayStatus(orderNo) { + return request({ + url: '/system/order/getPayStatus/' + orderNo, + method: 'get' + }) +} diff --git a/ruoyi-ui/src/assets/images/moren.png b/ruoyi-ui/src/assets/images/moren.png new file mode 100644 index 00000000..d85897bd Binary files /dev/null and b/ruoyi-ui/src/assets/images/moren.png differ diff --git a/ruoyi-ui/src/main.js b/ruoyi-ui/src/main.js index ae033d19..ead78c4d 100644 --- a/ruoyi-ui/src/main.js +++ b/ruoyi-ui/src/main.js @@ -38,6 +38,8 @@ import VueMeta from 'vue-meta' // 字典数据组件 import DictData from '@/components/DictData' import * as ElementUI from "element-ui"; +import VueQr from 'vue-qr' + // 全局方法挂载 Vue.prototype.getDicts = getDicts @@ -58,6 +60,7 @@ Vue.component('Editor', Editor) Vue.component('FileUpload', FileUpload) Vue.component('ImageUpload', ImageUpload) Vue.component('ImagePreview', ImagePreview) +Vue.component('VueQr', VueQr) Vue.use(directive) Vue.use(plugins) @@ -79,6 +82,7 @@ Vue.use(Element, { Vue.config.productionTip = false + new Vue({ el: '#app', router, diff --git a/ruoyi-ui/src/permission.js b/ruoyi-ui/src/permission.js index 2a8d3a23..39020b88 100644 --- a/ruoyi-ui/src/permission.js +++ b/ruoyi-ui/src/permission.js @@ -8,7 +8,7 @@ import { isRelogin } from '@/utils/request' NProgress.configure({ showSpinner: false }) -const whiteList = ['/login', '/register','/cus','/cusDetails','/cusDetPay','/userOrder','/note'] +const whiteList = ['/login', '/register','/cus','/cusDetails','/cusDetPay','/userOrder','/note','/payMent'] router.beforeEach((to, from, next) => { NProgress.start() diff --git a/ruoyi-ui/src/router/index.js b/ruoyi-ui/src/router/index.js index 6c96d1e7..b79bf599 100644 --- a/ruoyi-ui/src/router/index.js +++ b/ruoyi-ui/src/router/index.js @@ -81,6 +81,11 @@ export const constantRoutes = [ component: () => import('@/views/system/userFront/payBefore'), hidden: true }, + { + path: '/payMent', + component: () => import('@/views/system/userFront/payMent'), + hidden: true + }, { path: '/userOrder', component: () => import('@/views/system/userFront/order'), diff --git a/ruoyi-ui/src/views/system/order/index.vue b/ruoyi-ui/src/views/system/order/index.vue index 10ace686..059eeee9 100644 --- a/ruoyi-ui/src/views/system/order/index.vue +++ b/ruoyi-ui/src/views/system/order/index.vue @@ -4,7 +4,7 @@ @@ -28,10 +28,10 @@ - + @@ -90,24 +90,30 @@ - + + - - - - + + + + + + + @@ -202,14 +208,18 @@ export default { queryParams: { pageNum: 1, pageSize: 10, + id: null, orderNo: null, channel: null, + transactionId: null, payTime: null, goodsName: null, goodsmin: null, price: null, createId: null, - createTime: null + createTime: null, + payStatus: null, + openid: null }, // 表单参数 form: {}, @@ -226,7 +236,9 @@ export default { getList() { this.loading = true; listOrder(this.queryParams).then(response => { + console.log('order',this.queryParams) this.orderList = response.rows; + console.log('res',response) this.total = response.total; this.loading = false; }); @@ -242,12 +254,15 @@ export default { id: null, orderNo: null, channel: null, + transactionId: null, payTime: null, goodsName: null, goodsmin: null, price: null, createId: null, - createTime: null + createTime: null, + payStatus: null, + openid: null }; this.resetForm("form"); }, @@ -328,6 +343,14 @@ export default { default: return '未知支付方式'; } + }, + getPayStatus(channel) { + switch (channel) { + case 1: + return '已支付'; + case 2: + return '未支付'; + } } } }; diff --git a/ruoyi-ui/src/views/system/userFront/details.vue b/ruoyi-ui/src/views/system/userFront/details.vue index ba1b78d2..3befb3fa 100644 --- a/ruoyi-ui/src/views/system/userFront/details.vue +++ b/ruoyi-ui/src/views/system/userFront/details.vue @@ -214,7 +214,7 @@ export default { return; } if (!fileUrl.startsWith('http')) { - fileUrl = 'http://127.0.0.1:8080' + fileUrl; + fileUrl = 'http://127.0.0.1:40506' + fileUrl; } axios({ diff --git a/ruoyi-ui/src/views/system/userFront/index.vue b/ruoyi-ui/src/views/system/userFront/index.vue index ad506417..e5c9556c 100644 --- a/ruoyi-ui/src/views/system/userFront/index.vue +++ b/ruoyi-ui/src/views/system/userFront/index.vue @@ -77,7 +77,8 @@ - + +
{{ item.name }}
@@ -183,7 +184,8 @@ export default { name: null, type: null, }, - technicalType: null + technicalType: null, + defaultImage: require('@/assets/images/moren.png'), }; }, mounted() { diff --git a/ruoyi-ui/src/views/system/userFront/payBefore.vue b/ruoyi-ui/src/views/system/userFront/payBefore.vue index 940e571d..9acecf7b 100644 --- a/ruoyi-ui/src/views/system/userFront/payBefore.vue +++ b/ruoyi-ui/src/views/system/userFront/payBefore.vue @@ -17,7 +17,11 @@
- +

{{ goods.name }}

¥{{ goods.price }}

@@ -45,6 +49,8 @@ + +