10分钟完成微信JSAPI支付对接过程-JAVA后端接口
- 引入架包
<dependency><groupId>com.github.javen205</groupId><artifactId>IJPay-WxPay</artifactId><version>${ijapy.version}</version></dependency>


配置类
package com.joolun.web.config;import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;/*** <p>微信配置 Bean</p>** @author yuhaiguang*/
@Component
@PropertySource("classpath:/wxpay.properties")
@ConfigurationProperties(prefix = "wxpay")
public class WxPayBean {private String appId;private String appSecret;private String mchId;private String partnerKey;private String certPath;private String domain;public String getAppId() {return appId;}public void setAppId(String appId) {this.appId = appId;}public String getAppSecret() {return appSecret;}public void setAppSecret(String appSecret) {this.appSecret = appSecret;}public String getMchId() {return mchId;}public void setMchId(String mchId) {this.mchId = mchId;}public String getPartnerKey() {return partnerKey;}public void setPartnerKey(String partnerKey) {this.partnerKey = partnerKey;}public String getCertPath() {return certPath;}public void setCertPath(String certPath) {this.certPath = certPath;}public String getDomain() {return domain;}public void setDomain(String domain) {this.domain = domain;}@Overridepublic String toString() {return "WxPayBean [appId=" + appId + ", appSecret=" + appSecret + ", mchId=" + mchId + ", partnerKey="+ partnerKey + ", certPath=" + certPath + ", domain=" + domain + "]";}
}
controller
AbstractWxPayApiController
package com.joolun.web.controller.weixin;import com.ijpay.wxpay.WxPayApiConfig;public abstract class AbstractWxPayApiController {public abstract WxPayApiConfig getApiConfig();
}
接口:
package com.joolun.web.controller.weixin;import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.extension.api.R;
import com.ijpay.core.enums.SignType;
import com.ijpay.core.enums.TradeType;
import com.ijpay.core.kit.IpKit;
import com.ijpay.core.kit.WxPayKit;
import com.ijpay.wxpay.WxPayApi;
import com.ijpay.wxpay.WxPayApiConfig;
import com.ijpay.wxpay.WxPayApiConfigKit;
import com.ijpay.wxpay.model.UnifiedOrderModel;
import com.joolun.common.core.domain.AjaxResult;
import com.joolun.web.config.WxPayBean;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;import javax.servlet.http.HttpServletRequest;
import java.util.Map;@RestController
@RequestMapping("/wxPay")
public class WxPayController extends AbstractWxPayApiController{private final Logger log = LoggerFactory.getLogger(this.getClass());@Autowiredprivate WxPayBean wxPayBean;private String notifyUrl;private String refundNotifyUrl;@Overridepublic WxPayApiConfig getApiConfig() {WxPayApiConfig apiConfig;try {apiConfig = WxPayApiConfigKit.getApiConfig(wxPayBean.getAppId());} catch (Exception e) {apiConfig = WxPayApiConfig.builder().appId(wxPayBean.getAppId()).mchId(wxPayBean.getMchId()).partnerKey(wxPayBean.getPartnerKey()).certPath(wxPayBean.getCertPath()).domain(wxPayBean.getDomain()).build();}notifyUrl = apiConfig.getDomain().concat("/wxPay/payNotify");refundNotifyUrl = apiConfig.getDomain().concat("/wxPay/refundNotify");return apiConfig;}@RequestMapping(value = "/webPay", method = {RequestMethod.POST, RequestMethod.GET})@ResponseBodypublic R webPay(HttpServletRequest request) {// openId,采用 网页授权获取 access_token API:SnsAccessTokenApi获取String openId = (String) request.getSession().getAttribute("openId");if (openId == null) {openId = "oQe4A6_acTpnPFTuAaxKq0Ss-yMo";}if (StrUtil.isEmpty(openId)) {return R.failed("openId is null");}String ip = IpKit.getRealIp(request);if (StrUtil.isEmpty(ip)) {ip = "127.0.0.1";}WxPayApiConfig wxPayApiConfig = WxPayApiConfigKit.getWxPayApiConfig();Map<String, String> params = UnifiedOrderModel.builder().appid(wxPayApiConfig.getAppId()).mch_id(wxPayApiConfig.getMchId()).nonce_str(WxPayKit.generateStr()).body("微信网页内测试").attach("产品说名").out_trade_no(WxPayKit.generateStr()).total_fee("1").spbill_create_ip(ip).notify_url(notifyUrl).trade_type(TradeType.JSAPI.getTradeType()).openid(openId).build().createSign(wxPayApiConfig.getPartnerKey(), SignType.HMACSHA256);String xmlResult = WxPayApi.pushOrder(false, params);log.info(xmlResult);Map<String, String> resultMap = WxPayKit.xmlToMap(xmlResult);String returnCode = resultMap.get("return_code");String returnMsg = resultMap.get("return_msg");if (!WxPayKit.codeIsOk(returnCode)) {return R.failed(returnMsg);}String resultCode = resultMap.get("result_code");if (!WxPayKit.codeIsOk(resultCode)) {return R.failed(returnMsg);}// 以下字段在 return_code 和 result_code 都为 SUCCESS 的时候有返回String prepayId = resultMap.get("prepay_id");Map<String, String> packageParams = WxPayKit.prepayIdCreateSign(prepayId, wxPayApiConfig.getAppId(),wxPayApiConfig.getPartnerKey(), SignType.HMACSHA256);String jsonStr = JSON.toJSONString(packageParams);return R.failed(jsonStr);}}
配置初始化拦截器
package com.joolun.web.config;import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson.support.config.FastJsonConfig;
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;import com.joolun.web.interceptor.WxPayInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;@Configuration
public class IJPayConfigurer extends WebMvcConfigurationSupport {@Overridepublic void addInterceptors(InterceptorRegistry registry) {//registry.addInterceptor(new AliPayInterceptor()).addPathPatterns("/aliPay/**");registry.addInterceptor(new WxPayInterceptor()).addPathPatterns("/wxPay/**");super.addInterceptors(registry);}@Overridepublic void addResourceHandlers(ResourceHandlerRegistry registry) {// 将所有/static/** 访问都映射到classpath:/static/ 目录下registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/");}@Overridepublic void configureMessageConverters(List<HttpMessageConverter<?>> converters) {super.configureMessageConverters(converters);FastJsonHttpMessageConverter converter = new FastJsonHttpMessageConverter();FastJsonConfig config = new FastJsonConfig();config.setSerializerFeatures(SerializerFeature.WriteMapNullValue, // 保留map空的字段SerializerFeature.WriteNullStringAsEmpty, // 将String类型的null转成""SerializerFeature.WriteNullNumberAsZero, // 将Number类型的null转成0SerializerFeature.WriteNullListAsEmpty, // 将List类型的null转成[]SerializerFeature.WriteNullBooleanAsFalse, // 将Boolean类型的null转成falseSerializerFeature.DisableCircularReferenceDetect);// 避免循环引用converter.setFastJsonConfig(config);converter.setDefaultCharset(Charset.forName("UTF-8"));List<MediaType> mediaTypeList = new ArrayList<>();// 解决中文乱码问题,相当于在Controller上的@RequestMapping中加了个属性produces = "application/json"mediaTypeList.add(MediaType.APPLICATION_JSON);converter.setSupportedMediaTypes(mediaTypeList);converters.add(converter);converters.add(responseBodyConverter());}@Beanpublic HttpMessageConverter<String> responseBodyConverter() {return new StringHttpMessageConverter(Charset.forName("UTF-8"));}
}
package com.joolun.web.interceptor;import com.ijpay.wxpay.WxPayApiConfigKit;
import com.joolun.web.controller.weixin.AbstractWxPayApiController;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;/*** <p>微信支付拦截器</p>** @author yuhaiguang*/
public class WxPayInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object handler) {if (HandlerMethod.class.equals(handler.getClass())) {HandlerMethod method = (HandlerMethod) handler;Object controller = method.getBean();if (!(controller instanceof AbstractWxPayApiController)) {throw new RuntimeException("控制器需要继承 AbstractWxPayApiController");}WxPayApiConfigKit.setThreadLocalWxPayApiConfig(((AbstractWxPayApiController) controller).getApiConfig());return true;}return false;}
}

源码:
https://gitee.com/champion-myth/wx-shop/tree/dev-wx-pay/
相关文章:
10分钟完成微信JSAPI支付对接过程-JAVA后端接口
引入架包 <dependency><groupId>com.github.javen205</groupId><artifactId>IJPay-WxPay</artifactId><version>${ijapy.version}</version></dependency>配置类 package com.joolun.web.config;import org.springframework.b…...
如何寻找一个领域的顶级会议,并且判断这个会议的影响力?
如何寻找一个领域的顶级会议,并且判断这个会议的影响力? 会议之眼 快讯 很多同学都在问:学术会议不是期刊,即使被SCI检索,也无法查询影响因子。那么如何知道各个领域的顶级会议,并对各个会议有初步了解呢…...
真的假不了,假的真不了
大家好,我是瑶琴呀,拥有一头黑长直秀发的女程序员。 最近,17岁的中专生姜萍参加阿里巴巴 2024 年的全球数学竞赛,取得了 12 名的好成绩,一时间在网上沸腾不止。 从最开始的“数学天才”,到被质疑ÿ…...
看完这篇文章你就知道什么是未来软件开发的方向了!即生成式AI在软件开发领域的革新=CodeFlying
从最早的UGC(用户生成内容)到PGC(专业生成内容)再到AIGC(人工智能生成内容)体现了web1.0→web2.0→web3.0的发展历程。 毫无疑问UGC已经成为了当前拥有群体数量最大的内容生产方式。 同时随着人工智能技术…...
HTML5五十六个民族网站模板源码
文章目录 1.设计来源高山族1.1 登录界面演示1.2 注册界面演示1.3 首页界面演示1.4 中国民族界面演示1.5 关于高山族界面演示1.6 联系我们界面演示 2.效果和源码2.1 动态效果2.2 源代码2.3 源码目录 源码下载 作者:xcLeigh 文章地址:https://blog.csdn.ne…...
Linux_fileio实现copy文件
参考韦东山老师教程:https://www.bilibili.com/video/BV1kk4y117Tu?p12 目录 1. 通过read方式copy文件2. 通过mmap映射方式copy文件 1. 通过read方式copy文件 copy文件代码: #include <sys/types.h> #include <sys/stat.h> #include <…...
【JavaEE精炼宝库】多线程进阶(2)synchronized原理、JUC类——深度理解多线程编程
一、synchronized 原理 1.1 基本特点: 结合上面的锁策略,我们就可以总结出,synchronized 具有以下特性(只考虑 JDK 1.8): 开始时是乐观锁,如果锁冲突频繁,就转换为悲观锁。 开始是轻量级锁实现ÿ…...
【Linux进程通信】使用匿名管道制作一个简单的进程池
进程池是什么呢?我们可以类比内存池的概念来理解进程池。 内存池 内存池是在真正使用内存之前,先申请分配一定数量的、大小相等(一般情况下)的内存块留作备用。当有新的内存需求时,就从内存池中分出一部分内存块,若内存块不够再继…...
Django 多对多关系
多对多关系作用 Django 中,多对多关系模型的作用主要是为了表示两个模型之间的多对多关系。具体来说,多对多关系允许一个模型的实例与另一个模型的多个实例相关联,反之亦然。这在很多实际应用场景中非常有用,比如: 博…...
构建 Audio Unit 应用程序
构建 Audio Unit 应用程序 构建 Audio Unit 应用程序从选择设计模式开始I/O Pass ThroughI/O Without a Render Callback FunctionI/O with a Render Callback FunctionOutput-Only with a Render Callback Function其他设计模式 构建应用程序配置 audio session指定 audio uni…...
JavaScript 实用技巧
1. 使用 const 和 let 替代 var 在 ES6 之前,我们通常使用 var 声明变量。但如今,推荐使用 const 和 let,因为它们具有块级作用域,可以避免很多潜在的问题。 const PI 3.14; // 常量,无法重新赋值 let age 25; // …...
Python协作运动机器人刚体力学解耦模型
🎯要点 🎯腿式或固定式机器人模型 | 🎯网格、点云和体素网格碰撞检测 | 🎯正反向运动学和动力学 | 🎯机器人刚体力学计算 | 🎯编辑参考系姿势和路径 | 🎯软件接口实体机器人模拟 | Ἲ…...
可重入锁思想,设计MQ迁移方案
如果你的MQ消息要从Kafka切换到RocketMQ且不停机,怎么做?在让这个MQ消息调用第三方发奖接口,但无幂等字段又怎么处理?今天小傅哥就给大家分享一个关于MQ消息在这样的场景中的处理手段。 这是一种比较特例的场景,需要保…...
Redis安装与使用
目录 1、介绍 1、redis的特点: 2、缓存 2、安装Redis 1、安装单机版redis 2、redis-cli命令参数 3、清空数据库的两种方式和作用域: 4、redis的增删查改命令 5、redis的查看所有分类命令 6、redis过期时间与控制键的行为 7、redis的相关工具 1、介绍 r…...
base64字符串空格问题
客户端使用的Content-Type为application/x-www-form-urlencoded时,字符串中出现了空格,base64解码时出错了,因为原来的字符有号, Spring Boot 对于Content-Type为application/x-www-form-urlencoded的HTTP请求,默认情…...
【BES2500x系列 -- RTX5操作系统】深入探索CMSIS-RTOS RTX -- 同步与通信篇 -- 消息队列和邮箱处理 --(四)
💌 所属专栏:【BES2500x系列】 😀 作 者:我是夜阑的狗🐶 🚀 个人简介:一个正在努力学技术的CV工程师,专注基础和实战分享 ,欢迎咨询! Ὁ…...
电信NR零流量小区处理
【摘要】随着目前网络建设逐步完善,5G用户的不断发展,针对零流量小区的分析及处理存在着必要性,零流量小区的出现既是用户分布及行为的直观体现,也是发展用户的一个指引,同时也能发现设备的一些故障。一个站点的能够带…...
ArcTs布局入门03——层叠布局(Stack)
如果你也对鸿蒙开发感兴趣,加入“Harmony自习室”吧! 扫描下面的二维码关注公众号。 1、概述 叠布局(StackLayout)用于在屏幕上预留一块区域来显示组件中的元素,提供元素可以重叠的布局。层叠布局通过Stack容器组件实…...
C语言之线程的学习
线程属于某一个进程 共同点:都能并发 线程共享变量,进程不共享。 多线程任务中,其中某一个线程调用了exit了,其他线程会跟着一起退出 如果是特定的线程就调用pthread_exit 失败返回的是错误号 下面也是...
HT8691 内置升压模块的D类音频功率放大器芯片IC
一般描述 HT8691是一款内置升压模块的D类音频功率放大器。内置的升压模块可通过外置电阻调节升压值,即使是锂电池供电,在升压至6.5V时,10%THDN,4Ω负载条件下能连续输出5.5W功率;升压至7V,3Ω负载条件下则能连续输出7.0W功率。其支持外部设置…...
Python:操作 Excel 折叠
💖亲爱的技术爱好者们,热烈欢迎来到 Kant2048 的博客!我是 Thomas Kant,很开心能在CSDN上与你们相遇~💖 本博客的精华专栏: 【自动化测试】 【测试经验】 【人工智能】 【Python】 Python 操作 Excel 系列 读取单元格数据按行写入设置行高和列宽自动调整行高和列宽水平…...
JVM垃圾回收机制全解析
Java虚拟机(JVM)中的垃圾收集器(Garbage Collector,简称GC)是用于自动管理内存的机制。它负责识别和清除不再被程序使用的对象,从而释放内存空间,避免内存泄漏和内存溢出等问题。垃圾收集器在Ja…...
Frozen-Flask :将 Flask 应用“冻结”为静态文件
Frozen-Flask 是一个用于将 Flask 应用“冻结”为静态文件的 Python 扩展。它的核心用途是:将一个 Flask Web 应用生成成纯静态 HTML 文件,从而可以部署到静态网站托管服务上,如 GitHub Pages、Netlify 或任何支持静态文件的网站服务器。 &am…...
【2025年】解决Burpsuite抓不到https包的问题
环境:windows11 burpsuite:2025.5 在抓取https网站时,burpsuite抓取不到https数据包,只显示: 解决该问题只需如下三个步骤: 1、浏览器中访问 http://burp 2、下载 CA certificate 证书 3、在设置--隐私与安全--…...
uniapp微信小程序视频实时流+pc端预览方案
方案类型技术实现是否免费优点缺点适用场景延迟范围开发复杂度WebSocket图片帧定时拍照Base64传输✅ 完全免费无需服务器 纯前端实现高延迟高流量 帧率极低个人demo测试 超低频监控500ms-2s⭐⭐RTMP推流TRTC/即构SDK推流❌ 付费方案 (部分有免费额度&#x…...
html css js网页制作成品——HTML+CSS榴莲商城网页设计(4页)附源码
目录 一、👨🎓网站题目 二、✍️网站描述 三、📚网站介绍 四、🌐网站效果 五、🪓 代码实现 🧱HTML 六、🥇 如何让学习不再盲目 七、🎁更多干货 一、👨…...
技术栈RabbitMq的介绍和使用
目录 1. 什么是消息队列?2. 消息队列的优点3. RabbitMQ 消息队列概述4. RabbitMQ 安装5. Exchange 四种类型5.1 direct 精准匹配5.2 fanout 广播5.3 topic 正则匹配 6. RabbitMQ 队列模式6.1 简单队列模式6.2 工作队列模式6.3 发布/订阅模式6.4 路由模式6.5 主题模式…...
【VLNs篇】07:NavRL—在动态环境中学习安全飞行
项目内容论文标题NavRL: 在动态环境中学习安全飞行 (NavRL: Learning Safe Flight in Dynamic Environments)核心问题解决无人机在包含静态和动态障碍物的复杂环境中进行安全、高效自主导航的挑战,克服传统方法和现有强化学习方法的局限性。核心算法基于近端策略优化…...
(一)单例模式
一、前言 单例模式属于六大创建型模式,即在软件设计过程中,主要关注创建对象的结果,并不关心创建对象的过程及细节。创建型设计模式将类对象的实例化过程进行抽象化接口设计,从而隐藏了类对象的实例是如何被创建的,封装了软件系统使用的具体对象类型。 六大创建型模式包括…...
从物理机到云原生:全面解析计算虚拟化技术的演进与应用
前言:我的虚拟化技术探索之旅 我最早接触"虚拟机"的概念是从Java开始的——JVM(Java Virtual Machine)让"一次编写,到处运行"成为可能。这个软件层面的虚拟化让我着迷,但直到后来接触VMware和Doc…...
