小程序微信支付,微信支付

小程序微信支付,微信支付


在这里插入图片描述

1:下载相应的jar包

链接: 点我下载jar包 提取码: pk2y

2:对数据进行加密

①:设置相应参数

public Map<String, String> fillRequestData(Map<String, String> reqData) throws Exception {
    	//小程序id
        reqData.put("appid", wxPayConfigVlue.getAppID());
        //商户号
        reqData.put("mch_id", wxPayConfigVlue.getMchID());
        //小程序openid
        reqData.put("openid", "XXXXXXXXXXXXXXXXXXXXXXX");
        //随机字符串
        reqData.put("nonce_str", WXPayUtil.generateNonceStr());
        //商品描述
        reqData.put("body", "会员充值");
        //商户订单号
        reqData.put("out_trade_no", "123456");
        //标价金额
        reqData.put("total_fee", "1");
        //终端ip
        reqData.put("spbill_create_ip", "XXXXXXXXXXXXXXXXX");
        //通知地址
        reqData.put("notify_url", "http://www.weixin.qq.com/wxpay/pay.php");
        //交易类型
        reqData.put("trade_type", "JSAPI");
        //加密类型
        reqData.put("sign_type", "MD5");
        //wxPayConfigVlue.getKey() 商户支付秘钥(可登录微信支付平台获取)
        reqData.put("sign", WXPayUtil.generateSignature(reqData, wxPayConfigVlue.getKey()));
        return reqData;
    }

②:加密工具类

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();
    }
}
public class WXPayUtil {
    private static final String SYMBOLS = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
    private static final Random RANDOM = new SecureRandom();
    
	public static String generateSignature(final Map<String, String> data, String key) 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);
        return MD5(sb.toString()).toUpperCase();
        }

	/**
     * 生成 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();
    }
    /**
     * 将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;
    }

 	/**
     * 获取随机字符串 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);
    }

	/**
     * XML格式字符串转换为Map
     *
     * @param strXML XML字符串
     * @return XML数据转换后的Map
     * @throws Exception
     */
    public static Map<String, String> xmlToMap(String strXML) throws Exception {
        try {
            Map<String, String> data = new HashMap<String, String>();
            DocumentBuilder documentBuilder = WXPayXmlUtil.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;
        }

    }

}

在这里插入图片描述

3:发送请求

①:无证书请求

/**
     * 不需要证书的请求
     * @param urlSuffix String
     * @param reqData 向wxpay post的请求数据
     * @param connectTimeoutMs 超时时间,单位是毫秒
     * @param readTimeoutMs 超时时间,单位是毫秒
     * @return API返回数据
     * @throws Exception
     */
    public String requestWithoutCert(String urlSuffix, Map<String, String> reqData,
                                     int connectTimeoutMs, int readTimeoutMs) throws Exception {
        String msgUUID = reqData.get("nonce_str");
        String reqBody = WXPayUtil.mapToXml(reqData);

        String resp = String resp = new WXPayRequest().requestOnce(urlSuffix, msgUUID, reqBody, connectTimeoutMs, readTimeoutMs, true);
        return resp;
    }

②:创建WXPayRequest

public class WXPayRequest {
	private WXPayConfigVlue wxPayConfigVlue = new WXPayConfigVlue();
	public static final String WXPAYSDK_VERSION = "WXPaySDK/3.0.9";
	public static final String USER_AGENT = WXPAYSDK_VERSION +
            " (" + System.getProperty("os.arch") + " " + System.getProperty("os.name") + " " + System.getProperty("os.version") +
            ") Java/" + System.getProperty("java.version") + " HttpClient/" + HttpClient.class.getPackage().getImplementationVersion();
	public WXPayRequest(){}
	/**
     * 请求,只请求一次,不做重试
     * @param urlSuffix 请求地址
     * @param uuid 
     * @param data
     * @param connectTimeoutMs
     * @param readTimeoutMs
     * @param useCert 是否使用证书,针对退款、撤销等操作
     * @return
	 * @throws IOException 
	 * @throws ClientProtocolException 
     * @throws Exception
     */
    public String requestOnce(String urlSuffix, String uuid, String data, int connectTimeoutMs, int readTimeoutMs, boolean useCert) throws ClientProtocolException, IOException {
        BasicHttpClientConnectionManager connManager;
      
        
            connManager = new BasicHttpClientConnectionManager(
                    RegistryBuilder.<ConnectionSocketFactory>create()
                            .register("http", PlainConnectionSocketFactory.getSocketFactory())
                            .register("https", SSLConnectionSocketFactory.getSocketFactory())
                            .build(),
                    null,
                    null,
                    null
            );
        

        HttpClient httpClient = HttpClientBuilder.create()
                .setConnectionManager(connManager)
                .build();

        String url = "https://api.mch.weixin.qq.com/pay/unifiedorder";
        HttpPost httpPost = new HttpPost(url);

        RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(readTimeoutMs).setConnectTimeout(connectTimeoutMs).build();
        httpPost.setConfig(requestConfig);

        StringEntity postEntity = new StringEntity(data, "UTF-8");
        httpPost.addHeader("Content-Type", "text/xml");
        httpPost.addHeader("User-Agent", USER_AGENT + " " + wxPayConfigVlue.getMchID());
        httpPost.setEntity(postEntity);

        HttpResponse httpResponse = httpClient.execute(httpPost);
        HttpEntity httpEntity = httpResponse.getEntity();
        return EntityUtils.toString(httpEntity, "UTF-8");

    }
}

③:创建WXPayXmlUtil

public 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();
    }
}

在这里插入图片描述

4:将xml转成map集合

	/**
     * 处理 HTTPS API返回数据,转换成Map对象。return_code为SUCCESS时,验证签名。
     * @param xmlStr API返回的XML格式数据
     * @return Map类型数据
     * @throws Exception
     */
    public Map<String, String> processResponseXml(String xmlStr) throws Exception {
        String RETURN_CODE = "return_code";
        String return_code;
        Map<String, String> respData = WXPayUtil.xmlToMap(xmlStr);
        if (respData.containsKey(RETURN_CODE)) {
            return_code = respData.get(RETURN_CODE);
        }
        else {
            throw new Exception(String.format("No `return_code` in XML: %s", xmlStr));
        }

        if (return_code.equals("FAIL")) {
            return respData;
        }
        else if (return_code.equals("SUCCESS")) {  
               return respData;
        }
        else {
            throw new Exception(String.format("return_code value %s is invalid in XML: %s", return_code, xmlStr));
        }
    }

5:对数据进行二次加密

在这里插入图片描述

	//二次加密
    public void seconEncryption(Map map){
    	Map<String, String> seconMap = new HashMap<String,String>();
    	String timestamp = System.currentTimeMillis()+"";
    	System.out.println("生成的时间戳为");
    	System.out.println(timestamp);
    	//小程序appid
    	seconMap.put("appId", (String) map.get("appid"));
    	//随机字符串
    	seconMap.put("nonceStr", (String) map.get("nonce_str"));
    	//数据包
    	seconMap.put("package", "prepay_id="+map.get("prepay_id"));
    	//签名方式
    	seconMap.put("signType", "MD5");
    	//当前时间戳
    	seconMap.put("timeStamp", timestamp);

    	//加密
    	try {
			String secondMsg = WXPayUtil.generateSignature(seconMap, wxPayConfigVlue.getKey());
			System.out.println("二次加密后返回的值为");
			System.out.println(secondMsg);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
    }

在这里插入图片描述

6:前端根据后端传来的二次加密数据调起微信支付

	//调起微信支付
    wx.requestPayment(
      {
        'timeStamp': "XXXXXXXXXXX", //时间戳
        'nonceStr': 'XXXXXXXXXXXX', //随机字符串
        'package': 'prepay_id=XXXXXXXXXXXXX', //统一下单接口返回的 prepay_id 参数值
        'signType': 'MD5',
        'paySign': "XXXXXXXXXXXXXXXXXX",
        'success': function (res) {
          console.log("调起支付成功")
          console.log(res);
         },
        'fail': function (res) { 
          console.log("调起支付发生失败")
          console.log(res);
        },
        'complete': function (res) {
            console.log("调起支付结束");
            console.log(res);
         }
      })
发布了43 篇原创文章 · 获赞 19 · 访问量 3071

猜你喜欢

转载自blog.csdn.net/qq_41974199/article/details/104005650