# 微信扫码支付 **Repository Path**: fish-rubbish/wechat-qr-code-payment ## Basic Information - **Project Name**: 微信扫码支付 - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-03-14 - **Last Updated**: 2026-03-14 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # fish-wechat-pay PC 端微信 Native 扫码支付完整示例项目,前后端分离架构。 ``` fish-wechat-pay/ ├── server/ Spring Boot 3 + JDK 17 后端 └── web/ Vue 3 + Vite + TypeScript 前端 ``` --- ## 功能流程 ``` 用户填写商品信息 → 后端创建订单 → 调用微信 V3 Native 下单 → 前端渲染二维码 → 用户微信扫码 → 微信回调 notify_url → 后端验签解密 → 幂等更新订单为 PAID → 前端轮询到 PAID → 展示支付成功 ``` --- ## 技术栈 | 端 | 技术 | |---|---| | 后端 | Spring Boot 3、JDK 17、MyBatis Plus、MySQL、Lombok、Hutool、wechatpay-java SDK | | 前端 | Vue 3、Vite、TypeScript、Pinia、Axios、Naive UI、qrcode-vue3 | --- ## 快速开始 ### 1. 数据库初始化 ```sql -- 执行建表脚本 source server/src/main/resources/sql/init.sql ``` ### 2. 配置微信支付参数 编辑 `server/src/main/resources/application.yml`,填入真实商户信息: ```yaml spring: datasource: url: jdbc:mysql://localhost:3306/fish_wechat_pay?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai username: root password: your_password # ← 修改 wxpay: mch-id: your_mch_id # 商户号 api-v3-key: your_api_v3_key # API v3 密钥(32位) mch-serial-no: your_mch_serial_no # 证书序列号 private-key-path: classpath:cert/apiclient_key.pem app-id: your_app_id # 公众号/小程序 AppID notify-url: https://your-domain.com/api/pay/notify # 公网回调地址 ``` 将商户私钥文件放到: ``` server/src/main/resources/cert/apiclient_key.pem ``` > 本地开发时 notify_url 需要公网可访问,推荐使用 [ngrok](https://ngrok.com/) 做内网穿透: > ```bash > ngrok http 8080 > # 将生成的 https 地址填入 notify-url > ``` ### 3. 启动后端 ```bash cd server mvn spring-boot:run # 服务启动在 http://localhost:8080 ``` ### 4. 启动前端 ```bash cd web npm install npm run dev # 页面访问 http://localhost:5173 ``` --- ## 接口文档 ### POST /api/order/create 创建订单并获取微信支付二维码链接。 **请求体** ```json { "subject": "商品名称", "amount": 1.00 } ``` **响应** ```json { "code": 200, "message": "success", "data": { "orderNo": "20240101120000ABC123", "codeUrl": "weixin://wxpay/bizpayurl?pr=xxx" } } ``` --- ### GET /api/order/status/{orderNo} 查询订单状态,前端每 3 秒轮询一次。 **响应** ```json { "code": 200, "message": "success", "data": { "orderNo": "20240101120000ABC123", "status": "UNPAID", "amount": 1.00 } } ``` 订单状态说明: | 状态 | 含义 | |------|------| | UNPAID | 待支付 | | PAID | 已支付 | | CLOSED | 已关闭 | --- ### POST /api/pay/notify 微信支付异步回调,由微信服务器主动调用,无需前端触发。 处理流程:验签 → AES-GCM 解密 → 幂等更新订单状态 → 返回应答报文。 --- ## 项目结构 ``` server/src/main/java/com/fish/wechatpay/ ├── WechatPayApplication.java ├── common/ │ ├── ApiResponse.java # 统一响应结构 │ ├── ResultCode.java # 业务状态码 │ ├── GlobalExceptionHandler.java # 全局异常处理 │ └── exception/ │ ├── BusinessException.java │ ├── OrderNotFoundException.java │ └── WxPayException.java ├── config/ │ ├── WxPayProperties.java # 配置属性绑定 │ └── WxPayConfig.java # SDK Bean 初始化 └── module/ ├── order/ │ ├── controller/OrderController.java │ ├── service/OrderService.java │ ├── service/impl/OrderServiceImpl.java │ ├── mapper/OrderMapper.java │ ├── entity/Order.java │ └── dto/ # CreateOrderRequest/Response、OrderStatusResponse └── pay/ ├── controller/PayController.java ├── service/WxPayService.java ├── service/impl/WxPayServiceImpl.java └── dto/WxNotifyResponse.java web/src/ ├── main.ts / App.vue ├── types/index.ts # TypeScript 类型定义 ├── api/ │ ├── http.ts # Axios 封装 │ └── order.ts # 订单 API 函数 ├── stores/order.ts # Pinia 状态管理(含轮询逻辑) └── views/PayPage.vue # 支付主页面 ``` --- ## 运行测试 **后端单元测试** ```bash cd server mvn test ``` **前端单元测试** ```bash cd web npm run test ``` --- ## 注意事项 - 微信支付 notify_url 必须是 HTTPS 公网地址,本地开发需配合 ngrok - 商户私钥 `apiclient_key.pem` 不要提交到 Git,已在 `.gitignore` 中排除 - 金额在数据库中以**分**为单位存储,接口层自动转换为元 - 支付回调使用 `WHERE status='UNPAID'` 条件更新,天然幂等,无需额外加锁