1.前言

接上一篇《vue+element+SpringBoot+OAuth2+Spring Security+Redis+mybatis-plus+mysql+swagger模仿商城,前后端分离实现》。

上篇文章介绍了:

  1. 用户注册
  2. 用户登录
  3. 首页商品推荐展览
  4. 商品搜索
  5. 商品分类
  6. 按商品分类预览商品
  7. 商品详情预览
  8. 加入购物车

上一篇文章有说过已实现单一订单下单,即只能一个一个商品去下单购买,所以这次进行了优化完善,把单一订单改成了合并订单,即一个订单下面可包含多个订单行项目,也就是一次可购买多个商品,统一生成一个订单,然后进行扫码支付;

2.合并订单需要设计两个数据表:

大订单表:

  CREATE TABLE `product_order`
(`id` bigint NOT NULL COMMENT '主键',`order_num` varchar(100) DEFAULT NULL COMMENT '订单号',`user_id` bigint NOT NULL COMMENT '所属用户',`pay_amount` decimal(10, 2) NOT NULL DEFAULT 0 COMMENT '支付金额',`receiver_name` varchar(225) NOT NULL COMMENT '收货人姓名',`receiver_phone` varchar(225) NOT NULL COMMENT '收货人联系电话',`receiver_addr` varchar(225) NOT NULL COMMENT '收货人地址',`receiver_remark` varchar(225) DEFAULT NULL COMMENT '收货人备注',`pay_status`  TINYINT(1) DEFAULT 1 COMMENT '支付状态 1待支付 2待发货 3已发货 4已完成 5已取消',`deleted` tinyint(1) DEFAULT '0' COMMENT '逻辑删除标记 是否已删除: 0否  1是',`create_time` datetime(0) COMMENT '创建时间',`update_time` datetime(0) COMMENT '更新时间',PRIMARY KEY (`id`) USING BTREE,UNIQUE KEY `order_num` (`order_num`) USING BTREE
) ENGINE = InnoDBDEFAULT CHARSET = utf8mb4 COMMENT ='订单';

订单行项目表:

    -- 订单行项目CREATE TABLE `product_order_item`
(`id` bigint NOT NULL COMMENT '主键',`parent_id` bigint NOT NULL COMMENT '订单主键',`order_num` varchar(100) DEFAULT NULL COMMENT '订单号',`product_id` bigint NOT NULL COMMENT '商品主键',`product_name` varchar(225) NOT NULL COMMENT '商品名称',`product_des` varchar(225) DEFAULT NULL COMMENT '商品描述',`price` decimal(10, 2) NOT NULL DEFAULT 0 COMMENT '商品单价',`original_price` decimal(10, 2) NOT NULL DEFAULT 0 COMMENT '商品原价',`cover_path` varchar(500) DEFAULT NULL COMMENT '商品封面图片',`product_num` int(11) NULL DEFAULT 0 COMMENT '商品购买数量',`deleted` tinyint(1) DEFAULT '0' COMMENT '逻辑删除标记 是否已删除: 0否  1是',`create_time` datetime(0) COMMENT '创建时间',`update_time` datetime(0) COMMENT '更新时间',PRIMARY KEY (`id`) USING BTREE,
) ENGINE = InnoDBDEFAULT CHARSET = utf8mb4 COMMENT ='订单行项目';

3.生成支付二维码

controller:

/*** 微信支付->扫码支付(模式二)->统一下单->微信二维码*/@GetMapping("/getQrcode")public void wxPayPay(@Param("订单号") @RequestParam("orderNum") String orderNum, HttpServletResponse response) {wxPayService.getPayQrcode(orderNum,response);}

service:

 /*** 微信支付->扫码支付(模式二)->统一下单->微信二维码** @param orderNum 订单号* @param response 返回*/@Overridepublic void getPayQrcode(String orderNum, HttpServletResponse response) {String urlCode;// 获取订单信息WxpayVO vo = new WxpayVO();String outTradeNo = UUID.randomUUID().toString().replace("-", "");vo.setOutTradeNo(outTradeNo);// 账号信息vo.setAppId(wxPayConfig.getAppId());vo.setMchId(wxPayConfig.getMchId());vo.setKey(wxPayConfig.getKey());String currTime = PayToolUtil.getCurrTime();vo.setCurrTime(currTime);String strTime = currTime.substring(8, currTime.length());vo.setStrTime(strTime);String strRandom = String.valueOf(PayToolUtil.buildRandom(4));vo.setStrRandom(strRandom);String nonceStr = strTime + strRandom;vo.setNonceStr(nonceStr);vo.setSpbillCreateIp(wxPayConfig.getSpbillCreateIp());vo.setNotifyUrl(wxPayConfig.getNotifyUrl());vo.setTradeType("NATIVE");String totalFee = "1";vo.setTotalFee(totalFee);//价格的单位为分SortedMap<Object,Object> packageParams = new TreeMap<Object,Object>();packageParams.put("appid", wxPayConfig.getAppId());//公众账号IDpackageParams.put("mch_id", wxPayConfig.getMchId());//商户号packageParams.put("nonce_str", wxPayConfig.getNonceStr());//随机字符串packageParams.put("body", "资源");  //商品描述packageParams.put("out_trade_no", wxPayConfig.getNonceStr());//商户订单号packageParams.put("total_fee", totalFee); //标价金额 订单总金额,单位为分packageParams.put("spbill_create_ip", wxPayConfig.getSpbillCreateIp());//终端IP APP和网页支付提交用户端ip,Native支付填调用微信支付API的机器IPpackageParams.put("notify_url", wxPayConfig.getNotifyUrl());//通知地址 异步接收微信支付结果通知的回调地址,通知url必须为外网可访问的url,不能携带参数packageParams.put("trade_type", "NATIVE");//交易类型 NATIVE 扫码支付// 签名String sign = PayToolUtil.createSign("UTF-8", packageParams, wxPayConfig.getKey());packageParams.put("sign", sign);// 将请求参数转换为xml格式的stringString requestXML = PayToolUtil.getRequestXml(packageParams);log.info("requestXML:{}", requestXML);// 调用微信支付统一下单接口String resXml = HttpUtil.postData(PayConfigUtil.UFDODER_URL, requestXML);log.info("resXml: {}", resXml);// 解析微信支付结果Map map = null;try {map = XMLUtil4jdom.doXMLParse(resXml);log.info("map: {}", map);} catch (JDOMException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}// 返回微信支付的二维码连接urlCode = (String) map.get("code_url");log.info("urlCode:{}", urlCode);if(urlCode == null){//测试urlCode = "http://192.168.50.231:8089/order/updatePayStatus?orderNum=" + orderNum + "&payStatus=" + PayStatus.WAIT_SEND.getValue();}try {int width = 300;int height = 300;//二维码的图片格式String format = "gif";Hashtable hints = new Hashtable();//内容所使用编码hints.put(EncodeHintType.CHARACTER_SET, "utf-8");BitMatrix bitMatrix;bitMatrix = new MultiFormatWriter().encode(urlCode, BarcodeFormat.QR_CODE, width, height, hints);QRUtil.writeToStream(bitMatrix, format, response.getOutputStream());} catch (WriterException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}

注意:

urlCode = "http://192.168.50.231:8089/order/updatePayStatus?orderNum=" + orderNum + "&payStatus=" + PayStatus.WAIT_SEND.getValue();

这一句是为了本地测试加的,因为微信支付首先要去微信申请开通微信支付:

微信支付文档

二维码代表的内容就是urlCode的具体值,扫码模拟微信支付就会直接请求路径:http://192.168.50.231:8089/order/updatePayStatus?orderNum=" + orderNum + "&payStatus=" + PayStatus.WAIT_SEND.getValue(),进行订单状态更新,所以接口要开放白名单,即是无需登录即可请求。

当然如果是真实的微信支付,则需要配置支付回调地址,由微信官方通知服务器订单支付的状态,同样也要配置开放白名单,否则微信无法请求到我们的服务器。

微信回调:

controller:

/*** 微信支付-回调* @param request request请求* @param response response返回*/@PostMapping("/notify")public String wxPayNotify(HttpServletRequest request, HttpServletResponse response) {return wxPayService.wxPayNotify(request,response);}

service:

 /*** 微信支付回调** @param request 请求* @param response 返回* @return 结果*/@Overridepublic String wxPayNotify(HttpServletRequest request, HttpServletResponse response) {//读取参数InputStream inputStream ;StringBuffer sb = null;try {sb = new StringBuffer();inputStream = request.getInputStream();String s ;BufferedReader in = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));while ((s = in.readLine()) != null){sb.append(s);}in.close();inputStream.close();} catch (IOException e) {e.printStackTrace();}//解析xml成mapMap<String, String> map = new HashMap<String, String>();try {map = XMLUtil4jdom.doXMLParse(sb.toString());} catch (JDOMException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}//过滤空 设置 TreeMapSortedMap<Object,Object> packageParams = new TreeMap<Object,Object>();Iterator it = map.keySet().iterator();while (it.hasNext()) {String parameter = (String) it.next();String parameterValue = map.get(parameter);String v = "";if(null != parameterValue) {v = parameterValue.trim();}packageParams.put(parameter, v);}//判断签名是否正确if(PayToolUtil.isTenpaySign("UTF-8", packageParams, wxPayConfig.getKey())) {//------------------------------//处理业务开始//------------------------------String resXml = "";if("SUCCESS".equals((String)packageParams.get("result_code"))){// 这里是支付成功//执行自己的业务逻辑String mch_id = (String)packageParams.get("mch_id");String openid = (String)packageParams.get("openid");String is_subscribe = (String)packageParams.get("is_subscribe");String out_trade_no = (String)packageParams.get("out_trade_no");String total_fee = (String)packageParams.get("total_fee");//执行自己的业务逻辑productOrderService.updatePayStatus(out_trade_no,PayStatus.WAIT_SEND.getValue());log.info("支付成功");//通知微信.异步确认成功.必写.不然会一直通知后台.八次之后就认为交易失败了.resXml = "<xml>" + "<return_code><![CDATA[SUCCESS]]></return_code>"+ "<return_msg><![CDATA[OK]]></return_msg>" + "</xml> ";} else {resXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>"+ "<return_msg><![CDATA[报文为空]]></return_msg>" + "</xml> ";return ("fail");}//------------------------------//处理业务完毕//------------------------------try {BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream());out.write(resXml.getBytes());out.flush();out.close();} catch (IOException e) {e.printStackTrace();}} else{log.info("通知签名验证失败");}return ("success");}

4.模拟微信扫码支付,逻辑其实是一样的

1.单一商品下单,微信扫一扫:

轮询查询订单状态:

当订单状态为完成支付时,倒计时5秒跳转:

getByOrderNumFun(){getByOrderNum(this.orderNum).then(res => {if(res.code === 200){if(res.data.payStatus === 1){//待支付if(this.url === ''){this.url = '/api/wxPay/getQrcode?orderNum=' + this.orderNum;}}else if(res.data.payStatus === 2){//已支付clearInterval(this.inter);this.tipColor = '#67C23A';this.tip = '支付成功,正在为您跳转订单页面~';this.countDownFun(5,'/order/index');}else if(res.data.payStatus === 4){//已取消订单clearInterval(this.inter);this.tip = '订单已取消,正在为您跳转首页~';this.countDownFun(5,'/home/index');}else{clearInterval(this.inter);}}else{clearInterval(this.inter);}},error => {clearInterval(this.inter);})},

多个商品下单:

看到订单列表超过两个商品时显示样式有问题,修正优化~:

待支付,可以点击进行支付:

已付款,待发货:

可取消订单:

微信模拟扫码截图(忽略提示乱码):

5.至此订单告一段落

感谢看到这里,需要源码或有什么问题和想说的请私聊!

vue+element模仿电商商城,前后端分离实现,下单微信扫码支付相关推荐

  1. 基于springboot+vue的商城系统(电商平台)(前后端分离)

    博主主页:猫头鹰源码 博主简介:Java领域优质创作者.CSDN博客专家.公司架构师.全网粉丝5万+.专注Java技术领域和毕业设计项目实战 主要内容:毕业设计(Javaweb项目|小程序等).简历模 ...

  2. Java项目:网上电商项目(前后端分离+java+vue+Springboot+ssm+mysql+maven+redis)

    源码获取:博客首页 "资源" 里下载! 一.项目简述 本系统功能包括: 一款基于Springboot+Vue的电商项目,前后端分离项目,前台后台都有,前台商品展示购买,购物车分类, ...

  3. python全栈生鲜电商_Python前后端分离开发Vue+Django REST framework全栈打造生鲜电商项目...

    vue项目采用当前流行的前后端分离式开发技术,涉及RESTFul API基础知识和Vue项目结构分析,解决了技术开发单一的痛点,拥有超前的技术融合技能,让你在开发的领域比别人技高一筹! 1.项目初始化 ...

  4. 微信支付宝服务器分布,支付宝微信扫码支付中间件「第二届立创商城电子制作节30强作品」...

    原标题:支付宝微信扫码支付中间件「第二届立创商城电子制作节30强作品」 本作品为第二届立创商城电子制作节30强入围作品,作者立创社区ID:云逸Baby:转载请注明出处,未经允许不得用作商业用途.作品原 ...

  5. vue+element简单实现商城网站首页,模仿电商商城

    1.安装启动vue项目可参考 vue+element简单实现商城网站首页,模仿小米电商商城https://blog.csdn.net/lucky_fang/article/details/121544 ...

  6. vue实战项目-电商商城前台-(学习尚硅谷的)尚品汇

    文章目录 最好使用视频上的账号密码,13700000000 密:111111 最新服务端接口地址:http://gmall-h5-api.atguigu.cn 脚手架使用 1.创建项目 2.脚手架默认 ...

  7. 前后端分离的Java微信小程序B2C商城 H5+APP源码

    Java B2C商城微信小程序 H5+APP源码 前后端分离 H5+微信小程序+ Android+IOS, Java SpringBoot+vue 开发语言:JAVA 数据库:MySQL 开发工具:E ...

  8. Vue.js + Restful + PageHelper + Thymeleaf + Springboot 前后端分离 增删改查 CRUD 教程

    更多内容,点击了解: https://how2j.cn/k/springboot/springboot-vue/1788.html 目录 步骤 1 : 教程说明 步骤 2 : 数据库准备 步骤 3 : ...

  9. 基于VUE只是作为模版引擎的前后端分离

    首先请原谅本文标题取的有点大,但并非为了哗众取宠.本文取这个标题主要有3个原因,这也是写作本文的初衷: (1)目前国内几乎搜索不到全面讲解如何搭建前后端分离框架的文章,讲前后端分离框架思想的就更少了, ...

最新文章

  1. C++ 字符串字母大小写转换
  2. 2017-2018-1 20155328 《信息安全系统设计基础》第十四周学习总结
  3. python第三方库之Django学习笔记一
  4. python教学视频下载-Python机器学习入门教程全套视频下载【传智播客】
  5. 科大星云诗社动态20210525
  6. SQL数据导入导出问题总结
  7. Druid 连接池的实用 配置详解
  8. Windows杀死结束进程图形化界面操作方法
  9. java基础---多线程同步锁问题
  10. 2013 ACM/ICPC 长沙网络赛J题
  11. led大屏按实际尺寸设计画面_“差评”不断的LED户外大屏,到底缺了什么?
  12. 安装程序无法创建新的系统分区
  13. k3B软件下载_优麒麟20.10发布:简约、众智、兼容Windows有戏_办公软件
  14. 微信小程序布局理解——flex、block、inline
  15. BZOJ_4199_[Noi2015]品酒大会_后缀自动机
  16. 未受信任的企业级开发者_在 iOS 上安装自定企业级应用
  17. 七夕给男朋友送什么礼物好、七夕男朋友礼物清单
  18. bat一键清理系统垃圾/系统日志
  19. 网络攻防技术-Lab5-shellcode编写实验(SEED Labs – Shellcode Development Lab)
  20. 【运筹学】对偶理论总结 ( 对称性质 | 弱对偶定理 | 最优性定理 | 强对偶性 | 互补松弛定理 ) ★★★

热门文章

  1. Golang 定时任务 github/robfig/cron/v3 使用与源码解析
  2. 打印网页去掉不相关信息
  3. 使用python把批量xls文件转换为xlsx
  4. P1972 [SDOI2009] HH的项链
  5. 常见报错信息及解决方法
  6. Qt笔记-Windows管道通信
  7. PCB设计走线细节讲解(图文结合|强力推荐)
  8. 产品读书《AI进化论:解码人工智能商业场景与案例》
  9. 【ARM Cache 入门及渐进五--内存屏障ISB/DSB/DMB】
  10. itunes无法安装到win7系统更新服务器,Win7旗舰版电脑无法安装itunes怎么办