小程序微信退款(退款信息回调解密)

本文介绍如何在微信小程序中实现退款功能,包括生成预退款订单、使用微信证书发起退款请求及处理退款回调等步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

小程序微信退款是有点简单,类似支付要生成预支付订单,然后等待wx回调,不过请求微信后台时,退款请求要用到微信证书,直接从wx获得就行;有疑问在下面留言噢

 /**
     * weixin申请退款
     * @param out_trade_no 商户订单号 (由商户自定义生成)
     * @param out_refund_no 商户退款单号
     * @param total_amount 订单付款总金额,单位为分,参数值不能带小数)
     * @param refund_fee 退款金额
     *  notify_url 商户退款单号 String(64)
     * @return
     */
    public ResultBean weiXinRefundCreate(String out_trade_no,String out_refund_no, int total_amount, int refund_fee) {
        /**
         * 1:生产预创建退款订单
         */
        ResultBean res=ResultBean.builder().build();
        String entity = genRefundProductArgs(out_trade_no,out_refund_no,total_amount,refund_fee);  //TODO 生成环境支付金额换成 paymentAmt int 整数,不能带小数
        log.info("请求http创建退款订单参数|"+entity);
        //建立连接并发送数据
        try {
            String result = WxHttpClientUtils.sendPostWxRefundByCertApi(WeixinConfig.wx_pay_refund, entity,WeixinConfig.MCH_ID);//商户server调用统一下单接口请求订单 的 接口链接
                /**
                 * 2:解析返回的xml
                 * 微信退款SUCCESS退款申请接收成功,结果通过退款查询接口查询
                 */
            Map<String, String> resultMap = WeixinSignUtils.decodeXml(result);
            log.info("微信退款SUCCESS退款申请接收参数|"+JSON.toJSONString(resultMap));
            //退款返回标志码
            String return_code = resultMap.get("return_code").toString();
            String result_code = resultMap.get("result_code").toString();
            if("SUCCESS".equals(return_code) && "SUCCESS".equals(result_code)){
                String outRefunNo=resultMap.get("out_refund_no");
                log.info("发起微信退款成功outRefunNo:"+outRefunNo);
                AtRefunds record=AtRefunds.builder().refundId(resultMap.get("refund_id")).outRefundNo(outRefunNo).refundId(resultMap.get("refund_id")).build();
                AtRefundsExample example=new AtRefundsExample();
                example.createCriteria().andOutRefundNoEqualTo(outRefunNo).andOutTradeSeqEqualTo(resultMap.get("out_trade_no"));
                atRefundsMapper.updateByExampleSelective(record,example);
                //TODO 是否更新减去用户消费金额扩展
                res.setMsg("发起微信退款成功");
                res.setRet(ResponseCodeEnum.SUCCESS.getCode());
            }else if(return_code.equals("SUCCESS") && result_code.equals("FAIL")){
                log.info("FAIL提交业务失败!");
                res.setMsg("FAIL提交业务失败!");
                res.setRet(ResponseCodeEnum.FAIL.getCode());
            }else{
                log.info("微信原路返款失败!!");
                res.setMsg("微信原路返款失败!");
                res.setRet(ResponseCodeEnum.FAIL.getCode());
            }
        }catch (Exception e){
            //错误码https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=9_4
            log.error("微信返款失败 Exception.");
            e.printStackTrace();
        }
        return res;
    }
sendPostWxRefundByCertApi:
/**
	 * 微信退款(证书)请求微信服务器,获取预退款订单
	 * @param url 请求url
	 * @param mch_id 用于加密的商户id
	 * @return String 退款结果
	 */
	public static String sendPostWxRefundByCertApi(String url, String xmlBody,String mch_id)  throws Exception{
		ClassPathResource classPathResource = new ClassPathResource("apiclient_cert.p12");//证书路径(此处我用的相对路径,你也可以考虑安全性,放在项目外)
		InputStream instream = classPathResource.getInputStream();
		KeyStore keyStore = KeyStore.getInstance("PKCS12");
		try {
			keyStore.load(instream, mch_id.toCharArray());
		} catch (Exception e) {
			logger.error("微信退款(证书)请求 证书加载失败");
			e.printStackTrace();
		} finally {
			instream.close();
		}
		SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore, mch_id.toCharArray()).build();
		SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext, new String[] { "TLSv1" }, null, SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
		CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build();
		String result = "";
		try {
			HttpPost httpPost = new HttpPost(url);
			httpPost.setEntity(new StringEntity(xmlBody));
			CloseableHttpResponse response = httpclient.execute(httpPost);
			try {
				HttpEntity entity = response.getEntity();
				result = EntityUtils.toString(entity, "UTF-8");
				System.out.println(response.getStatusLine());
				EntityUtils.consume(entity);
			} finally {
				response.close();
			}
		} finally {
			httpclient.close();
		}
		//去除空格
		return result.replaceAll(" ", "");
	}

回调

/**
     * 微信小程序径山花海 退款回调通知
     * 特别说明:退款结果对重要的数据进行了加密,商户需要用商户秘钥进行解密后才能获得结果通知的内容
     */
    @PostMapping("/wxRefundCallback")
    public String weixin_refundCallback(HttpServletRequest request){
        String weixinparam = null;
        log.info("微信退款回调开始啦!!!!");
        try {
            InputStream inStream = request.getInputStream();
            int _buffer_size = 1024;
            if (inStream != null) {
                ByteArrayOutputStream outStream = new ByteArrayOutputStream();
                byte[] tempBytes = new byte[_buffer_size];
                int count = -1;
                while ((count = inStream.read(tempBytes, 0, _buffer_size)) != -1) {
                    outStream.write(tempBytes, 0, count);
                }
                tempBytes = null;
                outStream.flush();
                //将流转换成字符串
                weixinparam = new String(outStream.toByteArray(), "UTF-8");
            }
        } catch (IOException e) {
            log.error("微信退款回调返回数据样例格式化fail");
            e.printStackTrace();
        }
        if (weixinparam == null) return resWXfail();
        Map<String, String> resMap = WeixinSignUtils.decodeXml(weixinparam);
        log.info("wx退款回调xml解析|" + JSON.toJSONString(resMap));
        /**
         * 2:通信成功,解密参数
         */
        if ("SUCCESS".equals(resMap.get("return_code"))){
//            String appid = resMap.get("appid");
            String req_info = resMap.get("req_info");
            Map<String, String> reqMap =null;
            try {
                //2.1解密参数,业务处理
                String reqXml = AESUtil.wx_refund_decryptData(req_info,WeixinConfig.API_KEY);
                reqMap = WeixinSignUtils.decodeXml(reqXml);
            } catch (Exception e) {
                log.error("解密参数Exception ,req_info:"+req_info);
                e.printStackTrace();
            }
            if (reqMap == null) {
                return resWXfail();
            }
            int flag =otherPayCallbackService.weixin_refundCallback(reqMap);
            /**
             * 返回成功给微信
             */
            if (flag == 1) {
                StringBuffer sb = new StringBuffer();
                sb.append("<xml>");
                sb.append("<return_code><![CDATA[SUCCESS]]></return_code>");
                sb.append("</xml>");
                log.debug("返回SUCCESS给微信");
                return sb.toString();
            }else{
                log.error("返回failure给微信");
            }
        } else {
            log.error("wx退款回调xml解析error|"+resMap.get("return_msg"));
        }
        return resWXfail();
    }

开发中参考了https://blog.csdn.net/weixin_43820012/article/details/99092320

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值