SpringBoot 微信H5支付

  • 去微信支付申请得到三个参数 API_KEY、APP_ID、MCH_ID
  • 微信支付配置域名的时候直接配置一级域名。
  • 下面参数说明。文档地址https://pay.weixin.qq.com/wiki/doc/api/H5.php?chapter=9_20&index=1
    在这里插入图片描述
  • 调用微信统一下单接口,得到微信那边给过来的链接 ,前端直接 跳转打开这个链接 回自动唤醒微信支付功能。然后回调地址也必须是外网可以访问 。回调地址必须是微信支付配置的域名下,redirect_url可以用来做跳转页面,不管成功或者失败都会调到这个地址上面 (redirect_url 文档说明)
  • spbill_create_ip 不能是127.0.0.1 ,设置服务器IP地址即可
  • 代码里面有很多工具类,自己百度搞下就有
package com.example.demo.pay.service.Impl;


import com.example.demo.common.constants.Message;
import com.example.demo.common.enums.ResponseEnum;
import com.example.demo.common.utils.*;
import com.example.demo.pay.service.WeChatService;
import org.apache.commons.lang3.RandomStringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URLEncoder;
import java.util.*;

@Service
public class WeChatServiceImpl implements WeChatService {

    private final static Logger logger = LoggerFactory.getLogger(WeChatServiceImpl.class);

    //API_KEY
    private static String API_KEY = "xxxxxxx";
    //公众账号ID
    private static  String APP_ID="xxxxxxx";
    //商户号
    private static String MCH_ID="xxxxxxxxx";
    //回调地址
    private static String NOTIFY_URL="http://xxxxxxxx/wx/callBlack";
    //支付回调页面
    private static String REDIRECT_URL="http://xxxxxxxxxxxc/REDIRECT_URL.html?orderNo=";
    //服务端IP
     private static String SPBILL_CREATE_IP="xxx.xxx.xx.xx";
    // 微信支付统一接口(POST)
    private final static String WX_PAY_URL = "https://api.mch.weixin.qq.com/pay/unifiedorder";
    // 微信订单查询接口(POST)
    public final static String WX_CHECK_ORDER_URL = "https://api.mch.weixin.qq.com/pay/orderquery";

    /**
     * 微信h5支付
     *
     * @return
     */
    @Override
    public Message wxpay(HttpServletRequest request,String orderNo) {
        String nonce_str = generateNonceStr();
        int total_fee = 1;
        double money=total_fee;
        String body = "购买xxxxxxxxxx" + (money / 100) + "元";
        String out_trade_no = orderNo;
        String spbill_create_ip = SPBILL_CREATE_IP;
        //String time_start= DateUtil.getAtPersent();//交易起始时间
        //String time_expire= DateUtil.getBeformTime(5);//交易结束时间
        String trade_type = "MWEB";//H5支付的交易类型为 MWEB
        String scene_info = "{'h5_info': {'type':'Wap','wap_url': 'https://pay.qq.com','wap_name': '产品购买'}}";
        SortedMap<Object, Object> packageParams = new TreeMap<Object, Object>();
        packageParams.put("appid", APP_ID);// 公众账号ID
        packageParams.put("mch_id", MCH_ID);// 商户号
        packageParams.put("nonce_str", nonce_str);// 随机字符串
        packageParams.put("body", body);// 商品描述
        packageParams.put("out_trade_no", out_trade_no);// 商户订单号
        packageParams.put("total_fee", total_fee);// 总金额(单位分)
        packageParams.put("spbill_create_ip", spbill_create_ip);//发起人IP地址
        packageParams.put("notify_url", NOTIFY_URL);// 回调地址
        packageParams.put("trade_type", trade_type);// 交易类型
        packageParams.put("scene_info", scene_info);
        String sign = PayCommonUtil.createSign("UTF-8", packageParams, API_KEY);// 签名
        packageParams.put("sign", sign);
        String mweb_url = "";
        Map<String,Object> data=new HashMap<>();
        try {
            String requestXML = PayCommonUtil.getRequestXml(packageParams);
            String resXml = HttpRequest.postData(WX_PAY_URL, requestXML);
            Map map = XMLUtil.doXMLParse(resXml);
            logger.info("map:{}"+map);
            String returnCode = (String) map.get("return_code");
            if ("SUCCESS".equals(returnCode)) {
                String resultCode = (String) map.get("result_code");
                if ("SUCCESS".equals(resultCode)) {
                    logger.info("订单号:{}发起H5支付成功", out_trade_no);
                    mweb_url = (String) map.get("mweb_url");
                } else {
                    String errCodeDes = (String) map.get("err_code_des");
                    logger.info("订单号:{}发起H5支付(系统)失败:{}", out_trade_no, errCodeDes);
                }
            } else {
                String returnMsg = (String) map.get("return_msg");
                logger.info("(订单号:{}发起H5支付(通信)失败:{}", out_trade_no, map);
            }
        } catch (Exception e) {
            logger.error("订单号:{}发起H5支付失败(系统异常))", out_trade_no, e);
        }
        try {
            String url = URLEncoder.encode(REDIRECT_URL+out_trade_no, "utf-8");
            //redirect_url参数,来指定回调页面
            mweb_url=mweb_url+"&redirect_url="+url;
        }catch (Exception e){
              logger.error("URl进行Encode异常:{}", e);
        }
        data.put("url",mweb_url);
        data.put("orderNo",out_trade_no);
        return new Message(ResponseEnum.SUCCESS, data);
    }

    /**
     * 微信h5支付回调方法
     *
     * @param request
     * @param response
     */
    @Override
    public void weixinCallback(HttpServletRequest request, HttpServletResponse response) {
        try {
            // 读取参数
            InputStream inputStream = request.getInputStream();
            StringBuffer sb = new StringBuffer();
            String s;
            BufferedReader in = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
            while ((s = in.readLine()) != null) {
                sb.append(s);
            }
            in.close();
            inputStream.close();
            // 解析xml成map
            Map<String, String> m = new HashMap<String, String>();
            m = XMLUtil.doXMLParse(sb.toString());
            // 过滤空 设置 TreeMap
            SortedMap<Object, Object> packageParams = new TreeMap<Object, Object>();
            Iterator it = m.keySet().iterator();
            while (it.hasNext()) {
                String parameter =String.valueOf( it.next());
                String parameterValue = m.get(parameter);
                String v = "";
                if (null != parameterValue) {
                    v = parameterValue.trim();
                }
                packageParams.put(parameter, v);
            }
            logger.info("回调参数 map:{}"+packageParams);
            // 账号信息
            String key = API_KEY; // key
            // 判断签名是否正确
            if (PayCommonUtil.isTenpaySign("UTF-8", packageParams, key)) {
                logger.info("微信支付成功回调");
                // ------------------------------
                // 处理业务开始
                // ------------------------------
                String resXml = "";
                if ("SUCCESS".equals(String.valueOf(packageParams.get("result_code")))) {
                    // 这里是支付成功
                    String orderNo = String.valueOf(packageParams.get("out_trade_no"));
                    logger.info("付款成功,微信订单号:{}", orderNo);
                    // 这里 根据实际业务场景 做相应的操作
                    // 通知微信.异步确认成功.必写.不然会一直通知后台.八次之后就认为交易失败了.
                    resXml = "<xml>"
                            + "<return_code><![CDATA[SUCCESS]]></return_code>"
                            + "<return_msg><![CDATA[OK]]></return_msg>" + "</xml> ";
                } else {
                    logger.info("支付失败,错误信息:{}", packageParams.get("err_code"));
                    resXml = "<xml>"
                            + "<return_code><![CDATA[FAIL]]></return_code>"
                            + "<return_msg><![CDATA[报文为空]]></return_msg>"
                            + "</xml> ";
                }
                // ------------------------------
                // 处理业务完毕
                // ------------------------------
                BufferedOutputStream out = new BufferedOutputStream(
                        response.getOutputStream());
                out.write(resXml.getBytes());
                out.flush();
                out.close();
            } else {
                logger.info("通知签名验证失败");
            }
        } catch (Exception e) {
            logger.error("微信H5支付回调异常{}:", e.toString(), e);
        }
    }


    /**
     * 微信订单查询
     *
     * @param request
     * @param out_trade_no
     * @return
     */
    @Override
    public Message weChatQuery(HttpServletRequest request, String out_trade_no) {
        String nonce_str = generateNonceStr();
        SortedMap<Object, Object> packageParams = new TreeMap<Object, Object>();
        packageParams.put("appid", APP_ID);// 公众账号ID
        packageParams.put("mch_id", MCH_ID);// 商户号
        packageParams.put("nonce_str", nonce_str);// 随机字符串
        packageParams.put("out_trade_no",out_trade_no);//订单No
        String sign = PayCommonUtil.createSign("UTF-8", packageParams, API_KEY);// 签名
        packageParams.put("sign", sign);
        Map<String,Object> data=new HashMap<>();
        data.put("pay_success_url",PAY_SUCCESS_URL);
        data.put("pay_error_url",PAY_ERROR_URL);
        try {
            String requestXML = PayCommonUtil.getRequestXml(packageParams);
            String resXml = HttpRequest.postData(WX_CHECK_ORDER_URL, requestXML);
            Map map = XMLUtil.doXMLParse(resXml);
            logger.info("map:{}"+map);
            String returnCode = (String) map.get("return_code");
            if ("SUCCESS".equals(returnCode)) {
                String resultCode = (String) map.get("result_code");
                if ("SUCCESS".equals(resultCode)) {
                    String tradeState = (String) map.get("trade_state");
                    logger.info("tradeState:{}" + tradeState);
                    logger.info("订单号:{}", out_trade_no);
                    data.put("orders",map);
                    boolean paySuccess=paySuccess(tradeState);
                    if (paySuccess == true)
                        return new Message(ResponseEnum.SUCCESS, data);
                } else {
                    String errCodeDes = (String) map.get("err_code_des");
                    logger.info("订单号:{}订单查询失败(系统)失败:{}", out_trade_no, errCodeDes);
                }
            } else {
                String returnMsg = (String) map.get("return_msg");
                logger.info("(订单号:{}订单查询失败:{}", out_trade_no, returnMsg);
            }
        } catch (Exception e) {
            logger.error("订单号:{}订单查询失败(系统异常))", out_trade_no, e);
        }
        return new Message(ResponseEnum.FALL,data);
    }


    /**
     * 获取随机字符串 Nonce Str
     *
     * @return String 随机字符串
     */
    public static String generateNonceStr() {
        String noncestr = RandomStringUtils.randomAlphanumeric(16);
        return noncestr;
    }

    /**
     * 生成系统当前时间戳
     *
     * @return
     */
    public static String create_timestamp() {
        return Long.toString(System.currentTimeMillis() / 1000);
    }

    public static boolean paySuccess(String tradeState){
        if("SUCCESS".equalsIgnoreCase(tradeState)){
         return  true;
        }
        return  false;
    }
}

  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
SpringBoot是一个开源的Java应用程序框架,用于快速构建独立的、基于生产级别的Java应用程序。它提供了许多功能和工具,可以简化开发过程并提高开发效率。而H5微信支付是指在移动端网页上使用微信支付的一种方式。下面是使用SpringBoot来实现H5微信支付的步骤: 1. 准备工作:首先,您需要拥有微信公众号或小程序账号,并开通支付功能。您还需要有自己的服务器,以接收微信支付的通知。同时,确保您已经使用了Java SpringBoot框架。 2. 配置微信支付参数:在SpringBoot项目的配置文件中,添加微信支付所需的配置参数,包括AppID、商户号、支付密钥等。这些参数可以在微信开放平台上获取。 3. 引入相关依赖:在项目的构建文件中,添加微信支付相关的依赖项,如微信支付SDK或其他相关库。这些依赖项将帮助您在代码中调用微信支付接口。 4. 创建统一下单接口:使用SpringBoot框架创建一个用于接收支付请求的接口。在该接口中,您需要获取用户的支付信息,并调用微信支付统一下单接口生成预支付订单。 5. 处理支付结果通知:创建一个用于接收微信支付结果通知的接口。在该接口中,您需要验证支付结果的合法性,并处理相应的业务逻辑。 6. 前端页面开发:在前端页面中添加微信支付的相关逻辑,包括调用微信支付接口、展示支付结果等。 总结起来,要使用SpringBoot来实现H5微信支付,您需要进行准备工作,配置微信支付参数,引入相关依赖,创建统一下单接口,处理支付结果通知,以及在前端页面中添加支付逻辑。这样就可以实现使用SpringBoot进行H5微信支付了。<span class="em">1</span><span class="em">2</span><span class="em">3</span>
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值