java实现微信H5支付 2021-07-10

本文档介绍了如何在Java后端实现微信H5支付的流程,包括调用微信支付接口创建订单、处理回调以及查询订单状态的方法。示例代码展示了Spring Boot应用中使用微信支付SDK进行支付操作的细节,同时提醒了支付过程中需要注意的域名和回调地址一致性的要求,以及防止假支付的订单状态检查接口。
摘要由CSDN通过智能技术生成

微信支付已经做烂了,没啥好讲的。记录一下。
首先微信支付流程相信大家大致都了解,不知道的自己去微信开发文档上看,很简单,我这边不多说直接上代码。

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;


 @GetMapping(value = "pay")
    public String  wechatPayOrder(@RequestParam("orderId") String orderId, HttpServletRequest request, Model model){
        log.info("活动订单: {} 开始微信支付", orderId);
        // 调用serviceH5支付
        //将属性转化为xml格式,然后传给微信服务器,得到支付的URL
        String url = weChatPayService.wechatPayH5("标题", null, orderId(订单号),  String.valueOf(1)(价格,单位是分 1对应0.01, request);
        if(StringUtils.isEmpty(url)){
              log.error("活动订单: {} 微信支付失败, 获取到的支付url为空", "");
            return "/pay/error";//Result.error("no",null);
        }
        try {
          //将返回的url加上我们自己本地服务器上的返回路径redirect_url
            url = url + "&redirect_url="+ URLEncoder.encode(weChatConfig.redirect_url, "utf-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }

        model.addAttribute("pay",url);
        return  "pay/wxbuy";// Result.success(url);
    }
    
  /**
     * 微信支付完成后,微信回调的页面
     * @return
     */
    @GetMapping("/backll")
    public String backll(){
        System.out.println("-------------微信回调---------------:");
        return  "pay/back"; //Result.success("no");
    }


    /**
     * 查询订单,用于微信回调接口时查询订单是否完成。用户主动触发
     * @param orderId
     * @return
     */
    @GetMapping("/checkList")
    public String CheckList(@RequestParam("orderId")String orderId){
         weChatPayService.CheckList(orderId);
        return "pay/back";
    }


参数类,值就自己去自己配置文件中设置

@Component
public class WeChatConfig {
    @Value("${wxpay.appid}")
    public String appid;

    @Value("${wxpay.appsecret}")
    public String appsecret;

    @Value("${wxpay.mer_id}")
    public String merId;

    @Value("${wxpay.key}")
    public String key;

    // 支付回调
    @Value("${wxpay.callback}")
    public String callback;

    // 文档介绍: 正常流程用户支付完成后会返回至发起支付的页面,如需返回至指定页面,则可以在MWEB_URL后拼接上redirect_url参数,来指定回调页面。
    @Value("${wxpay.redirect_url}")
    public String redirect_url;
}

实现方法
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.net.ssl.SSLContext;
import javax.servlet.http.HttpServletRequest;

import java.io.FileInputStream;
import java.security.KeyStore;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;

@Service
public class WeChatPayServiceImpl implements WeChatPayService {

@Autowired
private WeChatConfig weChatConfig;

private static final Logger logger = LoggerFactory.getLogger("WeChatPayServiceImpl");
/**
 * 微信H5支付
 * @param remark 订单备注
 * @param attach 携带的附加数据. 可以不用
 * @param out_trade_no 订单号
 * @param money 金额
 * @param request
 * @return url
 */
@Override
public String wechatPayH5(String remark, String attach, String out_trade_no, String money, HttpServletRequest request) {
    String requestIp = CommonUtils.getIpAddr(request);
    //返回参数
    SortedMap<String,String> params = new TreeMap<>();
    params.put("appid", weChatConfig.appid);
    params.put("mch_id", weChatConfig.merId);
    params.put("nonce_str", CommonUtils.generateUUID()); // 随机字符串, 请求参数需要
    params.put("body", remark); // 支付备注
    params.put("out_trade_no", out_trade_no); // 订单号
    params.put("total_fee", "1"); // 支付金额
    params.put("spbill_create_ip",requestIp); // 设置创建订单的ip地址,不太明白是什么ip.有人用当前服务器的ip,我这里直接使用用户请求的ip,没有发现有什么影响.
    params.put("notify_url",weChatConfig.callback); // 支付回调,也就是支付成功后,我们业务员上需要做的操作
    params.put("trade_type", "MWEB"); // 交易类型,这里为H5
    String sign = WXPayUtil.createSign(params, weChatConfig.key);
    params.put("sign",sign);
    String payXml;
    try {
        // 微信支付要求调用统一下单接口的必须是一个xml
        payXml = WXPayUtil.mapToXml(params);
        logger.info("payXml: "+payXml);
        // 调用微信的统一下单接口
        String orderStr = HttpUtils.doPost("https://api.mch.weixin.qq.com/pay/unifiedorder",payXml,4000);
        if(StringUtils.isEmpty(orderStr)){
            logger.error("微信支付失败.原因: 调用微信统一下单接口失败");
            return null;
        }
         logger.info("orderStr: "+orderStr);
        // 调用成功, 返回的结果也是一个xml, 需要将返回的XML转化为一个map, 方便操作.
        Map<String, String> unifiedOrderMap =  WXPayUtil.xmlToMap(orderStr);
        if(unifiedOrderMap != null) {
            // 得到支付的url
            return unifiedOrderMap.get("mweb_url");
        }
    } catch (Exception e) {
        logger.error("微信支付失败.原因: map参数转xml失败({})", e.getMessage());
        e.printStackTrace();
    }
    return null;
}


public String CheckList(String orderId){
   //查询订单接口
    SortedMap<String,String> params = new TreeMap<>();
    params.put("appid", weChatConfig.appid);
    params.put("mch_id", weChatConfig.merId);
    params.put("nonce_str", CommonUtils.generateUUID()); // 随机字符串, 请求参数需要
    params.put("out_trade_no", orderId); // 订单号
    String sign = WXPayUtil.createSign(params, weChatConfig.key);
    params.put("sign",sign);
    String payXml;
    try {
        // 微信支付要求调用统一下单接口的必须是一个xml
        payXml = WXPayUtil.mapToXml(params);
       // logger.info("payXml: " + payXml);
        // 调用微信的统一下单接口
        String orderStr = HttpUtils.doPost("https://api.mch.weixin.qq.com/pay/orderquery", payXml, 4000);
        System.out.println(orderStr);
        Map<String, String> map =  WXPayUtil.xmlToMap(orderStr);
        System.out.println("状态码:  "+map.get("err_code")+"  ---订单状态----:"+map.get("err_code_des")+"-----:"+map.get("result_code"));
    }catch (Exception e){

    }
    return "";
}

java方面大致就是这样。但是微信返回的那个支付url是无法直接用浏览器打开的,所以我们得返回给html,让html去请求。
在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
           <input type="hidden" id="url2" th:value="${pay}"  name="token">
           <button th:onclick="first2([[${pay}]])"> 点击</button>

</body>

<script type="text/javascript" th:inline="javascript">

    function first2(ss) {


        window.location.href = ss;

    }
</script>
</html>

在这里插入图片描述
请求后就是这样,支付成功。
注意2点:一,请求时的域名地址必须和微信商城中设置的域名一样,回调的地址也是一样,不然会出现下列错误。
在这里插入图片描述
2.为了防止用户假支付,我们应该确认订单是否完成了。因为用户在取消支付或者停留页面过长,系统都会回调我们自己的接口。所以我们需要在里面设置一个查询订单状态的接口。用来判断订单是否完成。微信方面是希望我们设置一个页面让客户自己点击去触发这次操作。
在这里插入图片描述
还有一些就参数问题啊,配置问题啥的就不说了自己去微信开发平台看,里面都有详细说明。地址:https://pay.weixin.qq.com/wiki/doc/api/H5.php?chapter=15_4

整个支付流程就这样。具体有什么问题可以提出来。毕竟我也不保证能都没问题。如果没问题,麻烦点个赞 哈哈。

补充下,博友需要自己下载下微信的sdk。微信平台上有下载。当然也可以用maven自己去引进。
在这里插入图片描述
项目地址:https://download.csdn.net/download/qq_42729674/20156744?spm=1001.2014.3001.5501

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
Java可以通过调用微信支付提供的API来实现微信H5支付。下面是实现微信H5支付的大致步骤: 1. 首先,需要在微信支付商户平台上注册一个商户账号,并获取到商户ID(mch_id)、商户密钥(key)、AppID和AppSecret等必要的凭证信息。 2. 在Java项目中引入微信支付的SDK,可以使用第三方库,例如微信官方提供的微信支付Java SDK、Alipay等。 3. 创建一个支付接口,接收前端传递的支付请求参数。参数中需要包含订单号、订单金额、支付描述等信息。 4. 通过调用微信支付SDK中的统一下单接口(unifiedorder),传递必要的参数,包括商户ID、商户密钥、AppID、订单号、订单金额等,获取预支付交易会话标识(prepay_id)和支付签名。 5. 将预支付交易会话标识(prepay_id)和支付签名返回给前端,前端可以通过支付签名调起微信支付页面。 6. 在前端页面中,通过调用微信JSAPI的支付接口,传递预支付交易会话标识(prepay_id)等参数,拉起微信支付页面。 7. 用户在微信支付页面输入密码并完成支付后,微信会自动将支付结果返回给前端。 8. 前端将支付结果通知给后台,后台可以通过调用微信支付SDK中的查询订单接口(orderquery),传递必要的参数,包括商户ID、商户密钥、AppID、订单号等,获取到订单的支付结果。 9. 根据支付结果,可以进行相应的逻辑处理,例如更新订单状态、生成支付成功的通知等。 需要注意的是,在实现过程中要保证支付接口的安全性,例如使用HTTPS协议、对参数进行签名验证等,以防止支付过程中的信息泄露和篡改。
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值