JAVA-微信支付

依赖

        <!-- 微信支付apiv3版本 -->
        <dependency>
            <groupId>com.github.wechatpay-apiv3</groupId>
            <artifactId>wechatpay-java</artifactId>
            <version>0.2.14</version>
        </dependency>

微信支付工具类

package com.github.devcude.comp.plaza.mall.plat.util.core;

import com.github.devcude.comp.plaza.mall.plat.configuration.core.WxPayConfig;
import com.wechat.pay.java.core.Config;
import com.wechat.pay.java.core.RSAPublicKeyConfig;
import com.wechat.pay.java.core.notification.NotificationConfig;
import com.wechat.pay.java.service.payments.jsapi.JsapiService;
import com.wechat.pay.java.service.payments.jsapi.JsapiServiceExtension;
import com.wechat.pay.java.service.refund.RefundService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

/**
 * 微信普通商户支付工具类
 *
 * @ClassName WXPayUtil
 * @Description TODO
 * @Author orison
 * @Date 2024-08-12 17:09
 * @Version 1.0
 **/
@Component
@Slf4j
public class WXPayGeneralUtil implements ApplicationContextAware {
    @Autowired
    WxPayConfig wxPayConfig;

    /**
     * 公钥路径
     * 【微信推出了平台证书的替代公钥方案,两者使用场景完全相同,但公钥不会过期,后续新申请的商户号将使用公钥进行验签与敏感信息加密。
     * 微信支付公钥使用介绍:https://pay.weixin.qq.com/docs/merchant/products/platform-certificate/wxp-pub-key-guide.html
     * 平台证书切换微信支付公钥指引:https://pay.weixin.qq.com/docs/merchant/products/platform-certificate/update-pub-key.html
     * 新申请的商户不能再用平台证书,请申请公钥】
     */


    /**
     * 项目名
     */

    public static JsapiService service;//jsapi支付服务
    public static JsapiServiceExtension jsapiServiceExtension; //jsapi支付服务增强接口(强烈推荐)
    public static NotificationConfig notificationConfig;//回调配置
    public static RefundService refundService;//退款服务

    public JsapiServiceExtension getJsapiServiceExtension() {
        Config config = new RSAPublicKeyConfig.Builder()
                .merchantId(wxPayConfig.getMerchantId())
                .privateKeyFromPath(wxPayConfig.getPrivateKeyPath())
                .publicKeyFromPath(wxPayConfig.getPublicKeyPath())
                .publicKeyId(wxPayConfig.getPublicKeyId())
                .merchantSerialNumber(wxPayConfig.getMerchantSerialNumber())
                .apiV3Key(wxPayConfig.getApiV3Key())
                .build();
        return new JsapiServiceExtension.Builder().config(config).build();
    }

    public NotificationConfig getNotificationConfig() {
        Config config = new RSAPublicKeyConfig.Builder()
                .merchantId(wxPayConfig.getMerchantId())
                .privateKeyFromPath(wxPayConfig.getPrivateKeyPath())
                .publicKeyFromPath(wxPayConfig.getPublicKeyPath())
                .publicKeyId(wxPayConfig.getPublicKeyId())
                .merchantSerialNumber(wxPayConfig.getMerchantSerialNumber())
                .apiV3Key(wxPayConfig.getApiV3Key())
                .build();

        return (NotificationConfig) config;
    }

    public RefundService getRefundService() {
        Config config = new RSAPublicKeyConfig.Builder()
                .merchantId(wxPayConfig.getMerchantId())
                .privateKeyFromPath(wxPayConfig.getPrivateKeyPath())
                .publicKeyFromPath(wxPayConfig.getPublicKeyPath())
                .publicKeyId(wxPayConfig.getPublicKeyId())
                .merchantSerialNumber(wxPayConfig.getMerchantSerialNumber())
                .apiV3Key(wxPayConfig.getApiV3Key())
                .build();

        return new RefundService.Builder().config(config).build();
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {

    }


//    /**
//     * 根据退款单号查询退款单信息
//     * 参考文档:https://pay.weixin.qq.com/docs/merchant/apis/jsapi-payment/query-by-out-refund-no.html
//     *
//     * @param outRefundNo
//     * @return
//     */
//    public static Result queryRefund(String outRefundNo) {
//        try {
//            QueryByOutRefundNoRequest request = new QueryByOutRefundNoRequest();
//            request.setOutRefundNo(outRefundNo);
//            Refund refund = refundService.queryByOutRefundNo(request);
            status
            可选取值:
            SUCCESS: 退款成功
            CLOSED: 退款关闭
            PROCESSING: 退款处理中
            ABNORMAL: 退款异常
//            return Result.success(refund);
//        } catch (ServiceException e) {
//            log.error("普通商户-根据退款单号查询退款单信息异常", e);
//            return Result.fail(e.getErrorMessage());
//        }
//    }
//
//    /**
//     * 关闭订单
//     * 参考文档:https://pay.weixin.qq.com/docs/merchant/apis/jsapi-payment/close-order.html
//     *
//     * @param outTradeNo
//     * @return
//     */
//    public static Result closeOrder(String outTradeNo) {
//        try {
//            CloseOrderRequest request = new CloseOrderRequest();
//            request.setMchid(merchantId);
//            request.setOutTradeNo(outTradeNo);
//            service.closeOrder(request);
//            return Result.success();
//        } catch (ServiceException e) {
//            log.error("普通商户-关闭订单异常", e);
//            return Result.fail(e.getErrorMessage());
//        }
//    }
//
//    /**
//     * 根据系统业务单号查询订单
//     * (用于防止订单支付后微信没有回调支付接口,导致订单还是处于待支付,解决方案如:定时任务查询当天处于待支付订单)
//     * 参考文档:https://pay.weixin.qq.com/docs/merchant/apis/jsapi-payment/query-by-out-trade-no.html
//     *
//     * @param outTradeNo trade_state
//     *                   【交易状态】 交易状态,枚举值:
//     *                   * SUCCESS:支付成功
//     *                   * REFUND:转入退款
//     *                   * NOTPAY:未支付
//     *                   * CLOSED:已关闭
//     *                   * REVOKED:已撤销(仅付款码支付会返回)
//     *                   * USERPAYING:用户支付中(仅付款码支付会返回)
//     *                   * PAYERROR:支付失败(仅付款码支付会返回)
//     */
//    public static Result queryOrderByOutTradeNo(String outTradeNo) {
//        try {
//            QueryOrderByOutTradeNoRequest query = new QueryOrderByOutTradeNoRequest();
//            query.setMchid(merchantId);
//            query.setOutTradeNo(outTradeNo);
//            Transaction transaction = service.queryOrderByOutTradeNo(query);
//            return Result.success(transaction);
//        } catch (ServiceException e) {
//            log.error("普通商户-根据系统业务号查询订单异常", e);
//            return Result.fail(e.getErrorMessage());
//        }
//    }
//
//
//    /**
//     * 微信支付单号查询订单
//     * 参考文档:https://pay.weixin.qq.com/docs/merchant/apis/jsapi-payment/query-by-wx-trade-no.html
//     *
//     * @param transactionId 【微信支付订单号】 微信支付系统生成的订单号
//     * @return
//     */
//    public static Transaction queryOrderByTransactionId(String transactionId) {
//        QueryOrderByIdRequest request = new QueryOrderByIdRequest();
//        request.setMchid(merchantId);
//        request.setTransactionId(transactionId);
//        return service.queryOrderById(request);
//    }
//
//
//    /**
//     * 退款
//     * 参考文档:https://pay.weixin.qq.com/docs/merchant/apis/jsapi-payment/create.html
//     * 当交易发生之后一段时间内,由于买家或者卖家的原因需要退款时,卖家可以通过退款接口将支付款退还给买家,微信支付将在收到退款请求并且验证成功之后,按照退款规则将支付款按原路退到买家帐号上。
//     * 注意:
//     * 交易时间超过一年的订单无法提交退款(按支付成功时间+365天计算)
//     * 微信支付退款支持单笔交易分多次退款,多次退款需要提交原支付订单的商户订单号和设置不同的退款单号。申请退款总金额不能超过订单金额。 一笔退款失败后重新提交,请不要更换退款单号,请使用原商户退款单号
//     * 请求频率限制:150qps,即每秒钟正常的申请退款请求次数不超过150次
//     * 每个支付订单的部分退款次数不能超过50次
//     * 如果同一个用户有多笔退款,建议分不同批次进行退款,避免并发退款导致退款失败
//     * 申请退款接口的返回仅代表业务的受理情况,具体退款是否成功,需要通过退款查询接口获取结果
//     * 错误或无效请求频率限制:6qps,即每秒钟异常或错误的退款申请请求不超过6次
//     * 一个月之前的订单申请退款频率限制为:5000/min
//     * 同一笔订单多次退款的请求需相隔1分钟
//     *
//     * @param outTradeNo
//     */
//    public static Result refunds(String outTradeNo, long total, long refund, String uri) {
//        try {
//            String symbol = StringUtils.join(WXPayGeneralUtil.randomNum(6, 10).toArray(), ",").replace(",", "");
//            String str = new SimpleDateFormat("yyyyMMddHHmmssSSS").format(new Date()) + symbol;
//            String out_refund_no = str;//商户系统内部订单号,只能是数字、大小写字母_-*且在同一个商户号下唯一
//            CreateRequest request = new CreateRequest();
//            request.setOutTradeNo(outTradeNo);
//            request.setOutRefundNo(out_refund_no);
//            request.setNotifyUrl(notifyUrl + contextPath + uri);
//            AmountReq amountReq = new AmountReq();
//            amountReq.setRefund(refund);
//            amountReq.setTotal(total);
//            amountReq.setCurrency("CNY");
//            request.setAmount(amountReq);
//            refundService.create(request);
//            return Result.success("已申请退款", out_refund_no);
//        } catch (ServiceException e) {
//            log.error("普通商户-退款", e);
//            return Result.fail(e.getErrorMessage());
//        }
//    }
//
//    /**
//     * 对退款回调预处理
//     * 参考文档:https://pay.weixin.qq.com/docs/merchant/apis/jsapi-payment/refund-result-notice.html
//     *
//     * @param request
//     * @param response
//     * @return
//     */
//    public static Map refundsCallbackHandle(HttpServletRequest request, HttpServletResponse response) {
//        try {
//            //获取报文
//            String body = IOUtils.toString(request.getInputStream(), "UTF-8");
//            //随机串
//            String nonceStr = request.getHeader("Wechatpay-Nonce");
//            //微信传递过来的签名
//            String signature = request.getHeader("Wechatpay-Signature");
//            //证书序列号(微信平台)
//            String serialNo = request.getHeader("Wechatpay-Serial");
//            //时间戳
//            String timestamp = request.getHeader("Wechatpay-Timestamp");
//            // 签名方式
//            String signType = request.getHeader("Wechatpay-Signature-Type");
//            // 构造 RequestParam
//            com.wechat.pay.java.core.notification.RequestParam requestParam = new com.wechat.pay.java.core.notification.RequestParam.Builder()
//                    .serialNumber(serialNo)
//                    .nonce(nonceStr)
//                    .signature(signature)
//                    .timestamp(timestamp)
//                    .signType(signType)
//                    .body(body)
//                    .build();
//            // 如果已经初始化了 RSAAutoCertificateConfig,可以直接使用  config
//            // 初始化 NotificationParser
//            NotificationParser parser = new NotificationParser(notificationConfig);
//            // 验签、解密并转换成 Transaction
//            Map transaction = parser.parse(requestParam, Map.class);
//            return transaction;
//        } catch (Exception e) {
//            e.printStackTrace();
//            myWriter(response, 500);
//            log.error("微信支付回调Exception", e);
//        }
//        return null;
//    }
//
//
//    /**
//     * 生成指定范围的随机数字
//     *
//     * @param scope 需要生成的随机数字的个数
//     * @param total 数字范围
//     * @return
//     */
//    public static List<Integer> randomNum(int scope, int total) {
//        List<Integer> mylist = new ArrayList<>(); // 用于储存不重复的随机数
//        Random rd = new Random();
//        while (mylist.size() < scope) {
//            int myNum = rd.nextInt(total);
//            if (!mylist.contains(myNum += 1)) { // 判断容器中是否包含指定的数字
//                mylist.add(myNum); // 往集合里面添加数据。
//            }
//        }
//        return mylist;
//    }
//
//    /**
//     * 对支付回调预处理
//     * 参考文档:https://pay.weixin.qq.com/docs/merchant/apis/jsapi-payment/payment-notice.html
//     *
//     * @param request
//     * @param response
//     * @return
//     */
//    public static Map paymentCallbackHandle(HttpServletRequest request, HttpServletResponse response) {
//        try {
//            //获取报文
//            String body = IOUtils.toString(request.getInputStream(), "UTF-8");
//            //随机串
//            String nonceStr = request.getHeader("Wechatpay-Nonce");
//            //微信传递过来的签名
//            String signature = request.getHeader("Wechatpay-Signature");
//            //证书序列号(微信平台)
//            String serialNo = request.getHeader("Wechatpay-Serial");
//            //时间戳
//            String timestamp = request.getHeader("Wechatpay-Timestamp");
//            // 签名方式
//            String signType = request.getHeader("Wechatpay-Signature-Type");
//            // 构造 RequestParam
//            com.wechat.pay.java.core.notification.RequestParam requestParam = new com.wechat.pay.java.core.notification.RequestParam.Builder()
//                    .serialNumber(serialNo)
//                    .nonce(nonceStr)
//                    .signature(signature)
//                    .timestamp(timestamp)
//                    .signType(signType)
//                    .body(body)
//                    .build();
//            // 如果已经初始化了 RSAAutoCertificateConfig,可以直接使用  config
//            // 初始化 NotificationParser
//            NotificationParser parser = new NotificationParser(notificationConfig);
//            // 验签、解密并转换成 Transaction
//            Map transaction = parser.parse(requestParam, Map.class);
//
//            return transaction;
//        } catch (Exception e) {
//            e.printStackTrace();
//            myWriter(response, 500);
//            log.error("微信支付回调Exception", e);
//            return null;
//        }
//    }
//
//
//    private static void myWriter(HttpServletResponse response, int code) {
//        try {
//            // 设置HTTP应答状态码,例如200 OK
//            Map map = new HashMap();
//            if (code == 200) {
//                response.setStatus(200);
//                map.put("code", "SUCCESS");
//                map.put("message", "成功");
//            } else {
//                response.setStatus(500);
//                map.put("code", "FAIL");
//                map.put("message", "失败");
//            }
//            response.setCharacterEncoding("UTF-8");
//            response.setContentType("text/html; charset=utf-8");
//            PrintWriter writer = response.getWriter();
//            String resultStr = JSON.toJSONString(map);
//            writer.print(resultStr);
//            writer.close();
//        } catch (IOException e) {
//            log.error("Exception", e);
//        }
//    }
}

微信配置类

package com.github.devcude.comp.plaza.mall.plat.configuration.core;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

/**
 * @author caozhen
 * @ClassName WxPayConfig
 * @description: 微信支付配置类
 * @date 2024年01月03日
 * @version: 1.0
 */
@Data
@Component
@ConfigurationProperties(prefix = "wx")
public class WxPayConfig {
    //APPID
    private String appId;
    //mchid
    private String merchantId;
    //商户API私钥
    private String privateKeyPath;
    //商户证书序列号
    private String merchantSerialNumber;
    //商户APIv3密钥
    private String apiV3Key;
    //支付通知地址
    private String payNotifyUrl;
    //退款通知地址
    private String refundNotifyUrl;
    private String publicKeyId;
    private String publicKeyPath;
}

微信配置参数

#微信
wx.secret=cd4cbd9e64cae84f7797d9260b03****
#应用id(小程序id)
wx.appId=wx0aca260a96c6****
#商户号
wx.merchantId=170064****
#商户证书序列号
wx.merchantSerialNumber=1ABCC51EB4C596CD7B9BE2669E86F11DD62F****
#商户APIv3密钥
wx.apiV3Key=jsingkleis5216498520YLGCwijn****

#公钥id
wx.publicKeyId=PUB_KEY_ID_011700648250202501080035680000****
##168环境
wx.payNotifyUrl=http://n.****.com:19594/wxPay/callBack
#退款通知地址
wx.refundNotifyUrl=http://n.****.com:19594/wxPay/refundNotify
#商户API私钥
wx.privateKeyPath=/usr/share/app/wx-cert/apiclient_key.pem
#公钥路径
wx.publicKeyPath=/usr/share/app/wx-cert/pub_key.pem

调用方法

下单

  @RequestMapping
    public Object order(String orderNum, HttpServletRequest httpServletRequest) {
        PmUserBean pmUserBean = TokenUtil.getUser(httpServletRequest.getHeader("token"));
        pmUserBean = pmUserService.find(pmUserBean.getId());

        IntegralProductOrderBean integralProductOrderBean = integralProductOrderService.findByQuery(IntegralProductOrderParam.builder().num(orderNum).build());
        if (null == integralProductOrderBean) {
            return ResponseBean.serverError("找不到订单");
        }
        ProductBean productBean = productService.find(integralProductOrderBean.getProductId());
        if (null == productBean) {
            return ResponseBean.serverError("找不到商品");
        }

        String orderNo = integralProductOrderBean.getNum();
        Double price = integralProductOrderBean.getPrice();
        Integer totalFee = (int) (price * 100);
        String desc = productBean.getName();
        //totalFee = 1;

        try {
            JsapiServiceExtension jsapiServiceExtension = wxPayGeneralUtil.getJsapiServiceExtension();

            // request.setXxx(val)设置所需参数,具体参数可见Request定义
            com.wechat.pay.java.service.payments.jsapi.model.PrepayRequest request = new PrepayRequest();
            Amount amount = new Amount();
            amount.setTotal(totalFee);
            request.setAmount(amount);
            request.setAppid(wxPayConfig.getAppId());
            request.setMchid(wxPayConfig.getMerchantId());
            request.setDescription(desc);
            request.setNotifyUrl(wxPayConfig.getPayNotifyUrl());
            request.setOutTradeNo(orderNo);
            //request.setAttach(req.getOrderType());

            Payer payer = new Payer();
            payer.setOpenid(pmUserBean.getOpenid());
            //payer.setOpenid("oITTw64LaFAsci7mRXk0pBRthpgI");
            request.setPayer(payer);

            // 调用下单方法,得到应答
            PrepayWithRequestPaymentResponse response = jsapiServiceExtension.prepayWithRequestPayment(request);

            return ResponseBean.success("下单成功").addData("res", response);
        } catch (ServiceException e) {
            JSONObject parse = JSONObject.parseObject(e.getResponseBody());
            throw new RuntimeException(parse.getString("message"));
        } catch (Exception e) {
            throw new RuntimeException(e.toString());
        }

    }

支付回调

 /**
     * 对支付回调预处理
     * 参考文档:https://pay.weixin.qq.com/docs/merchant/apis/jsapi-payment/payment-notice.html
     *
     * @param request
     * @param response
     * @return
     */
    @RequestMapping
    public Object callBack(HttpServletRequest request, HttpServletResponse response) {
        try {
            NotificationConfig notificationConfig = wxPayGeneralUtil.getNotificationConfig();

            //获取报文
            String body = IOUtils.toString(request.getInputStream(), "UTF-8");
            //随机串
            String nonceStr = request.getHeader("Wechatpay-Nonce");
            //微信传递过来的签名
            String signature = request.getHeader("Wechatpay-Signature");
            //证书序列号(微信平台)
            String serialNo = request.getHeader("Wechatpay-Serial");
            //时间戳
            String timestamp = request.getHeader("Wechatpay-Timestamp");
            // 签名方式
            String signType = request.getHeader("Wechatpay-Signature-Type");
            // 构造 RequestParam
            com.wechat.pay.java.core.notification.RequestParam requestParam = new com.wechat.pay.java.core.notification.RequestParam.Builder()
                    .serialNumber(serialNo)
                    .nonce(nonceStr)
                    .signature(signature)
                    .timestamp(timestamp)
                    .signType(signType)
                    .body(body)
                    .build();

            NotificationParser parser = new NotificationParser(notificationConfig);
            // 验签、解密并转换成 Transaction
            Map transaction = parser.parse(requestParam, Map.class);
            log.info("支付回调结果:{}", transaction);

            String payStatus = (String) transaction.get("trade_state");
            String orderNum = (String) transaction.get("out_trade_no");

            IntegralProductOrderBean integralProductOrderBean = integralProductOrderService.findByQuery(IntegralProductOrderParam.builder().num(orderNum).build());
            if (null == integralProductOrderBean) {
                return ResponseBean.serverError("找不到订单");
            }

            log.info("支付返回状态:{}", payStatus);
            if (payStatus.equals("SUCCESS")) {
                return handleSuccess(integralProductOrderBean);
            }
            return ResponseBean.serverError("订单不存在");
        } catch (Exception e) {
            e.printStackTrace();
            log.error("微信支付回调Exception", e);
        }
        return ResponseBean.serverError("支付失败");
    }

退款

    /**
     * 发送退款申请
     */
    public Object refundPay(IntegralProductOrderBean integralProductOrderParam) {

        IntegralProductOrderBean integralProductOrderBean = integralProductOrderService.find(integralProductOrderParam.getId());
        if (null == integralProductOrderBean) {
            return ResponseBean.serverError("找不到订单");
        }

        //售后中
        integralProductOrderBean.setStatus("refunding");
        integralProductOrderBean.setRefundTime(new Date());
        //退款编号
        integralProductOrderBean.setRefundNum("TK" + busNumInstService.nextSeq(BbBsnmKeys.REFUND_NUM, CommonBsnmTplKeys.DATE_LENGTH_6_SEQ));
        //退款处理中
        integralProductOrderBean.setRefundStatus("refundHandle");

        //输入退款金额
        Double price = integralProductOrderBean.getPrice();
        Long refundPrice = (long) (price * 100);
        Double price1 = integralProductOrderBean.getPrice();
        Long total = (long) (price1 * 100);

        try {
            RefundService refundService = wxPayGeneralUtil.getRefundService();

            CreateRequest request = new CreateRequest();
            request.setOutTradeNo(integralProductOrderBean.getNum());
            request.setOutRefundNo(integralProductOrderBean.getRefundNum());
            request.setNotifyUrl(wxPayConfig.getRefundNotifyUrl());
            AmountReq amountReq = new AmountReq();
            amountReq.setRefund(refundPrice);
            amountReq.setTotal(total);
            amountReq.setCurrency("CNY");
            request.setAmount(amountReq);
            refundService.create(request);

            integralProductOrderService.update(integralProductOrderBean);

            return ResponseBean.success("已申请退款").addData("refundNum", integralProductOrderBean.getRefundNum());
        } catch (ServiceException e) {
            log.error("普通商户-退款", e);
            String errorMessage = e.getErrorMessage();
            return ResponseBean.serverError("退款失败:" + errorMessage);
        }
    }

退款回调

    /**
     * 退款回调
     */
    @RequestMapping
    public Object refundNotify(HttpServletRequest request, HttpServletResponse response) {
        try {
            NotificationConfig notificationConfig = wxPayGeneralUtil.getNotificationConfig();

            //获取报文
            String body = IOUtils.toString(request.getInputStream(), "UTF-8");
            //随机串
            String nonceStr = request.getHeader("Wechatpay-Nonce");
            //微信传递过来的签名
            String signature = request.getHeader("Wechatpay-Signature");
            //证书序列号(微信平台)
            String serialNo = request.getHeader("Wechatpay-Serial");
            //时间戳
            String timestamp = request.getHeader("Wechatpay-Timestamp");
            // 签名方式
            String signType = request.getHeader("Wechatpay-Signature-Type");
            // 构造 RequestParam
            com.wechat.pay.java.core.notification.RequestParam requestParam = new com.wechat.pay.java.core.notification.RequestParam.Builder()
                    .serialNumber(serialNo)
                    .nonce(nonceStr)
                    .signature(signature)
                    .timestamp(timestamp)
                    .signType(signType)
                    .body(body)
                    .build();
            // 如果已经初始化了 RSAAutoCertificateConfig,可以直接使用  config
            // 初始化 NotificationParser
            NotificationParser parser = new NotificationParser(notificationConfig);
            // 验签、解密并转换成 Transaction
            Map transaction = parser.parse(requestParam, Map.class);
            log.info("退款信息:{}", transaction);

            String refundStatus = (String) transaction.get("refund_status");
            log.info("退款状态:{}", refundStatus);

            String orderNum = (String) transaction.get("out_trade_no");

            IntegralProductOrderBean integralProductOrderBean = integralProductOrderService.findByQuery(IntegralProductOrderParam.builder().num(orderNum).build());
            if (null == integralProductOrderBean) {
                return ResponseBean.serverError("找不到订单");
            }
            if (refundStatus.equals("SUCCESS")) {
            //退款成功逻辑
 }
            return transaction;
        } catch (Exception e) {
            e.printStackTrace();
            log.error("微信支付回调Exception", e);
        }
        return ResponseBean.serverError("退款失败");
    }

微信发起提现

  /**
     * 商户转账到用户,提现
     *
     * @return
     */
    @RequestMapping
    public Object withdraw(WithdrawRecordParam withdrawRecordParam) {

        WithdrawRecordBean withdrawRecordBean = this.withdrawRecordService.find(withdrawRecordParam);

        if (withdrawRecordBean == null) {
            return ResponseBean.serverError("该记录不存在!");
        }

        PmUserBean pmUserBean = pmUserService.find(PmUserParam.builder().id(withdrawRecordBean.getUserId()).build());
        if (null == pmUserBean || StringUtils.isEmpty(pmUserBean.getOpenid())) {
            return ResponseBean.serverError("找不到用户");
        }

        //输入退款金额
        Double price = withdrawRecordBean.getPrice();
        Long totalPrice = (long) (price * 100);

        try {
            TransferBatchService transferBatchService = wxPayGeneralUtil.getTransferBatchService();

            InitiateBatchTransferRequest request = new InitiateBatchTransferRequest();
            request.setAppid(wxPayConfig.getAppId());
            request.setOutBatchNo(withdrawRecordBean.getNum());
            request.setBatchName("提现");
            request.setBatchRemark("提现");
            request.setTotalAmount(totalPrice);
            request.setTotalNum(1);
            List<TransferDetailInput> transferDetailList = new ArrayList<>();
            TransferDetailInput transferDetailInput = new TransferDetailInput();
            transferDetailInput.setOutDetailNo(withdrawRecordBean.getNum());
            transferDetailInput.setTransferAmount(totalPrice);
            transferDetailInput.setTransferRemark("提现");
            transferDetailInput.setOpenid(pmUserBean.getOpenid());//我的openid
            transferDetailList.add(transferDetailInput);
            request.setTransferDetailList(transferDetailList);

            InitiateBatchTransferResponse response = transferBatchService.initiateBatchTransfer(request);
            log.info(response.toString());

            return ResponseBean.success("发起提现成功").addData("num", withdrawRecordBean.getNum());
        } catch (ServiceException e) {
            log.error("提现失败", e);
            return ResponseBean.serverError("提现失败");
        }
    }

提现结果查询

  @RequestMapping
    public Object findWithdrawStatus(WithdrawRecordParam withdrawRecordParam) {

        WithdrawRecordBean withdrawRecordBean = this.withdrawRecordService.find(withdrawRecordParam);

        if (withdrawRecordBean == null) {
            return ResponseBean.serverError("该记录不存在!");
        }

        try {
            TransferBatchService transferBatchService = wxPayGeneralUtil.getTransferBatchService();

            GetTransferDetailByOutNoRequest request = new GetTransferDetailByOutNoRequest();
            request.setOutBatchNo(withdrawRecordBean.getNum());
            request.setOutDetailNo(withdrawRecordBean.getNum());

            //INIT: 初始态。 系统转账校验中
            //WAIT_PAY: 待确认。待商户确认, 符合免密条件时, 系统会自动扭转为转账中
            //PROCESSING:转账中。正在处理中,转账结果尚未明确
            //SUCCESS:转账成功
            //FAIL:转账失败。需要确认失败原因后,再决定是否重新发起对该笔明细单的转账(并非整个转账批次单)
            TransferDetailEntity transferDetailByOutNo = transferBatchService.getTransferDetailByOutNo(request);
            String status = transferDetailByOutNo.getDetailStatus();

            if (status.equals("SUCCESS")) {
                withdrawRecordBean.setStatus("success");
                withdrawRecordService.update(withdrawRecordBean);
            }

            return ResponseBean.success("操作成功").addData("data", transferDetailByOutNo);
        } catch (ServiceException e) {
            log.error("提现失败", e);
            return ResponseBean.serverError("操作失败");
        }
    }
注意要点: 1,Topay里面的参数要填好:appid,appsecret,mch_id,partnerkey,spbill_create_ip 2,openid 需要微信授权获取到 3,每次支付orderNo要不同 openid参考实例: 1,授权链接地址:https://open.weixin.qq.com/connect/oauth2/authorize?appid=wxba3445566677&redirect_uri=http://www.acc.com/weixin/pay/paydispatcher&response_type=code&scope=snsapi_userinfo&state=123#wechat_redirect 2,转向处理地址:通过第一个链接微信会把code传过来,之前参数获取就行 @RequestMapping(value = "/paydispatcher", method = { RequestMethod.GET }) public void payDispatcher(HttpServletRequest request, HttpServletResponse response) throws Exception { String code = request.getParameter("code"); String msg=""; if(code==null||code.equals("")){ msg="获取微信Code失败!"; request.setAttribute("msg" ,msg); request.getRequestDispatcher("/jsp/login.jsp").forward(request,response); }else{ WeixinUtil util = new WeixinUtil(); UserAccessToken token = (UserAccessToken) request.getSession().getAttribute("UserAccessToken"); if(null==token){ token = util.getAccessToken3(Constants.APPID, Constants.SECRET,code); request.getSession().setAttribute("UserAccessToken",token); } request.setAttribute("openid", token.getOpenid()); request.setAttribute("accessToken", token.getAccessToken()); request.setAttribute("refreshToken", token.getRefreshToken()); request.setAttribute("expiresIn", token.getExpiresIn()); request.getRequestDispatcher("/pay/index.jsp").forward(request,response); } } // 获取用户openid accesstoken public static UserAccessToken getAccessToken3(String appid , String appsecret,String code) { UserAccessToken accessToken = null; String requestUrl = Constants.GET_OPENID_ACCESSTOKEN_URL.replace("APPID" , appid).replace("APPSECRET" , appsecret).replace("CODE" , code); String json = httpRequest(requestUrl , "GET" , null); JSONObject jsonObject = JSONObject.fromObject(json); // 如果请求成功 if (null != jsonObject) { try { accessToken = new UserAccessToken(); accessToken.setAccessToken(jsonObject.getString("access_token")); accessToken.setRefreshToken(jsonObject.getString("refresh_token")); accessToken.setExpiresIn(jsonObject.getInt("expires_in")); accessToken.setOpenid(jsonObject.getString("openid")); accessToken.setScope(jsonObject.getString("scope")); } catch (Exception e) { accessToken = null; // 获取token失败 System.out.println("获取token失败 errcode:{} errmsg:{}"); } } return accessToken; }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值