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功率。其支持外部设置…...
【Axure高保真原型】引导弹窗
今天和大家中分享引导弹窗的原型模板,载入页面后,会显示引导弹窗,适用于引导用户使用页面,点击完成后,会显示下一个引导弹窗,直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…...
国防科技大学计算机基础课程笔记02信息编码
1.机内码和国标码 国标码就是我们非常熟悉的这个GB2312,但是因为都是16进制,因此这个了16进制的数据既可以翻译成为这个机器码,也可以翻译成为这个国标码,所以这个时候很容易会出现这个歧义的情况; 因此,我们的这个国…...
安宝特方案丨XRSOP人员作业标准化管理平台:AR智慧点检验收套件
在选煤厂、化工厂、钢铁厂等过程生产型企业,其生产设备的运行效率和非计划停机对工业制造效益有较大影响。 随着企业自动化和智能化建设的推进,需提前预防假检、错检、漏检,推动智慧生产运维系统数据的流动和现场赋能应用。同时,…...
生成 Git SSH 证书
🔑 1. 生成 SSH 密钥对 在终端(Windows 使用 Git Bash,Mac/Linux 使用 Terminal)执行命令: ssh-keygen -t rsa -b 4096 -C "your_emailexample.com" 参数说明: -t rsa&#x…...
跨链模式:多链互操作架构与性能扩展方案
跨链模式:多链互操作架构与性能扩展方案 ——构建下一代区块链互联网的技术基石 一、跨链架构的核心范式演进 1. 分层协议栈:模块化解耦设计 现代跨链系统采用分层协议栈实现灵活扩展(H2Cross架构): 适配层…...
C# SqlSugar:依赖注入与仓储模式实践
C# SqlSugar:依赖注入与仓储模式实践 在 C# 的应用开发中,数据库操作是必不可少的环节。为了让数据访问层更加简洁、高效且易于维护,许多开发者会选择成熟的 ORM(对象关系映射)框架,SqlSugar 就是其中备受…...
力扣热题100 k个一组反转链表题解
题目: 代码: func reverseKGroup(head *ListNode, k int) *ListNode {cur : headfor i : 0; i < k; i {if cur nil {return head}cur cur.Next}newHead : reverse(head, cur)head.Next reverseKGroup(cur, k)return newHead }func reverse(start, end *ListNode) *ListN…...
R 语言科研绘图第 55 期 --- 网络图-聚类
在发表科研论文的过程中,科研绘图是必不可少的,一张好看的图形会是文章很大的加分项。 为了便于使用,本系列文章介绍的所有绘图都已收录到了 sciRplot 项目中,获取方式: R 语言科研绘图模板 --- sciRplothttps://mp.…...
深度解析:etcd 在 Milvus 向量数据库中的关键作用
目录 🚀 深度解析:etcd 在 Milvus 向量数据库中的关键作用 💡 什么是 etcd? 🧠 Milvus 架构简介 📦 etcd 在 Milvus 中的核心作用 🔧 实际工作流程示意 ⚠️ 如果 etcd 出现问题会怎样&am…...
【阅读笔记】MemOS: 大语言模型内存增强生成操作系统
核心速览 研究背景 研究问题:这篇文章要解决的问题是当前大型语言模型(LLMs)在处理内存方面的局限性。LLMs虽然在语言感知和生成方面表现出色,但缺乏统一的、结构化的内存架构。现有的方法如检索增强生成(RA…...
