玩转小程序支付之退款

作者: 就叫小木木呀 | 来源:发表于2019-05-28 16:29 被阅读1次

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

    官方文档: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 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 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,因为证书是微信认证过的商户独有的。

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

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

    相关文章

      网友评论

        本文标题:玩转小程序支付之退款

        本文链接:https://www.haomeiwen.com/subject/vabdtctx.html