Browse Source

银行提现接口

小么熊🐻 3 years ago
parent
commit
bf7837f738

+ 1 - 0
jsjp-admin/src/main/java/com/miaxis/app/controller/wx/WxNotifyController.java

@@ -271,6 +271,7 @@ public class WxNotifyController {
         wxJsOrder.setTradeStateDesc(jsonObject.getString("trade_state_desc"));
         wxJsOrder.setTradeType(jsonObject.getString("trade_type"));
         wxJsOrder.setAttach(jsonObject.getString("attach"));
+        wxJsOrder.setOrderStatus("2");
 
         //插入VIP信息
         writeVipDataToDb(wxJsOrder);

+ 0 - 1
jsjp-admin/src/main/java/com/miaxis/pc/controller/order/WxJsOrderController.java

@@ -6,7 +6,6 @@ import com.miaxis.common.core.domain.Response;
 import com.miaxis.common.core.page.ResponsePageInfo;
 import com.miaxis.common.enums.BusinessTypeEnum;
 import com.miaxis.common.utils.OrderCodeFactory;
-import com.miaxis.common.utils.poi.ExcelUtil;
 import com.miaxis.wx.domain.WxJsOrder;
 import com.miaxis.wx.dto.WxJsOrderOutTradeNoDTO;
 import com.miaxis.wx.dto.WxNotifyReturnDTO;

+ 9 - 0
jsjp-admin/src/main/resources/wechatpay/public.pem

@@ -0,0 +1,9 @@
+-----BEGIN PUBLIC KEY-----
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5cD6KUwdmiiQ8UoKoyIr
++yo6IKc/hWAaSCpRK3LO2nFKDzmAIFqBnWDvzYu7E70vL/tq7NQFr/QX7I1MJjER
+3sJkIXXOvyh5ajsF57nsKfLc9qS+I9TClH2fVlieIoMaGhpnnpyeauVEK7cvboYO
+gC5yDmyr6e8F6u/X8vJk+YDCWkYWpfMgs7NvPmjIgo8hug58k2xApmQkfwfQ54qE
+5ymZdV37dONaMSgxiYsAETjYybOb17vvMsB5hV2GwOCwjvpXQeR6/PnKSY5p/uM9
+7mAKECDuExQpkrbow6i27AlVkrG9QPlp0d4yaSBjW7LUUshVtS0Rz1RjEgTGVsCp
+KQIDAQAB
+-----END PUBLIC KEY-----

+ 190 - 0
jsjp-admin/src/test/java/com/miaxis/test/HttpClientSSL.java

@@ -0,0 +1,190 @@
+package com.miaxis.test;
+
+import org.apache.http.HttpEntity;
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
+import org.apache.http.entity.StringEntity;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClients;
+import org.apache.http.ssl.SSLContexts;
+import org.apache.http.util.EntityUtils;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+
+import javax.net.ssl.SSLContext;
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.StringWriter;
+import java.security.KeyStore;
+import java.security.MessageDigest;
+import java.security.SecureRandom;
+import java.util.*;
+
+public class HttpClientSSL {
+    Logger log = LogManager.getLogger(HttpClientSSL.class);
+
+    private static String payUrl = "https://fraud.mch.weixin.qq.com/risk/getpublickey";
+    //商户key
+    private static String KEY = "7hM14893GvG3JK05575jk1l6P4tF042B";
+    //商户mch_id
+    private static String mchId = "1611324484";
+
+    public static void main(String[] args) throws Exception {
+        Map<String, String> parameterMap = new HashMap<>();
+        parameterMap.put("mch_id", mchId);
+        parameterMap.put("nonce_str", generateNonceStr());
+        try{
+
+            parameterMap.put("sign_type", "MD5");
+            parameterMap.put("sign", HttpClientSSL.generateSignature(parameterMap,KEY,"MD5"));
+            //要以xml格式传递
+            String postDataXML = HttpClientSSL.mapToXml(parameterMap);
+            String result = HttpClientSSL.wxRefundLink(postDataXML, mchId );
+
+            System.out.println(result);
+        }catch (Exception e){
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * 将Map转换为XML格式的字符串
+     *
+     * @param data Map类型数据
+     * @return XML格式的字符串
+     * @throws Exception
+     */
+    public static String mapToXml(Map<String, String> data) throws Exception {
+        org.w3c.dom.Document document = WXPayXmlUtil.newDocument();
+        org.w3c.dom.Element root = document.createElement("xml");
+        document.appendChild(root);
+        for (String key: data.keySet()) {
+            String value = data.get(key);
+            if (value == null) {
+                value = "";
+            }
+            value = value.trim();
+            org.w3c.dom.Element filed = document.createElement(key);
+            filed.appendChild(document.createTextNode(value));
+            root.appendChild(filed);
+        }
+        TransformerFactory tf = TransformerFactory.newInstance();
+        Transformer transformer = tf.newTransformer();
+        DOMSource source = new DOMSource(document);
+        transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
+        transformer.setOutputProperty(OutputKeys.INDENT, "yes");
+        StringWriter writer = new StringWriter();
+        StreamResult result = new StreamResult(writer);
+        transformer.transform(source, result);
+        String output = writer.getBuffer().toString(); //.replaceAll("\n|\r", "");
+        try {
+            writer.close();
+        }
+        catch (Exception ex) {
+        }
+        return output;
+    }
+
+    private static final String SYMBOLS = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
+
+    private static final Random RANDOM = new SecureRandom();
+    /**
+     * 获取随机字符串 Nonce Str
+     *
+     * @return String 随机字符串
+     */
+    public static String generateNonceStr() {
+        char[] nonceChars = new char[32];
+        for (int index = 0; index < nonceChars.length; ++index) {
+            nonceChars[index] = SYMBOLS.charAt(RANDOM.nextInt(SYMBOLS.length()));
+        }
+        return new String(nonceChars);
+    }
+    public static String generateSignature(Map<String, String> data, String key, String signType) throws Exception {
+        Set<String> keySet = data.keySet();
+        String[] keyArray = keySet.toArray(new String[keySet.size()]);
+        Arrays.sort(keyArray);
+        StringBuilder sb = new StringBuilder();
+        for (String k : keyArray) {
+            if (k.equals("sign")) {
+                continue;
+            }
+            if (data.get(k).trim().length() > 0) // 参数值为空,则不参与签名
+                sb.append(k).append("=").append(data.get(k).trim()).append("&");
+        }
+        sb.append("key=").append(key);
+        if ("MD5".equals(signType)) {
+            return MD5(sb.toString()).toUpperCase();
+        }
+        else {
+            throw new Exception(String.format("Invalid sign_type: %s", signType));
+        }
+    }
+    /**
+     * 生成 MD5
+     *
+     * @param data 待处理数据
+     * @return MD5结果
+     */
+    public static String MD5(String data) throws Exception {
+        java.security.MessageDigest md = MessageDigest.getInstance("MD5");
+        byte[] array = md.digest(data.getBytes("UTF-8"));
+        StringBuilder sb = new StringBuilder();
+        for (byte item : array) {
+            sb.append(Integer.toHexString((item & 0xFF) | 0x100).substring(1, 3));
+        }
+        return sb.toString().toUpperCase();
+    }
+
+    private static String  wxRefundLink(String postDataXML,String mch_id) throws Exception{
+        CloseableHttpClient httpClient = null;
+        CloseableHttpResponse httpResponse = null;
+        try{
+            //获取微信支付api证书
+            KeyStore keyStore = getCertificate(mch_id);
+            SSLContext sslContext = SSLContexts.custom().loadKeyMaterial(keyStore, mch_id.toCharArray()).build();
+            SSLConnectionSocketFactory sslf = new SSLConnectionSocketFactory(sslContext);
+            httpClient = HttpClients.custom().setSSLSocketFactory(sslf).build();
+            HttpPost httpPost = new HttpPost(payUrl);
+
+            StringEntity reqEntity = new StringEntity(postDataXML);
+            // 设置类型
+            reqEntity.setContentType("application/x-www-form-urlencoded");
+            httpPost.setEntity(reqEntity);
+            String result = null;
+            httpResponse = httpClient.execute(httpPost);
+            HttpEntity httpEntity = httpResponse.getEntity();
+            result = EntityUtils.toString(httpEntity, "UTF8");
+            EntityUtils.consume(httpEntity);
+            return result;
+        }finally {//关流
+            httpClient.close();
+            httpResponse.close();
+        }
+
+    }
+
+    /**
+     *
+     * @description: 获取微信支付api证书
+     */
+    private static KeyStore getCertificate(String mch_id){
+        //try-with-resources 关流
+        try {
+            String certificate_path = "D:\\ideaMiaxis\\jsjp\\jsjp-admin\\src\\main\\resources\\wechatpay" + File.separator + "apiclient_cert.p12";
+            FileInputStream inputStream = new FileInputStream(certificate_path);
+            KeyStore keyStore = KeyStore.getInstance("PKCS12");
+            keyStore.load(inputStream, mch_id.toCharArray());
+            return keyStore;
+        } catch (Exception e) {
+            throw new RuntimeException(e.getMessage(), e);
+        }
+    }
+
+}

+ 31 - 0
jsjp-admin/src/test/java/com/miaxis/test/WXPayXmlUtil.java

@@ -0,0 +1,31 @@
+package com.miaxis.test;
+
+import org.w3c.dom.Document;
+
+import javax.xml.XMLConstants;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+
+/**
+ * 2018/7/3
+ */
+public final class WXPayXmlUtil {
+    public static DocumentBuilder newDocumentBuilder() throws ParserConfigurationException {
+        DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
+        documentBuilderFactory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
+        documentBuilderFactory.setFeature("http://xml.org/sax/features/external-general-entities", false);
+        documentBuilderFactory.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
+        documentBuilderFactory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
+        documentBuilderFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
+        documentBuilderFactory.setXIncludeAware(false);
+        documentBuilderFactory.setExpandEntityReferences(false);
+
+        return documentBuilderFactory.newDocumentBuilder();
+    }
+
+    public static Document newDocument() throws ParserConfigurationException {
+        return newDocumentBuilder().newDocument();
+    }
+
+}

+ 36 - 0
jsjp-admin/src/test/java/com/miaxis/test/WxExtractTest.java

@@ -0,0 +1,36 @@
+package com.miaxis.test;
+
+import com.miaxis.JsjpApplication;
+import com.miaxis.wx.dto.WxExtractBankDTO;
+import com.miaxis.wx.service.IWxExtractService;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+
+@SpringBootTest(classes = JsjpApplication.class)
+@RunWith(SpringRunner.class)
+public class WxExtractTest {
+
+    @Autowired
+    private IWxExtractService wxExtractService;
+
+    @Test
+    public void test2() throws Exception {
+
+        WxExtractBankDTO cb = new WxExtractBankDTO();
+
+        cb.setBankCode(1003);
+        cb.setEncBankNo("6227001823210062458");
+        cb.setEncTrueName("张滨");
+        cb.setAmount(1);
+
+        wxExtractService.wxwithbankdrawal(cb);
+
+    }
+
+
+
+
+}

+ 6 - 0
jsjp-common/pom.xml

@@ -152,6 +152,12 @@
             <version>5.6.38</version>
         </dependency>
 
+        <dependency>
+            <groupId>com.github.wxpay</groupId>
+            <artifactId>wxpay-sdk</artifactId>
+            <version>0.0.3</version>
+        </dependency>
+
         <!--腾讯云sdk依赖,排除log4j依赖,解决与框架中logback的冲突-->
         <dependency>
             <groupId>com.qcloud</groupId>

+ 26 - 0
jsjp-common/src/main/java/com/miaxis/common/config/BeanConfig.java

@@ -15,6 +15,8 @@ import com.wechat.pay.contrib.apache.httpclient.WechatPayHttpClientBuilder;
 import com.wechat.pay.contrib.apache.httpclient.auth.AutoUpdateCertificatesVerifier;
 import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Validator;
 import org.apache.http.client.HttpClient;
+import org.bouncycastle.util.io.pem.PemObject;
+import org.bouncycastle.util.io.pem.PemReader;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.context.annotation.Bean;
@@ -22,7 +24,11 @@ import org.springframework.context.annotation.Configuration;
 import org.springframework.core.io.ClassPathResource;
 
 import java.io.File;
+import java.io.FileReader;
+import java.security.KeyFactory;
 import java.security.PrivateKey;
+import java.security.interfaces.RSAPublicKey;
+import java.security.spec.X509EncodedKeySpec;
 
 
 @Configuration
@@ -113,6 +119,26 @@ public class BeanConfig {
 
     }
 
+    /**
+     * 创建微信公钥 对象
+     * @return
+     * @throws Exception
+     */
+    @Bean
+    public RSAPublicKey readPublicKey() throws Exception {
+        KeyFactory factory = KeyFactory.getInstance("RSA");
+
+        File file = new ClassPathResource("wechatpay/public.pem").getFile();
+        try (FileReader keyReader = new FileReader(file);
+             PemReader pemReader = new PemReader(keyReader)) {
+
+            PemObject pemObject = pemReader.readPemObject();
+            byte[] content = pemObject.getContent();
+            X509EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(content);
+            return (RSAPublicKey) factory.generatePublic(pubKeySpec);
+        }
+    }
+
 
 
 

+ 94 - 0
jsjp-common/src/main/java/com/miaxis/common/config/WxPayConfigImpl.java

@@ -0,0 +1,94 @@
+package com.miaxis.common.config;
+
+import com.github.wxpay.sdk.WXPayConfig;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.core.io.ClassPathResource;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.FileInputStream;
+import java.io.InputStream;
+
+
+public class WxPayConfigImpl implements WXPayConfig {
+    public static String url = "你设置的回调接口";
+    private static WxPayConfigImpl wxPayConfig;
+    private byte[] certData = null;
+
+
+//    @Resource
+//    private WxpayConfig wxpayConfigBean;
+
+    @Value("${app.appid}")
+    private String appid;
+
+    public static WxPayConfigImpl getInstance() {
+        if (wxPayConfig == null) {
+            synchronized (WxPayConfigImpl.class) {
+                wxPayConfig = new WxPayConfigImpl();
+            }
+        }
+        return wxPayConfig;
+    }
+
+    public WxPayConfigImpl() {
+        try {
+            //这个证书的位置不是瞎鸡儿填的,你要在这个路径真的有一个证书
+            // InputStream is = new FileInputStream("F:\\twzd\\twzd\\twzd-admin\\src\\main\\resources\\wechatpay\\apiclient_cert.p12");
+            InputStream is = new FileInputStream(new ClassPathResource("wechatpay/apiclient_cert.p12").getFile());
+            ByteArrayOutputStream baos = new ByteArrayOutputStream();
+            byte[] bs = new byte[1024];
+            int cnt = -1;
+            while ((cnt = is.read(bs)) != -1) {
+                baos.write(bs, 0, cnt);
+            }
+            is.close();
+            certData = baos.toByteArray();
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    @Override
+    public String getAppID() {
+        return "wx67ca1b8c9816ef28";
+    }
+
+    @Override
+    public String getMchID() {
+        return "1615410794";
+    }
+
+    @Override
+    public String getKey() {
+        return "12345678123456781234567812345678";
+    }
+
+    @Override
+    public InputStream getCertStream() {
+        ByteArrayInputStream certBis;
+        certBis = new ByteArrayInputStream(this.certData);
+        return certBis;
+    }
+
+    @Override
+    public int getHttpConnectTimeoutMs() {
+        // TODO Auto-generated method stub
+        return 8000;
+    }
+
+    @Override
+    public int getHttpReadTimeoutMs() {
+        // TODO Auto-generated method stub
+        return 10000;
+    }
+
+
+    public String getPrimaryDomain() {
+        return "api.mch.weixin.qq.com";
+    }
+
+    public String getNotifyUrl(){
+        return url;
+    }
+}

+ 126 - 0
jsjp-common/src/main/java/com/miaxis/common/utils/RSAUtils.java

@@ -0,0 +1,126 @@
+package com.miaxis.common.utils;
+
+
+
+import org.apache.commons.codec.binary.Base64;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import javax.crypto.Cipher;
+import java.io.ByteArrayOutputStream;
+import java.security.PublicKey;
+import java.security.interfaces.RSAPublicKey;
+
+/**
+ * 描述:
+ *
+ * @author chen_q_i@163.com
+ * 2018/5/10 : 14:23.
+ * @version : 1.0
+ */
+@Component
+public class RSAUtils {
+    Logger log = LoggerFactory.getLogger(RSAUtils.class);
+    private static String RSA = "RSA";
+
+
+    @Autowired
+    private RSAPublicKey rsaPublicKey;
+
+    private static final int KEYLENGTH = 2048;
+    private static final int RESERVESIZE = 11;
+    /**
+     * 指定填充模式
+     */
+    private static final String CIPHERALGORITHM = "RSA/ECB/OAEPWITHSHA-1ANDMGF1PADDING";
+
+
+    /**
+     * 用公钥加密 <br>
+     * 每次加密的字节数,不能超过密钥的长度值减去11
+     *
+     * @param plainBytes 需加密数据的byte数据
+     * @param publicKey  公钥
+     * @return 加密后的byte型数据
+     */
+    public String encrypt(byte[] plainBytes, PublicKey publicKey) throws Exception {
+        int keyByteSize = KEYLENGTH / 8;
+        int encryptBlockSize = keyByteSize - RESERVESIZE;
+        int nBlock = plainBytes.length / encryptBlockSize;
+        if ((plainBytes.length % encryptBlockSize) != 0) {
+            nBlock += 1;
+        }
+        ByteArrayOutputStream outbuf = null;
+        try {
+            Cipher cipher = Cipher.getInstance(CIPHERALGORITHM);
+            cipher.init(Cipher.ENCRYPT_MODE, publicKey);
+
+            outbuf = new ByteArrayOutputStream(nBlock * keyByteSize);
+            for (int offset = 0; offset < plainBytes.length; offset += encryptBlockSize) {
+                int inputLen = plainBytes.length - offset;
+                if (inputLen > encryptBlockSize) {
+                    inputLen = encryptBlockSize;
+                }
+                byte[] encryptedBlock = cipher.doFinal(plainBytes, offset, inputLen);
+                outbuf.write(encryptedBlock);
+            }
+            outbuf.flush();
+            byte[] encryptedData = outbuf.toByteArray();
+            return Base64.encodeBase64String(encryptedData);
+        } catch (Exception e) {
+            throw new Exception("ENCRYPT ERROR:", e);
+        } finally {
+            try {
+                if (outbuf != null) {
+                    outbuf.close();
+                }
+            } catch (Exception e) {
+                throw new Exception("CLOSE ByteArrayOutputStream ERROR:", e);
+            }
+        }
+    }
+
+
+
+
+
+
+    /***
+     * decode by Base64
+     */
+    public byte[] decodeBase64(String input) throws Exception {
+        return Base64.decodeBase64(input);
+
+    }
+
+    /**
+     * encodeBase64
+     */
+    public String encodeBase64(byte[] input) throws Exception {
+        return Base64.encodeBase64String(input);
+    }
+
+    /**
+     * 打印公钥信息
+     *
+     * @param publicKey
+     */
+    public  void printPublicKeyInfo(PublicKey publicKey) {
+        RSAPublicKey rsaPublicKey = (RSAPublicKey) publicKey;
+        log.info("----------RSAPublicKey----------");
+        log.info("Modulus.length=" + rsaPublicKey.getModulus().bitLength());
+        log.info("Modulus=" + rsaPublicKey.getModulus().toString());
+        log.info("PublicExponent.length=" + rsaPublicKey.getPublicExponent().bitLength());
+        log.info("PublicExponent=" + rsaPublicKey.getPublicExponent().toString());
+    }
+
+    public String encryptData(String data) throws Exception {
+        return encrypt(data.getBytes("UTF-8"), rsaPublicKey);
+    }
+
+
+
+}
+

+ 161 - 0
jsjp-common/src/main/java/com/miaxis/common/utils/XmlUtil.java

@@ -0,0 +1,161 @@
+package com.miaxis.common.utils;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.io.StringWriter;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * xml util
+ * @author wwl
+ * @version 1.0
+ * @date 2021/10/26 14:55
+ */
+public class XmlUtil {
+
+    private static final Logger log = LoggerFactory.getLogger(XmlUtil.class);
+
+    /**
+     * 将Map转换为XML格式的字符串
+     *
+     * @param data Map类型数据
+     * @return XML格式的字符串
+     * @throws Exception
+     */
+    public static String mapToXml(Map<String, String> data) throws Exception {
+        log.info("----mapToXml-----"+data);
+        DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
+        DocumentBuilder documentBuilder= documentBuilderFactory.newDocumentBuilder();
+        org.w3c.dom.Document document = documentBuilder.newDocument();
+        org.w3c.dom.Element root = document.createElement("xml");
+        document.appendChild(root);
+        for (String key: data.keySet()) {
+            String value = data.get(key);
+            if (value == null) {
+                value = "";
+            }
+            value = value.trim();
+            org.w3c.dom.Element filed = document.createElement(key);
+            filed.appendChild(document.createTextNode(value));
+            root.appendChild(filed);
+        }
+        TransformerFactory tf = TransformerFactory.newInstance();
+        Transformer transformer = tf.newTransformer();
+        DOMSource source = new DOMSource(document);
+        transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
+        transformer.setOutputProperty(OutputKeys.INDENT, "yes");
+        StringWriter writer = new StringWriter();
+        StreamResult result = new StreamResult(writer);
+        transformer.transform(source, result);
+        String output = writer.getBuffer().toString(); //.replaceAll("\n|\r", "");
+        try {
+            writer.close();
+        } catch (Exception ex) {
+
+        }
+        log.info("----mapToXml-return-----"+output);
+        return output;
+    }
+
+
+    /**
+     * 微信回复图片 map转换xml
+     * @param data
+     * @return
+     * @throws Exception
+     */
+    public static String mapToXmlSpecial(Map<String, String> data) throws Exception {
+        log.info("----mapToXml-----"+data);
+        DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
+        DocumentBuilder documentBuilder= documentBuilderFactory.newDocumentBuilder();
+        org.w3c.dom.Document document = documentBuilder.newDocument();
+        org.w3c.dom.Element root = document.createElement("xml");
+        document.appendChild(root);
+
+        org.w3c.dom.Element toUserName = document.createElement("ToUserName");
+        toUserName.setTextContent(data.get("ToUserName"));
+        root.appendChild(toUserName);
+        org.w3c.dom.Element fromUserName = document.createElement("FromUserName");
+        fromUserName.setTextContent(data.get("FromUserName"));
+        root.appendChild(fromUserName);
+        org.w3c.dom.Element createTime = document.createElement("CreateTime");
+        createTime.setTextContent(data.get("CreateTime"));
+        root.appendChild(createTime);
+        org.w3c.dom.Element msgType = document.createElement("MsgType");
+        msgType.setTextContent(data.get("MsgType"));
+        root.appendChild(msgType);
+        org.w3c.dom.Element image = document.createElement("Image");
+        root.appendChild(image);
+        org.w3c.dom.Element mediaId = document.createElement("MediaId");
+        mediaId.setTextContent(data.get("MediaId"));
+        image.appendChild(mediaId);
+
+        TransformerFactory tf = TransformerFactory.newInstance();
+        Transformer transformer = tf.newTransformer();
+        DOMSource source = new DOMSource(document);
+        transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
+        transformer.setOutputProperty(OutputKeys.INDENT, "yes");
+        StringWriter writer = new StringWriter();
+        StreamResult result = new StreamResult(writer);
+        transformer.transform(source, result);
+        String output = writer.getBuffer().toString(); //.replaceAll("\n|\r", "");
+        try {
+            writer.close();
+        } catch (Exception ex) {
+
+        }
+        log.info("----mapToXml-return-----"+output);
+        return output;
+    }
+
+
+    /**
+     * XML格式字符串转换为Map
+     *
+     * @param strXML XML字符串
+     * @return XML数据转换后的Map
+     * @throws Exception
+     */
+    public static Map<String, String> xmlToMap(String strXML) throws Exception {
+        log.info("4....");
+        try {
+            Map<String, String> data = new HashMap<>();
+            DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
+            DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
+            InputStream stream = new ByteArrayInputStream(strXML.getBytes("UTF-8"));
+            org.w3c.dom.Document doc = documentBuilder.parse(stream);
+            doc.getDocumentElement().normalize();
+            NodeList nodeList = doc.getDocumentElement().getChildNodes();
+            for (int idx = 0; idx < nodeList.getLength(); ++idx) {
+                Node node = nodeList.item(idx);
+                if (node.getNodeType() == Node.ELEMENT_NODE) {
+                    org.w3c.dom.Element element = (org.w3c.dom.Element) node;
+                    data.put(element.getNodeName(), element.getTextContent());
+                }
+            }
+            try {
+                stream.close();
+            } catch (Exception ex) {
+                // do nothing
+            }
+            return data;
+        } catch (Exception ex) {
+            throw ex;
+        }
+    }
+
+
+}

+ 26 - 0
jsjp-service/src/main/java/com/miaxis/wx/dto/WxExtractBankDTO.java

@@ -0,0 +1,26 @@
+package com.miaxis.wx.dto;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+@Data
+public class WxExtractBankDTO {
+    private static final long serialVersionUID = 1L;
+
+    @ApiModelProperty(value = "银行编号",required = true)
+    private Integer bankCode;
+
+    @ApiModelProperty(value = "银行卡",required = true)
+    private String encBankNo;
+
+    @ApiModelProperty(value = "收款人姓名",required = true)
+    private String encTrueName;
+
+    @ApiModelProperty(value = "提现金额",required = true)
+    private Integer amount;
+
+
+
+
+
+}

+ 10 - 0
jsjp-service/src/main/java/com/miaxis/wx/service/IWxExtractService.java

@@ -0,0 +1,10 @@
+package com.miaxis.wx.service;
+
+import com.miaxis.wx.dto.WxExtractBankDTO;
+
+public interface IWxExtractService {
+
+
+    public String wxwithbankdrawal(WxExtractBankDTO dto) throws Exception;
+
+}

+ 68 - 0
jsjp-service/src/main/java/com/miaxis/wx/service/impl/WxExtreactServiceImpl.java

@@ -0,0 +1,68 @@
+package com.miaxis.wx.service.impl;
+
+import com.github.wxpay.sdk.WXPay;
+import com.github.wxpay.sdk.WXPayConfig;
+import com.github.wxpay.sdk.WXPayConstants;
+import com.github.wxpay.sdk.WXPayUtil;
+import com.miaxis.common.config.WxPayConfigImpl;
+import com.miaxis.common.config.WxpayConfig;
+import com.miaxis.common.exception.CustomException;
+import com.miaxis.common.utils.RSAUtils;
+import com.miaxis.common.utils.XmlUtil;
+import com.miaxis.wx.dto.WxExtractBankDTO;
+import com.miaxis.wx.service.IWxExtractService;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.RandomStringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.Map;
+import java.util.TreeMap;
+
+import static com.miaxis.common.utils.OrderCodeFactory.getOrderCode;
+
+@Service
+@Slf4j
+public class WxExtreactServiceImpl implements IWxExtractService {
+
+
+    @Autowired
+    private WxpayConfig wxpayConfig;
+
+    @Autowired
+    private RSAUtils rsaUtils;
+
+    @Override
+    public String wxwithbankdrawal(WxExtractBankDTO dto) throws Exception {
+
+        Map<String, String> sortMap = new TreeMap<String, String>();
+        sortMap.put("mch_id",wxpayConfig.getMerchantId());
+        sortMap.put("nonce_str", RandomStringUtils.randomAlphanumeric(32));
+        sortMap.put("partner_trade_no",getOrderCode(null));
+        sortMap.put("amount",String.valueOf(dto.getAmount()));
+        sortMap.put("desc","用户银行卡提现");
+
+
+        // 进行签名服务
+        sortMap.put("enc_true_name",rsaUtils.encryptData(dto.getEncTrueName()) );
+        sortMap.put("enc_bank_no",rsaUtils.encryptData(dto.getEncBankNo()));
+        sortMap.put("bank_code",dto.getBankCode().toString());
+
+
+        WXPayConfig config = new WxPayConfigImpl();
+        String sign = WXPayUtil.generateSignature(sortMap, config.getKey(), WXPayConstants.SignType.MD5);
+        sortMap.put("sign", sign);
+        WXPay pay = new WXPay(config);
+
+        String url = "https://api.mch.weixin.qq.com/mmpaysptrans/pay_bank";
+       //Map<String, String> resMap;
+        String xmlStr = pay.requestWithCert(url, sortMap, config.getHttpConnectTimeoutMs(), config.getHttpReadTimeoutMs());
+        Map<String, String> resMap = XmlUtil.xmlToMap(xmlStr);
+        if (!"SUCCESS".equals(resMap.get("return_code"))||!"SUCCESS".equals(resMap.get("result_code"))){
+            throw new CustomException(resMap.get("return_msg"));
+        }
+
+
+        return resMap.get("return_msg");
+    }
+}