Java Springboot对接微信支付(JSAPI等)API-V3

作者: ʘᴗʘ发布时间:2021-10-29 20:57 浏览量:1513 点赞:1222 售价:0
Java Springboot对接微信支付(JSAPI等)API-V3
微信支付的接口从V2升级到V3了,作者为了全平台升级到api-V3折腾了一周,发现了很多很多坑,有些是文档太分散不好找,有些是压根没说,得自己猜。现在把工作成果写成教程分享给大家,加快大家对接微信支付V3的速度。
文章:2篇

本文代码绝对可用,本站微信支付就是使用这套代码的!

准备工作

因为微信升级了微信支付的API,从API-V2升级到了API-V3,安全机制方面变动很大,所以在上一篇文章中,我们将整个微信支付API-V3所需要的证书、秘钥之类的封装成了一个HTTP请求类,只要使用这个类调用微信支付的API,即可自动完成所需的安全认证操作。没看的朋友可以点击链接阅读Java Springboot使用OkHttp实现微信支付API-V3签名、证书的管理和使用 。上篇文章中,我们一共封装了四个类,这里简单介绍一下:

  • WxOkHttpUtil 这个类就是我们之后调用微信支付API的HTTP请求类。
  • OkHttpUtil 这个类是上面类的基础,只是简单的HTTP请求封装,没有微信相关的业务逻辑。
  • AesUtilWxCertUtil微信安全机制相关的秘钥、证书加解密类,有兴趣的可以看看,没兴趣的直接粘贴到项目里用就行了。里面的参数介绍,在上一篇文章中。

还有两个POJO类,这里就不解释了,直接粘贴到你的项目中即可。

JSAPI微信下单接口

下单接口都差不多,无非是个别参数有所不同。这里以微信支付JSAPI API-V3接口为例。

新建一个springboot的service(如果你没有使用springboot,那就新建一个静态类),然后编写下单接口的代码,完整代码如下:

package com.coderbbb.book1.service;

import com.coderbbb.book1.utils.WxOkHttpUtil;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;

@Service
public class WxPayService {

    public String prePay() throws Exception {

        /**
         * 支付金额
         */
        BigDecimal money = new BigDecimal("10086");

        BigDecimal fen = money.multiply(new BigDecimal("100"));

        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX");

        String timeExpire = format.format(new Date(System.currentTimeMillis() + 300 * 1000));

        /**
         * 改成你的APP_ID
         */
        String appId = "WX_APP_ID";
        /**
         * 商户号
         */
        String mchId = "WX_MCH_ID";

        String notifyUrl = "通知URL,请填写https://开头的完整网址";

        /**
         * 发起支付的用户的OpenID
         */
        String openId = "openid";

        HashMap<String, Object> amountMap = new HashMap<>(1);
        amountMap.put("total", fen.intValue());

        HashMap<String, Object> payerMap = new HashMap<>(1);
        payerMap.put("openid", openId);

        HashMap<String, Object> map = new HashMap<>();
        map.put("appid", appId);
        map.put("mchid", mchId);

        map.put("description", "支付商品描述");
        map.put("out_trade_no", "商户订单号");

        map.put("time_expire", timeExpire);
        map.put("notify_url", notifyUrl);
        map.put("amount", amountMap);
        map.put("payer", payerMap);

        ObjectMapper mapper = new ObjectMapper();
        String json = mapper.writeValueAsString(map);

        String content = WxOkHttpUtil.wxPost("https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi", json, null);
        if (content == null) {
            throw new Exception("下单失败");
        }

        JsonNode jsonNode = mapper.readTree(content);
        if (!jsonNode.has("prepay_id")) {
            throw new Exception("下单失败");
        }

        return jsonNode.get("prepay_id").asText();
    }

}

上面的代码中,有些参数需要改成你自己的,这里简单列举一下:

  1. money变量,这个是支付金额,不用解释了吧。
  2. appId变量,这个是从你的微信支付所绑定的公众号复制的。
  3. mchId变量,商户号,从微信支付后台复制。
  4. notifyUrl变量,就是支付成功后,微信通知你的URL。每次支付完成,微信都会访问这个变量里填的URL,来通知你支付结果,是异步通知。同步通知是每次支付完,你调用微信的查单接口,去查结果。
  5. map里的description,商品描述信息,显示在用户支付成功后的账单里。
  6. map里的out_trade_no,商户订单号,就是你自己生成的订单号。长度不超过32位。

调用这个方法之后,会返回一些支付信息,这些支付信息要传给前端,让前端H5网页唤醒微信支付。当用户支付成功之后,微信调用你的notifyUrl来通知你支付成功。

微信JSAPI支付前端代码

JSAPI调起支付API,需要一些参数,微信支付官方文档介绍如下:

Java Springboot对接微信支付(JSAPI等)API-V3

上图所示的所有参数,这里逐一介绍一下:

  • appId:商户申请的公众号对应的appid,由微信支付生成,可在公众号后台查看。若下单时传了sub_appid,可为sub_appid的值。示例值:wx8888888888888888
  • timeStamp:时间戳,标准北京时间,时区为东八区,自1970年1月1日 0点0分0秒以来的秒数。注意:部分系统取到的值为毫秒级,需要转换成秒(10位数字)。 示例值:1414561699
  • nonceStr:随机字符串,不长于32位。示例值:5K8264ILTKCH16CQ2502SI8ZNMTM67VS
  • package:填写下单接口的返回值即可。上面微信下单接口的代码,返回了一个字符串,填入这里即可。
  • signType:填入RSA
  • paySign:签名。签名方法已经在前面的文章中提供代码了。使用WxCertUtil.rsaSign()方法即可得到签名结果。

演示代码如下:

/**
 * 构造微信前端JSAPI调起支付API的参数
 * @param prePay
 * @return
 */
public WxPayJsDTO getWxPayJsDTO(String prePay) {

    prePay = "prepay_id=" + prePay;

    WxPayJsDTO wxPayJsDTO = new WxPayJsDTO();
    wxPayJsDTO.setPrePay(prePay);
    wxPayJsDTO.setNonceStr(RandomStringUtils.random(21, true, true));
    wxPayJsDTO.setTimeStamp(String.valueOf(System.currentTimeMillis() / 1000));
    wxPayJsDTO.setSignType("RSA");

    String appId = websiteConfigService.getConfig(BaseWebsiteConfig.WX_FWH_APP_ID);

    String signStr = Stream.of(appId, wxPayJsDTO.getTimeStamp(), wxPayJsDTO.getNonceStr(), prePay).collect(Collectors.joining("\n", "", "\n"));

    wxPayJsDTO.setPaySign(WxCertUtil.rsaSign(signStr));

    return wxPayJsDTO;
}

上面的代码简单演示了如何构造前端JSAPI调起支付API的参数,仅供参考。

微信支付异步通知验签

当支付成功后,微信会调用我们的notifyUrl来通知我们。此时,我们需要验证微信携带的签名等信息是否合法。这部分,我们在上篇文章中,已经提供了封装好的验签类WxOkHttpUtil.checkServletRequestSign。使用方法截图如下:

Java Springboot对接微信支付(JSAPI等)API-V3

版权声明:《Java Springboot对接微信支付(JSAPI等)API-V3》为CoderBBB作者「ʘᴗʘ」的原创文章,转载请附上原文出处链接及本声明。

原文链接:https://www.coderbbb.com/articles/27

其它推荐:

  • 【亲测有效】解决win10 git文件状态图标不显示的问题

    本文解决了win10系统下Git文件状态图标不显示的问题,并详细讲解了问题的根本原因。如果你也遇到了类似win10系统overplay icon图标不显示的问题,请参考本文解决。

  • linux环境后台运行、重启springboot jar包脚本命令

    本文介绍了如何在linux上通过shell脚本来运行、重启jar包。在安装git、nginx后,还支持代码push到git后,借助gitlab等的webhook钩子功能,自动重启服务器上的jar包,实现最简单的部署效果。

  • springboot打印error报错信息到钉钉群

    本文介绍了一种全新的springboot日志打印形式。通过一些配置,可以直接将springboot项目的报错打印到钉钉群,加大减轻了运维人员工作量,并能够及时的获取到服务器的错误信息,更快修正。

  • cookie一段时间免登录、登录保持设计思路

    本文介绍了如何通过cookie实现常见的网站登录保持、免登录。详细讲解了cookie在日常使用中的一些安全问题,并逐一提供了解决方案。按照本文的思路和步骤,可以方便的实现一个最基础的cookie免登录机制。

  • Java Springboot使用OkHttp实现微信支付API-V3签名、证书的管理和使用

    新版的微信支付API-V3中,最让人头疼的就是各种安全措施。各种凌乱的概念让人摸不着头脑。比如微信平台证书、商户证书、API KEY等等概念。本文从零开始,引导读者一步一步实现了整个微信支付的安全验证,通过本文可以快速完成微信支付的安全开发。

  • Springboot上传图片到阿里云OSS新手教程(完整代码)

    本文详细介绍了使用springboot上传图片、文件到阿里云OSS的两种方案,并对比了常规表单上传和WEB直传之间的优缺点。两种方案都提供了完整的代码可以参考、运行,欢迎使用。

  • java实现62进制和10进制转换算法

    本文介绍如何使用java来实现62进制和10进制之间的转换,代码经过大量场景验证,可以直接复制使用。

  • 【手把手教你】win10 java jdk8、JDK11下载安装配置环境变量新手教程

    本文详细介绍了如何快速安装配置Oracle JDK8、Oracle JDK11到win10系统中,文章提供了各个常见版本的JDK下载地址(均为Oracle官方下载地址),并介绍了环境变量的配置、测试方法。

  • springboot使用redis限制并发请求、限流

    日常开发中经常会遇到需要限流、限制并发的需求,网上有很多算法、框架的介绍,但通常比较复杂,对于小项目来讲过于复杂。本文介绍了一种通过redis incr函数来实现的简便限流算法,并提供了完整源代码,可以快速的整合到你的项目中,实现API限流。

  • java通过selenium实现网页全屏截图

    本文介绍了如何使用java截图网页,通过本文介绍的方案可以实现全屏截图网页。该方案使用的是java+selenium+chrome的技术。