尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Spring Boot + Maven实战:从零搭建微信支付商户后台(附完整代码)

Spring Boot + Maven实战:从零搭建微信支付商户后台(附完整代码) Spring Boot Maven实战从零搭建微信支付商户后台附完整代码微信支付作为国内主流的移动支付解决方案其商户后台系统的开发一直是中小企业和个人开发者的刚需。本文将带你用Spring Boot和Maven这两个Java生态中的黄金组合从零开始构建一个功能完整的微信支付商户后台系统。不同于简单的Demo演示我们会深入每个关键环节包括微信支付的核心流程、安全机制和异常处理等实战细节。1. 环境准备与项目初始化1.1 开发环境配置推荐使用IntelliJ IDEA作为开发工具它对Spring Boot和Maven的支持最为完善。以下是基础环境要求JDK 1.8或以上版本Maven 3.6.3Spring Boot 2.7.xLombok插件简化代码必备!-- pom.xml中的基础依赖 -- dependencies dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency dependency groupIdorg.projectlombok/groupId artifactIdlombok/artifactId optionaltrue/optional /dependency /dependencies1.2 项目结构设计一个规范的微信支付项目应该包含以下核心模块src/main/java ├── com.example.wxpay │ ├── config # 配置类 │ ├── controller # 控制器 │ ├── service # 业务逻辑 │ ├── util # 工具类 │ └── dto # 数据传输对象 src/main/resources ├── application.yml # 配置文件 └── wxpay # 微信支付证书提示微信支付需要用到商户证书建议将证书文件放在resources/wxpay目录下并通过.gitignore排除提交。2. 微信支付核心配置2.1 申请商户平台参数在微信商户平台需要获取以下关键信息参数名称获取位置示例格式商户号(MCH_ID)账户中心-商户信息1230000109API密钥账户中心-API安全32位随机字符串AppID产品中心-AppID账号管理wx8888888888888888证书序列号账户中心-API安全-证书444F4865EA9B344C...2.2 Spring Boot配置类创建微信支付配置类集中管理所有支付参数Configuration public class WxPayConfig { Value(${wxpay.app-id}) private String appId; Value(${wxpay.mch-id}) private String mchId; Value(${wxpay.api-key}) private String apiKey; Value(${wxpay.cert-path}) private String certPath; Bean public WxPayService wxPayService() throws Exception { WxPayConfig payConfig new WxPayConfig(); payConfig.setAppId(appId); payConfig.setMchId(mchId); payConfig.setKeyPath(certPath); payConfig.setApiV3Key(apiKey); return new WxPayServiceImpl(payConfig); } }对应的application.yml配置wxpay: app-id: wx8888888888888888 mch-id: 1230000109 api-key: your-api-v3-key-32chars-long cert-path: classpath:wxpay/apiclient_cert.p123. 实现支付核心功能3.1 Native支付接口实现Native支付是PC网站常用的支付方式通过生成支付二维码完成交易。以下是Controller层实现RestController RequestMapping(/api/pay) RequiredArgsConstructor public class PayController { private final WxPayService wxPayService; PostMapping(/native) public ResultMapString, String nativePay(RequestBody OrderDTO orderDTO) { try { WxPayUnifiedOrderRequest request new WxPayUnifiedOrderRequest(); request.setBody(orderDTO.getDescription()); request.setOutTradeNo(orderDTO.getOrderNo()); request.setTotalFee(orderDTO.getAmount()); request.setSpbillCreateIp(orderDTO.getClientIp()); request.setNotifyUrl(https://yourdomain.com/api/pay/notify); request.setTradeType(NATIVE); WxPayUnifiedOrderResult result wxPayService.unifiedOrder(request); return Result.success(Collections.singletonMap( code_url, result.getCodeURL())); } catch (WxPayException e) { log.error(微信支付失败, e); return Result.fail(e.getReturnMsg()); } } }3.2 支付回调处理支付回调是微信支付最重要的安全环节必须严格验证签名PostMapping(/notify) public String payNotify(HttpServletRequest request) { try { String xmlData IOUtils.toString(request.getInputStream(), StandardCharsets.UTF_8); WxPayOrderNotifyResult notifyResult wxPayService.parseOrderNotifyResult(xmlData); // 处理业务逻辑 if (SUCCESS.equals(notifyResult.getResultCode())) { orderService.processPayment(notifyResult.getOutTradeNo()); return xmlreturn_code![CDATA[SUCCESS]]/return_code/xml; } } catch (Exception e) { log.error(支付回调处理异常, e); } return xmlreturn_code![CDATA[FAIL]]/return_code/xml; }注意回调处理必须返回XML格式的响应且要在5秒内完成否则微信会重复通知。4. 高级功能与安全优化4.1 接口幂等性设计支付系统必须保证接口的幂等性防止重复支付Service RequiredArgsConstructor public class OrderServiceImpl implements OrderService { private final OrderMapper orderMapper; private final RedisTemplateString, String redisTemplate; Transactional public void processPayment(String orderNo) { // 使用Redis分布式锁防止并发问题 String lockKey pay:lock: orderNo; Boolean locked redisTemplate.opsForValue() .setIfAbsent(lockKey, 1, 5, TimeUnit.MINUTES); if (Boolean.FALSE.equals(locked)) { throw new BusinessException(订单处理中请勿重复操作); } try { Order order orderMapper.selectByOrderNo(orderNo); if (order.getStatus() ! OrderStatus.UNPAID) { return; // 已处理过的订单直接返回 } // 更新订单状态 orderMapper.updateStatus(orderNo, OrderStatus.PAID); // 其他业务逻辑... } finally { redisTemplate.delete(lockKey); } } }4.2 敏感数据加密存储支付系统涉及大量敏感信息必须做好数据加密public class DataEncryptor { private static final String AES_KEY your-32byte-aes-key; public static String encrypt(String data) { try { Cipher cipher Cipher.getInstance(AES/GCM/NoPadding); SecretKeySpec keySpec new SecretKeySpec(AES_KEY.getBytes(), AES); cipher.init(Cipher.ENCRYPT_MODE, keySpec); byte[] iv cipher.getIV(); byte[] encrypted cipher.doFinal(data.getBytes()); return Base64.getEncoder().encodeToString( ByteBuffer.allocate(iv.length encrypted.length) .put(iv).put(encrypted).array()); } catch (Exception e) { throw new RuntimeException(加密失败, e); } } public static String decrypt(String encrypted) { // 解密实现... } }5. 测试与部署方案5.1 沙箱环境测试微信支付提供沙箱环境用于测试Test public void testSandboxPay() { WxPayConfig config new WxPayConfig(); config.setUseSandboxEnv(true); // 启用沙箱环境 WxPayService sandboxService new WxPayServiceImpl(config); WxPayUnifiedOrderRequest request new WxPayUnifiedOrderRequest(); // 设置请求参数... try { WxPayUnifiedOrderResult result sandboxService.unifiedOrder(request); assertNotNull(result.getCodeURL()); } catch (WxPayException e) { fail(沙箱支付失败: e.getReturnMsg()); } }5.2 生产环境部署建议对于生产环境部署需要考虑以下关键点使用Nginx反向代理配置SSL证书启用HTTP/2提升性能配置合理的JVM参数设置完善的监控告警# 示例启动命令 java -Xms512m -Xmx1024m -XX:UseG1GC \ -Dspring.profiles.activeprod \ -jar wxpay-merchant.jar6. 常见问题排查在实际开发中经常会遇到以下典型问题签名错误检查API密钥是否正确注意V2和V3版本的密钥不同确保参数顺序和签名算法正确证书加载失败确保证书文件路径正确检查证书密码是否为商户号回调通知失败验证服务器是否能被外网访问检查防火墙和Nginx配置支付金额不符微信支付金额单位为分前端传参前需要转换// 金额转换示例 public static Integer yuanToFen(BigDecimal yuan) { return yuan.multiply(new BigDecimal(100)).intValue(); }7. 完整代码结构项目完整代码包含以下核心文件WxPayController.java- 支付接口入口WxPayService.java- 支付核心逻辑WxPayConfig.java- 支付配置OrderService.java- 订单业务处理SecurityConfig.java- 安全配置exception/- 异常处理模块resources/- 配置和证书文件代码已托管至GitHub仓库包含详细的README说明和示例请求github.com/example/wxpay-merchant
返回列表