微信支付接入网址:https://pay.weixin.qq.com/index.php/core/home/login?return_url=%2F
微信公众号网址:https://mp.weixin.qq.com/cgi-bin/registermidpage?action=index&lang=zh_CN&token=
随机密码生成:https://suijimimashengcheng.bmcx.com/
获取密钥—>生成证书
项目实现:
1.依赖注入:
<!-- Swagger-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.7.0</version>
</dependency>
<!-- Swagger ui-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.7.0</version>
</dependency>
2.swagger配置:
@Configuration
@EnableSwagger2
public class Swagger2Config {
@Bean
public Docket docket(){
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(new ApiInfoBuilder().title("微信支付开发文档").build());
}
}
// 之后访问 http://localhost:8090/swagger-ui.html#/
3.sql语句:
create database payment_demo;
USE `payment_demo`;
/*Table structure for table `t_order_info` */
DROP TABLE IF EXISTS `t_order_info`;
CREATE TABLE `t_order_info` (
`id` BIGINT(11) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '订单id',
`title` VARCHAR(256) DEFAULT NULL COMMENT '订单标题',
`order_no` VARCHAR(50) DEFAULT NULL COMMENT '商户订单编号',
`user_id` BIGINT(20) DEFAULT NULL COMMENT '用户id',
`product_id` BIGINT(20) DEFAULT NULL COMMENT '支付产品id',
`total_fee` INT(11) DEFAULT NULL COMMENT '订单金额(分)',
`code_url` VARCHAR(50) DEFAULT NULL COMMENT '订单二维码连接',
`order_status` VARCHAR(10) DEFAULT NULL COMMENT '订单状态',
`create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间' ,
PRIMARY KEY (`id`)
) ENGINE=INNODB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4;
DROP TABLE IF EXISTS `t_payment_info`;
CREATE TABLE `t_payment_info`(
`id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '支付记录id',
`order_no` VARCHAR (50) DEFAULT NULL COMMENT '商户订单编号',
`transaction_id` VARCHAR(50) DEFAULT NULL COMMENT '支付系统交易编号',
`payment_type` VARCHAR(20) DEFAULT NULL COMMENT '支付类型',
`trade_type` VARCHAR (20) DEFAULT NULL COMMENT '交易类型',
`trade_state` VARCHAR(50) DEFAULT NULL COMMENT '交易状态',
`payer_total` INT(11) DEFAULT NULL COMMENT '支付金额(分)',
`content` TEXT COMMENT '通知参数',
`create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间' ,
`update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`)
) ENGINE=INNODB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4;
DROP TABLE IF EXISTS `t_product`;
CREATE TABLE `t_product` (
`id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '商Bid',
`title` VARCHAR(20) DEFAULT NULL COMMENT '商品名称',
`price` INT(11) DEFAULT NULL COMMENT '价格(分)',
`create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`)
) ENGINE=INNODB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4;
/*Data for the table 't_product' */
INSERT INTO `t_product` (`title`, `price`) VALUES ('Java程',1);
INSERT INTO `t_product` (`title`, `price`) VALUES ('大数据课程', 1);
INSERT INTO `t_product` (`title`,`price`) VALUES ('前端端程', 1);
INSERT INTO `t_product` (`title`, `price`) VALUES ('UI程' ,1);
/*Table structure for table it_refund_info' */
DROP TABLE IF EXISTS `t_refund_info`;
CREATE TABLE `t_refund_info`(
`id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '款单id',
`order_no` VARCHAR (50) DEFAULT NULL COMMENT '商户订单编号',
`refund_no` VARCHAR(50) DEFAULT NULL COMMENT '商户退款单编号',
`refund_id` VARCHAR(50) DEFAULT NULL COMMENT '支付系统退款单号',
`total_fee` INT(11) DEFAULT NULL COMMENT '原订单金额(分)',
`refund` INT(11) DEFAULT NULL COMMENT '退款金额(分)',
`reason` VARCHAR(50) DEFAULT NULL COMMENT '退款原因',
`refund_status` VARCHAR(10) DEFAULT NULL COMMENT '退款状态',
`content_return` TEXT COMMENT '申请退款返回参数',
`content_notify` TEXT COMMENT '退款结果通知参数',
`create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`)
) ENGINE=INNODB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
4.yml配置:
server:
port: 8090
spring:
application:
name: payment-demo
mvc:
pathmatch:
matching-strategy: ANT_PATH_MATCHER
jackson:
date-format: yyyy-MM-dd HH:mm:ss
datasource:
url: jdbc:mysql://localhost:3306/payment_demo?serverTimezone=UTC&useUnicode=true&characterEncoding=utf8
driver-class-name: com.mysql.cj.jdbc.Driver
username: root
password: chen123456
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
mapper-locations: classpath:mapper/*.xml
5.微信支付配置:
# 微信支付相关参数
# 商户号
wxpay.mch-id=1558950191
# 商户API证书序列号
wxpay.mch-serial-no=34345964330B66427E0D3D28826C4993C77E631F
#商户私钥文件
wxpay.private-key-path=apiclient_key.pem
#APIv3密钥
wxpay.api-v3-key=UDuLFDcmy5Eb6o0nTNZdu6ek4DDh4K8B
#APPID
wxpay.appid=wx74862e0dfcf69954
#微信服务器地址
wxpay.domain=https://api.mch.weixin.qq.com
#接收结果通知地址
wxpay.notify-domain=https://7d92-115-171-63-135.ngrok.io
6.生成自定义的元素数据配置信息
<!-- 生成自定义配置的元素数据信息 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
</dependency>
7.SDK配置:
访问地址:
https://github.com/wechatpay-apiv3/wechatpay-apache-httpclient
引入依赖
<!-- 微信支付SDK-->
<dependency>
<groupId>com.github.wechatpay-apiv3</groupId>
<artifactId>wechatpay-apache-httpclient</artifactId>
<version>0.4.5</version>
</dependency>
8.定时更新平台证书功能配置
/**
* 获取签名验证其器
* @return
*/
@Bean
public Verifier getVerifiers(){
//获取商户私钥
PrivateKey privateKey = getPrivateKey(privateKeyPath);
// 私钥签名对象
PrivateKeySigner keySigner = new PrivateKeySigner(mchSerialNo, privateKey);
// 身份认证对象
WechatPay2Credentials wechatPay2Credentials = new WechatPay2Credentials(mchId, keySigner);
// 获取证书管理器实例
CertificatesManager certificatesManager = CertificatesManager.getInstance();
// 向证书管理器增加需要自动更新平台证书的商户信息
try {
certificatesManager.putMerchant(mchId, wechatPay2Credentials,
apiV3Key.getBytes(StandardCharsets.UTF_8));
} catch (IOException | GeneralSecurityException | HttpCodeException e) {
e.printStackTrace();
}
// ... 若有多个商户号,可继续调用putMerchant添加商户信息
Verifier verifier = null;
try {
verifier = certificatesManager.getVerifier(mchId);
} catch (NotFoundException e) {
e.printStackTrace();
}
return verifier;
}
/**
* 获取http请求对象
* @return
*/
@Bean
public CloseableHttpClient getWxPayClient(Verifier verifier){
//获取商户私钥
PrivateKey privateKey = getPrivateKey(privateKeyPath);
// 从证书管理器中获取verifier
WechatPayHttpClientBuilder builder = WechatPayHttpClientBuilder.create()
.withMerchant(mchId, mchSerialNo, privateKey)
.withValidator(new WechatPay2Validator(verifier));
// ... 接下来,你仍然可以通过builder设置各种参数,来配置你的HttpClient
// 通过WechatPayHttpClientBuilder构造的HttpClient,会自动的处理签名和验签,并进行证书自动更新
CloseableHttpClient httpClient = builder.build();
return httpClient;
}
9.二维码弹窗的实现:
<!-- 在package.json中配置依赖 -->
"dependencies": {
"vue-qriously": "^1.1.1",
}
// 在main.js中进行引入
// 二维码生成器
import VueQriously from 'vue-qriously'
Vue.use(VueQriously)
可以使用标签: 引入二维码
<!-- 在div标签中的实现 -->
<!-- 微信支付二维码 -->
<el-dialog
:visible.sync="codeDialogVisible"
:show-close="false"
@close="closeDialog"
width="350px"
center>
<qriously :value="codeUrl" :size="300"/>
<!-- <img src="../assets/img/code.png" alt="" style="width:100%"><br> -->
使用微信扫码支付
</el-dialog>
<script>
export default{
data () {
return {
codeDialogVisible: false, //微信支付二维码弹窗
}
},
</script>
<!-- 在微信支付时打开弹窗-->
//打开二维码弹窗
this.codeDialogVisible = true
10.签名认证过程:
Authorization: 认证类型,签名信息
签名信息:
- 发起请求的商户(包括直连商户,服务商户)
- 商户API证书序列号serial_no
- 请求随机串nonce_str
- 时间戳timestamp
- 签名值signature
11.内网穿透
内网穿透,也即 NAT 穿透,进行 NAT 穿透是为了使具有某一个特定源 IP 地址和源端口号的数据包不被 NAT 设备屏蔽而正确路由到内网主机。
内网穿透工具:ngrok.com 访问注册
下载windows版解压:
// 配置访问令牌
ngrok config add-authtoken 29EYy38ronN63XiZnlu146Ksmze_5nYH1g8kKJuq8gvJEJbtd
// 默认的下载地址
C:\Users\86183\AppData\Local/ngrok/ngrok.yml
// 帮助文档
ngrok help
// 创建映射地址
ngrok http 8090
演示结果:
首页
支付页:
具体的代码讲解到这里找环环老师:
https://www.bilibili.com/video/BV1US4y1D77m?spm_id_from=333.1007.top_right_bar_window_default_collection.content.click