10分钟完成微信JSAPI支付对接过程-JAVA后端接口

news2024/10/6 22:33:57
  1. 引入架包
		<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;
	}

	@Override
	public 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());
    @Autowired
    private WxPayBean wxPayBean;

    private String notifyUrl;
    private String refundNotifyUrl;
    @Override
    public 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})
    @ResponseBody
    public 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 {
	@Override
	public void addInterceptors(InterceptorRegistry registry) {
		//registry.addInterceptor(new AliPayInterceptor()).addPathPatterns("/aliPay/**");
		registry.addInterceptor(new WxPayInterceptor()).addPathPatterns("/wxPay/**");
		super.addInterceptors(registry);
	}

	@Override
	public void addResourceHandlers(ResourceHandlerRegistry registry) {
		// 将所有/static/** 访问都映射到classpath:/static/ 目录下
		registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/");
	}

	@Override
	public 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转成0

			SerializerFeature.WriteNullListAsEmpty, // 将List类型的null转成[]

			SerializerFeature.WriteNullBooleanAsFalse, // 将Boolean类型的null转成false

			SerializerFeature.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());
	}

	@Bean
	public 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 {

	@Override
	public 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/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1876341.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【算法专题--栈】栈的压入、弹出序列 -- 高频面试题(图文详解,小白一看就懂!!)

目录 一、前言 二、题目描述 三、解题方法 &#x1f4a7;栈模拟法&#x1f4a7;-- 双指针 ⭐ 解题思路 ⭐ 案例图解 四、总结与提炼 五、共勉 一、前言 栈的压入、弹出序列 这道题&#xff0c;可以说是--栈专题--&#xff0c;最经典的一道题&#xff0c;也是在…

贪心法思想-求最大子数组和案例图解

贪心法思想 ​ 基本思想是在问题的每个决策阶段&#xff0c;都选择当前看起来最优的选择&#xff0c;即贪心地做出局部最优的决策&#xff0c;以期获得全局最优解。 ​ 正如其名字一样&#xff0c;贪心法在解决问题的策略上目光短浅&#xff0c;只根据当前已有的信息做出选择…

【FFmpeg】avformat_write_header函数

FFmpeg相关记录&#xff1a; 示例工程&#xff1a; 【FFmpeg】调用ffmpeg库实现264软编 【FFmpeg】调用ffmpeg库实现264软解 【FFmpeg】调用ffmpeg库进行RTMP推流和拉流 【FFmpeg】调用ffmpeg库进行SDL2解码后渲染 流程分析&#xff1a; 【FFmpeg】编码链路上主要函数的简单分…

VMware中安装CentOS系统

VMware中安装CentOS系统 CentOS 镜像的准备创建虚拟机Cent OS系统的安装 CentOS 镜像的准备 下载链接&#xff1a;清华园CenOS 7镜像下载 VMware的安装参考&#xff1a;VMware workstation pro 16 虚拟机的安装 创建虚拟机 1.打开VMware workstation pro 16->创建新的虚拟…

[leetcode]insert-into-a-binary-search-tree

. - 力扣&#xff08;LeetCode&#xff09; class Solution { public:TreeNode* insertIntoBST(TreeNode* root, int val) {if (root nullptr) {return new TreeNode(val);}TreeNode* pos root;while (pos ! nullptr) {if (val < pos->val) {if (pos->left nullptr…

掌握Python编程的深层技能

一、Python基础语法、变量、列表、字典等运用 1.运行python程序的两种方式 1.交互式即时得到程序的运行结果 2.脚本方式把程序写到文件里(约定俗称文件名后缀为.py),然后用python解释器解释执行其中的内容2.python程序运行的三个步骤 python3.8 C:\a\b\c.py 1.先启动python3…

揭秘循环购模式:消费即赚钱,私域电商新纪元

消费1000送2000、每天领钱、钱还可以提现&#xff0c;这样的商业模式——循环购模式&#xff0c;确实在私域电商领域引起了广泛的关注。这种模式的成功并非偶然&#xff0c;而是基于合理的返利规则和商业模式创新。下面我将为您详细解析循环购模式为何能够吸引消费者&#xff0…

记录一次——RK100键盘按键失效修复

一、背景说明: 背景&#xff1a;购买的键盘是RK的型号RK100&#xff0c;具有紧凑的外观&#xff0c;并搭配了TTC金粉轴&#xff0c;使用起来还不错&#xff0c;目前已经是第3年了。问题&#xff1a;前几个月会出现H按键失效的问题&#xff0c;但是过一段时间又会修复。最近是Q…

深入解析链表:解锁数据结构核心奥秘

一. 链表的定义 链表是一种线性数据结构&#xff0c;由一系列节点组成。每个节点包含两个部分&#xff1a; 数据域&#xff08;Data&#xff09;&#xff1a;存储节点的数据。指针域&#xff08;Pointer&#xff09;&#xff1a;存储指向下一个节点的地址。 链表的第一个节点…

一招教你用python代码给朋友写一个爱心代码

有人问我马上要跟女朋友一周年了&#xff0c;能不能用代码给他写一个爱心代码呢&#xff1f;那算你问对人了&#xff0c;来上才艺 可以使用Python的turtle模块来绘制一个爱心形状。下面是一个简单的示例代码&#xff0c;我将详细解释每一步&#xff1a; import turtle # 创建一…

制定班规要注意哪些事项

对于如何管理班级&#xff0c;制定班规是一项至关重要的任务。关系到班级的日常秩序&#xff0c;影响着学生的集体荣誉感。制定班规并非易事&#xff0c;需要深思熟虑和周全考虑。 班规的制定应以学生为中心。深入了解学生的需求和期望&#xff0c;以及他们在学习和生活中可能遇…

统计信号处理基础 习题解答11-6

题目 考虑例11.1对WGN中单个正弦信号的数据模型&#xff0c;将模型重写为 其中&#xff1a; &#xff0c;证明A的PDF是瑞丽的&#xff0c;的PDF是&#xff0c;且和是相互独立的。 解答 根据例11.1&#xff1a; 由于N维联合高斯分布为&#xff1a; 由&#xff1a; 因此&#…

Java程序员学习Go开发Higress的WASM插件

Java程序员学习Go开发Higress的WASM插件 契机 ⚙ 今年天池大赛有higress相关挑战&#xff0c;研究一下。之前没搞过go&#xff0c;踩了很多坑&#xff0c;最主要的就是tinygo打包&#xff0c;多方寻求解决无果&#xff0c;结论是tinygo0.32go1.19无法在macos arm架构下打包。…

一键掌控,文件格式转换无忧!轻松驾驭各种文件格式,高效管理您的数字世界

信息爆炸的时代&#xff0c;我们每天都会接触到各种各样的文件格式。无论是工作文档、图片、视频还是音频文件&#xff0c;它们都以不同的格式存在于我们的电脑和移动设备中。然而&#xff0c;不同的软件和应用往往只支持特定的文件格式&#xff0c;这给我们的工作和生活带来了…

Petal-X :心血管疾病临床风险可视化工具

心血管疾病&#xff08;Cardiovascular diseases, CVDs&#xff09;是全球致死的首要原因&#xff0c;但在大多数情况下&#xff0c;它们是可以通过行为干预来预防的。因此&#xff0c;在个体层面上&#xff0c;有效地传达心血管疾病的风险以及通过风险因素的修改来预计风险降低…

无线WiFi毫米波雷达传感器成品,智能照明人体感应开关,飞睿智能点亮智慧生活

在智能科技飞速发展的今天&#xff0c;我们的生活正被各种智能设备所包围&#xff0c;其中智能照明作为智能家居的重要组成部分&#xff0c;正逐渐改变着我们的生活方式。而在这背后&#xff0c;有一个默默工作的“小助手”——飞睿智能毫米波雷达传感器&#xff0c;它就像智能…

周边美食小程序系统的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;用户管理&#xff0c;美食店铺管理&#xff0c;菜品分类管理&#xff0c;标签管理&#xff0c;菜品信息管理&#xff0c;系统管理 微信端账号功能包括&#xff1a;系统首页&#xff0c;美食店铺&#…

网页用事件监听器播放声音

一、什么是监听器&#xff1a; 在前端页面中&#xff0c;事件监听器&#xff08;Event Listener&#xff09;是一种编程机制&#xff0c;它允许开发者指定当特定事件&#xff08;如用户点击按钮、鼠标悬停、页面加载完成等&#xff09;发生时执行特定的代码块。简而言之&#x…

css 滚动词云

css javascript 实现滚动词云效果 // 163css.js var radius 120; var dtr Math.PI / 180; var d 300; var mcList []; var active false; var lasta 1; var lastb 1; var distr true; var tspeed 10; var size 250; var mouseX 0; var mouseY 0; var howElliptic…

使用面向对象方式编写ROS2节点

1.使用c方式创建节点 在d2lros2/chapt2/chapt2_ws/src/example_cpp/src下新建node_03.cpp&#xff0c;接着输入下面的代码。 #include "rclcpp/rclcpp.hpp" /* 创建一个类节点&#xff0c;名字叫做Node03,继承自Node. */ class Node03 : public rclcpp::Node {…