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

news/2024/7/7 12:36:19 标签: java, 微信, 开发语言, 微信支付, jsapi, 支付
  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.niftyadmin.cn/n/5536648.html

相关文章

【物联网工程导论期末复习完整知识点】第一章物联网概论

物联网工程导论第一章 第一章物联网概论物联网发展的社会背景物联网概念的提出物联网与智慧地球欧盟与各国政府物联网产业的发展规划物联网与我国战略性新兴产业 物联网发展的技术背景普适计算的特征CPS主要技术特征 物联网定义与主要技术特征物联网的定义物联网的主要技术特征…

docker介绍与详细安装

1 docker 介绍 1.1 虚拟化 在计算机中&#xff0c;虚拟化&#xff08;英语&#xff1a;Virtualization&#xff09;是一种资源管理技术&#xff0c;是将计算机的各种实体资源&#xff0c;如服务器、网络、内存及存储等&#xff0c;予以抽象、转换后呈现出来&#xff0c;打破实…

Perl 语言开发(五):循环语句

目录 1. 循环语句概述 2. while 循环 2.1 基本语法 2.2 示例 2.3 无限循环 3. until 循环 3.1 基本语法 3.2 示例 3.3 无限循环 4. for 循环 4.1 基本语法 4.2 示例 4.3 嵌套循环 5. foreach 循环 5.1 基本语法 5.2 示例 5.3 遍历哈希 6. 循环控制语句 6.1 …

【unity实战】使用unity的新输入系统InputSystem+有限状态机设计一个玩家状态机控制——实现玩家的待机 移动 闪避 连击 受击 死亡状态切换

最终效果 文章目录 最终效果前言人物素材新输入系统InputSystem的配置动画配置代码文件路径状态机脚本创建玩家不同的状态脚本玩家控制动画优化&#xff08;补充&#xff09;闪避手动优化受伤和死亡同理 源码完结 前言 前面我们已经写过了使用有限状态机制作一个敌人AI&#x…

kubernetes service 服务

1 service作用 使用kubernetes集群运行工作负载时&#xff0c;由于Pod经常处于用后即焚状态&#xff0c;Pod经常被重新生成&#xff0c;因此Pod对应的IP地址也会经常变化&#xff0c;导致无法直接访问Pod提供的服务&#xff0c;Kubernetes中使用了Service来解决这一问题&#…

SHELL脚本学习(十三)初识 gawk 编辑器

概述 gawk提供了一种编程语言&#xff0c;而不仅仅是编辑器命令。 在gawk语言中&#xff0c;可以实现如下操作&#xff1a; 定义变量保存数据使用算数和字符串运算符处理数据使用结构化编程概念 为数据处理添加处理逻辑提取文件中的数据并将其重新排列组合&#xff0c;最后生…

Flume集群部署(手把手部署图文详细版)

前景概要&#xff1a; Kafka消息订阅系统在大数据业务中有着重要运用&#xff0c;尤其在实时业务中&#xff0c;kafka是必不可少的组件之一。 Flume是大数据组件中重要的数据采集工具&#xff0c;我们常利用Flume采集各种数据源的数据供其他组件分析使用。例如在实时业务中&…

Flutter本地数据持久化的几种方式

目录 前言 一、shared_preferences 1.添加依赖 2.保存数据 3.读取数据 4.移除数据 5.Shared_preferences的优缺点 6.完整的示例代码 二、path_provider 1.导入path_provider 2.创建文件读写的目录 3.向文件中写入数据 4.从文件中读取数据 5.完整的示例代码 三、…