玩转小程序支付之退款

完成小程序支付和保存支付通知内容之后,接下来就是退款啦

官方文档:https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=9_4

注意:

证书

调用API时需要使用证书,所以我们需要下载证书,并放在服务器里某个位置

/*
* 密钥证书文件的存放路径
*/
public static final String KEY_PATH = "/wwwroot/web/wechat/apiclient_cert.p12";

 代码如下:

----SpringBoot 的Controller
 
/**
       * 申请退款
       * @return
       */
      @RequestMapping(value = "/refund", method = RequestMethod.GET)
      @Transactional
      public @ResponseBody Map<String, Object> refund(String id,String user) {
            Map<String,Object> result = new HashMap<String,Object>();
            String currTime = PayUtils.getCurrTime();
            String strTime = currTime.substring(8, currTime.length());
            String strRandom = PayUtils.buildRandom(4) + "";
            String nonceStr = strTime + strRandom;
            String outRefundNo = "wx@re@"+PayUtils.getTimeStamp();
            String outTradeNo = "";
             
            ProfPayLog payLog = wxappOrderService.findByPayLogId(Long.valueOf(id));
            DecimalFormat df = new DecimalFormat("######0");
            String fee = String.valueOf(df.format((Double.valueOf(payLog.getTotalFee())*100)));
            SortedMap<String, String> packageParams = new TreeMap<String, String>();
            packageParams.put("appid", appId);
            packageParams.put("mch_id", mchId);//微信支付分配的商户号
            packageParams.put("nonce_str", nonceStr);//随机字符串,不长于32位
            packageParams.put("op_user_id", mchId);//操作员帐号, 默认为商户号
            //out_refund_no只能含有数字、字母和字符_-|*@
            packageParams.put("out_refund_no", outRefundNo);//商户系统内部的退款单号,商户系统内部唯一,同一退款单号多次请求只退一笔
            packageParams.put("out_trade_no", outTradeNo);//商户侧传给微信的订单号32位
            packageParams.put("refund_fee", fee);
            packageParams.put("total_fee", fee);
            packageParams.put("transaction_id", payLog.getTransactionId());//微信生成的订单号,在支付通知中有返回
            String sign = PayUtils.createSign(packageParams,key);
             
            String refundUrl = "https://api.mch.weixin.qq.com/secapi/pay/refund";
            String xmlParam="<xml>"+
                    "<appid>"+appId+"</appid>"+
                    "<mch_id>"+mchId+"</mch_id>"+
                    "<nonce_str>"+nonceStr+"</nonce_str>"+
                    "<op_user_id>"+mchId+"</op_user_id>"+
                    "<out_refund_no>"+outRefundNo+"</out_refund_no>"+
                    "<out_trade_no>"+outTradeNo+"</out_trade_no>"+
                    "<refund_fee>"+fee+"</refund_fee>"+
                    "<total_fee>"+fee+"</total_fee>"+
                    "<transaction_id>"+payLog.getTransactionId()+"</transaction_id>"+
                    "<sign>"+sign+"</sign>"+
                    "</xml>";
            String resultStr = PayUtils.post(refundUrl, xmlParam);
            //解析结果
            try {
                Map map =  PayUtils.doXMLParse(resultStr);
                String returnCode = map.get("return_code").toString();
                if(returnCode.equals("SUCCESS")){
                    String resultCode = map.get("result_code").toString();
                    if(resultCode.equals("SUCCESS")){
                        ProfPayLog profPayLog = new ProfPayLog();
                        profPayLog.setCreatedAt(new Date());
                        profPayLog.setSource(payLog.getSource());
                        profPayLog.setTotalFee(payLog.getTotalFee());
                        profPayLog.setTradeNo(payLog.getTradeNo());
                        profPayLog.setTransactionId(map.get("refund_id").toString());
                        profPayLog.setUserId(user);
                        profPayLog.setType(ProfPayLog.Type.Refund);
                        profPayLog = wxappOrderService.save(profPayLog);
                        result.put("status", "success");
                    }else{
                        result.put("status", "fail");
                    }
                }else{
                    result.put("status", "fail");
                }
            } catch (Exception e) {
                e.printStackTrace();
                result.put("status", "fail");
            }
            return result;
      }
----PayUtils 
 
public static String post(String url, String xmlParam){
        StringBuilder sb = new StringBuilder();
         try {
                KeyStore keyStore  = KeyStore.getInstance("PKCS12");
                FileInputStream instream = new FileInputStream(new File(KEY_PATH));
                try {
                    keyStore.load(instream, "商户id".toCharArray());
                } finally {
                    instream.close();
                }
          
                // 证书
                SSLContext sslcontext = SSLContexts.custom()
                        .loadKeyMaterial(keyStore, "商户id".toCharArray())
                        .build();
                // 只允许TLSv1协议
                SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
                        sslcontext,
                        new String[] { "TLSv1" },
                        null,
                        SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
                //创建基于证书的httpClient,后面要用到
                CloseableHttpClient client = HttpClients.custom()
                        .setSSLSocketFactory(sslsf)
                        .build();
                 
             HttpPost httpPost = new HttpPost(url);//退款接口
             StringEntity  reqEntity  = new StringEntity(xmlParam);
             // 设置类型
             reqEntity.setContentType("application/x-www-form-urlencoded");
             httpPost.setEntity(reqEntity);
             CloseableHttpResponse response = client.execute(httpPost);
             try {
                 HttpEntity entity = response.getEntity();
                 System.out.println(response.getStatusLine());
                 if (entity != null) {
                     BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(entity.getContent(),"UTF-8"));
                     String text="";
                     while ((text = bufferedReader.readLine()) != null) {
                         sb.append(text);
                     }
                 }
                 EntityUtils.consume(entity);
             } catch(Exception e){
                 e.printStackTrace();
             }finally {
                 try {
                    response.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
             }
         } catch (Exception e) {
                e.printStackTrace();
        }

注意:商户id是指前面用到的mch_id,因为证书是微信认证过的商户独有的。

码字不易,如果觉得有帮助,一定要给我点赞哟~~

不然信不信我砸了你家灯,半夜偷亲你 ( ̄ε  ̄) !!!

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
要实现Java小程序支付退款和账单查询,需要做以下准备工作: 1. 接入支付系统:首先,你需要选择一个支持Java的支付系统,比如支付宝或微信支付,并且按照其开发文档要求进行注册和认证。注册后,会获得相应的接入凭证,包括商户号、支付密钥等。 2. 集成支付SDK:根据支付系统提供的官方SDK(Software Development Kit,软件开发工具包),将其集成到你的Java小程序中。SDK提供了一系列的API(Application Programming Interface,应用程序编程接口),方便你调用支付相关的功能,比如生成支付订单、处理支付结果等。 3. 处理支付功能:在你的Java代码中,根据业务需求使用SDK提供的API,实现支付功能。你需要编写逻辑代码来生成支付订单,包括商品信息、金额、回调URL等,并将订单信息传递给支付系统。支付系统会返回一个支付链接或二维码,供用户进行支付。你需要监听支付结果回调,验证支付结果的合法性,并更新订单状态。 4. 实现退款功能:在支付成功后,可能会出现用户退款的情况。你需要编写代码来处理退款请求,包括退款金额、退款原因等,并与支付系统进行交互。支付系统会验证退款请求的合法性,并将退款结果返回给你的小程序。你需要验证退款结果,并更新订单状态。 5. 实现账单查询功能:为了方便商户查看交易记录和对账,你可以编写代码实现账单查询功能。通过调用支付系统提供的账单查询API,你可以获取某一时间段内的交易记录,包括交易金额、支付时间、退款状态等。 总结起来,实现Java小程序支付退款和账单查询,你需要接入支付系统、集成支付SDK,编写代码来处理支付退款和账单查询功能,并与支付系统进行交互。确保遵循支付系统的开发文档和规范,处理好支付安全、订单状态更新和退款结果验证等关键问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

东皋长歌

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

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

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

打赏作者

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

抵扣说明:

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

余额充值