JAVA 微信小程序V3支付(保姆级)

2024.05.07更新方法

更新WXPaySignatureCertificateUtil.java 工具类 详细看3.1

许多人对AutoUpdateCertificatesVerifier验证有疑问 

所以此次更新使用Verifier验证

这里有两种验证证书方式

AutoUpdateCertificatesVerifier和Verifier

两者自选使用

app去下面

JAVA 微信APPV3支付(保姆级)

现在Java微信支付文章五花八门 看不懂 看的懵 掺杂业务逻辑不知名的返回封装 爆红一片 不妨看看这篇

 1.加入Maven依赖

        <!-- 微信支付V3 目前新版本-->
        <dependency>
            <groupId>com.github.wechatpay-apiv3</groupId>
            <artifactId>wechatpay-apache-httpclient</artifactId>
            <version>0.4.9</version>
        </dependency>

 2.创建WxV3PayConfig.java配置类 

/**
 * implements WXPayConfig
 */
@Data
public class WxV3PayConfig {

    //平台证书序列号
    public static String mchSerialNo = "xxxxxxxxxxxxxx";

    //appID
    public static String APP_ID = "xxxxxxxxxxxxxx";

    //商户id
    public static String Mch_ID = "xxxxxxxxxxxxxx";

    // API V3密钥
    public static String apiV3Key = "xxxxxxxxxxxxxx";

  

    }

3.创建WXPaySignatureCertificateUtil.java 工具类

使用AutoUpdateCertificatesVerifier验证

复制粘贴即可

/***
*
*包都在这
*
*
*
*/
import com.wechat.pay.contrib.apache.httpclient.WechatPayHttpClientBuilder;
import com.wechat.pay.contrib.apache.httpclient.auth.AutoUpdateCertificatesVerifier;
import com.wechat.pay.contrib.apache.httpclient.auth.PrivateKeySigner;
import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Credentials;
import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Validator;
import com.wechat.pay.contrib.apache.httpclient.util.PemUtil;
import lombok.SneakyThrows;
import org.apache.http.impl.client.CloseableHttpClient;
import javax.servlet.http.HttpServletRequest;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.*;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Base64;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
import java.util.stream.Stream;
 
public class WXPaySignatureCertificateUtil {
 
 
 
 
    /**
     * 证书验证
     * 自动更新的签名验证器
     */
    public static CloseableHttpClient checkSign() throws IOException {
        //验签
        CloseableHttpClient httpClient = null;
        PrivateKey merchantPrivateKey = WXPaySignatureCertificateUtil.getPrivateKey();
        httpClient = WechatPayHttpClientBuilder.create()
                .withMerchant(WxV3PayConfig.Mch_ID, WxV3PayConfig.mchSerialNo, merchantPrivateKey)
                .withValidator(new WechatPay2Validator(WXPaySignatureCertificateUtil.getVerifier(WxV3PayConfig.mchSerialNo)))
                .build();
 
        return httpClient;
    }
 
 
 
 
    /**
     * 保存微信平台证书
     */
    private static final ConcurrentHashMap<String, AutoUpdateCertificatesVerifier> verifierMap = new ConcurrentHashMap<>();
 
    /**
     * 功能描述:获取平台证书,自动更新
     * 注意:这个方法内置了平台证书的获取和返回值解密
     */
    static AutoUpdateCertificatesVerifier getVerifier() {
        String mchSerialNo = WxV3PayConfig.mchSerialNo;
        AutoUpdateCertificatesVerifier verifier = null;
        if (verifierMap.isEmpty() || !verifierMap.containsKey(mchSerialNo)) {
            verifierMap.clear();
            try {
                 //传入证书
                 PrivateKey privateKey = getPrivateKey();
                //刷新
                PrivateKeySigner signer = new PrivateKeySigner(mchSerialNo, privateKey);
                WechatPay2Credentials credentials = new WechatPay2Credentials(WxV3PayConfig.Mch_ID, signer);
                verifier = new AutoUpdateCertificatesVerifier(credentials
                        , WxV3PayConfig.apiV3Key.getBytes("utf-8"));
                verifierMap.put(verifier.getValidCertificate().getSerialNumber()+"", verifier);
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
        } else {
            verifier = verifierMap.get(mchSerialNo);
        }
        return verifier;
    }
 
 
 
    /**
     * app生成带签名支付信息
     *
     * @param timestamp 时间戳
     * @param nonceStr  随机数
     * @param prepayId  预付单
     * @return 支付信息
     * @throws Exception
     */
    public static String appPaySign(String timestamp, String nonceStr, String prepayId) throws Exception {
        //上传私钥
        PrivateKey privateKey = getPrivateKey();
        String signatureStr = Stream.of(WxV3PayConfig.APP_ID, timestamp, nonceStr, prepayId)
                .collect(Collectors.joining("\n", "", "\n"));
        Signature sign = Signature.getInstance("SHA256withRSA");
        sign.initSign(privateKey);
        sign.update(signatureStr.getBytes(StandardCharsets.UTF_8));
        return Base64.getEncoder().encodeToString(sign.sign());
    }
 
    /**
     * 小程序及其它支付生成带签名支付信息
     *
     * @param timestamp 时间戳
     * @param nonceStr  随机数
     * @param prepayId  预付单
     * @return 支付信息
     * @throws Exception
     */
    public static String jsApiPaySign(String timestamp, String nonceStr, String prepayId) throws Exception {
        //上传私钥
        PrivateKey privateKey = getPrivateKey();
        String signatureStr = Stream.of(WxV3PayConfig.APP_ID, timestamp, nonceStr, "prepay_id="+prepayId)
                .collect(Collectors.joining("\n", "", "\n"));
        Signature sign = Signature.getInstance("SHA256withRSA");
        sign.initSign(privateKey);
        sign.update(signatureStr.getBytes(StandardCharsets.UTF_8));
        return Base64.getEncoder().encodeToString(sign.sign());
    }
 
 
    /**
     * 获取私钥。
     * 证书路径 本地使用如: D:\\微信平台证书工具\\7.9\\apiclient_key.pem
     * 证书路径 线上使用如: /usr/apiclient_key.pem
     * String filename 私钥文件路径  (required)
     * @return 私钥对象
     */
    public static PrivateKey getPrivateKey() throws IOException {
        String content = new String(Files.readAllBytes(Paths.get("D:\\微信平台证书工具\\7.9\\apiclient_key.pem")), "utf-8");
        try {
            String privateKey = content.replace("-----BEGIN PRIVATE KEY-----", "")
                    .replace("-----END PRIVATE KEY-----", "")
                    .replaceAll("\\s+", "");
 
            KeyFactory kf = KeyFactory.getInstance("RSA");
            return kf.generatePrivate(
                    new PKCS8EncodedKeySpec(Base64.getDecoder().decode(privateKey)));
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("当前Java环境不支持RSA", e);
        } catch (InvalidKeySpecException e) {
            throw new RuntimeException("无效的密钥格式");
        }
    }
 
}

3.1.更新创建WXPaySignatureCertificateUtil.java 工具类

使用Verifier验证

/***
*
*包都在这
*
*
*
*/
import com.wechat.pay.contrib.apache.httpclient.WechatPayHttpClientBuilder;
import com.wechat.pay.contrib.apache.httpclient.auth.AutoUpdateCertificatesVerifier;
import com.wechat.pay.contrib.apache.httpclient.auth.PrivateKeySigner;
import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Credentials;
import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Validator;
import com.wechat.pay.contrib.apache.httpclient.util.PemUtil;
import lombok.SneakyThrows;
import org.apache.http.impl.client.CloseableHttpClient;
import javax.servlet.http.HttpServletRequest;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.*;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Base64;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
import java.util.stream.Stream;
 
public class WXPaySignatureCertificateUtil {
 
 
 
 
    private static final ConcurrentHashMap<String, Verifier> verifierMaps = new ConcurrentHashMap<>();
 
 
   /**
     * 证书验证
     * 自动更新的签名验证器
     */
    public static CloseableHttpClient checkSign() throws IOException {
        //验签
        CloseableHttpClient httpClient = null;
        PrivateKey merchantPrivateKey = WXPaySignatureCertificateUtil.getPrivateKey();
        httpClient = WechatPayHttpClientBuilder.create()
                .withMerchant(WxV3PayConfig.Mch_ID, WxV3PayConfig.mchSerialNo, merchantPrivateKey)
                .withValidator(new WechatPay2Validator(WXPaySignatureCertificateUtil.getVerifier(WxV3PayConfig.mchSerialNo)))
                .build();
 
        return httpClient;
    }
        
 
 
    /**
     * 功能描述:获取平台证书,自动更新
     * 注意:这个方法内置了平台证书的获取和返回值解密
     */
    public static Verifier getVerifiers(String mchSerialNo) {
        Verifier verifier = null;
        if (verifierMaps.isEmpty() || !verifierMaps.containsKey(mchSerialNo)) {
            verifierMaps.clear();
            try {
                PrivateKey privateKey = getPrivateKey();
                //刷新
                PrivateKeySigner signer = new PrivateKeySigner(mchSerialNo, privateKey);
                WechatPay2Credentials credentials = new WechatPay2Credentials(WxV3PayConfig.Mch_ID, signer);
                verifier = new AutoUpdateCertificatesVerifier(credentials
                        , apiV3Key.getBytes("utf-8"));
                verifierMaps.put(verifier.getValidCertificate().getSerialNumber()+"", verifier);
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        } else {
            verifier = verifierMaps.get(mchSerialNo);
        }
        return verifier;
    }
 
 
    /**
     * app生成带签名支付信息
     *
     * @param timestamp 时间戳
     * @param nonceStr  随机数
     * @param prepayId  预付单
     * @return 支付信息
     * @throws Exception
     */
    public static String appPaySign(String timestamp, String nonceStr, String prepayId) throws Exception {
        //上传私钥
        PrivateKey privateKey = getPrivateKey();
        String signatureStr = Stream.of(WxV3PayConfig.APP_ID, timestamp, nonceStr, prepayId)
                .collect(Collectors.joining("\n", "", "\n"));
        Signature sign = Signature.getInstance("SHA256withRSA");
        sign.initSign(privateKey);
        sign.update(signatureStr.getBytes(StandardCharsets.UTF_8));
        return Base64.getEncoder().encodeToString(sign.sign());
    }
 
    /**
     * 小程序及其它支付生成带签名支付信息
     *
     * @param timestamp 时间戳
     * @param nonceStr  随机数
     * @param prepayId  预付单
     * @return 支付信息
     * @throws Exception
     */
    public static String jsApiPaySign(String timestamp, String nonceStr, String prepayId) throws Exception {
        //上传私钥
        PrivateKey privateKey = getPrivateKey();
        String signatureStr = Stream.of(WxV3PayConfig.APP_ID, timestamp, nonceStr, "prepay_id="+prepayId)
                .collect(Collectors.joining("\n", "", "\n"));
        Signature sign = Signature.getInstance("SHA256withRSA");
        sign.initSign(privateKey);
        sign.update(signatureStr.getBytes(StandardCharsets.UTF_8));
        return Base64.getEncoder().encodeToString(sign.sign());
    }
 
 
    /**
     * 获取私钥。
     * 证书路径 本地使用如: D:\\微信平台证书工具\\7.9\\apiclient_key.pem
     * 证书路径 线上使用如: /usr/apiclient_key.pem
     * String filename 私钥文件路径  (required)
     * @return 私钥对象
     */
    public static PrivateKey getPrivateKey() throws IOException {
        String content = new String(Files.readAllBytes(Paths.get("D:\\微信平台证书工具\\7.9\\apiclient_key.pem")), "utf-8");
        try {
            String privateKey = content.replace("-----BEGIN PRIVATE KEY-----", "")
                    .replace("-----END PRIVATE KEY-----", "")
                    .replaceAll("\\s+", "");
 
            KeyFactory kf = KeyFactory.getInstance("RSA");
            return kf.generatePrivate(
                    new PKCS8EncodedKeySpec(Base64.getDecoder().decode(privateKey)));
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("当前Java环境不支持RSA", e);
        } catch (InvalidKeySpecException e) {
            throw new RuntimeException("无效的密钥格式");
        }
    }
 
}

4.创建WXPayConstants.java类

package com.yingzi.smallprogram.util.wxPay;

/**
 * 常量
 */  
public class WXPayConstants {

    public static final String DOMAIN_API = "https://api.mch.weixin.qq.com/v3";


    public static final String FAIL     = "FAIL";
    public static final String SUCCESS  = "SUCCESS";
    public static final Object RESOURCE_NOT_EXISTS = "RESOURCE_NOT_EXISTS";
    public static final Object USER_ACCOUNT_ABNORMAL = "USER_ACCOUNT_ABNORMAL";
    public static final String RSA = "RSA";


    //jsapi下单
    public static final String JSAPI_TRANSACTIONS_APP = "/pay/transactions/jsapi";


    //申请退款
    public static final String REFUND_DOMESTIC_REFUNDS = "/refund/domestic/refunds";

    //jsapi微信支付回调
    public static final String WECHAT_PAY_NOTIFY_URL = "https://xxx.xxx.top/xxx/applet/api/appOrderPay/weChatPayNotify";


    //jspi微信退款回调
    public static final String WECHAT_REFUNDS_NOTIFY_URL = "https://xxx.xxx.top/xxx/applet/api/appOrderPay/weChatPayRefundsNotify";

}

这里以小程序支付和退款为例

5.创建WechatPaymentService.java

/**
 * @author 影子
 */
public interface WechatPaymentService
{


    /**
     * 微信商品支付
     * @param payParam
     * @return
     */
    public Map<String, Object>weChatDoUnifiedOrder() throws Exception;




    /**
     * 微信支付回调通知
     * @param
     * @return
     */
    public Map<String, Object> weChatNotificationHandler(HttpServletRequest request, HttpServletResponse response);



    /**
     * 申请退款
     * @param
     * @return
     */
    public Map<String, Object> weChatPayRefundsNotify(HttpServletRequest request);
 



    /**
     * 微信退款回调
     * @param outTradeNo 订单号
     * @return
     */
    public Map<String, Object> weChatRefunds(String outTradeNo);
}

6.创建WeChatPaymentServiceImpl.java

/*
*
* 照顾找包困难的朋友吧
*
*/
import com.alibaba.fastjson.JSONObject;
import com.alipay.api.internal.util.file.ByteArrayOutputStream;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.github.wxpay.sdk.WXPayUtil;
import com.wechat.pay.contrib.apache.httpclient.notification.Notification;
import com.wechat.pay.contrib.apache.httpclient.notification.NotificationHandler;
import com.wechat.pay.contrib.apache.httpclient.notification.NotificationRequest;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.util.EntityUtils;

public class WeChatPaymentServiceImpl implements WechatPaymentService {



 /**
     * V3微信支付统一下单
     *
     * @param payParam
     * @return
     * 
     */
    @Override
    public Map<String, Object>weChatDoUnifiedOrder() {
        Map<String,Object> map =new HashMap<>();
        //支付总金额
        BigDecimal totalPrice = BigDecimal.ZERO;
        totalPrice = totalPrice.add(BigDecimal.valueOf(600));
        //转换金额保留两位小数点
        Integer money=new BigDecimal(String.valueOf(totalPrice)).movePointRight(2).intValue();
            try {
                //验证证书
                CloseableHttpClient httpClient = WXPaySignatureCertificateUtil.checkSign();
                //app下单
                HttpPost httpPost = new HttpPost(WXPayConstants.DOMAIN_API+WXPayConstants.PAY_TRANSACTIONS_APP);
                httpPost.addHeader("Accept", "application/json");
                httpPost.addHeader("Content-type", "application/json; charset=utf-8");
                ByteArrayOutputStream bos = new ByteArrayOutputStream();
                ObjectMapper objectMapper = new ObjectMapper();
                ObjectNode rootNode = objectMapper.createObjectNode();
                 rootNode.put("mchid", "商户id")
                        .put("appid", "APPID")
                        .put("out_trade_no", "订单号");
                        .put("description","描述")
                        .put("notify_url", WXPayConstants.WECHAT_PAY_NOTIFY_URL);
                rootNode.putObject("amount")
                        .put("total",money);
                rootNode.putObject("payer")
                        .put("openid","openid");
                objectMapper.writeValue(bos, rootNode);

                httpPost.setEntity(new StringEntity(bos.toString("UTF-8"), "UTF-8"));
                //完成签名并执行请求
                CloseableHttpResponse response = httpClient.execute(httpPost);
                //获取返回状态
                int statusCode = response.getStatusLine().getStatusCode();
                if (statusCode == 200) { //处理成功
                    String result = EntityUtils.toString(response.getEntity(), "UTF-8");
                    JSONObject object = JSONObject.parseObject(result);
                    //获取预付单
                    String prepayId = object.getString("prepay_id");
                    //生成签名
                    Long timestamp = System.currentTimeMillis() / 1000;
                    //随机字符串
                    //该方法org.apache.commons.lang3.RandomStringUtils依赖自带随机生成字符串 RandomStringUtils.randomAlphanumeric(32) 代表生成32位
                    String nonceStr = RandomStringUtils.randomAlphanumeric(32);
                    Map<String, String> param = new HashMap<>();
                   //生成带签名支付信息
                    String paySign = WXPaySignatureCertificateUtil.jsApiPaySign(String.valueOf(timestamp), nonceStr, prepayId);
                    Map<String, String> param = new HashMap<>();
                    param.put("package", "prepay_id="+prepayId);
                    param.put("noncestr", nonceStr);
                    param.put("timestamp", String.valueOf(timestamp));
                    param.put("paySign", paySign);
                    param.put("signType", RSA);
                    map.put("code",200);
                    map.put("message", "下单成功");
                    map.put("data", param);
                    return map;
                }
                    map.put("code",200);
                    map.put("message", "下单失败");
                    map.put("data", response);
                    return map;
            } catch (Exception e) {
                e.printStackTrace();
            }
    }


    /**
     * 微信支付回调通知
     * @return
     */
    @Override
    public Map<String, Object> weChatNotificationHandler(HttpServletRequest request, HttpServletResponse response){
        Map<String,Object> map = new HashMap<>();
        try {
            BufferedReader br = request.getReader();
            String str = null;
            StringBuilder sb = new StringBuilder();
            while ((str = br.readLine())!=null) {
                sb.append(str);
            }
            // 构建request,传入必要参数
            NotificationRequest requests = new NotificationRequest.Builder()
                    .withSerialNumber(request.getHeader("Wechatpay-Serial"))
                    .withNonce(request.getHeader("Wechatpay-Nonce"))
                    .withTimestamp(request.getHeader("Wechatpay-Timestamp"))
                    .withSignature(request.getHeader("Wechatpay-Signature"))
                    .withBody(String.valueOf(sb))
                    .build();
            //验签
            NotificationHandler handler = new NotificationHandler(WXPaySignatureCertificateUtil.getVerifier(), WxV3PayConfig.apiV3Key.getBytes(StandardCharsets.UTF_8));
            //解析请求体
            Notification notification = handler.parse(requests);
            String decryptData = notification.getDecryptData();
            //解析
            JSONObject jsonObject = JSONObject.parseObject(decryptData);
            //支付状态交易状态,枚举值: SUCCESS:支付成功 REFUND:转入退款 NOTPAY:未支付 CLOSED:已关闭 REVOKED:已撤销(付款码支付)
            // USERPAYING:用户支付中(付款码支付) PAYERROR:支付失败(其他原因,如银行返回失败)
            String trade_state = String.valueOf(jsonObject.get("trade_state"));
            if (trade_state.equals("SUCCESS")) {
                //订单号
                String orderNumber = String.valueOf(jsonObject.get("out_trade_no"));
                //微信支付微信生成的订单号
                String transactionId = String.valueOf(jsonObject.get("transaction_id"));
                //省略查询订单
                //此处处理业务
                    map.put("code",SUCCESS);
                    map.put("message","成功");
                    //消息推送成功
                    return map;
                }
                map.put("code",RESOURCE_NOT_EXISTS);
                map.put("message", "订单不存在");
                return map;
            }catch (Exception e) {
            e.printStackTrace();
        }
        map.put("code",FAIL);
        map.put("message", "失败");
        return map;
    }

 /**
     * 微信退款
     * @param outTradeNo 订单号
     * @return
     */
    @Override
    public Map<String, Object> weChatRefunds(String outTradeNo) {
        Map<String,Object> map = new HashMap<>();
        //退款总金额
        BigDecimal totalPrice = BigDecimal.ZERO;
        totalPrice = totalPrice.add(BigDecimal.valueOf(600));
        //转换金额
        Integer money=new BigDecimal(String.valueOf(totalPrice)).movePointRight(2).intValue();
        
        try {
            //验证证书
             CloseableHttpClient httpClient = WXPaySignatureCertificateUtil.checkSign();
            //申请退款接口
            HttpPost httpPost = new HttpPost(WXPayConstants.DOMAIN_API+WXPayConstants.REFUND_DOMESTIC_REFUNDS);
            httpPost.addHeader("Accept", "application/json");
            httpPost.addHeader("Content-type","application/json; charset=utf-8");
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            ObjectMapper objectMapper = new ObjectMapper();
            ObjectNode rootNode = objectMapper.createObjectNode();
            //微信支付订单号
            rootNode.put("transaction_id", "微信支付订单号")
                    //退款订单号
                    .put("out_refund_no","生成退款订单号")
                    .put("notify_url","退款回调");
                    //退款金额
            rootNode.putObject("amount")
                    .put("refund", "100.00")
                    //原订单金额
                    .put("total", "100.00")
                    .put("currency","CNY");
            objectMapper.writeValue(bos, rootNode);
            httpPost.setEntity(new StringEntity(bos.toString("UTF-8"), "UTF-8"));
            CloseableHttpResponse response = httpClient.execute(httpPost);
            //退款成功返回消息
            String bodyAsString = EntityUtils.toString(response.getEntity());
            JSONObject jsonObject = JSONObject.parseObject(bodyAsString);
            if (jsonObject.get("status").equals("SUCCESS") || jsonObject.get("status").equals("PROCESSING")) {
                //code返回
                map.put("code",200);
                map.put("message", "退款成功");
                return map;
            }
        }catch (Exception e) {
            e.printStackTrace();
        }
        map.put("code",500);
        map.put("message", "申请退款失败!");
        map.put("data", jsonObject);
        return map;
    }

    /**
     * 申请退款回调
     * @param request
     * @return
     */
    @Override
    public Map<String,Object> weChatPayRefundsNotify(HttpServletRequest request) {
        Map<String,Object> map = new HashMap<>();
        try {
            BufferedReader br = request.getReader();
            String str = null;
            StringBuilder sb = new StringBuilder();
            while ((str = br.readLine())!=null) {
                sb.append(str);
            }
            // 构建request,传入必要参数
            NotificationRequest requests = new NotificationRequest.Builder()
                    .withSerialNumber(request.getHeader("Wechatpay-Serial"))
                    .withNonce(request.getHeader("Wechatpay-Nonce"))
                    .withTimestamp(request.getHeader("Wechatpay-Timestamp"))
                    .withSignature(request.getHeader("Wechatpay-Signature"))
                    .withBody(String.valueOf(sb))
                    .build();
            //验签
            NotificationHandler handler = new NotificationHandler(WXPaySignatureCertificateUtil.getVerifier(), WxV3PayConfig.apiV3Key.getBytes(StandardCharsets.UTF_8));
            //解析请求体
            Notification notification = handler.parse(requests);
            String decryptData = notification.getDecryptData();
            //解析
            JSONObject jsonObject = JSONObject.parseObject(decryptData);
            String refund_status = String.valueOf(jsonObject.get("refund_status"));
            if (refund_status.equals("SUCCESS")) {
                //订单号
                String orderNumber = String.valueOf(jsonObject.get("out_trade_no"));
                //微信支付订单号
                String transactionId = String.valueOf(jsonObject.get("transaction_id"));

                //这里是处理业务逻辑
                
                
                //code 退款码请前往微信支付文档查询
                map.put("code","RESOURCE_NOT_EXISTS");
                map.put("message", "订单不存在");
                return map;
            }
        }catch (Exception e) {
            e.printStackTrace();
        }
        map.put("code","USER_ACCOUNT_ABNORMAL");
        map.put("message", "退款请求失败");
        return map;
    }

}

代码可复制粘贴使用 无业务逻辑代码 支付代码简洁

修改方式 根据官方文档返回参数类型为准

你学废了吗?

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 11
    评论
Quartz是OpenSymphony开源组织在Job scheduling领域又一个开源项目,它可以与J2EE与J2SE应用程序相结合也可以单独使用。Quartz可以用来创建简单或为运行十个,百个,甚至是好几万个Jobs这样复杂的程序。Jobs可以做成标准的Java组件或 EJBs。 Quartz的优势: 1、Quartz是一个任务调度框架(库),它几乎可以集成到任何应用系统中。 2、Quartz是非常灵活的,它让您能够以最“自然”的方式来编写您的项目的代码,实现您所期望的行为 3、Quartz是非常轻量的,只需要非常少的配置 —— 它实际上可以被跳出框架来使用,如果你的需求是一些相对基本的简单的需求的话。 4、Quartz具有容错机制,并且可以在重启服务的时候持久化(”记忆”)你的定时任务,你的任务也不会丢失。 5、可以通过Quartz,封装成自己的分布式任务调度,实现强大的功能,成为自己的产品。6、有很多的互联网公司也都在使用Quartz。比如美团 Spring是一个很优秀的框架,它无缝的集成了Quartz,简单方便的让企业应用更好的使用Quartz进行任务的调度。   课程说明:在我们的日常开发中,各种大型系统的开发少不了任务调度,简单的单机任务调度已经满足不了我们的系统需求,复杂的任务会让程序猿头疼, 所以急需一套专门的框架帮助我们去管理定时任务,并且可以在多台机器去执行我们的任务,还要可以管理我们的分布式定时任务。本课程从Quartz框架讲起,由浅到深,从使用到结构分析,再到源码分析,深入解析Quartz、Spring+Quartz,并且会讲解相关原理, 让大家充分的理解这个框架和框架的设计思想。由于互联网的复杂性,为了满足我们特定的需求,需要对Spring+Quartz进行二次开发,整个二次开发过程都会进行讲解。Spring被用在了越来越多的项目中, Quartz也被公认为是比较好用的定时器设置工具,学完这个课程后,不仅仅可以熟练掌握分布式定时任务,还可以深入理解大型框架的设计思想。
[入门数据分析的第一堂课]这是一门为数据分析小白量身打造的课程,你从网络或者公众号收集到很多关于数据分析的知识,但是它们零散不成体系,所以第一堂课首要目标是为你介绍:Ø  什么是数据分析-知其然才知其所以然Ø  为什么要学数据分析-有目标才有动力Ø  数据分析的学习路线-有方向走得更快Ø  数据分析的模型-分析之道,快速形成分析思路Ø  应用案例及场景-分析之术,掌握分析方法[哪些同学适合学习这门课程]想要转行做数据分析师的,零基础亦可工作中需要数据分析技能的,例如运营、产品等对数据分析感兴趣,想要更多了解的[你的收获]n  会为你介绍数据分析的基本情况,为你展现数据分析的全貌。让你清楚知道自己该如何在数据分析地图上行走n  会为你介绍数据分析的分析方法和模型。这部分是讲数据分析的道,只有学会底层逻辑,能够在面对问题时有自己的想法,才能够下一步采取行动n  会为你介绍数据分析的数据处理和常用分析方法。这篇是讲数据分析的术,先有道,后而用术来实现你的想法,得出最终的结论。n  会为你介绍数据分析的应用。学到这里,你对数据分析已经有了初步的认识,并通过一些案例为你展现真实的应用。[专享增值服务]1:一对一答疑         关于课程问题可以通过微信直接询问老师,获得老师的一对一答疑2:转行问题解答         在转行的过程中的相关问题都可以询问老师,可获得一对一咨询机会3:打包资料分享         15本数据分析相关的电子书,一次获得终身学习
Java 实现微信小程序 V3 版本的支付需要依赖微信支付 V3 版本的 Java SDK。具体实现步骤如下: 1. 引入微信支付 V3 版本的 Java SDK。 ``` <dependency> <groupId>com.github.wechatpay-apiv3</groupId> <artifactId>wechatpay-apiv3-sdk</artifactId> <version>1.1.0</version> </dependency> ``` 2. 构建微信支付 V3 版本的配置信息。 ``` WechatPayConfig config = new WechatPayConfig.Builder() .appId("微信小程序的 AppID") .mchId("商户号") .apiKey("API 密钥") .certSerialNo("API 证书序列号") .privateKey("API 密钥对应的私钥") .build(); ``` 3. 构建微信支付 V3 版本的 API 客户端。 ``` WechatPayHttpClientBuilder builder = WechatPayHttpClientBuilder.create() .withMerchant(config); WechatPayHttpClient client = builder.build(); ``` 4. 构建微信支付 V3 版本的请求参数。 ``` WxPayNativeOrderRequest request = new WxPayNativeOrderRequest(); request.setAppid("微信小程序的 AppID"); request.setMchid("商户号"); request.setOutTradeNo("商户订单号"); request.setTotal("订单总金额"); request.setDescription("订单描述"); request.setNotifyUrl("支付回调地址"); ``` 5. 调用微信支付 V3 版本的 API 完成支付。 ``` WxPayNativeOrderResult result = client.execute(request); ``` 需要注意的是,微信支付 V3 版本的 API 接口和参数有所变化,需要根据官方文档进行调整。同时,需要在微信支付后台配置小程序支付回调地址,并保证服务器能够正常接收和处理支付回调信息。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值