SpringBoot集成微信支付微信退款

本文档详细介绍了如何在Java环境中集成微信支付V2.0版本,包括下单支付、支付回调处理和退款操作。示例代码展示了如何创建XML请求和响应,校验签名,以及处理微信支付接口的调用。此外,还提供了微信支付回调的处理逻辑和退款接口的实现。整个流程涵盖了订单支付、退款和回调验证的关键步骤。

微信支付

备注:本次支付接入的是微信支付v2.0版本,其中所有的请求格式均为XML。

如有需求可直接参阅官方文档 https://pay.weixin.qq.com/wiki/doc/api/index.html

官网支付demo地址(v2.0): https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=11_1

微信支付V3.0版本是基于JSON格式的API。

个人支付案例git地址[微信支付/支付宝支付/华为支付/苹果支付/小米支付]:https://gitee.com/wazk2008/demo-pay

1.下单支付(跳转微信进行支付)

微信接口名称: 统一下单

微信接口地址: https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1

个人支付代码demo

@RestController
@RequestMapping(value = "/pay")
@Slf4j
public class PayController {
   
   

    @Autowired
    private WechatService wechatService;

    @PostMapping(value = "/wechat")
    public Result<PayWechatResponse> payWechat (@RequestBody PayWechatRequest payWechatRequest) {
   
   
        try {
   
   
            log.info("微信支付接口开始执行,请求参数:{}", JSON.toJSONString(payWechatRequest));
            PayWechatResponse payWechatResponse = wechatService.pay(payWechatRequest);
            log.info("微信支付接口执行成功,请求参数:{},响应参数:{}", JSON.toJSONString(payWechatRequest), JSON.toJSON(payWechatResponse));
            return Result.getSuccess(payWechatResponse);
        } catch (ResponseException e) {
   
   
            log.error("微信支付接口执行失败1,请求参数:{},异常原因:{}", JSON.toJSONString(payWechatRequest), e.getMessage());
            e.printStackTrace();
            return Result.getFail(e);
        } catch (Exception e) {
   
   
            log.error("微信支付接口执行失败2,请求参数:{},异常原因:{}", JSON.toJSONString(payWechatRequest), e.getMessage());
            e.printStackTrace();
            return Result.getFail(ResultCode.INTERNAL_SERVER_ERROR);
        }
    }

}
@Service
@Slf4j
public class WechatService {
   
   

    @Autowired
    private WechatConfig wechatConfig;
    @Autowired
    private Map<String, WechatAppConfig> wechatApps;
    @Autowired
    private HttpXmlRequest httpXmlRequest;

    public PayWechatResponse pay (PayWechatRequest payWechatRequest) throws Exception {
   
   
        // 这里可以写各种校验
        // 校验appid是否合法
        String appid = payWechatRequest.getAppid();
        WechatAppConfig wechatApp = wechatApps.get(appid);
        if (Objects.isNull(wechatApp)) {
   
   
            throw new ResponseException(ResultCode.WECHAT_PAY_APPID_ERROR);
        }

        // 校验支付方式tradeType是否合法
        String tradeType = payWechatRequest.getTradeType();
        boolean isContainTradeType = wechatApp.getTradeType().contains(tradeType);
        if (!isContainTradeType) {
   
   
            throw new ResponseException(ResultCode.WECHAT_PAY_TRADE_TYPE_NAME_ERROR);
        }

        // todo 校验该比订单的支付金额是否合法
        // todo 校验该笔订单的状态是否为待支付

        // 获取请求微信的xml参数
        String xml = getPayValidRequestXml(payWechatRequest);
        String responseXml = httpXmlRequest.postXml(wechatConfig.getUnifiedOrderUrl(), xml);
        Map<String, String> map = WXPayUtil.xmlToMap(responseXml);
        // 返回状态码==SUCCESS && 业务结果==SUCCESS  表示退款申请成功
        if (WechatConstant.SUCCESS.equals(map.get(WechatConstant.RETURN_CODE)) && WechatConstant.SUCCESS.equals(map.get(WechatConstant.RESULT_CODE))) {
   
   
            // todo 这里可以保存用户微信支付的唤醒记录
            WechatTradeTypeEnum wechatTradeTypeEnum = WechatTradeTypeEnum.valueOf(payWechatRequest.getTradeType());
            return generatePayWechatResponse(wechatTradeTypeEnum, appid, map);
        }
        throw new ResponseException(ResultCode.WECHAT_PAY_ERROR);
    }

    // 获取请求微信的xml参数
    private String getPayValidRequestXml (PayWechatRequest payWechatRequest) throws Exception {
   
   
        // 获取请求微信的xml对应的map
        Map<String, String> payXmlMap = getPayXmlMap(payWechatRequest);

        // 校验生成的签名
        boolean signatureValid = WXPayUtil.isSignatureValid(payXmlMap, wechatApps.get(payWechatRequest.getAppid()).getAppSecret());
        if (!signatureValid) {
   
   
            throw new ResponseException(ResultCode.WECHAT_PAY_SIGNATURE_VALID_ERROR);
        }

        //
        return WXPayUtil.mapToXml(payXmlMap);
    }


    private Map<String, String> getPayXmlMap (PayWechatRequest payWechatRequest) {
   
   
        Map<String, String> reqData = new HashMap<>();

        String appid = payWechatRequest.getAppid();
        WechatAppConfig wechatApp = wechatApps.get(appid);

        reqData.put(WechatConstant.APPID, appid);
        reqData.put(WechatConstant.MCH_ID, wechatApp.getMchId());
        reqData.put(WechatConstant.NONCE_STR , WXPayUtil.generateNonceStr());
        reqData.put(WechatConstant.BODY , payWechatRequest.getBody());
        reqData.put(WechatConstant.OUT_TRADE_NO , payWechatRequest.getOrderNo());
        reqData.put(WechatConstant.TOTAL_FEE , payWechatRequest.getFee());
        reqData.put(WechatConstant.SPBILL_CREATE_IP , payWechatRequest.getSpbillCreateIp());
        reqData.put(WechatConstant.NOTIFY_URL , wechatConfig.getUnifiedOrderCallbackUrl());
        reqData.put(WechatConstant.TRADE_TYPE , payWechatRequest.getTradeType());
        if (WechatTradeTypeEnum.JSAPI.name().equals(payWechatRequest.getTradeType())) {
   
   
            reqData.put(WechatConstant.OPENID , payWechatRequest.getOpenid());
        }
        if (WechatConstant.MD5.equals(wechatApp.getSignType())) {
   
   
            reqData.put(WechatConstant.SIGN_TYPE, WechatConstant.MD5);
        }
        else if (WechatConstant.HMACSHA256.equals(wechatApp.getSignType())) {
   
   
            reqData.put(WechatConstant.SIGN_TYPE, WechatConstant.HMACSHA256);
        } else {
   
   
            throw new ResponseException(ResultCode.WECHAT_CONFIG_SIGN_TYPE_ERROR);
        }
        try {
   
   
            reqData.put(WechatConstant.SIGN, WXPayUtil.generateSignature(reqData, wechatApp.getAppSecret(), WechatSignTypeEnum.valueOf(wechatApp.getSignType())));
        } catch (Exception e) {
   
   
            log.error("微信支付生成签名错误");
            e.printStackTrace();
            throw new ResponseException(ResultCode.WECHAT_PAY_GENERATE_SIGN_ERROR);
        }
        return reqData;
    }


    private PayWechatResponse generatePayWechatResponse(WechatTradeTypeEnum wechatTradeTypeEnum, String appid, Map<String, String> map) throws Exception {
   
   
        PayWechatResponse payWechatResponse = new PayWechatResponse();
        switch (wechatTradeTypeEnum) {
   
   
            case APP:
                payWechatResponse.setAppResponse(generatePayWechatAppResponse(appid, map));
                break;
            case JSAPI:
                payWechatResponse.setJsapiResponse(generatePayWechatJsapiResponse(appid, map));
                break;
            case NATIVE:
                break;
            case MWEB:
                break;
            default:
                break;
        }
        return payWechatResponse;
    }

    private PayWechatJsapiResponse generatePayWechatJsapiResponse (String appid, Map<String, String> map) throws Exception{
   
   
        // 对于微信返回的参数再签名
        Map<String, String> pkg = new HashMap<>();
        pkg.put("appId", appid);
        pkg.put("timeStamp", String.valueOf(System.currentTimeMillis()/1000));
        pkg.put("nonceStr", WXPayUtil.generateNonceStr());
        pkg.put("package", "prepay_id=" + map
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

难过的风景

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值