外国做问卷可以赚钱的网站/品牌推广营销平台
目录
- Native 下单
- 1、创建课程订单保存到数据库
- 1-1:需求:
- 1-2:代码:
- 1-3:测试结果:
- 2、保存支付二维码的url
- 2-1:需求:
- 2-2:代码:
- 2-3:测试:
- 2-4:完整代码:
- 后端:
- WxPayController
- WxPayService
- WxPayServiceImpl
- OrderInfoService
- OrderInfoServiceImpl
- 3、显示订单列表
- 3-1:需求:
- 3-2:代码:
- 前端:
- 后端:
- 3-3:测试:
- 查看swagger
- 查看订单列表
- 3-4:完整代码
- 后端:
- OrderInfoController
- OrderInfoService
- OrderInfoServiceImpl
Native 下单
1、创建课程订单保存到数据库
1-1:需求:
之前的下单,只是获取支付二维码,但是并没有将订单存到数据库
需求1:点击确认支付后,创建商品的订单存到数据库
需求2:每次确认支付之前,要判断这个人是否存在已下单未支付的订单,有的话就不用再创建订单了,把他的订单查询出来给他就行。
1-2:代码:
需求1:点击确认支付后,创建商品的订单存到数据库
需求2:每次确认支付之前,要判断这个人是否存在已下单未支付的订单,有的话就不用再创建订单了,把他的订单查询出来给他就行。
1-3:测试结果:
成功在数据库添加订单,并且多次点击确认下单,并不会重复添加订单到数据库
2、保存支付二维码的url
2-1:需求:
上面创建订单的时候,是没有存二维码的url到数据库的,这里需要在创建订单的时候,把url存进去。
Native调起支付
2-2:代码:
解释:
因为获取支付二维码url的代码在创建订单之后,所以第一次创建订单是没有支付二维码的url的。
所以在往下的代码中,添加了保存二维码的代码。
2-3:测试:
保存二维码成功,并且在重复访问的时候,因为存在二维码,所以不会再去调用微信的下单接口。
因为二维码有效期为2小时,所以后面还需要优化,如果二维码过期,需要再次更新数据库中的二维码。
2-4:完整代码:
包含创建订单和保存支付二维码的代码
后端:
WxPayController
@CrossOrigin //跨域
@RestController
@RequestMapping("/api/wx-pay")
@Api(tags = "网站微信支付API") //swagger 注解
@Slf4j
public class WxPayController
{@Resourceprivate WxPayService wxPayService;//调用统一下单API,生成支付二维码的链接和订单号//swagger注解@ApiOperation("调用统一下单API,生成支付二维码")@PostMapping("/native/{productId}")public R nativePay(@PathVariable Long productId) throws Exception{log.info("发起支付请求");//返回支付二维码的链接和订单号Map<String,Object> map = wxPayService.nativePay(productId);return R.ok().setData(map);}
}
WxPayService
public interface WxPayService
{//调用统一下单API,生成支付二维码的链接和订单号Map<String, Object> nativePay(Long productId) throws Exception;
}
WxPayServiceImpl
//创建订单,调用 Native 支付接口
@Service
@Slf4j
public class WxPayServiceImpl implements WxPayService
{@Resourceprivate WxPayConfig wxPayConfig;/* 原本应该注 入WxPayConfig 这个类,然后调用 getWxPayClient() 方法获取 HttpClient请求对象* 但是因为 getWxPayClient() 方法加了@Bean注解,交给了spring容器管理,所以项目启动的时候就会执行这个方法,* 就会存在返回值为 CloseableHttpClient 类型的 HttpClient请求对象* 所以这里可以直接注入这个 CloseableHttpClient 对象*/@Resourceprivate CloseableHttpClient wxPayClient;@Resourceprivate OrderInfoService orderInfoService;/*** 创建订单,调用 Native 支付接口** @param productId 商品id* @return code_url 和 订单号* @throws Exception*///调用统一下单API,生成支付二维码的链接和订单号@Overridepublic Map<String, Object> nativePay(Long productId) throws Exception{//生成订单OrderInfo orderInfo = orderInfoService.createOrderInfoByProduct(productId);//获取二维码url-----如果是第一次生成订单,那么这个订单是没有二维码url的String codeUrl = orderInfo.getCodeUrl();//判断--如果订单存在,并且二维码的url也存在,那么就不需要再去调用微信的下单接口来获取支付二维码了if (orderInfo != null && !StringUtils.isEmpty(codeUrl)){//创建一个包含url和订单号的返回值Map<String, Object> map = new HashMap<>();map.put("codeUrl", codeUrl);map.put("orderNo", orderInfo.getOrderNo());return map;}/** 官方提供的 Native下单 接口* 支持商户:【普通商户】* 请求方式:【POST】/v3/pay/transactions/native* 请求域名:【主域名】https://api.mch.weixin.qq.com* "https://api.mch.weixin.qq.com/v3/pay/transactions/native" 改成* wxPayConfig.getDomain().concat(WxApiType.NATIVE_PAY.getType())*/log.info("调用统一下单API.....");//调用统一下单API---拷贝官网的实例代码进行修改---统一下单的接口地址//封装统一下单API 的urlHttpPost httpPost = new HttpPost(wxPayConfig.getDomain().concat(WxApiType.NATIVE_PAY.getType()));// 请求body参数---------调用接口需要的参数Gson gson = new Gson();//数据类型不固定,所以就不写泛型了Map paramsMap = new HashMap();//设置参数 --- 根据官网要求设置对应的参数paramsMap.put("appid", wxPayConfig.getAppid()); //公众号IDparamsMap.put("mchid", wxPayConfig.getMchId()); //直连商户号paramsMap.put("description", orderInfo.getTitle()); // 商品描述paramsMap.put("out_trade_no", orderInfo.getOrderNo()); //商户订单号paramsMap.put("notify_url", wxPayConfig.getNotifyDomain().concat(WxNotifyType.NATIVE_NOTIFY.getType())); //通知地址//订单金额有两个参数--嵌套数据Map amountMap = new HashMap();amountMap.put("total", orderInfo.getTotalFee()); //总金额amountMap.put("currency", "CNY"); //货币类型paramsMap.put("amount", amountMap); // 订单金额//将参数转成字符串String jsonParams = gson.toJson(paramsMap);log.info("支付的请求参数:" + jsonParams);//把参数设置到请求体当中StringEntity entity = new StringEntity(jsonParams, "utf-8");entity.setContentType("application/json");httpPost.setEntity(entity);//希望得到的响应类型httpPost.setHeader("Accept", "application/json");//完成签名并执行请求CloseableHttpResponse response = wxPayClient.execute(httpPost);//这些就是对调用下单方法的响应结果的处理了try{//字符串形式的响应体String bodyAsString = EntityUtils.toString(response.getEntity());//响应状态码int statusCode = response.getStatusLine().getStatusCode();if (statusCode == 200){ //处理成功System.out.println("成功, 返回结果 = " + bodyAsString);} else if (statusCode == 204){ //处理成功,无返回BodySystem.out.println("成功");} else{System.out.println("下单失败, 响应码 = " + statusCode + ", 返回结果 = " + bodyAsString);throw new IOException("请求失败 request failed");}//响应结果---如果下单成功,获取响应结果, gson.fromJson()用于将 JSON 字符串转换为 Java 对象Map<String, String> resultMap = gson.fromJson(bodyAsString, HashMap.class);//二维码---从返回的结果中获取二维码的url, 从官网看出 code_url 是 二维码的keycodeUrl = resultMap.get("code_url");//保存二维码String orderNo = orderInfo.getOrderNo();orderInfoService.saveCodeUrl(orderNo,codeUrl);//创建一个包含url和订单号的返回值Map<String, Object> map = new HashMap<>();map.put("codeUrl", codeUrl);map.put("orderNo", orderInfo.getOrderNo());return map;} finally{response.close();}}
}
OrderInfoService
public interface OrderInfoService extends IService<OrderInfo> {/*** 根据商品id创建商品订单* @param productId 商品id* @return 订单对象*/OrderInfo createOrderInfoByProduct(Long productId);/*** 将支付二维码的url存到订单中* @param orderNo 订单编号* @param codeUrl 支付二维码的地址url*/void saveCodeUrl(String orderNo, String codeUrl);}
OrderInfoServiceImpl
@Service
public class OrderInfoServiceImpl extends ServiceImpl<OrderInfoMapper, OrderInfo> implements OrderInfoService
{@Resourceprivate ProductMapper productMapper;@Resourceprivate OrderInfoMapper orderInfoMapper;//创建商品订单@Overridepublic OrderInfo createOrderInfoByProduct(Long productId){//用户点击确认支付,要先查找该用户是否存在已下单未支付的订单OrderInfo orderInfo = this.getNoPayOrderByProductId(productId);if (orderInfo != null){//表示该用户已经下单了,还没有支付,那就直接把他的订单返回回去就行了,否则就创建新订单return orderInfo;}//根据商品的id获取到该商品对象数据Product product = productMapper.selectById(productId);orderInfo = new OrderInfo();orderInfo.setTitle(product.getTitle()); //订单标题orderInfo.setOrderNo(OrderNoUtils.getOrderNo()); //生成订单号orderInfo.setProductId(productId); //商品idorderInfo.setTotalFee(1); //单位是:分orderInfo.setOrderStatus(OrderStatus.NOTPAY.getType()); //支付状态//把商品订单存到数据库orderInfoMapper.insert(orderInfo);return orderInfo;}/*** 根据商品id查询已下单未支付的订单,防止重复创建订单* @param productId 商品id* @return 订单对象*/private OrderInfo getNoPayOrderByProductId(Long productId){//QueryWrapper 是 MyBatis-Plus 提供的一个用于构建查询条件的工具类QueryWrapper<OrderInfo> queryWrapper = new QueryWrapper<>();//相当于封装查询对象,这是查询条件//就是查询该表中,是否有 列名 product_id 对应的值等于这个 productId ,有就查询出来queryWrapper.eq("product_id", productId);queryWrapper.eq("order_status", OrderStatus.NOTPAY.getType());//把 queryWrapper 作为查询条件对象//selectOne 就是查询出一条,如果查询出多条,则会报错OrderInfo orderInfo = orderInfoMapper.selectOne(queryWrapper);return orderInfo;}/*** 将支付二维码的url存到订单中* @param orderNo 订单编号* @param codeUrl 支付二维码的地址url*/@Overridepublic void saveCodeUrl(String orderNo, String codeUrl){//QueryWrapper 是 MyBatis-Plus 提供的一个用于构建查询条件的工具类QueryWrapper<OrderInfo> queryWrapper = new QueryWrapper<>();//组装查询条件queryWrapper.eq("order_no",orderNo);//要修改的字段,存到这个 orderInfo 对象里面OrderInfo orderInfo = new OrderInfo();orderInfo.setCodeUrl(codeUrl);//执行sqlorderInfoMapper.update(orderInfo,queryWrapper);}}
3、显示订单列表
3-1:需求:
在我的订单页面按时间倒序显示订单列表
目前是有订单,但是没展示出来。
3-2:代码:
前端:
调用后端接口的是api模块
<script> 脚本模块
<template> 模板,是用来定义组件的模板部分,用于描述组件的结构和布局
将后端返回的list商品订单列表赋值给 orders.vue 这个类后,就需要对这个数据进行渲染。
后端:
创建一个订单的controller
3-3:测试:
查看swagger
查看订单列表
成功显示
3-4:完整代码
后端:
OrderInfoController
@CrossOrigin //开放前端的跨域访问
@RestController
@RequestMapping(value = "/api/order-info")
@Api(tags = "商品订单管理")
public class OrderInfoController
{//依赖注入@Resourceprivate OrderInfoService orderInfoService;@ApiOperation("显示商品订单列表")@GetMapping("/list")public R getOrderInfoList(){List<OrderInfo> list =orderInfoService.getOrderInfoListByCreateTimeDesc();return R.ok().data("list",list);}
}
OrderInfoService
/*** 获取商品订单列表,并按时间倒序显示* @return 商品订单列表,倒序显示*/List<OrderInfo> getOrderInfoListByCreateTimeDesc();
OrderInfoServiceImpl
/*** 获取商品订单列表,并按时间倒序显示* @return 商品订单列表,倒序显示*/@Overridepublic List<OrderInfo> getOrderInfoListByCreateTimeDesc(){//QueryWrapper 是 MyBatis-Plus 提供的一个用于构建查询条件的工具类QueryWrapper<OrderInfo> queryWrapper = new QueryWrapper<>();//组装查询条件queryWrapper.orderByDesc("create_time");//查询List<OrderInfo> list = orderInfoMapper.selectList(queryWrapper);return list;}
相关文章:

03、SpringBoot + 微信支付 ---- 创建订单、保存二维码url、显示订单列表
目录 Native 下单1、创建课程订单保存到数据库1-1:需求:1-2:代码:1-3:测试结果: 2、保存支付二维码的url2-1:需求:2-2:代码:2-3:测试:…...

【echarts基础】在柱形图上设置文本
一、需求描述 在柱状图上设置文本标签,按需修改它的颜色、大小、边框、阴影等,如下。 二、代码展示 series:[{name:"螺蛳粉",type:"bar",data:data.data.chartData.chartData.num.螺蛳粉,label:{//图形上显示文本标签formatter:&q…...

小户型工业风,陌生上开花知书香。福州中宅装饰,福州装修
漫步陌上 只因陌上花开 花是自然的那种 朴素而恬淡,不落尘俗。—徐志摩 小户型工业风格 满足业主需求 筑造书香押韵家 从动线、色彩、选材、定制等各个环节 与业主一起畅谈家的构造 形成别“居”一格的温暖品质家 以书做墙 告别电视墙 这是一个实用性很强的…...

Gorm 中的迁移指南
探索使用 GORM 在 Go 中进行数据库迁移和模式更改的世界 在应用程序开发的不断变化的景观中,数据库模式更改是不可避免的。GORM,强大的 Go 对象关系映射库,通过迁移提供了一种无缝的解决方案来管理这些变化。本文将作为您全面的指南…...

基于.NET、Uni-App开发支持多平台的小程序商城系统 - CoreShop
前言 小程序商城系统是当前备受追捧的开发领域,它可以为用户提供一个更加便捷、流畅、直观的购物体验,无需下载和安装,随时随地轻松使用。今天给大家推荐一个基于.NET、Uni-App开发支持多平台的小程序商城系统(该商城系统完整开源…...

[python] 在多线程中将`logging.info`输出到不同的文件中 (生产者消费者)
在多线程中将logging.info输出到不同的文件中,可以使用Python标准库中的Queue和Thread模块。具体实现步骤如下: 创建多个Queue队列用于不同线程的日志输出,每个队列对应一个日志文件。 import queue# 创建三个队列用于不同线程的日志输出 l…...

MySQL进阶_5.逻辑架构和SQL执行流程
文章目录 第一节、逻辑架构剖析1.1、服务器处理客户端请求1.2、Connectors1.3、第1层:连接层1.4、第2层:服务层1.5、 第3层:引擎层1.6、 存储层1.7、小结 第二节、SQL执行流程2.1、查询缓存2.2、解析器2.3、优化器2.4、执行器 第三节、数据库…...

【油猴脚本】学习笔记
目录 新建用户脚本模板源注释 测试代码获取图标 Tampermonkey v4.19.0 原教程:手写油猴脚本,几分钟学会新技能——王子周棋洛 Tampermonkey首页 面向 Web 开发者的文档 Greasy Fork 新建用户脚本 打开【管理面板】 点击【】,即…...

宝塔面板使用Supervisor进程守护插件,配置守护Mysql的操作教程。
本篇文章主要讲解,在宝塔面板中使用Supervisor进程守护插件,配置守护Mysql的操作教程。 作者:任聪聪 日期:2023年11月5日 一、安装守护进程插件 安装插件一、进程守护插件 安装说明:在软件商店中搜索“进程守护”&am…...

Electron[2] Electron使用准备
1 背景 介绍一个技术栈的入门基础,往往要以该技术栈的入门案例作为开始比较合适,更能诱惑到刚需的粉丝,深度的学习。Electron的入门也不例外。在入门案例的讲解过程中,我们会学习到Electron引入需要的准备工作有哪些。 2 入门案例…...

npm create vue@latest 原理
文章目录 使用实际调用流程 使用 npm create vitelatest当执行上述命令时,会通过一个可交互的命令行终端下载模版,实际最终是调用 create-vue 库实现的 实际调用流程 npm create、innit 实际是 npm init 别名 ,npm init 后面加包名时,实际…...

【Unity基础】7.动画状态参数
【Unity基础】7.动画状态参数 大家好,我是Lampard~~ 欢迎来到Unity基础系列博客,所学知识来自B站阿发老师~感谢 (一)创建动画状态 (1) 创建动画状态 不好意思各位~最近工作比较忙,稍微耽误了这两周的博客。话…...

C语言映射表在串口数据解析中的应用
一、映射表在串口数据解析中的应用 1、数据结构 typedef struct {char CMD[CMDLen];unsigned char (*cmd_operate)(char *data); }Usart_Tab; 2、指令、函数映射表 static const Usart_Tab InstructionList[CMDMax] {{"PWON",PowOn},{"PWOFF",PowOff}…...

叁[3],感兴趣区域ROI
1,简介 ROI,感兴趣区域(region of interest),截取图像 2,获取方法 方法1:使用Rect cv::Mat srccv::imread("*.bmp");//读取原图 cv::Mat matROI src(cv::Rect(100,200,50,100));//截取原图&am…...

文件数据交换格式说明
对于文件的说明 二进制文件和文本文件的对比 对比项二进制文件文本文件定义二进制文件直接由二进制数字0和1组成,不存在统一的字符编码。文本文件是基于字符编码的文件,一般采用定长编码方式,如ASCII编码、UNICODE编码。优势1. 存储利用率高…...

2023NOIP A层联测24 总结
T1 给出树的一度点和三度点的数量,构造树的形态,节点数不超过 2000 2000 2000。我考虑先构造出三度点,发现这一度点至少是三度点2,打完后测样例不对,发现加一度点时要特判是否为三度点,花 5min 打完&#…...

vue3 项目如何配置测试环境打包
vue3 项目如何配置测试环境打包 根目录下创建.env.staging # 测试环境 NODE_ENV staging VUE_APP_MODE staging VUE_APP_TITLE 系统名称# 测试环境API接口地址 VUE_APP_API_URL 接口地址package.json文件中 scripts配置中添加以下代码 "scripts": {"serve&q…...

【CSS】样式的计算过程
标签的 CSS 样式 现在有这么一段 HTML 代码: <div class"test"><h1>Hello World</h1> </div>目前我们没有给 h1 设置任何样式,可以看到 h1 自带了一些样式,eg:font-size、font-weight、margi…...

【ArcGIS微课1000例】0076:KMZ转换KML的方法
文章目录 ArcGIS转kmzkmz转kmlArcGIS转kmz ArcGIS可以很方便的将dwg,shp、等矢量数据转为kmz。 拓展阅读: 【ArcGIS微课1000例】0075:将AutoCAD(Dwg、Dxf)文件转换为shp、KML(kml、kmz)文件...

Python基础入门例程46-NP46 菜品的价格(条件语句)
最近的博文: Python基础入门例程45-NP45 禁止重复注册(条件语句)-CSDN博客 Python基础入门例程44-NP44 判断列表是否为空(条件语句)-CSDN博客 Python基础入门例程43-NP43 判断布尔值(条件语句࿰…...

Docker数据管理、网络与Cgroup资源限制
目录 一、Docker的数据管理 1、数据卷 2、数据卷容器 3、端口映射 4、容器互联 二、Docker网络 2.1Docker网络实现原理 2.2Docker 的网络模式 3.3网络模式详解: host模式 container模式 none模式 bridge模式 自定义网络 创建自定义网络 三、Cgroup资源…...

ubuntu strings | grep使用说明
例子1 查找/bin/ls路径中中,包含libc的字符串,不区分大小写: strings /bin/ls | grep -i libc strings /bin/ls | grep -i libcstrings表示查找字符/bin/ls表示路径| grep表示抓取 -i 表示不区分大小写libc表示要查询的内容 例子2 strings …...

<Vue>使用依赖注入的方式共享数据
什么是vue依赖注入? Vue是一个用于构建用户界面的渐进式框架。 它提供了一种简单而灵活的方式来管理组件之间的数据流,即依赖注入(Dependency Injection,DI)。 依赖注入是一种设计模式,它允许一个组件从另一…...

从0到1:腾讯云服务器使用教程
腾讯云服务器入门教程包括云服务器CPU内存带宽配置选择,选择云服务器CVM或轻量应用服务器,云服务器创建后重置密码、远程连接、搭建程序环境等,腾讯云服务器网txyfwq.com分享从0到1腾讯云服务器入门教程: 目录 腾讯云服务器入门…...

VScode + opencv + c++ + win配置教程
准备: 1、下载opencv 2、下载MinGw 3、 3、下载CMake 下载完解压放到一个文件夹里面,便于环境管理,文件夹我重命名了,解压出来文件名不一样正常 环境变量配置 C:\Users\wuxulong\cpp_env\MinGw\mingw64\bin C:\Users\wuxulon…...

机器学习---SVM目标函数求解,SMO算法
1. 线性可分支持向量机 1.1 定义输入数据 假设给定⼀个特征空间上的训练集为: 其中,(x , y )称为样本点。 x 为第i个实例(样本)。 y 为x 的标记: 当y 1时,x 为正例;当y −1时,x…...

044_第三代软件开发-保存PDF
第三代软件开发-保存PDF 文章目录 第三代软件开发-保存PDF项目介绍保存PDF头文件源文件使用 关键字: Qt、 Qml、 pdf、 painter、 打印 项目介绍 欢迎来到我们的 QML & C 项目!这个项目结合了 QML(Qt Meta-Object Languageÿ…...

2023红帽论坛:构建开放AI生态,助力企业数字革新之路
随着人工智能技术的飞速发展,各行各业正面临着一场前所未有的数字化转型浪潮。尤其是AIGC(人工智能生成内容)技术自2022年底以来的蓬勃兴起,不仅重塑了用户体验,也为企业运营带来了深刻的变革。 在这样的大背景下&…...

阿里云国际站和华为云国际站之间该如何选择?
阿里云国际站和华为云国际站都是知名的云计算服务提供商,它们各自具有一些独特的优势和劣势。以下是它们之间的一些对比,九河云根据不同的使用场景提供的建议: 阿里云国际站: 优势: 全球覆盖:阿里云国际…...

JavaScript设计模式之责任链模式
适用场景:一个完整的流程,中间分成多个环节,各个环节之间存在一定的顺序关系,同时中间的环节的个数不一定,可能添加环节,也可能减少环节,只要保证顺序关系就可以。 如下图: ES5写法…...