SpringBoot整合微信H5支付 详解 (有源文件)

简介与支付接口运行原理
这次介绍的是微信H5支付,会了这个其他类型的也是大同小异,因为调用的都是统一下单接口,只是在某些参数上存在差异。H5支付只能在手机上使用与非微信内使用。这次案例是在真实环境下测试的,并不是沙箱环境。

本次演示的项目基本环境是:SpringBoot,JPA,MySql,Thymeleaf。

注:如果你用的是MyBatis影响不大。

搭建微信支付需要的条件:

服务号(需要公司才能申请),备案的域名,能连接外网的服务器。

运行原理:

首先是一个form表单收集好订单的基本信息如:下单人的账号标识,购买的商品标识,下单的金额,这些是订单的基础。然后我们要自己生成一个商户订单号,这个可以用当前时间戳作为商户订单号。这个时候就将这些信息保存到我们自己的数据库。再将必要的信息传入支付接口(详细下面再介绍)这时候手机就会弹出微信支付的页面,用户完成支付后,点击完成就会返回到支付的页面。微信只有异步回调,支付成功后微信会回调信息到发起订单时我们自己设置的回调链接中(回调链接中的域名需要在服务号中进行绑定才行),在回调方法中签名校验成功就可以认为这是成功的支付,当然回调的时候里面会有你传入的商户订单号,这个就是标识是哪一个订单支付完成了,处理完订单业务后,需要返回成功的标识给接口。

官方给出的运行原理图:
在这里插入图片描述
基本配置说明
首先下载微信支付SDK,官方并没有上传SDK到Maven上面,为了安全起见从官网下载SDK并配置好。

下载地址:

https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=11_1

操作如下图:
在这里插入图片描述
下载完微信支付SDK,分析一下目录结构:
在这里插入图片描述
上面图片中README.md文件简单说明了用法,但是里面的介绍有滞后性,比如里面介绍的配置类MyConfig,它里面介绍的是实现一个接口,但实际情况是需要继承一个WXPayConfig抽象类并实现里面的抽象方法。

从上面图片的pom.xml文件中,我们发现里面有微信支付SDK的依赖,我将必要的依赖提取出来放在我们自己项目的pom.xml文件中,代码如下:

<!-- https://mvnrepository.com/artifact/org.apache.httpcomponents/httpclient -->
<dependency>
  <groupId>org.apache.httpcomponents</groupId>
  <artifactId>httpclient</artifactId>
  <version>4.5.3</version>
</dependency>

我们在项目中新建一个sdk文件夹,将下载好的微信支付SDK的Java文件放在其中,肯定会有报错,只需要修改一下包路径即可,操作如下图:
在这里插入图片描述
配置微信支付参数:

微信支付SDK里面有一个WXPayConfig类。我们在sdk文件夹下创建一个MyWXPayConfig类,继承这个WXPayConfig抽象类并实现方法。代码如下图:

package com.heiban.springboot.sdk;

import java.io.InputStream;

public class MyWXPayConfig extends WXPayConfig {

    /**
     * 获取 App ID
     * @return App ID
     */
    @Override
    public String getAppID() {
        return "----根据自己的商户进行填写---";
    }

    /**
     * 获取 Mch ID 商户号
     * @return Mch ID
     */
    @Override
    public String getMchID() {
        return "----根据自己的商户进行填写---";
    }
    
    /**
     * 获取 API 密钥
     * @return API密钥
     */
    @Override
    public String getKey() {
        return "----根据自己的商户进行填写---";
    }

    /**
     * 获取商户证书内容
     * @return 商户证书内容
     */
    @Override
    public InputStream getCertStream() {
        return null;
    }
    
    /**
     * 获取WXPayDomain, 用于多域名容灾自动切换
     * @return
     */
    @Override
    IWXPayDomain getWXPayDomain() {
        return new IWXPayDomain() {
            @Override
            public void report(String domain, long elapsedTimeMillis, Exception ex) {

            }
            @Override
            public DomainInfo getDomain(WXPayConfig config) {
                return new IWXPayDomain.DomainInfo(WXPayConstants.DOMAIN_API, true);
            }
        };
    }
}

上面的代码中有三个参数需要自己根据商户进行填写 分别是appid(公众账号ID)、mch_id(商户号)、API密钥。

到这里基本的配置操作都已经完成了,可以进行支付功能的开发了。

支付接口实现
注意:在真实环中默认生成的是HMAC-SHA256签名。

支付订单发起核心代码(完整代码可以按照文章末尾的提示获取):

MyWXPayConfig config = new MyWXPayConfig();//配置类
WXPay wxpay = new WXPay(config);//统一下单接口

Map<String, String> data = new HashMap<String, String>();
data.put("device_info", "WEB"); //设备号 PC网页或公众号内支付可以传"WEB"
data.put("nonce_str",WXPayUtil.generateNonceStr());//随机字符串
data.put("body", commodity); //商品描述
data.put("out_trade_no", nowtime); //商户订单号
data.put("total_fee", money); //标价金额 单位是分
data.put("spbill_create_ip", userIp); //用户的客户端IP
data.put("notify_url", "http://heibanyufenbi.xyz/notify_url"); //通知地址
data.put("trade_type", "MWEB");  // 交易类型  JSAPI--JSAPI支付(或小程序支付)、NATIVE--Native支付、APP--app支付,MWEB--H5支付

 try {
    Map<String, String> resp = wxpay.unifiedOrder(data);
    logger.trace(resp.toString());
    logger.trace("需要请求的地址:"+resp.get("mweb_url"));

    //跳转URL  //redirect_url则为支付后返回的指定页面
    String url = resp.get("mweb_url")+"&redirect_url=http://heibanyufenbi.xyz/information.html";

    //重定向页面
    return "redirect:"+url;
 } catch (Exception e) {
     e.printStackTrace();
 }
  • 简单介绍一下统一下单接口,实例化一个MyWXPayConfig配置类,将配置类传入统一下单接口的WXPay的构造方法中,然后就新建一个Map将必要的参数添加到Map中,最后用统一下单对象的unifiedOrder方法并传入Map参数,即可调起支付。
  • 其中的spbill_create_ip字段是需要自己获取用户下单的IP地址,详细获取客户端IP地址的代码看文末的提示获取整个项目的源文件。

如果是其他类型的支付Map中还需要添加其他参数,具体可以参看官方文档(API列表)链接地址:

https://pay.weixin.qq.com/wiki/doc/api/H5.php?chapter=9_20&index=1

还有值得注意的是notify_url字段,这个字段就是支付成功后微信支付回调的地址,该字段传入的域名必须是要备案成功的、在商户中进行绑定过了,在商户中绑定如下图:
在这里插入图片描述
订单支付成功处理(完整的代码):

@ResponseBody
@RequestMapping("/notify_url")
public String notify_url(HttpServletRequest request, HttpServletResponse response) throws Exception {
    logger.trace("支付信息回调中");
    String notifyData = "";
    try{

        InputStream inputStream = request.getInputStream();
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        byte[] buffer = new byte[2048];
        int len = 0;
        while ((len = inputStream.read(buffer)) != -1) {
            outputStream.write(buffer, 0, len);
        }

        notifyData = new String(outputStream.toByteArray(), "utf-8");// 支付结果通知的xml格式数据

        //关闭流
        outputStream.close();
        inputStream.close();
        logger.trace("获取xml格式数据成功:\n"+notifyData);
     }catch (Exception e){
        logger.trace("解析回调数据发生异常");
     }

     MyWXPayConfig config = new MyWXPayConfig();//配置类

     Map<String, String> notifyMap = WXPayUtil.xmlToMap(notifyData);  // 转换成map
     logger.trace("notifyMap = "+notifyMap);
     logger.trace("sign = "+notifyMap.get("sign"));

  if (WXPayUtil.isSignatureValid(notifyMap,config.getKey(),WXPayConstants.SignType.HMACSHA256)) {//HMACSHA256签名验证方法
//if (WXPayUtil.isSignatureValid(notifyMap,config.getKey())) {//MD5签名验证方法
      // 签名正确
      // 进行处理。
      // 注意特殊情况:订单已经退款,但收到了支付结果成功的通知,不应把商户侧订单状态从退款改成支付成功

      String out_trade_no = notifyMap.get("out_trade_no");//获取商户订单号
      String transaction_id = notifyMap.get("transaction_id");//微信支付订单号

       //处理标记付款成功
      Order order = orderRepository.findByOuttradeno(out_trade_no);
         if(order.getTrade_no()==null){
           order.setPlay(1);//设置为支付成功
           order.setTrade_no(transaction_id);//设置微信支付订单号
           orderRepository.save(order);//保存到数据库
           logger.trace("回调验证成功 业务代码已经处理");
         }
      //返回给微信的数据 标志成功
      Map<String,String> map = new HashMap<String, String>();
      map.put("return_code","SUCCESS");//SUCCESS表示商户接收通知成功并校验成功
      map.put("return_msg","OK");

      logger.trace("验签成功");

      return WXPayUtil.mapToXml(map);
  }
  else {
     // 签名错误,如果数据里没有sign字段,也认为是签名错误
     //返回给微信的数据 标志失败
     Map<String,String> map = new HashMap<String, String>();
     map.put("return_code","FAIL");
     map.put("return_msg","NO");

     logger.trace("验签失败");
     return WXPayUtil.mapToXml(map);
   }
}

简单介绍一下回调方法,获取返回的XML数据 ,将XML数据转换成Map,校验签名是否正确,如果正确就新建一个Map添加添加return_code与return_msg字段,再通过WXPayUtil.mapToXml(map)转换成XML格式,返回给支付接口,证明这是处理过的,所以需要在方法的头部标@ResponseBody注解。

签名选择与配置
特别注意:
签名(sgin字段):
微信支付有两种签名方式分别是MD5、HMAC-SHA256。在发起订单的时候调用统一下单接口,如果你是在沙箱环境下默认帮用MD5的方式生成签名,但是在真实环境中下默认帮你用HMAC-SHA256生成签名。(看API中 WXPay类 的构造方法得知)。

统一下单接口默认帮你用什么签名方式生成,你就要用什么签名方式去验证签名(在API中 WXPayUtil类中可以选择验证签名的方法)。所以在发起订单的时候其实sign_type(签名类型)这个是不用传递的。下面详细介绍如何切换这两种签名方式。

MD5、HMAC-SHA256这两种签名的方式有什么区别呢?很明显HMAC-SHA256这个更加安全。

如果你想用在真实环境中用MD5签名方式,你需要修改 WXPay类 的构造方法。操作如下图:
在这里插入图片描述
如上图中两个箭头,解除注释,将下面的代码注释即可在真实环境中使用MD5签名方式。

MD5与HMAC-SHA256签名方式,在回调方法中的校验签名的方法是不同的。
MD5签名方式在回调方法中应该调用,如下代码进行签名校验(具体代码请看原文件):

if (WXPayUtil.isSignatureValid(notifyMap,config.getKey())) {//MD5签名验证方法

HMAC-SHA256签名方式在回调方法中应该调用,如下代码进行签名校验(具体代码请看原文件):

if (WXPayUtil.isSignatureValid(notifyMap,config.getKey(),WXPayConstants.SignType.HMACSHA256)) {//HMACSHA256签名验证方法

本次例子目录结构如下图:
在这里插入图片描述
如果你想搭建该项目 你要做的是:

需要在能连接外网的服务器中,支付域名需要备案,需要有服务号。

搭建Mysql数据库 密码123456 并且创建数据库名称为wxpay的数据库,项目启动后JPA会自动创建数据库表。

你还需要自己配置MyWXPayConfig.java中的appid(公众账号ID)、mch_id(商户号)、API密钥配置

### 回答1: Vue、Spring Boot、微信H5支付、电商、Git 是一些常见的技术和工具。下面我将依次对它们进行解释和描述: Vue 是一个现代化的前端框架,采用了一种响应式的编程方式,可以轻松构建交互丰富、高性能、可维护的web应用程序。Vue 提供了诸多的功能和特性,例如组件化开发、虚拟DOM、数据双向绑定等,极大地提高了前端开发的效率。 Spring Boot 是一个轻量级、快速开发的Java后端框架,它简化了Spring应用程序的配置和部署,提供了自动化配置和快速启动的特性。Spring Boot具有强大的生态系统和丰富的功能,可以方便地构建高效、安全且可扩展的后端应用程序。 微信H5支付微信公众平台提供的一种在线支付方式,可以通过微信支付接口实现在手机浏览器中进行支付。它支持用户在H5页面中通过微信进行支付,适用于电商、在线购物等需要在线支付的场景。微信H5支付具有便捷、安全的特点,可以提供良好的用户支付体验。 电商是指以电子商务技术为支撑,通过互联网进行商品、服务的交易和商务活动的行业。电商平台的建设包括商品展示、购物车、订单管理、支付处理等模块,需求复杂多样。Vue和Spring Boot可以结合使用,前端通过Vue来实现电商平台的用户界面,后端采用Spring Boot来开发后台接口和处理业务逻辑。 Git 是一个分布式版本控制系统,用于保存和管理软件开发过程中的各个版本。团队可以通过Git来协同开发,追踪代码变更、回滚、合并等。在开发电商平台时,Git助力多人合作开发,有效地管理代码库,解决并发开发、版本控制的问题。团队成员可以通过Git来共享和提交自己的代码,并通过分支管理功能来进行并行开发和版本控制。 总结来说,Vue是一个前端框架,Spring Boot是一个后端框架,微信H5支付是一种在线支付方式,电商是基于电子商务技术的行业,Git是一个用于版本控制的工具。这些技术和工具可以相互结合,用于开发电商平台,并实现高效、可靠的软件开发和交付。 ### 回答2: Vue是一种流行的前端框架,它使用JavaScript和HTML来构建交互式的用户界面。它具有简单易学、灵活性强以及性能优化等优势,因此在前端开发中得到了广泛的应用。 Spring Boot是一个用于简化基于Java的应用程序开发的框架。它提供了开箱即用的功能,使开发人员能够快速构建高效、可扩展的应用程序。Spring Boot还具有自动化配置和简化部署等特性,使开发过程更加便捷。 微信H5支付是一种在线支付方式,允许用户在手机端使用微信进行购物支付。它具有支付安全、使用便捷以及适用范围广泛的特点,已经成为电商领域中非常常见的支付方式。 Git是一个分布式版本控制系统,它用于跟踪文件的修改和历史记录。在开发过程中,开发人员可以使用Git来管理代码版本,通过分支、合并等功能来协同开发和解决冲突。 综上所述,Vue和Spring Boot是用于构建应用程序的框架,微信H5支付是一种在线支付方式,而Git是用于版本控制的工具。它们在电商领域中都扮演着重要角色,能够使开发人员更加高效地开发、部署和维护应用程序。 ### 回答3: Vue是一个用于构建用户界面的开源JavaScript框架,它采用了MVVM的架构模式,能够使开发者更高效地构建Web应用程序。Vue具有简单易学、灵活可扩展以及高性能等特点,因此在前端开发中广受欢迎。 Spring Boot是一个基于Spring框架的快速开发框架,它通过内嵌的Web服务器、自动化配置和约定优于配置的原则,极大地简化了Java Web应用的开发工作。Spring Boot提供了丰富的开发工具和组件,使得开发人员可以更轻松地构建出高效、健壮的后端应用。 微信H5支付是指在移动端浏览器中使用微信支付功能的一种支付方式,用户可以通过浏览器直接打开商户的H5页面进行支付微信H5支付不需要下载或安装微信客户端,能够为电商平台提供更便捷的支付方式,提升用户体验并增加交易转化率。 Git是一个分布式版本控制系统,它可以记录和管理代码的版本变更。在团队协作开发中,Git可以帮助开发人员更好地进行代码管理、合并和回滚等操作,确保团队开发的代码始终处于一个稳定的状态。Git也是目前最流行的版本控制工具之一,被广泛应用于软件开发行业。 综上所述,Vue、Spring Boot、微信H5支付和Git分别代表了前端开发、后端开发、支付方式和版本控制等不同方面的技术和工具。结合这些技术和工具,我们可以构建出一个使用Vue作为前端框架,Spring Boot作为后端框架,集成微信H5支付的电商平台,并且通过Git进行代码版本管理和团队协作开发。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值