微信支付V3 小程序 APP JSAP 基本都是一样的就下单传的参数不一样 直接copy就能用,除了下单不一样 其他方法app 小程序等基本上都是一样的

maven

<dependency>
    <groupId>com.github.wechatpay-apiv3</groupId>
    <artifactId>wechatpay-apache-httpclient</artifactId>
    <version>0.4.9</version>
</dependency>

controller  

/**
 * 微信支付回调
 */
@PostMapping(value = "weChartPayBack/{userType}")
@SkipLoginVerify
@NoBindingFilter  //这个注解是用来不走过滤器的,不然body会验签失败
public String weChartPayBack(@PathVariable("userType") String userType, HttpServletRequest request, HttpServletResponse response) {
    Map<String, Object> map = weChatService.weChatCallback(request, response, userType,"payment");
    return new Gson().toJson(map);

}


/**
 * 微信支付退款回调
 */
@PostMapping(value = "weChartRefundBack/{userType}")
@SkipLoginVerify
@NoBindingFilter
public String weChartRefundBack(@PathVariable("userType") String userType, HttpServletRequest request, HttpServletResponse response) {
    Map<String, Object>  map = weChatService.weChatCallback(request, response, userType,"refund");
    return new Gson().toJson(map);
}

service 需要自己改一下逻辑,微信支付一块基本上没问题 订单逻辑需要自己更改

package com.yilin.platform.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
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.Verifier;
import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Credentials;
import com.wechat.pay.contrib.apache.httpclient.cert.CertificatesManager;
import com.wechat.pay.contrib.apache.httpclient.exception.NotFoundException;
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 com.wechat.pay.contrib.apache.httpclient.util.PemUtil;
import com.yilin.platform.base_core.application.MathUtil;
import com.yilin.platform.base_core.commons.exception.BusinessException;
import com.yilin.platform.base_core.commons.utils.*;
import com.yilin.platform.base_core.tools.wechat.WeChatConfig;
import com.yilin.platform.base_core.tools.wechat.WeChatUtils;
import com.yilin.platform.entity.capital.TradeFlow;
import com.yilin.platform.entity.user.AccountConfigure;
import com.yilin.platform.entity.weChat.WeChatTradeRecord;
import com.yilin.platform.mapper.weChat.WeChatTradeRecordMapper;
import com.yilin.platform.service.IWeChatService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Service
public class WeChatService extends ServiceImpl<WeChatTradeRecordMapper, WeChatTradeRecord> implements IWeChatService {
    private Logger logger = LoggerFactory.getLogger(WeChatService.class);
    @Resource
    private WeChatConfig weChatConfig;
    @Resource
    private WeChatTradeRecordMapper weChatTradeRecordMapper;
    @Resource
    private UserService userService;
    @Resource
    private TradeFlowService tradeFlowService;

    /*微信app下单*/
    @Override
    public Map<String, Object> wxChartAppTransactions(WeChatTradeRecord weChatTradeRecord) {
        Map<String, Object> amountJson = new HashMap<>();
        Integer amt = new BigDecimal(String.valueOf(weChatTradeRecord.getTranAmount())).multiply(new BigDecimal("100")).setScale(0, RoundingMode.HALF_EVEN).intValue();
        amountJson.put("total", amt);
        amountJson.put("currency", "CNY");
        Map<String, Object> param = new HashMap<>();
        String userType = String.valueOf(weChatTradeRecord.getUserType());
        param.put("appid", weChatConfig.getAppId(userType));
        param.put("mchid", weChatConfig.getMchId(userType));
        param.put("description", weChatTradeRecord.getTradeName());
        param.put("out_trade_no", weChatTradeRecord.getTradeNo());
        param.put("notify_url", weChatConfig.getCallbackUrl() + "/platform/weChat/weChartPayBack/" + userType);
        param.put("amount", amountJson);
        try {
            logger.info("微信app支付请求数据" + new Gson().toJson(param));
            Map<String, Object> response = WeChatUtils.weChatV3Post(weChatConfig, userType, param, "https://api.mch.weixin.qq.com/v3/pay/transactions/app");
            logger.info("微信app支付返回数据" + new Gson().toJson(response));
            weChatTradeRecord.setWeChatTradeStatus(WeChatTradeRecord.WeChatTradeStatus.handle);
            weChatTradeRecord.setInitiateTime(new Date());
            weChatTradeRecord.setWeChatTradeType(WeChatTradeRecord.WeChatTradeType.payment);
            weChatTradeRecord.setWeChatType(WeChatTradeRecord.WeChatType.app);
            weChatTradeRecord.setQueryWaitCount(0);
            weChatTradeRecord.setSyncTaskCount(0);
            weChatTradeRecord.setNextWaitTime(new Date());
            weChatTradeRecord.setNextNotificationTime(new Date());
            saveOrUpdate(weChatTradeRecord);
            String timestamp = System.currentTimeMillis() / 1000 + "";  //时间戳
            String nonceStr = UUID.randomUUID().toString().replace("-", ""); //随机串
            String sign = WeChatUtils.getSign(nonceStr, timestamp, new Gson().toJson(param), weChatConfig.getPrivateKeyUrl(userType), "GET");
            Map<String, Object> map = new HashMap<>();
            map.put("prepayid", response.get("prepay_id"));
            map.put("timestamp", timestamp);
            map.put("noncestr", nonceStr);
            map.put("sign", sign);
            map.put("appid", weChatConfig.getAppId(userType));
            map.put("package", "Sign=WXPay");
            map.put("partnerid", weChatConfig.getMchId(userType));
            map.put("universalLink", weChatConfig.getUniversalLink(userType));//用于唤起APP
            return map;
        } catch (Exception e) {
            logger.info("微信支付APP发起支付异常" + e.getMessage());
            throw new BusinessException("微信支付APP发起支付异常" + e.getMessage());
        }
    }

    /*微信app下单*/
    @Override
    public Map<String, Object> wxChartAppTransactionsH5(WeChatTradeRecord weChatTradeRecord) {
        Map<String, Object> amountJson = new HashMap<>();
        Integer amt = new BigDecimal(String.valueOf(weChatTradeRecord.getTranAmount())).multiply(new BigDecimal("100")).setScale(0, RoundingMode.HALF_EVEN).intValue();
        amountJson.put("total", amt);
        amountJson.put("currency", "CNY");
        Map<String, Object> param = new HashMap<>();
        String userType = String.valueOf(weChatTradeRecord.getUserType());
        param.put("appid", weChatConfig.getAppId(userType));
        param.put("mchid", weChatConfig.getMchId(userType));
        param.put("description", weChatTradeRecord.getTradeName());
        param.put("out_trade_no", weChatTradeRecord.getTradeNo());
        param.put("notify_url", weChatConfig.getCallbackUrl() + "/platform/weChat/weChartPayBack/" + userType);
        param.put("amount", amountJson);
        try {
            logger.info("微信H5支付请求数据" + new Gson().toJson(param));
            Map<String, Object> response = WeChatUtils.weChatV3Post(weChatConfig, userType, param, "https://api.mch.weixin.qq.com/v3/pay/transactions/native");
            logger.info("微信H5支付返回数据" + new Gson().toJson(response));
            weChatTradeRecord.setWeChatTradeStatus(WeChatTradeRecord.WeChatTradeStatus.handle);
            weChatTradeRecord.setWeChatTradeType(WeChatTradeRecord.WeChatTradeType.payment);
            weChatTradeRecord.setInitiateTime(new Date());
            weChatTradeRecord.setWeChatType(WeChatTradeRecord.WeChatType.app);
            weChatTradeRecord.setQueryWaitCount(0);
            weChatTradeRecord.setSyncTaskCount(0);
            weChatTradeRecord.setNextWaitTime(new Date());
            weChatTradeRecord.setNextNotificationTime(new Date());
            saveOrUpdate(weChatTradeRecord);
            Map<String, Object> map = new HashMap<>();
            map.put("code_url", response.get("code_url"));
            return map;
        } catch (Exception e) {
            logger.error("微信支付H5发起支付异常" + e.getMessage());
            throw new BusinessException("微信支付H5发起支付异常" + e.getMessage());
        }
    }

    /*微信app支付查询
     * 备注:调这个方法之后需要掉用订单通知接口
     * */
    @Override
    public WeChatTradeRecord wxChartAppQueryTransactions(String tradeNo) {
        try {
            WeChatTradeRecord weChatTradeRecord = getWeChatTradeRecordByTradeNo(tradeNo);
            ParamUtil.isNull(weChatTradeRecord, "获支付单为null");
            String userType = String.valueOf(weChatTradeRecord.getUserType());
            String url = "https://api.mch.weixin.qq.com/v3/pay/transactions/out-trade-no/" + weChatTradeRecord.getTradeNo() + "?mchid=" + weChatConfig.getMchId(userType);
            logger.info("微信app支付查询请求数据" + new Gson().toJson(url));
            Map<String, Object> response = WeChatUtils.weChatV3Get(weChatConfig, userType, url);
            logger.info("微信app支付查询返回数据" + new Gson().toJson(response));
            String state = MapUtil.getMapString(response, "trade_state");
            if (MapUtil.getMapString(response, "transaction_id") != null)
                weChatTradeRecord.setBankFlowNo(MapUtil.getMapString(response, "transaction_id"));
            if (MapUtil.getMapString(response, "trade_state_desc") != null && weChatTradeRecord.getRemark() == null)
                weChatTradeRecord.setRemark(MapUtil.getMapString(response, "trade_state_desc"));
            if (MapUtil.getMapString(response, "success_time") != null)
                weChatTradeRecord.setCompleteTime(DateTimeUtil.wxStringToDate(MapUtil.getMapString(response, "success_time"), null));
            Map<String, Object> payer = (Map<String, Object>) response.get("payer");
            if (weChatTradeRecord.getOutAcctNo() == null)
                weChatTradeRecord.setOutAcctNo(MapUtil.getMapString(payer, "openid"));
            if (weChatTradeRecord.getInAcctNo() == null) weChatTradeRecord.setInAcctNo(weChatConfig.getMchId(userType));
            if (state.equals("SUCCESS") || state.equals("REFUND")) {
                weChatTradeRecord.setWeChatTradeStatus(WeChatTradeRecord.WeChatTradeStatus.success);
            } else if (state.equals("CLOSED")) {
                weChatTradeRecord.setWeChatTradeStatus(WeChatTradeRecord.WeChatTradeStatus.close);
            } else if (state.equals("PAYERROR")) {
                weChatTradeRecord.setWeChatTradeStatus(WeChatTradeRecord.WeChatTradeStatus.fail);
            } else if (state.equals("NOTPAY")) {
                weChatTradeRecord.setWeChatTradeStatus(WeChatTradeRecord.WeChatTradeStatus.notpay);
            } else {
                weChatTradeRecord.setWeChatTradeStatus(WeChatTradeRecord.WeChatTradeStatus.handle);
            }
            saveTradeFlow(weChatTradeRecord.getTradeName(), weChatTradeRecord);
            saveOrUpdate(weChatTradeRecord);
            return weChatTradeRecord;
        } catch (Exception e) {
            logger.error("微信支付APP支付查询异常" + e.getMessage());
            throw new BusinessException("微信支付APP支付查询异常" + e.getMessage());
        }
    }

    /*微信app发起退款*/
    @Override
    public WeChatTradeRecord wxChartAppRefund(WeChatTradeRecord weChatTradeRecord, WeChatTradeRecord tradeRecordOrgin) {
        try {
            Map<String, Object> amountJson = new HashMap<>();
            amountJson.put("refund", CommonUtil.intValue(MathUtil.multiply(weChatTradeRecord.getTranAmount(), 100D)));
            amountJson.put("total", CommonUtil.intValue(MathUtil.multiply(tradeRecordOrgin.getTranAmount(), 100D)));
            amountJson.put("currency", "CNY");
            String userType = String.valueOf(weChatTradeRecord.getUserType());
            Map<String, Object> param = MapUtil.generate(map -> {
                map.put("out_trade_no", tradeRecordOrgin.getTradeNo());
                map.put("out_refund_no", weChatTradeRecord.getTradeNo());
                map.put("reason", weChatTradeRecord.getRemark());
                map.put("notify_url", weChatConfig.getCallbackUrl() + "/platform/weChat/weChartPayBack/" + userType);
                map.put("amount", amountJson);
            });
            logger.info("微信app支付退款请求数据" + new Gson().toJson(param));
            Map<String, Object> response = WeChatUtils.weChatV3Post(weChatConfig, userType, param, "https://api.mch.weixin.qq.com/v3/refund/domestic/refunds");
            logger.info("微信app支付退款返回数据" + new Gson().toJson(response));
            String state = MapUtil.getMapString(response, "status");
            weChatTradeRecord.setBankFlowNo(MapUtil.getMapString(response, "refund_id"));
            weChatTradeRecord.setWeChatTradeType(WeChatTradeRecord.WeChatTradeType.refund);
            weChatTradeRecord.setUserType(tradeRecordOrgin.getUserType());
            if (weChatTradeRecord.getOutAcctNo() == null)
                weChatTradeRecord.setOutAcctName(tradeRecordOrgin.getInAcctNo());
            if (weChatTradeRecord.getInAcctNo() == null) weChatTradeRecord.setInAcctNo(tradeRecordOrgin.getOutAcctNo());
            if (state.equals("SUCCESS")) {
                weChatTradeRecord.setWeChatTradeStatus(WeChatTradeRecord.WeChatTradeStatus.success);
                weChatTradeRecord.setBankMsg(MapUtil.getMapString(response, "user_received_account"));
            } else if (state.equals("CLOSED")) {
                weChatTradeRecord.setWeChatTradeStatus(WeChatTradeRecord.WeChatTradeStatus.close);
            } else if (state.equals("ABNORMAL")) {
                weChatTradeRecord.setWeChatTradeStatus(WeChatTradeRecord.WeChatTradeStatus.fail);
            } else {
                weChatTradeRecord.setWeChatTradeStatus(WeChatTradeRecord.WeChatTradeStatus.handle);
            }
            weChatTradeRecord.setQueryWaitCount(0);
            weChatTradeRecord.setSyncTaskCount(0);
            weChatTradeRecord.setNextWaitTime(new Date());
            weChatTradeRecord.setNextNotificationTime(new Date());
            saveOrUpdate(weChatTradeRecord);
            return weChatTradeRecord;
        } catch (Exception e) {
            logger.error("微信支付APP发起退款异常" + e.getMessage());
            throw new BusinessException("微信支付APP发起退款异常" + e.getMessage());
        }
    }

    //公共: 保存流水
    private void saveTradeFlow(String tradeName, WeChatTradeRecord weChatTradeRecord) {
        if (weChatTradeRecord.getWeChatTradeStatus() != WeChatTradeRecord.WeChatTradeStatus.success) return;
        TradeFlow[] tradeFlows = tradeFlowService.generateTradeFlows(tradeName, TradeFlow.PayType.weixin, weChatTradeRecord);
        tradeFlowService.saveOrUpdateBatch(ArrayUtil.initList(tradeFlows));
    }

    /*微信app退款查询
     * 备注:调这个方法之后需要掉用订单通知接口
     * */
    @Override
    public WeChatTradeRecord wxChartAppQueryRefund(String tradeNo) {
        try {
            WeChatTradeRecord weChatTradeRecord = getWeChatTradeRecordByTradeNo(tradeNo);
            String userType = String.valueOf(weChatTradeRecord.getUserType());
            ParamUtil.isNull(weChatTradeRecord, "获支付单为null");
            String url = "https://api.mch.weixin.qq.com/v3/refund/domestic/refunds/" + weChatTradeRecord.getTradeNo();
            logger.info("微信app支付退款查询请求数据" + new Gson().toJson(url));
            Map<String, Object> response = WeChatUtils.weChatV3Get(weChatConfig, userType, url);
            logger.info("微信app支付退款查询返回数据" + new Gson().toJson(response));
            String state = MapUtil.getMapString(response, "status");
            if (MapUtil.getMapString(response, "transaction_id") != null)
                weChatTradeRecord.setBankFlowNo(MapUtil.getMapString(response, "transaction_id"));
            if (MapUtil.getMapString(response, "success_time") != null)
                weChatTradeRecord.setCompleteTime(DateTimeUtil.wxStringToDate(MapUtil.getMapString(response, "success_time"), null));
            if (state.equals("SUCCESS")) {
                weChatTradeRecord.setWeChatTradeStatus(WeChatTradeRecord.WeChatTradeStatus.success);
                weChatTradeRecord.setBankMsg(MapUtil.getMapString(response, "user_received_account"));
                saveTradeFlow(weChatTradeRecord.getTradeName(), weChatTradeRecord);
            } else if (state.equals("CLOSED")) {
                weChatTradeRecord.setWeChatTradeStatus(WeChatTradeRecord.WeChatTradeStatus.close);
            } else if (state.equals("ABNORMAL")) {
                weChatTradeRecord.setWeChatTradeStatus(WeChatTradeRecord.WeChatTradeStatus.fail);
            } else {
                weChatTradeRecord.setWeChatTradeStatus(WeChatTradeRecord.WeChatTradeStatus.handle);
            }
            saveOrUpdate(weChatTradeRecord);
            return weChatTradeRecord;
        } catch (Exception e) {
            logger.error("微信支付APP查询退款异常" + e.getMessage());
            throw new BusinessException("微信支付APP查询退款异常" + e.getMessage());
        }
    }



    @Override
    public Map<String, Object> weChatCallback(HttpServletRequest request, HttpServletResponse response, String userType, String type) {
        Map<String, Object> map = new HashMap<>();
        try {
            String body = readData(request);
            logger.info("微信支付付款回调数据" + body);
            String nonce = request.getHeader("Wechatpay-Nonce");  //随机串
            String signature = request.getHeader("Wechatpay-Signature");   //微信传递过来的签名
            String wechatPaySerial = request.getHeader("Wechatpay-Serial");  //证书序列号(微信平台)
            String timestamp = request.getHeader("Wechatpay-Timestamp"); //时间戳
            String mchId = weChatConfig.getMchId(userType);
            String privateKey = weChatConfig.getPrivateKeyUrl(userType);
            String serialNo = weChatConfig.getSerialNo(userType);
            String apiV3Key = weChatConfig.getApiV3Key(userType);
            PrivateKey merchantPrivateKey = PemUtil.loadPrivateKey(Files.newInputStream(Paths.get(privateKey)));
            // 获取证书管理器实例
            CertificatesManager certificatesManager = CertificatesManager.getInstance();
            // 向证书管理器增加需要自动更新平台证书的商户信息
            certificatesManager.putMerchant(mchId, new WechatPay2Credentials(mchId,
                            new PrivateKeySigner(serialNo, merchantPrivateKey)),
                    apiV3Key.getBytes(StandardCharsets.UTF_8));
            Verifier verifier = certificatesManager.getVerifier(mchId);
            NotificationRequest notificationRequest = new NotificationRequest.Builder().withSerialNumber(wechatPaySerial)
                    .withNonce(nonce)
                    .withTimestamp(timestamp)
                    .withSignature(signature)
                    .withBody(body)
                    .build();
            // 这个解析器是微信支付SDK里的,他会帮我们做验签等一系列的事,不需要我们去做
            NotificationHandler handler = new NotificationHandler(verifier, apiV3Key.getBytes(StandardCharsets.UTF_8));
            Notification notification = handler.parse(notificationRequest);
            String decryptData = notification.getDecryptData();
            JSONObject jsonObject = JSONObject.parseObject(decryptData);

            if (type.equals("payment")) {
                map = wxCallPay(jsonObject, mchId);
            } else if (type.equals("refund")) {
                map = wxCallPayRefund(jsonObject);
            } else {
                throw new BusinessException("回调地址错误平地址" + type);
            }
        } catch (Exception e) {
            map.put("code", "FAIL");
            map.put("message", "失败");
            logger.info("微信APP支付" + (type.equals("payment") ? "支付" : "退款") + "回调异常请检查:" + e.getMessage());
        }
        return map;
    }
    /*微信支付回调*/
    public Map<String, Object> wxCallPay(JSONObject jsonObject, String mchId) {
        Map<String, Object> map = new HashMap<>();
        String state = String.valueOf(jsonObject.get("trade_state"));
        String orderNumber = String.valueOf(jsonObject.get("out_trade_no"));
        WeChatTradeRecord weChatTradeRecord = getWeChatTradeRecordByTradeNo(orderNumber);
        if (weChatTradeRecord.getRemark() == null)
            weChatTradeRecord.setRemark(String.valueOf(jsonObject.get("attach")));
        weChatTradeRecord.setBankFlowNo(String.valueOf(jsonObject.get("transaction_id")));
        weChatTradeRecord.setCompleteTime(DateTimeUtil.wxStringToDate(String.valueOf(jsonObject.get("success_time")), null));
        Map<String, Object> payer = (Map<String, Object>) jsonObject.get("payer");
        if (weChatTradeRecord.getOutAcctNo() == null)
            weChatTradeRecord.setOutAcctNo(MapUtil.getMapString(payer, "openid"));
        if (weChatTradeRecord.getInAcctNo() == null) weChatTradeRecord.setInAcctNo(mchId);
        if (state.equals("SUCCESS") || state.equals("REFUND")) {
            weChatTradeRecord.setWeChatTradeStatus(WeChatTradeRecord.WeChatTradeStatus.success);
        } else if (state.equals("CLOSED")) {
            weChatTradeRecord.setWeChatTradeStatus(WeChatTradeRecord.WeChatTradeStatus.close);
        } else if (state.equals("PAYERROR")) {
            weChatTradeRecord.setWeChatTradeStatus(WeChatTradeRecord.WeChatTradeStatus.fail);
        } else if (state.equals("NOTPAY")) {
            weChatTradeRecord.setWeChatTradeStatus(WeChatTradeRecord.WeChatTradeStatus.notpay);
        } else {
            weChatTradeRecord.setWeChatTradeStatus(WeChatTradeRecord.WeChatTradeStatus.handle);
        }
        try {
            saveTradeFlow(weChatTradeRecord.getTradeName(), weChatTradeRecord);
        } catch (Exception e) {
            logger.error("微信支付退款回调通知保存流水失败" + e.getMessage());
        }
        try {
            if (weChatTradeRecord.getWeChatTradeStatus() != WeChatTradeRecord.WeChatTradeStatus.create
                    && weChatTradeRecord.getWeChatTradeStatus() != WeChatTradeRecord.WeChatTradeStatus.handle
                    && weChatTradeRecord.getWeChatTradeStatus() != WeChatTradeRecord.WeChatTradeStatus.notpay) {
                processNotificationStatus(Collections.singletonList(weChatTradeRecord));
            }
        } catch (Exception e) {
            logger.error("微信支付回调通知失败" + e.getMessage());
        }
        map.put("code", "SUCCESS");
        map.put("message", "成功");
        return map;
    }

    /*微信退款回调*/
    public Map<String, Object> wxCallPayRefund(JSONObject jsonObject) {
        Map<String, Object> map = new HashMap<>();
        String state = String.valueOf(jsonObject.get("refund_status"));
        String orderNumber = String.valueOf(jsonObject.get("out_refund_no"));
        WeChatTradeRecord weChatTradeRecord = getWeChatTradeRecordByTradeNo(orderNumber);
        weChatTradeRecord.setBankFlowNo(String.valueOf(jsonObject.get("refund_id")));
        weChatTradeRecord.setCompleteTime(DateTimeUtil.wxStringToDate(String.valueOf(jsonObject.get("success_time")), null));
        if (state.equals("SUCCESS")) {
            weChatTradeRecord.setWeChatTradeStatus(WeChatTradeRecord.WeChatTradeStatus.success);
        } else if (state.equals("CLOSED")) {
            weChatTradeRecord.setWeChatTradeStatus(WeChatTradeRecord.WeChatTradeStatus.close);
        } else if (state.equals("ABNORMAL")) {
            weChatTradeRecord.setWeChatTradeStatus(WeChatTradeRecord.WeChatTradeStatus.fail);
        } else {
            weChatTradeRecord.setWeChatTradeStatus(WeChatTradeRecord.WeChatTradeStatus.handle);
        }
        try {
            saveTradeFlow(weChatTradeRecord.getTradeName(), weChatTradeRecord);
        } catch (Exception e) {
            logger.error("微信支付退款回调通知保存流水失败" + e.getMessage());
        }
        try {
            if (weChatTradeRecord.getWeChatTradeStatus() != WeChatTradeRecord.WeChatTradeStatus.create
                    && weChatTradeRecord.getWeChatTradeStatus() != WeChatTradeRecord.WeChatTradeStatus.handle
                    && weChatTradeRecord.getWeChatTradeStatus() != WeChatTradeRecord.WeChatTradeStatus.notpay) {
                processNotificationStatus(Collections.singletonList(weChatTradeRecord));
            }
        } catch (Exception e) {
            logger.error("微信支付退款回调通知失败" + e.getMessage());
        }
        map.put("code", "SUCCESS");
        map.put("message", "成功");
        return map;
    }


    @Override
    public WeChatTradeRecord getWeChatTradeRecordById(String tradeRecordId) {
        return weChatTradeRecordMapper.selectById(tradeRecordId);
    }

    @Override
    public WeChatTradeRecord getWeChatTradeRecordByTradeNo(String tradeNo) {
        QueryWrapper<WeChatTradeRecord> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("trade_no", tradeNo);
        queryWrapper.eq("is_deleted", 0);
        return weChatTradeRecordMapper.selectOne(queryWrapper);
    }

    @Override
    public List<WeChatTradeRecord> getNotificationList() {
        QueryWrapper<WeChatTradeRecord> queryWrapper = new QueryWrapper<>();
        queryWrapper.nested(i ->
                        i.or(j -> j.in("we_chat_trade_status", 3,5).le("next_wait_time", new Date()))
                                .or(j -> j.eq("we_chat_trade_status", 1).eq("notified_yilin", 0))
                                .or(j -> j.eq("we_chat_trade_status", 2).eq("notified_yilin", 0))
                                .or(j -> j.eq("we_chat_trade_status", 4).eq("notified_yilin", 0)))
                .eq("is_deleted", 0)
                .le("next_notification_time", new Date());
        return weChatTradeRecordMapper.selectList(queryWrapper);
    }

    @Override
    public void myTaskOneMinute() {
        List<WeChatTradeRecord> recordFlowList = getNotificationList();
        if (recordFlowList == null || recordFlowList.isEmpty()) return;
        List<WeChatTradeRecord> recordSuccess = new ArrayList<>();
        List<WeChatTradeRecord> recordHandle = new ArrayList<>();
        for (WeChatTradeRecord weChatTradeRecord : recordFlowList) {
            try {
                if (weChatTradeRecord.getWeChatTradeStatus() == WeChatTradeRecord.WeChatTradeStatus.handle) {
                    if (weChatTradeRecord.getWeChatTradeType() == WeChatTradeRecord.WeChatTradeType.payment) {
                        weChatTradeRecord = wxChartAppQueryTransactions(weChatTradeRecord.getTradeNo());
                    } else if (weChatTradeRecord.getWeChatTradeType() == WeChatTradeRecord.WeChatTradeType.payment) {
                        weChatTradeRecord = wxChartAppQueryRefund(weChatTradeRecord.getTradeNo());
                    }
                }
            } catch (Exception e) {
                logger.info("微信支付定时函数查询单笔转账异常:" + e.getMessage());
                weChatTradeRecord.setNextWaitTime(DateTimeUtil.getWeChataAliPayTime(new Date(), weChatTradeRecord.getQueryWaitCount()));
                weChatTradeRecord.setQueryWaitCount(weChatTradeRecord.getQueryWaitCount() + 1);
                recordHandle.add(weChatTradeRecord);
                continue;
            }
            if (weChatTradeRecord.getWeChatTradeStatus() != WeChatTradeRecord.WeChatTradeStatus.handle
                    &&weChatTradeRecord.getWeChatTradeStatus() != WeChatTradeRecord.WeChatTradeStatus.create
                    && weChatTradeRecord.getWeChatTradeStatus() != WeChatTradeRecord.WeChatTradeStatus.notpay)
                recordSuccess.add(weChatTradeRecord);
            else if(weChatTradeRecord.getWeChatTradeStatus() == WeChatTradeRecord.WeChatTradeStatus.handle|| weChatTradeRecord.getWeChatTradeStatus() == WeChatTradeRecord.WeChatTradeStatus.notpay) {
                weChatTradeRecord.setNextWaitTime(DateTimeUtil.getWeChataAliPayTime(new Date(), weChatTradeRecord.getQueryWaitCount()));
                weChatTradeRecord.setQueryWaitCount(weChatTradeRecord.getQueryWaitCount() + 1);
                recordHandle.add(weChatTradeRecord);
            }
        }
        if (!recordHandle.isEmpty()) saveOrUpdateBatch(recordHandle);
        if (!recordSuccess.isEmpty()) processNotificationStatus(recordSuccess);
    }
    @Override
    public void processNotificationStatus(List<WeChatTradeRecord> recordList) {
        if (!recordList.isEmpty()) {
            AccountConfigure accountConfigure = userService.getAccountConfigure();
            Map<String, Object> paramMap = MapUtil.generate(map -> {
                map.put("jsonResult", new Gson().toJson(recordList));
                map.put("apiKey", accountConfigure.getSafeKey());
            });
            String status = null;
            try {
                status = userService.request("/capital/callback/wePayResult", null, paramMap, new TypeToken<String>() {
                });
            } catch (Exception e) {
                for (WeChatTradeRecord recordFlow : recordList) {
                    recordFlow.setNextNotificationTime(DateTimeUtil.addTimeByCount(new Date(), recordFlow.getSyncTaskCount()));
                    recordFlow.setSyncTaskCount(recordFlow.getSyncTaskCount() + 1);
                }
                saveOrUpdateBatch(recordList);
                logger.error("微信通知支付订单失败:错误信息:" + e.getMessage());
                throw new BusinessException(e.getMessage());
            }
            if (status == null) return;
            for (WeChatTradeRecord recordFlow : recordList) {
                if (status.equals("SUCCESS")) {
                    recordFlow.setSyncTaskCount(0);
                    recordFlow.setNotifiedYilin(true);
                    recordFlow.setNotifyTime(new Date());
                } else {
                    recordFlow.setNextNotificationTime(DateTimeUtil.addTimeByCount(new Date(), recordFlow.getSyncTaskCount()));
                    recordFlow.setSyncTaskCount(recordFlow.getSyncTaskCount() + 1);
                }
            }
            saveOrUpdateBatch(recordList);
        }
    }
    public static String readData(HttpServletRequest request) {
        try (BufferedReader reader = request.getReader()) {
            String line;
            StringBuilder result = new StringBuilder();
            while ((line = reader.readLine()) != null) {
                if (result.length() > 0) {
                    result.append("\n");
                }
                result.append(line);
            }
            return result.toString();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

WeChatConfig    自己在yml里面配置 或者自己定义WeChatConfig

package com.yilin.platform.base_core.tools.wechat;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component
public class WeChatConfig {
    @Value("${we-chat-enterprise.callback-url}")
    private String callbackUrl;//回调地址
    private String mchId; //商户号
    private String appId; //ppid
    private String universalLink;//IOS跳转链接
    private String certFolderUrl; //微信SSL证书路径
    private String privateKeyUrl; //商户私钥路径
    private String serialNo;  //证书序列号

    private String apiV3Key;//apiV3秘钥

    @Value("${we-chat-enterprise.shipper-mchId}")
    private String shipperMchId; //商户号
    @Value("${we-chat-enterprise.shipper-appId}")
    private String shipperAppId; //Appid
    @Value("${we-chat-enterprise.shipper-universal-link}")
    private String shipperUniversalLink;//IOS跳转链接
    @Value("${we-chat-enterprise.shipper-cert-url}")
    private String shipperCertUrl; //微信SSL证书路径
    @Value("${we-chat-enterprise.shipper-serial-no}")
    private String shipperSerialNo;  //证书序列号
    @Value("${we-chat-enterprise.shipper-api-v3-key}")
    private String shipperApiV3Key;//apiV3秘钥
    @Value("${we-chat-enterprise.trucker-mchId}")
    private String truckerMchId;//商户号
    @Value("${we-chat-enterprise.trucker-appId}")
    private String truckerAppId;//Appid
    @Value("${we-chat-enterprise.trucker-universal-link}")
    private String truckerUniversalLink;//IOS跳转链接
    @Value("${we-chat-enterprise.trucker-cert-url}")
    private String truckCertUrl;//微信SSL证书路径
    @Value("${we-chat-enterprise.trucker-serial-no}")
    private String truckerSerialNo;  //证书序列号
    @Value("${we-chat-enterprise.trucker-api-v3-key}")
    private String truckerApiV3Key; //apiV3秘钥

    public String getCallbackUrl() {
        return callbackUrl;
    }

    public String getMchId(String userType) {
        if ("shipperUser".equals(userType)) {
            return this.shipperMchId;
        } else if ("truckerUser".equals(userType)) {
            return this.truckerMchId;
        } else {
            return null;
        }
    }

    public String getAppId(String userType) {
        if ("shipperUser".equals(userType)) {
            return this.shipperAppId;
        } else if ("truckerUser".equals(userType)) {
            return this.truckerAppId;
        } else {
            return null;
        }
    }

    public String getUniversalLink(String userType) {
        if ("shipperUser".equals(userType)) {
            return this.shipperUniversalLink;
        } else if ("truckerUser".equals(userType)) {
            return this.truckerUniversalLink;
        } else {
            return null;
        }
    }

    public String getCertFolderUrl(String userType) {
        if ("shipperUser".equals(userType)) {
            return this.shipperCertUrl+"\\apiclient_cert.pem";
        } else if ("truckerUser".equals(userType)) {
            return this.truckCertUrl+"\\apiclient_cert.pem";
        } else {
            return null;
        }
    }

    public String getPrivateKeyUrl(String userType) {
        if ("shipperUser".equals(userType)) {
            return this.shipperCertUrl+"\\apiclient_key.pem";
        } else if ("truckerUser".equals(userType)) {
            return this.truckCertUrl+"\\apiclient_key.pem";
        } else {
            return null;
        }
    }

    public String getSerialNo(String userType) {
        if ("shipperUser".equals(userType)) {
            return this.shipperSerialNo;
        } else if ("truckerUser".equals(userType)) {
            return this.truckerSerialNo;
        } else {
            return null;
        }
    }

    public String getApiV3Key(String userType) {
        if ("shipperUser".equals(userType)) {
            return this.shipperApiV3Key;
        } else if ("truckerUser".equals(userType)) {
            return this.truckerApiV3Key;
        } else {
            return null;
        }
    }
}

WeChatUtils

package com.yilin.platform.base_core.tools.wechat;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.wechat.pay.contrib.apache.httpclient.WechatPayHttpClientBuilder;
import com.wechat.pay.contrib.apache.httpclient.auth.PrivateKeySigner;
import com.wechat.pay.contrib.apache.httpclient.auth.Verifier;
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.cert.CertificatesManager;
import com.wechat.pay.contrib.apache.httpclient.exception.HttpCodeException;
import com.wechat.pay.contrib.apache.httpclient.exception.NotFoundException;
import com.wechat.pay.contrib.apache.httpclient.util.PemUtil;
import com.yilin.platform.base_core.application.AppUtil;
import com.yilin.platform.base_core.commons.exception.BusinessException;

import java.io.*;
import java.lang.reflect.Type;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.*;
import java.util.Base64;

import okhttp3.HttpUrl;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
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;

import java.util.HashMap;
import java.util.Map;

public class WeChatUtils {
    static HttpUrl httpurl = HttpUrl.parse("https://api.mch.weixin.qq.com/v3/certificates");
    private static CloseableHttpClient httpClient;
    private static CertificatesManager certificatesManager;
    private static Verifier verifier;
    /*微信支付POSt请求*/
    public static Map<String, Object> weChatV3Post(WeChatConfig weChatConfig, String userType, Map<String, Object> param, String url) {
        if (httpClient == null) setup(weChatConfig, userType);
        ObjectMapper objectMapper = new ObjectMapper();
        String paramJson = null;
        try {
            paramJson = objectMapper.writeValueAsString(param);
        } catch (JsonProcessingException e) {
            throw new BusinessException("微信请求Map转换失败!" + e.getMessage());
        }
        HttpPost httpPost = new HttpPost(url);
        httpPost.addHeader("Accept", "application/json");
        httpPost.addHeader("Content-type", "application/json; charset=utf-8");
        httpPost.setEntity(new StringEntity(paramJson, "UTF-8")); // 设置请求实体为 paramJson
        CloseableHttpResponse response;
        try {
            response = httpClient.execute(httpPost);
        } catch (IOException e) {
            throw new BusinessException("微信请求GET请求失败:" + e.getMessage());
        }
        return getResponse(response);
    }
    /*微信支付GEt请求*/
    public static Map<String, Object> weChatV3Get(WeChatConfig weChatConfig, String userType, String url) {

        if (httpClient == null) setup(weChatConfig, userType);
        HttpGet httpGet = new HttpGet(url);
        httpGet.addHeader("Accept", "application/json");
        httpGet.addHeader("Content-type", "application/json; charset=utf-8");
        CloseableHttpResponse response = null;
        try {
            response = httpClient.execute(httpGet);
        } catch (IOException e) {
            throw new BusinessException("微信请求GET请求失败:" + e.getMessage());
        }
        return getResponse(response);
    }

    /*微信支付GEt下载请求*/
    public static Map<String, Object> weChatV3GetDown(WeChatConfig weChatConfig, String userType, String url) {
        // 假设这是你的请求参数
        if (httpClient == null) setup(weChatConfig, userType);
        String mchid = weChatConfig.getMchId(userType);
        String nonce_str = AppUtil.getUUID();
        String timestamp = System.currentTimeMillis()/1000+"";
        String serial_no = weChatConfig.getSerialNo(userType);
        String privateKeyFilePath = weChatConfig.getPrivateKeyUrl(userType);
        // 生成签名
        String signature = getSign(nonce_str, timestamp, url, privateKeyFilePath,"GET");
        // 组装Authorization头部值
        String authorizationHeader = "WECHATPAY2-SHA256-RSA2048 mchid=\"" + mchid + "\", " +
                "nonce_str=\"" + nonce_str + "\", " +
                "signature=\"" + signature + "\", " +
                "timestamp=\"" + timestamp + "\", " +
                "serial_no=\"" + serial_no + "\"";
        // 发起HTTP请求
        HttpGet httpGet = new HttpGet(url);
        httpGet.addHeader("Authorization", authorizationHeader);
        CloseableHttpResponse response = null;
        try {
            response = httpClient.execute(httpGet);
        } catch (IOException e) {
            throw new BusinessException("微信请求GET请求失败:" + e.getMessage());
        }
        return getResponse(response);
    }


    //    获取帧数
    private static void setup(WeChatConfig weChatConfig, String userType) {
        try {
            String mchId =weChatConfig.getMchId(userType);
            String serialNo = weChatConfig.getSerialNo(userType);
            String privateKeyFilePath =  weChatConfig.getPrivateKeyUrl(userType);
            String apiV3Key =  weChatConfig.getApiV3Key(userType);
            byte[] privateKeyBytes = Files.readAllBytes(Paths.get(privateKeyFilePath));
            PrivateKey merchantPrivateKey = PemUtil.loadPrivateKey(new ByteArrayInputStream(privateKeyBytes));
            certificatesManager = CertificatesManager.getInstance();
            certificatesManager.putMerchant(mchId, new WechatPay2Credentials(mchId, new PrivateKeySigner(serialNo, merchantPrivateKey)), apiV3Key.getBytes(StandardCharsets.UTF_8));
            verifier = certificatesManager.getVerifier(mchId);
            httpClient = WechatPayHttpClientBuilder.create().withMerchant(mchId, serialNo, merchantPrivateKey).withValidator(new WechatPay2Validator(certificatesManager.getVerifier(mchId))).build();
        } catch (IOException | NotFoundException | HttpCodeException | GeneralSecurityException e) {
            e.printStackTrace();
        }
    }

    // 请求返回处理
    private static Map<String, Object> getResponse(CloseableHttpResponse response) {
        try {
            int statusCode = response.getStatusLine().getStatusCode();
            Map<String, Object> map = new HashMap<>();
            if (statusCode == 200) {
                HttpEntity entity = response.getEntity();
                if (entity != null) {
                    Gson gson = new Gson();
                    Type type = new TypeToken<Map<String, Object>>() {
                    }.getType();
                    map = gson.fromJson(EntityUtils.toString(entity, "UTF-8"), type);
                }
                return map;
            } else {
                throw new BusinessException("微信请求失败,请求失败码:" + statusCode);
            }
        } catch (IOException e) {
            throw new BusinessException("微信请求失败,失败信息" + e.getMessage());
        }
    }

    //##############################################内部方法#########################################################
    public static String getSign(String nonceStr, String timestamp, String body, String privateKey,String method) {
        String message = buildMessage(method, httpurl, timestamp, nonceStr, body);
        return sign(message.getBytes(StandardCharsets.UTF_8), privateKey);
    }

    private static String sign(byte[] message, String privateKey) {
        try {
            byte[] privateKeyBytes = Files.readAllBytes(Paths.get(privateKey));
            PrivateKey merchantPrivateKey = PemUtil.loadPrivateKey(new ByteArrayInputStream(privateKeyBytes));
            Signature sign = Signature.getInstance("SHA256withRSA");
            sign.initSign(merchantPrivateKey);
            sign.update(message);
            return Base64.getEncoder().encodeToString(sign.sign());
        } catch (NoSuchAlgorithmException | IOException | SignatureException | InvalidKeyException e) {
            e.printStackTrace();
        }
        return null;
    }
    private static String buildMessage(String method, HttpUrl url, String timestamp, String nonceStr, String body) {
        String canonicalUrl = url.encodedPath();
        if (url.encodedQuery() != null) {
            canonicalUrl += "?" + url.encodedQuery();
        }
        return method + "\n"
                + canonicalUrl + "\n"
                + timestamp + "\n"
                + nonceStr + "\n"
                + body + "\n";
    }

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值