微信支付的学习链接:https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=9_1
一、数据库准备

t_order表 主要完成订单查询

/*Navicat Premium Data TransferSource Server         : MichinaishSource Server Type    : MySQLSource Server Version : 80011Source Host           : localhost:3306Source Schema         : wechatTarget Server Type    : MySQLTarget Server Version : 80011File Encoding         : 65001Date: 16/08/2022 19:52:38
*/SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;-- ----------------------------
-- Table structure for t_order
-- ----------------------------
DROP TABLE IF EXISTS `t_order`;
CREATE TABLE `t_order`  (`id` char(19) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '',`order_no` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '订单号',`course_id` varchar(19) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '课程id',`course_title` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '课程名称',`course_cover` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '课程封面',`teacher_name` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '讲师名称',`member_id` varchar(19) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '会员id',`nickname` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '会员昵称',`mobile` varchar(11) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '会员手机',`total_fee` decimal(10, 2) NULL DEFAULT 0.01 COMMENT '订单金额(分)',`pay_type` tinyint(3) NULL DEFAULT NULL COMMENT '支付类型(0:微信 1:支付宝)',`status` tinyint(3) NULL DEFAULT NULL COMMENT '订单状态(0:未支付 1:已支付)',`is_deleted` tinyint(1) UNSIGNED NOT NULL DEFAULT 0 COMMENT '逻辑删除 1(true)已删除, 0(false)未删除',`gmt_create` datetime(0) NOT NULL COMMENT '创建时间',`gmt_modified` datetime(0) NOT NULL COMMENT '更新时间',PRIMARY KEY (`id`) USING BTREE,UNIQUE INDEX `ux_order_no`(`order_no`) USING BTREE,INDEX `idx_course_id`(`course_id`) USING BTREE,INDEX `idx_member_id`(`member_id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '订单' ROW_FORMAT = Compact;-- ----------------------------
-- Records of t_order
-- ----------------------------
INSERT INTO `t_order` VALUES ('0195f142a5824e0b88f', 'c60801fbdd2d45f9bc6', '1408424998648799234', 'Java初中级系统架构师组合套餐课(含12门课程)', 'https://kk-books.oss-cn-hangzhou.aliyuncs.com/44df362b-8d51-43a9-b823-090b02a3f2e8.jpg', '张飞', '1402269617551667201', '仲梦君', '15092182775', 32.00, 1, 0, 0, '2021-06-25 23:03:35', '2021-06-25 23:03:35');
INSERT INTO `t_order` VALUES ('21e04d165a324e59b96', '0322b37415384df0bbf', '1408421906918268930', '从零学习netty网络IO通讯开发视频教程', 'https://kk-books.oss-cn-hangzhou.aliyuncs.com/7b4a1bc6-b016-4afa-84c2-9ecfa0fae14d.jpg', '张飞', '1306495996639842305', '邱成相', '15092182541', 120.00, 1, 1, 0, '2020-06-25 23:02:27', '2020-06-25 23:02:27');
INSERT INTO `t_order` VALUES ('383714ba15e9474eb1a', 'e334ce2a6b1d4bc6936', '1408411851292532738', '姜维自传', 'https://kk-books.oss-cn-hangzhou.aliyuncs.com/8f731951-d606-4b86-8d4d-1cea38ee39f5.jpg', '姜维', '1408590478277685250', '李白', '15972331424', 0.01, 0, 0, 0, '2021-06-26 09:08:56', '2021-06-26 09:08:56');
INSERT INTO `t_order` VALUES ('39a3553e85bb4d69894', '9de332298489407fa81', '1408413427792994305', '成功的秘诀', 'https://kk-books.oss-cn-hangzhou.aliyuncs.com/03fa648e-a619-4500-a832-4750b3fa44ec.jpg', '张飞', '1402269617551667201', '仲梦君', '15092182775', 20.00, 0, 1, 0, '2021-06-25 23:09:34', '2021-06-25 23:09:50');
INSERT INTO `t_order` VALUES ('3fbd422bd60a4614a3b', '3d2e34a108174a67aba', '1408410177668767745', '水淹七军', 'https://kk-books.oss-cn-hangzhou.aliyuncs.com/74b7e90d-8463-4801-bdf8-52efd9cb6e41.jpg', '关羽', '1448200763102928897', NULL, '15660773278', 0.01, 0, 0, 0, '2021-10-13 16:17:05', '2021-10-13 16:17:05');
INSERT INTO `t_order` VALUES ('699aba8a2753439eb6a', '858c6dc73bb84c898a5', '1408409971229319170', '大白话领域驱动设计', 'https://kk-books.oss-cn-hangzhou.aliyuncs.com/5ae6a380-dbd6-4e74-8c99-a8c2ede79455.jpg', '张飞', '1408590478277685250', '李白', '15972331424', 0.01, 0, 1, 0, '2021-06-26 08:59:31', '2021-06-26 08:59:47');
INSERT INTO `t_order` VALUES ('7951387ce957484c80c', '2e4a952c118b4c47a79', '1408410177668767745', '水淹七军', 'https://kk-books.oss-cn-hangzhou.aliyuncs.com/74b7e90d-8463-4801-bdf8-52efd9cb6e41.jpg', '关羽', '1402268479037206530', '舒隆振', '15092182328', 0.01, 0, 1, 0, '2021-06-25 23:22:56', '2021-06-25 23:24:02');
INSERT INTO `t_order` VALUES ('9de56a01d7fb4a9895a', '7ff948d22cf04e61a06', '1408411851292532738', '姜维自传', 'https://kk-books.oss-cn-hangzhou.aliyuncs.com/8f731951-d606-4b86-8d4d-1cea38ee39f5.jpg', '姜维', '1448200763102928897', NULL, '15660773278', 0.01, 0, 0, 0, '2021-10-13 16:37:28', '2021-10-13 16:38:20');
INSERT INTO `t_order` VALUES ('b25d3987e7e94092b53', 'da27dfff1ae440c2aed', '1408411851292532738', '姜维自传', 'https://kk-books.oss-cn-hangzhou.aliyuncs.com/8f731951-d606-4b86-8d4d-1cea38ee39f5.jpg', '姜维', '1306495996639842305', '邱成相', '15092182541', 100.00, 0, 0, 0, '2019-06-25 21:54:13', '2019-06-25 21:54:13');
INSERT INTO `t_order` VALUES ('b9d4382ae2d84c568f9', '67164fb9916a4209876', '1408410177668767745', '水淹七军', 'https://kk-books.oss-cn-hangzhou.aliyuncs.com/74b7e90d-8463-4801-bdf8-52efd9cb6e41.jpg', '关羽', '1406792661091491841', '景晨曦', '15007124873', 10.00, 0, 0, 0, '2021-06-25 23:09:51', '2021-06-25 23:10:13');
INSERT INTO `t_order` VALUES ('c1fddde4bdae4ad68a6', 'def097eeafe44d7b8dd', '1408425438857781250', '亿级电商微服务优惠劵系统全实现', 'https://kk-books.oss-cn-hangzhou.aliyuncs.com/08a1a97e-a059-4ed7-a026-131890a4700f.JPG', '张飞', '1402269617551667201', '仲梦君', '15092182775', 0.01, 0, 0, 0, '2021-06-25 23:11:04', '2021-06-25 23:11:04');
INSERT INTO `t_order` VALUES ('dbad9d7063ab47a9b8b', '821d7109fa6d4520982', '1408409971229319170', '大白话领域驱动设计', 'https://kk-books.oss-cn-hangzhou.aliyuncs.com/5ae6a380-dbd6-4e74-8c99-a8c2ede79455.jpg', '张飞', '1448200763102928897', NULL, '15660773278', 211.00, 1, 0, 0, '2021-10-13 16:16:42', '2021-10-13 16:16:42');
INSERT INTO `t_order` VALUES ('e5f80e6712894b8793c', '28d54a53bdf14c3c853', '1408409971229319170', '大白话领域驱动设计', 'https://kk-books.oss-cn-hangzhou.aliyuncs.com/5ae6a380-dbd6-4e74-8c99-a8c2ede79455.jpg', '张飞', '1402269617551667201', '仲梦君', '15092182775', 210.00, 0, 0, 0, '2018-06-25 21:54:13', '2018-06-25 21:54:13');
INSERT INTO `t_order` VALUES ('ea744617fe8d4112796', 'e334ce2a6b1c4bc6018', '1408411851292532738', '姜维自传', 'https://kk-books.oss-cn-hangzhou.aliyuncs.com/8f731951-d606-4b86-8d4d-1cea38ee39f5.jpg', '姜维', '1306147989314703362', '木白', '15700085997', 0.01, 0, 0, 0, '2021-10-27 17:54:32', '2022-08-14 17:27:26');SET FOREIGN_KEY_CHECKS = 1;

t_pay_log 主要是用于支付成功后 记录显示

/*Navicat Premium Data TransferSource Server         : MichinaishSource Server Type    : MySQLSource Server Version : 80011Source Host           : localhost:3306Source Schema         : wechatTarget Server Type    : MySQLTarget Server Version : 80011File Encoding         : 65001Date: 16/08/2022 19:52:45
*/SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;-- ----------------------------
-- Table structure for t_pay_log
-- ----------------------------
DROP TABLE IF EXISTS `t_pay_log`;
CREATE TABLE `t_pay_log`  (`id` char(19) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '',`order_no` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '订单号',`pay_time` datetime(0) NULL DEFAULT NULL COMMENT '支付完成时间',`total_fee` decimal(10, 2) NULL DEFAULT 0.01 COMMENT '支付金额(分)',`transaction_id` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '交易流水号',`trade_state` char(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '交易状态',`pay_type` tinyint(3) NOT NULL DEFAULT 0 COMMENT '支付类型(0:微信 1:支付宝)',`attr` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '其他属性',`is_deleted` tinyint(1) UNSIGNED NOT NULL DEFAULT 0 COMMENT '逻辑删除 1(true)已删除, 0(false)未删除',`gmt_create` datetime(0) NOT NULL COMMENT '创建时间',`gmt_modified` datetime(0) NOT NULL COMMENT '更新时间',PRIMARY KEY (`id`) USING BTREE,UNIQUE INDEX `uk_order_no`(`order_no`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '支付日志表' ROW_FORMAT = Compact;SET FOREIGN_KEY_CHECKS = 1;

二、后端准备
(1)配置application.properities

#连接数据库
server.port=8999
spring.datasource.druid.url=jdbc:mysql://localhost:3306/wechat?serverTimezone=Asia/Shanghai
spring.datasource.druid.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.druid.username=root
spring.datasource.druid.password=root
#初始化的个数
spring.datasource.druid.initial-size=5
# 最大活跃数
spring.datasource.druid.max-active=10
# 最大等待时间
spring.datasource.druid.max-wait=3000
# 最小的闲置个数
spring.datasource.druid.min-idle=5# 微信的appid 商家id 密钥---填上自己的就行(无法申请因为需要营业执照)
weixin.appid=
weixin.mch_id=
weixin.api_key=

(2)在pom.xml引入依赖
这里可以使自己的springboot版本降低会比较稳定

<dependencies><!--微信依赖--><dependency><groupId>repMaven.com.github.wxpay</groupId><artifactId>wxpay-sdk</artifactId><version>0.0.3</version></dependency><!--Java端发送请求--><dependency><groupId>repMaven.org.apache.httpcomponents</groupId><artifactId>httpclient</artifactId><version>4.5.3</version></dependency><dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId><version>1.2.8</version></dependency><dependency><groupId>com.spring4all</groupId><artifactId>swagger-spring-boot-starter</artifactId><version>1.9.1.RELEASE</version></dependency><dependency><groupId>com.github.xiaoymin</groupId><artifactId>swagger-bootstrap-ui</artifactId><version>1.7.8</version></dependency><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-generator</artifactId><version>3.5.1</version></dependency><dependency><groupId>org.freemarker</groupId><artifactId>freemarker</artifactId><version>2.3.28</version><scope>compile</scope></dependency><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.5.2</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.2.2</version></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><scope>runtime</scope></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies>

(3)使用代码生成器 对俩表自动生成
代码生成器配置类为:

public class GeneCode {public static void main(String[] args) {//数据库配置String url="jdbc:mysql://localhost:3306/wechat?serverTimezone=Asia/Shanghai";//要自动生成的表名 多个表之间使用逗号隔开String[] tables = {"t_order","t_pay_log"};//获取本项目的路径String projectPath = System.getProperty("user.dir");//包项目路径String outputDir =projectPath+"/src/main/java";//xml文件路径String outputDirMapper = projectPath+"/src/main/resources/mapper";//快速创建FastAutoGenerator.create(url, "root", "root").globalConfig(builder -> {builder.author("wx") // 设置作者.enableSwagger() // 开启 swagger 模式.fileOverride() // 覆盖已生成文件.outputDir(outputDir); // 指定输出目录}).packageConfig(builder -> {builder.parent("com.wx") // 设置父包名.pathInfo(Collections.singletonMap(OutputFile.mapperXml, outputDirMapper)); // 设置mapperXml生成路径}).strategyConfig(builder -> {builder.addInclude(tables) // 设置需要生成的表名.addTablePrefix("t_"); // 设置过滤表前缀,多个前缀可用逗号隔开}).templateEngine(new FreemarkerTemplateEngine()) // 使用Freemarker引擎模板,默认的是Velocity引擎模板.execute();}
}

(4)配置类
用于Java端模拟浏览器

public class HttpClient {private String url;private Map<String, String> param;private int statusCode;private String content;private String xmlParam;private boolean isHttps;public boolean isHttps() {return isHttps;}public void setHttps(boolean isHttps) {this.isHttps = isHttps;}public String getXmlParam() {return xmlParam;}public void setXmlParam(String xmlParam) {this.xmlParam = xmlParam;}public HttpClient(String url, Map<String, String> param) {this.url = url;this.param = param;}public HttpClient(String url) {this.url = url;}public void setParameter(Map<String, String> map) {param = map;}public void addParameter(String key, String value) {if (param == null)param = new HashMap<String, String>();param.put(key, value);}public void post() throws ClientProtocolException, IOException {HttpPost http = new HttpPost(url);setEntity(http);execute(http);}public void put() throws ClientProtocolException, IOException {HttpPut http = new HttpPut(url);setEntity(http);execute(http);}public void get() throws ClientProtocolException, IOException {if (param != null) {StringBuilder url = new StringBuilder(this.url);boolean isFirst = true;for (String key : param.keySet()) {if (isFirst)url.append("?");elseurl.append("&");url.append(key).append("=").append(param.get(key));}this.url = url.toString();}HttpGet http = new HttpGet(url);execute(http);}/*** set http post,put param*/private void setEntity(HttpEntityEnclosingRequestBase http) {if (param != null) {List<NameValuePair> nvps = new LinkedList<NameValuePair>();for (String key : param.keySet())nvps.add(new BasicNameValuePair(key, param.get(key))); // 参数http.setEntity(new UrlEncodedFormEntity(nvps, Consts.UTF_8)); // 设置参数}if (xmlParam != null) {http.setEntity(new StringEntity(xmlParam, Consts.UTF_8));}}private void execute(HttpUriRequest http) throws ClientProtocolException,IOException {CloseableHttpClient httpClient = null;try {if (isHttps) {SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() {// 信任所有public boolean isTrusted(X509Certificate[] chain,String authType)throws CertificateException {return true;}}).build();SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext);httpClient = HttpClients.custom().setSSLSocketFactory(sslsf).build();} else {httpClient = HttpClients.createDefault();}CloseableHttpResponse response = httpClient.execute(http);try {if (response != null) {if (response.getStatusLine() != null)statusCode = response.getStatusLine().getStatusCode();HttpEntity entity = response.getEntity();// 响应内容content = EntityUtils.toString(entity, Consts.UTF_8);}} finally {response.close();}} catch (Exception e) {e.printStackTrace();} finally {httpClient.close();}}public int getStatusCode() {return statusCode;}public String getContent() throws ParseException, IOException {return content;}
}

(5)添加和修改实体类

Result类用于返回给前端

@AllArgsConstructor
@NoArgsConstructor
@Data
@ApiModel(value = "统一json数据")
public class Result {@ApiModelProperty("状态码2000表示成功 5000表示失败")private Integer code;@ApiModelProperty("响应的消息内容")private String msg;@ApiModelProperty("响应的数据")private Object data;
}

修改实体类 主要用于mp 可以自动注入时间

package com.wx.entity;import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;/*** <p>* 订单* </p>** @author wx* @since 2022-08-13*/
@TableName("t_order")
@ApiModel(value = "Order对象", description = "订单")
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Order implements Serializable {private static final long serialVersionUID = 1L;private String id;@ApiModelProperty("订单号")private String orderNo;@ApiModelProperty("课程id")private String courseId;@ApiModelProperty("课程名称")private String courseTitle;@ApiModelProperty("课程封面")private String courseCover;@ApiModelProperty("讲师名称")private String teacherName;@ApiModelProperty("会员id")private String memberId;@ApiModelProperty("会员昵称")private String nickname;@ApiModelProperty("会员手机")private String mobile;@ApiModelProperty("订单金额(分)")private BigDecimal totalFee;@ApiModelProperty("支付类型(0:微信 1:支付宝)")private Integer payType;@ApiModelProperty("订单状态(0:未支付 1:已支付)")private Integer status;@ApiModelProperty("逻辑删除 1(true)已删除, 0(false)未删除")private Boolean isDeleted;@ApiModelProperty("创建时间")private LocalDateTime gmtCreate;@ApiModelProperty("更新时间")private LocalDateTime gmtModified;
}
package com.wx.entity;import com.baomidou.mybatisplus.annotation.*;import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDateTime;import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;/*** <p>* 支付日志表* </p>** @author wx* @since 2022-08-13*/
@TableName("t_pay_log")
@ApiModel(value = "PayLog对象", description = "支付日志表")
@Data
@AllArgsConstructor
@NoArgsConstructor
public class PayLog implements Serializable {private static final long serialVersionUID = 1L;@TableId(value = "id",type = IdType.ASSIGN_ID)private Long id;@ApiModelProperty("订单号")private String orderNo;@ApiModelProperty("支付完成时间")@JsonDeserialize(using = LocalDateTimeDeserializer.class)@JsonSerialize(using = LocalDateTimeSerializer.class)@TableField(fill = FieldFill.INSERT)private LocalDateTime payTime;@ApiModelProperty("支付金额(分)")private BigDecimal totalFee;@ApiModelProperty("交易流水号")private String transactionId;@ApiModelProperty("交易状态")private String tradeState;@ApiModelProperty("支付类型(0:微信 1:支付宝)")private Integer payType;@ApiModelProperty("其他属性")private String attr;@ApiModelProperty("逻辑删除 1(true)已删除, 0(false)未删除")@TableLogicprivate Boolean isDeleted;@ApiModelProperty("创建时间")@JsonDeserialize(using = LocalDateTimeDeserializer.class)@JsonSerialize(using = LocalDateTimeSerializer.class)@TableField(fill = FieldFill.INSERT)private LocalDateTime gmtCreate;@ApiModelProperty("更新时间")@JsonDeserialize(using = LocalDateTimeDeserializer.class)@JsonSerialize(using = LocalDateTimeSerializer.class)@TableField(fill = FieldFill.INSERT_UPDATE)private LocalDateTime gmtModified;
}

(6)配置自动修改和创建时间的配置文件

package com.wx.config;import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;import java.time.LocalDateTime;@Slf4j
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {@Overridepublic void insertFill(MetaObject metaObject) {log.info("start insert fill ....");this.strictInsertFill(metaObject, "gmtCreate", LocalDateTime.class, LocalDateTime.now());this.strictInsertFill(metaObject, "gmtModified", LocalDateTime.class, LocalDateTime.now());this.strictInsertFill(metaObject, "payTime", LocalDateTime.class, LocalDateTime.now());this.strictInsertFill(metaObject, "isDeleted", Boolean.class, false);System.out.println("我执行了");}@Overridepublic void updateFill(MetaObject metaObject) {log.info("start update fill ....");// 默认提供的strictUpdateFill为有值不覆盖, gmtModified需要覆盖,利用通用塞值的方法填充this.setFieldValByName("gmtModified", LocalDateTime.now(), metaObject);}
}

(7)修改控制层代码–添加业务

@RestController
@RequestMapping("/order")
public class OrderController {@Autowiredprivate IOrderService orderService;@PostMapping("createQRCode/{orderNo}")public Result createQRCode(@PathVariable String orderNo){return orderService.createQRCode(orderNo);}@PostMapping("queryPayStatus/{orderNo}")public Result queryPayStatus(@PathVariable String orderNo){return orderService.queryPayStatus(orderNo);}
}

(8)修改service及其实现类

package com.wx.service.impl;import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.wxpay.sdk.WXPayUtil;
import com.wx.entity.Order;
import com.wx.entity.PayLog;
import com.wx.mapper.OrderMapper;
import com.wx.mapper.PayLogMapper;
import com.wx.service.IOrderService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wx.utils.HttpClient;
import com.wx.vo.Result;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;/*** <p>* 订单 服务实现类* </p>** @author wx* @since 2022-08-13*/
@Service
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements IOrderService {@Autowiredprivate OrderMapper orderMapper;/*获取微信的appid*/@Value("${weixin.appid}")private String appId;/*获取配置文件中的商家id*/@Value("${weixin.mch_id}")private String mchId;/*获取密钥*/@Value("${weixin.api_key}")private String apiKey;@Autowiredprivate PayLogMapper payLogMapper;/*创建订单*/@Overridepublic Result createQRCode(String orderNo) {/*查询orderNo的订单信息*/QueryWrapper wrapper = new QueryWrapper();wrapper.eq("order_no", orderNo);wrapper.eq("status", 0);Order order = orderMapper.selectOne(wrapper);/*不为空 才能进行业务操作*/if (order != null) {try {//获取下单的接口urlHttpClient client = new HttpClient("https://api.mch.weixin.qq.com/pay/unifiedorder");//设置支持https请求client.setHttps(true);/*以下的字段是必填字段* https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=9_1* 该链接中对必填字段有描述* */Map<String, String> parms = new HashMap<>();parms.put("appid", appId);parms.put("mch_id", mchId);parms.put("nonce_str", WXPayUtil.generateNonceStr());parms.put("body", order.getCourseTitle());parms.put("out_trade_no", orderNo);parms.put("total_fee", (order.getTotalFee().multiply(new BigDecimal(100))).longValue() + "");parms.put("spbill_create_ip", "127.0.0.1");parms.put("notify_url", "http://localhost:8999/pay/back");parms.put("trade_type","NATIVE");client.setXmlParam(WXPayUtil.generateSignedXml(parms, apiKey));/*post请求*/client.post();String content = client.getContent();/*得到的content其实是xml格式 所以要转为map格式*/Map<String,String> map = WXPayUtil.xmlToMap(content);/*若返回值成功 就会有一个codeurl 该值返回给前端会通过vue将连接转为二维码*/if(map.get("result_code").equals("SUCCESS")){/*将需要的值返回给前端*/Map<String,Object> result = new HashMap<>();result.put("codeUrl",map.get("code_url"));result.put("price",order.getTotalFee());result.put("orderNo",order.getOrderNo());return new Result(2000,"生成二维码成功",result);}} catch (Exception e) {e.printStackTrace();}}return new Result(5000, "创建失败", null);}/*创建订单后 要查询订单的状态*/@Override@Transactionalpublic Result queryPayStatus(String orderNo) {try {/*https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=9_2注意查询状态和获取订单的url不一样* * */HttpClient client = new HttpClient("https://api.mch.weixin.qq.com/pay/orderquery");client.setHttps(true);Map<String, String> parms = new HashMap<>();parms.put("appid", appId);parms.put("mch_id", mchId);parms.put("out_trade_no", orderNo);parms.put("nonce_str", WXPayUtil.generateNonceStr());client.setXmlParam(WXPayUtil.generateSignedXml(parms, apiKey));client.post();String content = client.getContent();System.out.println(content);Map<String,String> map = WXPayUtil.xmlToMap(content);String transactionId = map.get("out_trade_no");/*支付成功就会得到交易状态 若成功继续执行*/if(map.get("trade_state").equals("SUCCESS")){Order order = new Order();/*成功后改变当前订单的状态*/order.setStatus(1);order.setGmtModified(LocalDateTime.now());QueryWrapper<Order> wrapper = new QueryWrapper<>();wrapper.eq("order_no",orderNo);wrapper.eq("status",0);Order one = orderMapper.selectOne(wrapper);orderMapper.update(order,wrapper);/*支付成功后修改t_pay_log*/String tradeState = map.get("trade_state");PayLog payLog = new PayLog();payLog.setOrderNo(orderNo);payLog.setPayType(one.getPayType());payLog.setTotalFee(one.getTotalFee());payLog.setTransactionId(transactionId);payLog.setTradeState(tradeState);payLog.setIsDeleted(false);payLogMapper.insert(payLog);return new Result(2000,"支付成功",null);}} catch (Exception e) {e.printStackTrace();}return new Result(5000,"支付失败",null);}
}

前后端分离需要解决跨域问题

package com.wx.config;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;@Configuration
public class CorsConfig {// 当前跨域请求最大有效时长。这里默认1天private static final long MAX_AGE = 24 * 60 * 60;@Beanpublic CorsFilter corsFilter() {UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();CorsConfiguration corsConfiguration = new CorsConfiguration();corsConfiguration.addAllowedOrigin("*"); // 1 设置访问源地址corsConfiguration.addAllowedHeader("*"); // 2 设置访问源请求头corsConfiguration.addAllowedMethod("*"); // 3 设置访问源请求方法corsConfiguration.setMaxAge(MAX_AGE);source.registerCorsConfiguration("/**", corsConfiguration); // 4 对接口配置跨域设置return new CorsFilter(source);}
}

三、前端准备

前端需要引入 vue-qr依赖

(1)前端主页面

<template><div><el-button type="primary" @click="pay">支付</el-button><el-dialogtitle="收银台":visible.sync="dialogVisible"width="30%"><div style="text-align: center"><p>微信支付{{payResult.price}}元</p><div style="border: 10px solid grey;width:160px;padding:10px;margin:0px auto"><vue-qr:text="payResult.codeUrl"colorLight="#fff":size="160"margin="0":logo-src="require('../assets/3.webp')"></vue-qr></div><el-divider></el-divider><div style="font-size: 13px">提示:<br>支付成功前请勿手动关闭页面<br>二维码两个小时有效,请及时扫码支付<br></div></div></el-dialog></div></template><script>import vueQr from 'vue-qr'export default {components:{vueQr},name: "WeChatPay",data(){return{orderNo:"e334ce2a6b1c4bc6018",payResult:{codeUrl:"",price:0,orderNo:'',},dialogVisible:false,timer:"",flag:0,}},methods:{queryPayStatus(orderNo){this.$http.post("/order/queryPayStatus/"+orderNo).then(result=>{if(result.data.code===2000){clearInterval(this.timer);this.timer=null;this.$message.success("支付成功");this.dialogVisible = false;}})},pay(){this.dialogVisible = true;/*创建订单*/this.$http.post("order/createQRCode/"+this.orderNo).then(result=>{if(result.data.code===2000){this.payResult = result.data.data;/*每隔三秒查询订单的状态 是否支付*/this.timer = setInterval(()=>{this.queryPayStatus(this.payResult.orderNo)},3000);}})},}}
</script><style scoped></style>

(2)修改main.js

import Vue from 'vue'
import App from './App.vue'
import router from './router'
import './plugins/element.js'
import axios from "axios";
axios.defaults.baseURL="http://localhost:8999/"
Vue.config.productionTip = false
Vue.prototype.$http=axios
new Vue({router,render: h => h(App)
}).$mount('#app')


springboot+mybatis-plus+vue完成微信支付(前后端分离)相关推荐

  1. Java前端笔记-后端Springboot,前端vue,Nginx使前后端分离

    目录 基本概念 代码实例 基本概念 这是一个很6的模式,以目前本人C++ Qt的技术,是做不出的,但Java已经有雏形了. 后端采用Spring Boot主要是回json数据,如下所示: 这里的数据都 ...

  2. Springboot+vue 社团管理系统(前后端分离)

    Springboot+vue 社团管理系统(前后端分离) zero.项目功能设计图 一.数据库设计(项目准备) 1.建表 2.表目录 二.前端编写(vue) 1.搭建Vue框架 2.放入静态资源(as ...

  3. 大前端–Vue前端体系、前后端分离

    大前端–Vue前端体系.前后端分离 前言 Soc:关注点分离原则 HTML+CSS+JS(视图):给用户看,刷新后台给的数据 网络通信:axios 页面跳转:vue-router 状态管理:vuex ...

  4. SprinBoot-data-jpa整合Vue使用Swagger2实现前后端分离

    SprinBoot整合Vue使用Swagger2实现前后端分离 首先是后台 Swagger相关的依赖 <!--添加对swagger的依赖--><dependency><g ...

  5. Thinkphp 6 + Vue 2 + ElementUI + Vxe-table 前后端分离的,一键生成代码和API接口的,通用后台管理系统 快速开发框架,开发小程序和APP的推荐框架!

    Thinkphp 6 + Vue 2 + ElementUI + Vxe-table 前后端分离的,一键生成代码和API接口的,通用后台管理系统 快速开发框架,开发小程序和APP的推荐框架! 概述 R ...

  6. SpringBoot+Vue分页实现,前后端分离

    一.前期准备 1.简介 熟悉SpringBoot,Mybatis,Vue,Element UI等框架的使用:Vue-cli脚手架工具的使用:掌握前后端分离思想,熟悉单体架构等思想. 2.工具下载(No ...

  7. 毕设:基于SpringBoot+Vue 实现云音乐(前后端分离)

    文章目录 一.简介 2.项目介绍 二.功能 2.功能介绍 三.核心技术 1.系统架构图 2.技术选型 五.运行 3.截图 前端界面 后台管理界面 总结 1.完整工程 2.其他 一.简介 2.项目介绍 ...

  8. js 获得明天0点时间戳_Python 3+Django 3 结合Vue.js框架构建前后端分离Web开发平台实战...

    点击上方"测试开发技术",选择设为"设为星标" 优质文章,第一时间送达! 学习全文大概需要 12分钟,内容实战性较强. 1. 前言 本篇将基于Python 3. ...

  9. java开源springboot项目_springBoot 搭建web项目(前后端分离,附项目源代码地址)...

    概述 该项目包含springBoot-example-ui 和 springBoot-example,分别为前端与后端,前后端分离,利用ajax交互. springBoot-example-ui 注意 ...

  10. 基于Vue+nodejs实现的前后端分离疫情防控系统

    作者主页:编程指南针 简介:Java领域优质创作者.CSDN博客专家  Java项目.简历模板.学习资料.面试题库.技术互助 文末获取源码 本项目主要实现校园/公司/各类组织疫情防控管理,个人健康上报 ...

最新文章

  1. knockout的使用
  2. C语言二分法求最小值解,C语言用二分法求方程的近似解的方法
  3. 补充小知识:文件句柄与文件标识符
  4. Firebird数据库的Select语句
  5. 2013校队选拔——最短路——二分最大边的最小值
  6. 学习电子书和视频大全
  7. 视频教程-C语言编程初级入门-C/C++
  8. java扩展类库_Java 类库和常用类库
  9. 阿里“小前台、大中台”的解读
  10. 微信第三方网页关闭当前页面回到微信对话窗口
  11. PC微信hook学习笔记(一)—— 获取个人信息
  12. 江苏理工学院计算机网络期末,江苏理工学院数据中心机房管理制度
  13. 年底找工作,怎么解释离职的原因?
  14. PLSQL12.0.7的下载、安装及使用教程
  15. 各类网线的有效传输距离
  16. FontStruct——制作你自己的个性化字体
  17. 【数论】博弈论 —— nim游戏
  18. NetSpot Pro一款非常强大的可视化wifi检测工具
  19. java同名变量在list中添加两次_去除集合中自定义对象的重复值(对象的成员变量值都相同)...
  20. Android手机,charles安装证书时提示“键入凭据存储的密码”问题

热门文章

  1. Activiti应用
  2. 音视频开发5. ZLMediaKit库入门使用 编译安装
  3. 用html制作发帖与回帖,发帖代码
  4. iwatch 1234 代的区别
  5. 第32节-事件-情形-动作(Events-Cases-Actions) | 剑雨Axure RP9系列【基础】
  6. 家谱文化研究①:乾隆干预民间修谱有哪些正面影响和负面影响?
  7. 游戏服务器多钱一个月呢?
  8. 学习UCGUI的苦闷!!
  9. 湖南大学 实验八 青蛙与蚊子
  10. IDEA在push出现Pushed master to new branch origin/master错误