• 关于微信和支付宝自动退款接口的接入总结


    一:支付宝的自动退款接口接入

      支付宝官方api:https://doc.open.alipay.com/doc2/apiDetail.htm?spm=a219a.7629065.0.0.PlTwKb&apiId=759&docType=4

      支付宝的自动退款按照官方文档开发都非常明了,不做太多的累赘:

      有一点不太清楚的地方是,在退款成功后没有返回支付宝自己的退款单号 

      官方文档截图如下:

     部分代码如下:

    public void orderPayRefund(OpsOrderRefundDetailModel refundDetailModel, String refundPrice) throws Exception{
    String appId = DataRequest.resources.getProperty("ali.app.appId");
    String publicKey = DataRequest.resources.getProperty("ali.public.key");
    AlipayClient alipayClient = new DefaultAlipayClient(
    "https://openapi.alipay.com/gateway.do",appId,PRIVATE_KEY,"json",
    "utf-8",publicKey,AlipayConstants.SIGN_TYPE_RSA);
    AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
    request.setBizContent("{" +
    " "out_trade_no":""+refundDetailModel.getOutTradeNo()+""," +
    " "refund_amount":"+refundPrice+"," +
    " "refund_reason":"正常退款"," +
    " "out_request_no":""+refundDetailModel.getId()+""" +
    " }");
    AlipayTradeRefundResponse response = alipayClient.execute(request);
    if(response.isSuccess()){
    dealRefundSuccess(refundDetailModel,refundPrice,response.getTradeNo());
    } else {
    logger.error(response.getMsg()+"退款失败");
    throw new UserHintException(response.getMsg());
    }
    }

    二:微信的自动退款接口接入

      微信官方api:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_4

      微信退款比较麻烦的是需要证书的双向认证,并且有签名算法做签名认证。

      官方文档截图如下:

      

     对于证书的使用以及签名生成算法可以在官方文档中详细去阅读,部分代码如下:

    public void refundApp(OpsOrderRefundDetailModel refundDetailModel,String refundPrice) throws Exception{
      // 1.证书的使用(这个证书使用可以在官方文档证书使用里面有官方demo)
    KeyStore keyStore = KeyStore.getInstance("PKCS12");
    InputStream instream = this.getClass().getResourceAsStream(DataRequest.resources.getProperty("weixin.app.cert"));
    try {
    keyStore.load(instream, DataRequest.resources.getProperty("weixin.app.mchId").toCharArray());
    } catch (Exception e){
    e.printStackTrace();
    }finally {
    instream.close();
    }
    // Trust own CA and all self-signed certs
    SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore,DataRequest.resources.getProperty("weixin.app.mchId").toCharArray()).build();
    // Allow TLSv1 protocol only
    SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
    sslcontext,
    new String[] { "TLSv1" },
    null,
    SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
    CloseableHttpClient httpclient = HttpClients.custom()
    .setSSLSocketFactory(sslsf)
    .build();
      //http请求创建
    HttpPost httppost = new HttpPost("https://api.mch.weixin.qq.com/secapi/pay/refund");
    UnifiedRefundRequest req = new UnifiedRefundRequest();
    req.setAppid(DataRequest.resources.getProperty("weixin.app.appId"));
    req.setMch_id(DataRequest.resources.getProperty("weixin.app.mchId"));
    req.setOut_trade_no(refundDetailModel.getOutTradeNo());
    req.setOut_refund_no(refundDetailModel.getId());
    req.setTotal_fee(refundDetailModel.getOrderPayedPrice().multiply(new BigDecimal(100)).intValue());
    req.setRefund_fee(new BigDecimal(refundPrice).multiply(new BigDecimal(100)).intValue());
    req.setOp_user_id("admin");
      // 这里createXml 方法已经完成了签名
    String xml = req.createXml();
      //<xml>
       //  <appid>wx2421b1c4370ec43b</appid>
       //  <mch_id>10000100</mch_id>
       //  <nonce_str>6cefdb308e1e2e8aabd48cf79e546a02</nonce_str>
       //  <op_user_id>10000100</op_user_id>
       //  <out_refund_no>1415701182</out_refund_no>
       //  <out_trade_no>1415757673</out_trade_no>
       //   <refund_fee>1</refund_fee>
       //  <total_fee>1</total_fee>
       //  <transaction_id></transaction_id>
       //  <sign>FE56DD4AA85C0EECA82C35595A69E153</sign>
      //</xml>
      //上面注掉的<xml>就是createXml的结果 红色的地方就是签名
    StringEntity entity = new StringEntity(xml, "UTF-8");
    httppost.setEntity(entity);
      //退款接口请求结果接受和处理
    CloseableHttpResponse responseEntry = httpclient.execute(httppost);
    HttpEntity resEntity = responseEntry.getEntity();
    String returnObj = (resEntity == null) ? null : EntityUtils.toString(resEntity, Consts.UTF_8);
    UnifiedOrderResponse resp = AbstractWxResponse.toBean(returnObj, UnifiedOrderResponse.class);
    resp.toVerify();
    if("SUCCESS".equals(resp.getResult_code())){
    dealRefundSuccess(refundDetailModel,refundPrice,resp.getRefund_id());
    }else{
    logger.error(resp.getErr_code_des()+"退款失败");
    throw new UserHintException(resp.getErr_code_des());
    }
    }

     简单的一个总结,希望能对大家有所帮助或者启发,当然最直接的东西还是看官方文档。

  • 相关阅读:
    CMake 从文件路径中提取文件名
    std::multimap 按照key遍历---
    Windows / Linux 一件编译zlib库
    C++ 11 可变模板参数的两种展开方式
    cmake 生成VS项目文件夹
    C++ 利用文件流复制文件
    利用 getsockname 和 getpeername 来获取某一个链接的本地地址和远端地址
    Windows 用VS编译libevent源码
    揭示同步块索引(上):从lock开始
    C手写一个多线程,供java调用
  • 原文地址:https://www.cnblogs.com/web-jiagou/p/6908946.html
Copyright © 2020-2023  润新知