1、pom.xml依赖配置

<!-- 微信支付 -->
<dependency>
  <groupId>com.egzosn</groupId>
  <artifactId>pay-java-wx</artifactId>
  <version>2.12.4</version>
</dependency>

2、application.yml文件配置微信公众号的基础信息

#微信公众号支付配置
wechatpay:
 mchId: # 商户Id
 appId: #应用id
 storePassword: #秘钥支付密码
 secretKey: # 密钥
 notifyUrl: #微信支付回调
 keyStore:  # 证书所在位置

3、设置配置文件 WechatPayConfig.java

package com.example.emoticon.wechat;
 
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
 
/**
 * @ClassName WechatPayConfig
 * @Description 微信支付配置
 * @Author WangJing
 * @Date 2021/3/23 4:38 下午
 * @Version V1.1.0
 */
 
@Data
@Component
@ConfigurationProperties(prefix = "wechatpay")
public class WechatPayConfig {
 
  private String mchId;//合作者id(商户号
 
  private String appId;//应用id
 
  private String secretKey;//密钥
 
  private String notifyUrl;
  private String keyStore;// 支付密钥存放位置 文件是以.p12为后缀名字
  private String storePassword;
 
}

4、controller 逻辑代码

package com.example.emoticon.controller;
 
import com.egzosn.pay.common.api.PayService;
import com.egzosn.pay.common.bean.PayOrder;
import com.egzosn.pay.common.bean.RefundOrder;
import com.egzosn.pay.common.http.HttpConfigStorage;
import com.egzosn.pay.common.util.sign.SignUtils;
import com.egzosn.pay.wx.api.WxPayConfigStorage;
import com.egzosn.pay.wx.api.WxPayService;
import com.egzosn.pay.wx.bean.WxTransactionType;
import com.example.emoticon.wechat.WechatPayConfig;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
 
import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.Date;
import java.util.Map;
 
/**
 * @ClassName WechatPayController
 * @Description 微信支付Controller
 * @Author WangJing
 * @Date 2021/3/23 4:35 下午
 * @Version V1.1.0
 */
@RestController
@RequestMapping("/wechatPay")
@Slf4j
public class WechatPayController {
 
 
  @Autowired
  WechatPayConfig wechatPayConfig;
 
  private PayService service = null;
 
  @PostConstruct
  public void init() {
    WxPayConfigStorage wxPayConfigStorage = new WxPayConfigStorage();
    wxPayConfigStorage.setMchId(wechatPayConfig.getMchId()); // 合作者id(商户号
    wxPayConfigStorage.setAppid(wechatPayConfig.getAppId()); // 应用id
    wxPayConfigStorage.setSecretKey(wechatPayConfig.getSecretKey()); // 密钥
    wxPayConfigStorage.setNotifyUrl(wechatPayConfig.getNotifyUrl()); // 异步回调地址 http://域名:端口号/项目名/回调接口名称
    wxPayConfigStorage.setSignType(SignUtils.MD5.name());
    wxPayConfigStorage.setInputCharset("utf-8");
    // 支付api证书设置,退款必须 方式一
    HttpConfigStorage httpConfigStorage = new HttpConfigStorage();
    httpConfigStorage.setKeystore(wechatPayConfig.getKeyStore());// 支付密钥存放位置 文件是以.p12为后缀名字
    httpConfigStorage.setStorePassword(wechatPayConfig.getStorePassword());
    // 是否为证书地址
    httpConfigStorage.setPath(true);
    service = new WxPayService(wxPayConfigStorage, httpConfigStorage);
    // 请求连接池配置
    // 最大连接数
    httpConfigStorage.setMaxTotal(20);
    // 默认的每个路由的最大连接数
    httpConfigStorage.setDefaultMaxPerRoute(10);
    service.setRequestTemplateConfigStorage(httpConfigStorage);
  }
 
  @ApiOperation("返回订单信息")
  @RequestMapping(value = "weixinpay", method = RequestMethod.POST)
  public Map<String, Object> weixinpay(HttpServletRequest request) {
    //备注:这个可以获取预支付的订单,根据需要调用这个接口,可有前台向后台传递参数。然后后台根据需要进行处理。
    init();
    // 在这一步,可以传入一个订单Id,自行去搜索订单信息,并填写以下内容
    PayOrder payOrder = new PayOrder();// 这个就是支付成功后,在微信支付里面返回的信息(支付订单信息)
    // 一下内容需要分情况而定,自行填写。
    payOrder.setSubject("商品名称");
    payOrder.setBody("商品描述");
    payOrder.setAddition("附加信息");
    payOrder.setPrice(new BigDecimal(0.2));// 价格
    payOrder.setOutTradeNo("商户订单号");
    payOrder.setBankType("银行卡类型");
    payOrder.setDeviceInfo("设备信息");
    payOrder.setSpbillCreateIp("支付创建ip");// 可用IPUtils.getIpAddr(request)
    payOrder.setOpenid("用户微信openid");
    payOrder.setTransactionType(WxTransactionType.JSAPI);// 支付方式
    Map orderInfo = service.orderInfo(payOrder);// 返回创建的订单信息
    log.debug("获取预支付订单信息回参" + orderInfo.toString());
    // 可自行选择 ,是否将支付的流水插入到数据库中。返回的信息由:signType appId timeStamp nonceStr package sign
    return orderInfo;
  }
 
  /**
   * 这就是支付回调地址
   *
   * @param request
   * @return
   * @throws IOException
   */
  @ApiOperation("回调地址")
  @RequestMapping(value = "weixinpayBack")
  public String payBack(HttpServletRequest request) throws IOException {
    init();
    // 获取支付方返回的对应参数
    Map<String, Object> params = service.getParameter2Map(request.getParameterMap(), request.getInputStream());
    if (null == params) {
      log.debug("通知失败");
      return service.getPayOutMessage("failed", "通知失败").toMessage();
    }
    log.debug("微信公众号支付结果通知:" + params.toString());
    // 校验
    if (service.verify(params)) {
      // 这里处理业务逻辑 支付成功后的代码逻辑块
      // ......业务逻辑处理块........
      log.debug("通知支付成功");
      return service.getPayOutMessage("success", "支付成功").toMessage();
    }
    log.debug("通知支付失败");
    return service.getPayOutMessage("fail", "支付失败").toMessage();
  }
 
 
  @ApiOperation("微信公众号退款")
  @RequestMapping(value = "weixinAccRefund")
  public String weixinRefund() {
    init();
    RefundOrder refundOrder = new RefundOrder();//退款订单信息
    refundOrder.setRefundNo("退款单号,每次进行退款的单号,此处唯一");
    refundOrder.setTradeNo("支付平台订单号,交易号");
    refundOrder.setOutTradeNo("商户单号");
    refundOrder.setRefundAmount(new BigDecimal(0.2));//退款金额
    refundOrder.setTotalAmount(new BigDecimal(0.5));//订单总金额
    refundOrder.setOrderDate(new Date());//退款交易日期
    refundOrder.setDescription("退款说明");
    Map<String, Object> refund = service.refund(refundOrder);//微信退款
    //退款成功后,写其他的逻辑
    log.debug("微信公众号退款结果:=" + refund.toString());
 
    return "Success";
 
  }
}

到此这篇关于SpringBoot + 微信公众号JSAPI支付功能的实现的文章就介绍到这了,更多相关SpringBoot 微信公众号JSAPI支付内容请搜索程序员的世界以前的文章或继续浏览下面的相关文章希望大家以后多多支持程序员的世界!

SpringBoot + 微信公众号JSAPI支付功能的实现的更多相关文章

  1. 如何讲清楚 Java 面向对象的问题与知识?(类与对象,封装,继承,多态,接口,内部类...)

    如何讲清楚 Java 面向对象的问题与知识?(类与对象,封装,继承,多态,接口,内部类...)写在最前面这个项目是从20年末就立好的 flag,经过几年的学习,回过头再去看很多知识点又有新的理解。所以趁着找实习的准备,结合以前的学习储备,创建一个主要针对应届生和初学者的 Java 开源知识项目,专注......

  2. Java中判断字符串是否相等的实现

    在最近的开发中,我踩到一个坑,过程是这样的。我需要在Java中判断两个字符串是否相等,按照以往的经历使用 == 双等号的操作符来判断,但是在Java中,这样写却没有实现我想要的效果。经过查阅资料后,把得到的经验分享给大家。相等判断操作符==Java中,==相等判断符用于判断基本数据类型和引用数据类型......

  3. Java SPI 与 Dubbo SPI

    SPI(Service Provider Interface)是JDK内置的一种服务提供发现机制。本质是将接口实现类的全限定名配置在文件中,并由服务加载器读取配置文件,加载实现类。这样可以在运行时,动态为接口替换实现类。在Java中SPI是被用来设计给服务提供商做插件使用的。基于策略模式来实现动态加......

  4. 万万没想到,JVM内存区域的面试题也可以问的这么难?

    二、Java内存区域1、Java内存结构内存结构程序计数器当前线程所执行字节码的行号指示器。若当前方法是native的,那么程序计数器的值就是undefined。线程私有,Java内存区域中唯一一块不会发生OOM或StackOverflow的区域。虚拟机栈就是常说的Java栈,存放栈帧,栈帧里存放局......

  5. Java DriverManager.getConnection()获取数据库连接

    DriverManager.getConnection一共有四个重载方法,前三个由public修饰,用来获取不同类型的参数,这三个getConnection实际相当于一个入口,他们最终都会return第四个私有化的getConnection方法,最终向第四个私有化方法的传入参数都是url,java.......

  6. SpringBoot + 微信公众号JSAPI支付功能的实现

    1、pom.xml依赖配置<!-- 微信支付 --><dependency><groupId>com.egzosn</groupId><artifactId>pay-java-wx</artifactId><version......

  7. 文件监控性能问题【BUG】

    文件监控性能问题【BUG】背景:JAVA写了一个文件夹目录监控的程序,使用的是org.apache.commons.io.monitor 包,项目稳定运行了一个月,现场反馈,文件夹数据处理越来越慢,等到数据推送到前端要好几分钟,于是开始了寻找问题的路程。监控代码之前写的文件监控代码问题发现我在Ap......

  8. 深入浅出Java线程池:使用篇

    前言很高兴遇见你~借助于很多强大的框架,现在我们已经很少直接去管理线程,框架的内部都会为我们自动维护一个线程池。例如我们使用最多的okHttp以及他的封装框架Retrofit,线程封装框架RxJava和kotlin协程等等。为了更好地使用这些框架,则必须了解他的实现原理,而了解他的原理,线程池是永远......

  9. Java Object类 和 String类 常见问答

    Java常见对象 Object类 和 String类 常见问答 6k字+总结写在最前面这个项目是从20年末就立好的 flag,经过几年的学习,回过头再去看很多知识点又有新的理解。所以趁着找实习的准备,结合以前的学习储备,创建一个主要针对应届生和初学者的 Java 开源知识项目,专注 Java 后端面......

  10. Java 类的加载与初始化

    本文结构:1.先看几道题2.类的加载于初始化(1)类的加载(2)类的初始化(a)会发生类的初始化的情况(b)不会发生类的初始化的情况首先看几道题。解析可在看完讲解后再看Demo1public class Demo1 {public static void main(String args[]) {D......

随机推荐

  1. 详解如何使用Pytest进行自动化测试

    为什么需要自动化测试自动化测试有很多优点,但这里有3个主要的点可重用性:不需要总是编写新的脚本,除非必要,即使是新的操作系统版本也不需要编写脚本。可靠性:人容易出错,机器不太可能。当运行不能跳过的重复步骤/测试时,速度会更快。全天运行:您可以在任何时间或远程启动测试。夜间运行正在测试你的软件,即使是......

  2. C# 实现一个基于值相等性比较的字典

    C# 实现一个基于值相等性比较的字典C# 实现一个基于值相等性比较的字典Intro今天在项目里遇到一个需求,大概是这样的我要比较两个 JSON 字符串是不是相等,JSON 字符串其实是一个 Dictionary 但是顺序可能不同,和上一篇 record 使用场景 中的第一个需求类似,前面我们介绍过使......

  3. java中ExecutorService创建方法总结

    在对线程进行控制时,Executor虽然能够对其进行管理,但是缺少终止的功能,所以我们要用到Executor的进阶方法ExecutorServic来处理。ExecutorServic也是一种接口,相比较Executor功能更加丰富,支持一些前者没有的用法。下面我们就ExecutorService进行......

  4. 自己动手实现java断点/单步调试(二)

    自从上一篇《自己动手实现java断点/单步调试(一)》是时候应该总结一下JDI的事件了事件类型描述ClassPrepareEvent装载某个指定的类所引发的事件ClassUnloadEvent卸载某个指定的类所引发的事件BreakingpointEvent设置断点所引发的事件ExceptionEve......

  5. 【JAVA并发第三篇】线程间通信

    线程间的通信JVM在运行时会将自己管理的内存区域,划分为不同的数据区,称为运行时数据区。每个线程都有自己私有的内存空间,如下图示:Java线程按照自己虚拟机栈中的方法代码一步一步的执行下去,在这一过程中不可避免的会使用到线程共享的内存区域堆或方法区。为了防止多个线程在同一时刻访问同一个内存地址,需要......

  6. JVM笔记 -- Java跨平台和JVM跨语言

    学习JVM的重要性从上层应用程序到底层操作系统,到底有哪些东西?平时开发的应用程序主要基于各种框架,譬如Spring,SpringMVC,Mybatis,而各种框架又是基于Java API来实现的,Java API调用执行是在JVM上的,而JVM则是运行在操作系统上的,操作系统是在物理机器打交道的。......

  7. SQL注入语句

    1、返回的是连接的数据库名and db_name()>02、作用是获取连接用户名and user>03、将数据库备份到Web目录下面;backup database 数据库名 to disk='c:\inetpub\wwwroot\1.db';--4、显示SQL系统版本and 1=(se......

  8. python 如何用 Hypothesis 来自动化单元测试

    高质量的代码离不开单元测试,而设计单元测试的用例往往又比较耗时,而且难以想到一些极端情况,本文讲述如何使用 Hypothesis 来自动化单元测试刷过力扣算法题的同学都知道,有时候觉得代码已经很完善了,一提交才发现很多情况没有考虑到。然后感叹力扣的单元测试真的牛比。因此,高质量的代码离不开单元测试,......

  9. JavaScript canvas实现文字时钟

    本文实例为大家分享了canvas实现文字时钟的具体代码,供大家参考,具体内容如下 先看看效果图 代码 <!DOCTYPE html> <htmllang="en"> <head> <metacharset......

  10. PostgreSQL 使用raise函数打印字符串

    raise函数在PostgreSQL中,该函数用于打印字符串,类似于Java中的System.out.println(),Oracle中的dbms_output.put_line()。用法如下:raise notice 'My name is %, I am a %.', 'Lewis', 'cod......