最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java微信退款開發(fā)

 更新時(shí)間:2018年09月29日 10:14:10   作者:thinkhui  
這篇文章主要為大家詳細(xì)介紹了Java微信退款開發(fā)的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下

一、下載證書并導(dǎo)入到系統(tǒng)

微信支付接口中,涉及資金回滾的接口會(huì)使用到商戶證書,包括退款、撤銷接口。商家在申請(qǐng)微信支付成功后,可以按照以下路徑下載:微信商戶平臺(tái)(pay.weixin.qq.com)-->賬戶設(shè)置-->API安全-->證書下載。

下載的時(shí)候需要手機(jī)驗(yàn)證及登錄密碼。下載后找到apiclient_cert.p12這個(gè)證書,雙擊導(dǎo)入,導(dǎo)入的時(shí)候提示輸入密碼,這個(gè)密碼就是商戶ID,且必須是在自己的商戶平臺(tái)下載的證書。否則會(huì)出現(xiàn)密碼錯(cuò)誤的提示:

導(dǎo)入正確的提示:

二、編寫代碼

首先初始化退款接口中的請(qǐng)求參數(shù),如微信訂單號(hào)transaction_id(和商戶訂單號(hào)只需要知道一個(gè))、訂單金額total_fee等;其次調(diào)用MobiMessage中的RefundResData2xml方法解析成需要的類型;最后調(diào)用RefundRequest類的httpsRequest方法觸發(fā)請(qǐng)求。

/**
 * 處理退款請(qǐng)求
 * @param request
 * @return
 * @throws Exception
 */
 @RequestMapping("/refund")
 @ResponseBody
 public JsonApi refund(HttpServletRequest request) throws Exception {
  //獲得當(dāng)前目錄
  String path = request.getSession().getServletContext().getRealPath("/");
  LogUtils.trace(path);
 
  Date now = new Date();
  SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmss");//可以方便地修改日期格式
  String outRefundNo = "NO" + dateFormat.format( now );
 
  //獲得退款的傳入?yún)?shù)
  String transactionID = "4008202001201609012791655620";
  String outTradeNo = "20160901141024";
  Integer totalFee = 1;
  Integer refundFee = totalFee;
 
  RefundReqData refundReqData = new RefundReqData(transactionID,outTradeNo,outRefundNo,totalFee,refundFee);
 
  String info = MobiMessage.RefundReqData2xml(refundReqData).replaceAll("__", "_");
  LogUtils.trace(info);
 
  try {
   RefundRequest refundRequest = new RefundRequest();
   String result = refundRequest.httpsRequest(WxConfigure.REFUND_API, info, path);
   LogUtils.trace(result);
 
   Map<String, String> getMap = MobiMessage.parseXml(new String(result.toString().getBytes(), "utf-8"));
   if("SUCCESS".equals(getMap.get("return_code")) && "SUCCESS".equals(getMap.get("return_msg"))){
    return new JsonApi();
   }else{
    //返回錯(cuò)誤描述
    return new JsonApi(getMap.get("err_code_des"));
   }
  }catch(Exception e){
   e.printStackTrace();
   return new JsonApi();
  }
}

初始化退款接口需要的數(shù)據(jù),隱藏了get和set方法。

public class RefundReqData {
 
 //每個(gè)字段具體的意思請(qǐng)查看API文檔
 private String appid = "";
 private String mch_id = "";
 private String nonce_str = "";
 private String sign = "";
 private String transaction_id = "";
 private String out_trade_no = "";
 private String out_refund_no = "";
 private int total_fee = 0;
 private int refund_fee = 0;
 private String op_user_id = "";
 
 /**
  * 請(qǐng)求退款服務(wù)
  * @param transactionID 是微信系統(tǒng)為每一筆支付交易分配的訂單號(hào),通過這個(gè)訂單號(hào)可以標(biāo)識(shí)這筆交易,它由支付訂單API支付成功時(shí)返回的數(shù)據(jù)里面獲取到。建議優(yōu)先使用
  * @param outTradeNo 商戶系統(tǒng)內(nèi)部的訂單號(hào),transaction_id 、out_trade_no 二選一,如果同時(shí)存在優(yōu)先級(jí):transaction_id>out_trade_no
  * @param outRefundNo 商戶系統(tǒng)內(nèi)部的退款單號(hào),商戶系統(tǒng)內(nèi)部唯一,同一退款單號(hào)多次請(qǐng)求只退一筆
  * @param totalFee 訂單總金額,單位為分
  * @param refundFee 退款總金額,單位為分
  */
 public RefundReqData(String transactionID,String outTradeNo,String outRefundNo,int totalFee,int refundFee){
 
  //微信分配的公眾號(hào)ID(開通公眾號(hào)之后可以獲取到)
  setAppid(WxConfigure.AppId);
 
  //微信支付分配的商戶號(hào)ID(開通公眾號(hào)的微信支付功能之后可以獲取到)
  setMch_id(WxConfigure.Mch_id);
 
  //transaction_id是微信系統(tǒng)為每一筆支付交易分配的訂單號(hào),通過這個(gè)訂單號(hào)可以標(biāo)識(shí)這筆交易,它由支付訂單API支付成功時(shí)返回的數(shù)據(jù)里面獲取到。
  setTransaction_id(transactionID);
 
  //商戶系統(tǒng)自己生成的唯一的訂單號(hào)
  setOut_trade_no(outTradeNo);
 
  setOut_refund_no(outRefundNo);
 
  setTotal_fee(totalFee);
 
  setRefund_fee(refundFee);
 
  setOp_user_id(WxConfigure.Mch_id);
 
  //隨機(jī)字符串,不長(zhǎng)于32 位
  setNonce_str(StringUtil.generateRandomString(16));
 
 
  //根據(jù)API給的簽名規(guī)則進(jìn)行簽名
  SortedMap<Object, Object> parameters = new TreeMap<Object, Object>();
  parameters.put("appid", appid);
  parameters.put("mch_id", mch_id);
  parameters.put("nonce_str", nonce_str);
  parameters.put("transaction_id", transaction_id);
  parameters.put("out_trade_no", out_trade_no);
  parameters.put("out_refund_no", out_refund_no);
  parameters.put("total_fee", total_fee);
  parameters.put("refund_fee", refund_fee);
  parameters.put("op_user_id", op_user_id);
 
 
  String sign = DictionarySort.createSign(parameters);
  setSign(sign); //把簽名數(shù)據(jù)設(shè)置到Sign這個(gè)屬性中
 
 }

MobiMessage實(shí)現(xiàn)json數(shù)據(jù)類型和xml數(shù)據(jù)之間的轉(zhuǎn)換。

public class MobiMessage {
 
 public static Map<String,String> xml2map(HttpServletRequest request) throws IOException, DocumentException {
  Map<String,String> map = new HashMap<String, String>();
  SAXReader reader = new SAXReader();
  InputStream inputStream = request.getInputStream();
  Document document = reader.read(inputStream);
  Element root = document.getRootElement();
  List<Element> list = root.elements();
  for(Element e:list){
   map.put(e.getName(), e.getText());
  }
  inputStream.close();
  return map;
 }
 
 
 //訂單轉(zhuǎn)換成xml
 public static String JsApiReqData2xml(JsApiReqData jsApiReqData){
  /*XStream xStream = new XStream();
  xStream.alias("xml",productInfo.getClass());
  return xStream.toXML(productInfo);*/
  MobiMessage.xstream.alias("xml",jsApiReqData.getClass());
  return MobiMessage.xstream.toXML(jsApiReqData);
 }
 
 public static String RefundReqData2xml(RefundReqData refundReqData){
  /*XStream xStream = new XStream();
  xStream.alias("xml",productInfo.getClass());
  return xStream.toXML(productInfo);*/
  MobiMessage.xstream.alias("xml",refundReqData.getClass());
  return MobiMessage.xstream.toXML(refundReqData);
 }
 
 public static String class2xml(Object object){
 
  return "";
 }
 public static Map<String, String> parseXml(String xml) throws Exception {
  Map<String, String> map = new HashMap<String, String>();
  Document document = DocumentHelper.parseText(xml);
  Element root = document.getRootElement();
  List<Element> elementList = root.elements();
  for (Element e : elementList)
   map.put(e.getName(), e.getText());
  return map;
 }
 
 //擴(kuò)展xstream,使其支持CDATA塊
 private static XStream xstream = new XStream(new XppDriver() {
  public HierarchicalStreamWriter createWriter(Writer out) {
   return new PrettyPrintWriter(out) {
    // 對(duì)所有xml節(jié)點(diǎn)的轉(zhuǎn)換都增加CDATA標(biāo)記
    boolean cdata = true;
 
    //@SuppressWarnings("unchecked")
    public void startNode(String name, Class clazz) {
     super.startNode(name, clazz);
    }
 
    protected void writeText(QuickWriter writer, String text) {
     if (cdata) {
      writer.write("<![CDATA[");
      writer.write(text);
      writer.write("]]>");
     } else {
      writer.write(text);
     }
    }
   };
  }
 });
 
 
}

RefundRequest類中initCert方法加載證書到系統(tǒng)中,其中證書地址如下:

public static String certLocalPath = "/WEB-INF/cert/apiclient_cert.p12";  

RefundRequest類中httpsRequest方法調(diào)用微信接口,觸發(fā)請(qǐng)求。

/**
 * User: rizenguo
 * Date: 2014/10/29
 * Time: 14:36
 */
public class RefundRequest {
 
 //連接超時(shí)時(shí)間,默認(rèn)10秒
 private int socketTimeout = 10000;
 
 //傳輸超時(shí)時(shí)間,默認(rèn)30秒
 private int connectTimeout = 30000;
 
 //請(qǐng)求器的配置
 private RequestConfig requestConfig;
 
 //HTTP請(qǐng)求器
 private CloseableHttpClient httpClient;
 
 /**
  * 加載證書
  * @param path
  * @throws IOException
  * @throws KeyStoreException
  * @throws UnrecoverableKeyException
  * @throws NoSuchAlgorithmException
  * @throws KeyManagementException
  */
 private void initCert(String path) throws IOException, KeyStoreException, UnrecoverableKeyException, NoSuchAlgorithmException, KeyManagementException {
  //拼接證書的路徑
  path = path + WxConfigure.certLocalPath;
  KeyStore keyStore = KeyStore.getInstance("PKCS12");
 
  //加載本地的證書進(jìn)行https加密傳輸
  FileInputStream instream = new FileInputStream(new File(path));
  try {
   keyStore.load(instream, WxConfigure.Mch_id.toCharArray()); //加載證書密碼,默認(rèn)為商戶ID
  } catch (CertificateException e) {
   e.printStackTrace();
  } catch (NoSuchAlgorithmException e) {
   e.printStackTrace();
  } finally {
   instream.close();
  }
 
  // Trust own CA and all self-signed certs
  SSLContext sslcontext = SSLContexts.custom()
    .loadKeyMaterial(keyStore, WxConfigure.Mch_id.toCharArray())  //加載證書密碼,默認(rèn)為商戶ID
    .build();
  // Allow TLSv1 protocol only
  SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
    sslcontext,
    new String[]{"TLSv1"},
    null,
    SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
 
  httpClient = HttpClients.custom()
    .setSSLSocketFactory(sslsf)
    .build();
 
  //根據(jù)默認(rèn)超時(shí)限制初始化requestConfig
  requestConfig = RequestConfig.custom().setSocketTimeout(socketTimeout).setConnectTimeout(connectTimeout).build();
 
 }
 
 
 /**
  * 通過Https往API post xml數(shù)據(jù)
  * @param url API地址
  * @param xmlObj 要提交的XML數(shù)據(jù)對(duì)象
  * @param path 當(dāng)前目錄,用于加載證書
  * @return
  * @throws IOException
  * @throws KeyStoreException
  * @throws UnrecoverableKeyException
  * @throws NoSuchAlgorithmException
  * @throws KeyManagementException
  */
 public String httpsRequest(String url, String xmlObj, String path) throws IOException, KeyStoreException, UnrecoverableKeyException, NoSuchAlgorithmException, KeyManagementException {
  //加載證書
  initCert(path);
 
  String result = null;
 
  HttpPost httpPost = new HttpPost(url);
 
  //得指明使用UTF-8編碼,否則到API服務(wù)器XML的中文不能被成功識(shí)別
  StringEntity postEntity = new StringEntity(xmlObj, "UTF-8");
  httpPost.addHeader("Content-Type", "text/xml");
  httpPost.setEntity(postEntity);
 
  //設(shè)置請(qǐng)求器的配置
  httpPost.setConfig(requestConfig);
 
  try {
   HttpResponse response = httpClient.execute(httpPost);
 
   HttpEntity entity = response.getEntity();
 
   result = EntityUtils.toString(entity, "UTF-8");
 
  } catch (ConnectionPoolTimeoutException e) {
   LogUtils.trace("http get throw ConnectionPoolTimeoutException(wait time out)");
 
  } catch (ConnectTimeoutException e) {
   LogUtils.trace("http get throw ConnectTimeoutException");
 
  } catch (SocketTimeoutException e) {
    LogUtils.trace("http get throw SocketTimeoutException");
 
  } catch (Exception e) {
    LogUtils.trace("http get throw Exception");
 
  } finally {
   httpPost.abort();
  }
 
  return result;
 }
}

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • Java lastIndexOf類使用方法原理解析

    Java lastIndexOf類使用方法原理解析

    這篇文章主要介紹了Java lastIndexOf類使用方法解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-07-07
  • JavaWeb 使用Session實(shí)現(xiàn)一次性驗(yàn)證碼功能

    JavaWeb 使用Session實(shí)現(xiàn)一次性驗(yàn)證碼功能

    這篇文章主要介紹了JavaWeb 使用Session實(shí)現(xiàn)一次性驗(yàn)證碼功能,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2019-08-08
  • java版實(shí)現(xiàn)2048游戲功能

    java版實(shí)現(xiàn)2048游戲功能

    這篇文章主要為大家詳細(xì)介紹了java版實(shí)現(xiàn)2048游戲功能,相加數(shù)字出現(xiàn)2048即可,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-07-07
  • Java建造者設(shè)計(jì)模式詳解

    Java建造者設(shè)計(jì)模式詳解

    這篇文章主要為大家詳細(xì)介紹了Java建造者設(shè)計(jì)模式,對(duì)建造者設(shè)計(jì)模式進(jìn)行分析理解,感興趣的小伙伴們可以參考一下
    2016-02-02
  • SpringBoot整合Mybatis-Plus實(shí)現(xiàn)關(guān)聯(lián)查詢

    SpringBoot整合Mybatis-Plus實(shí)現(xiàn)關(guān)聯(lián)查詢

    Mybatis-Plus(簡(jiǎn)稱MP)是一個(gè)Mybatis的增強(qiáng)工具,只是在Mybatis的基礎(chǔ)上做了增強(qiáng)卻不做改變,MyBatis-Plus支持所有Mybatis原生的特性,本文給大家介紹了SpringBoot整合Mybatis-Plus實(shí)現(xiàn)關(guān)聯(lián)查詢,需要的朋友可以參考下
    2024-08-08
  • SpringBoot實(shí)現(xiàn)異步消息處理的代碼示例

    SpringBoot實(shí)現(xiàn)異步消息處理的代碼示例

    在現(xiàn)代應(yīng)用程序中,異步消息處理是一項(xiàng)至關(guān)重要的任務(wù)。它可以提高應(yīng)用程序的性能、可伸縮性和可靠性,同時(shí)也可以提供更好的用戶體驗(yàn),本文將介紹如何使用Spring Boot實(shí)現(xiàn)異步消息處理,并提供相應(yīng)的代碼示例
    2023-06-06
  • java?Map集合中取鍵和值的4種方式舉例

    java?Map集合中取鍵和值的4種方式舉例

    Java中的Map是一種鍵值對(duì)存儲(chǔ)的數(shù)據(jù)結(jié)構(gòu),其中每個(gè)鍵都唯一,與一個(gè)值相關(guān)聯(lián),這篇文章主要給大家介紹了關(guān)于java?Map集合中取鍵和值的4種方式,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2024-01-01
  • 使用Nacos作為配置中心的命名空間、配置分組

    使用Nacos作為配置中心的命名空間、配置分組

    文章詳細(xì)介紹了Spring Cloud Config配置中心的命名空間、配置集、配置集ID、配置分組以及如何在微服務(wù)中加載和使用這些配置,通過配置中心,可以實(shí)現(xiàn)配置隔離和集中管理,簡(jiǎn)化微服務(wù)的配置維護(hù)
    2024-12-12
  • java實(shí)現(xiàn)短信驗(yàn)證碼5分鐘有效時(shí)間

    java實(shí)現(xiàn)短信驗(yàn)證碼5分鐘有效時(shí)間

    這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)短信驗(yàn)證碼5分鐘有效時(shí)間,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-07-07
  • Java編程技巧:if-else優(yōu)化實(shí)踐總結(jié)歸納

    Java編程技巧:if-else優(yōu)化實(shí)踐總結(jié)歸納

    這篇文章主要介紹了Java中避免過多if-else的幾種方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧
    2021-06-06

最新評(píng)論

福海县| 来凤县| 滨海县| 土默特右旗| 焉耆| 祁连县| 乐亭县| 会泽县| 正阳县| 南涧| 贡觉县| 海宁市| 定边县| 磐石市| 陆良县| 孟连| 恩平市| 六枝特区| 商河县| 满城县| 堆龙德庆县| 柞水县| 衡阳市| 平武县| 天全县| 百色市| 金阳县| 郸城县| 青州市| 义乌市| 手机| 亚东县| 利辛县| 松原市| 牡丹江市| 柳江县| 长岛县| 吕梁市| 九龙县| 全椒县| 塔城市|