微信支付之企业付款到个人(提现)

    xiaoxiao2022-07-12  386

    先去官网了解开发文档:https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=14_2

    1、先去下载证书

    apiclient_cert.p12证书:在微信商户平台–>账户设置–>API安全–>证书中下载的 。 (自行下载)

    将下载好的证书放在src/main/resources下

    2、导入相关pom依赖

    <!-- xml --> <dependency> <groupId>net.sf.kxml</groupId> <artifactId>kxml2</artifactId> <version>2.3.0</version> </dependency> <dependency> <groupId>xmlpull</groupId> <artifactId>xmlpull</artifactId> <version>1.1.3.1</version> </dependency> <--httpclient--> <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> </dependency>

    3、代码相关

    /** *只是一个简单的示例,像一些余额的校验,还有限额的操作这里没有写 * 微信提现(企业付款) * @param userId * @param amount 提现金额 * @param request * @return */ @GetMapping("/wechat/cash") @CrossOrigin public Map<String , Object> cash(@RequestParam("openId") String openId, @RequestParam("amount") String amount, HttpServletRequest request){ Map<String , Object> resMap = new HashMap<String,Object>(); try { UserInfo userInfo = iUserInfoService.queryByUesrId(Integer.valueOf(userId)); if(null == userInfo) { resMap.put("code",0); resMap.put("msg","用户不存在"); return resMap; } if(userInfo.getOpenid()==null) { resMap.put("code",0); resMap.put("msg","openid为空,请先去授权"); return resMap; } //校验 UserAccount userAccount = iUserAccountService.queryByUserId(Long.valueOf(userId)); if(null != userAccount) { if(userAccount.getAccountAmount().compareTo(new BigDecimal(amount)) == -1) {//余额小于提现金额 resMap.put("code",0); resMap.put("msg","余额不足"); return resMap; } } //企业付款参数 Map<String, String> paraMap = new HashMap<String, String>(); //获取请求ip地址 String ip = request.getHeader("x-forwarded-for"); if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)){ ip = request.getHeader("Proxy-Client-IP"); } if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)){ ip = request.getHeader("WL-Proxy-Client-IP"); } if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)){ ip = request.getRemoteAddr(); } if(ip.indexOf(",")!=-1){ String[] ips = ip.split(","); ip = ips[0].trim(); } String NewDate = DateUtil.getDateFormat(new Date(), "yyyyMMddHHmmss"); String partnerTradeNo = NewDate+"UID"+userInfo.getId(); String money = new BigDecimal(amount).multiply(new BigDecimal(100)).setScale(0,BigDecimal.ROUND_DOWN).toString();; paraMap.put("mch_appid", WXPayConstants.APP_ID); paraMap.put("mchid", WXPayConstants.MCH_ID); paraMap.put("nonce_str", WXPayUtil.generateNonceStr()); paraMap.put("partner_trade_no", partnerTradeNo); paraMap.put("openid", userInfo.getOpenid()); paraMap.put("check_name", "NO_CHECK"); paraMap.put("amount", money); paraMap.put("desc", "提现"+amount+"元"); paraMap.put("spbill_create_ip", ip); //用公众号key 失败 ----改为商户key 19-3-12 //String sign = WXPayUtil.generateSignature(paraMap, WXPayConstants.PATERNER_KEY);//微信公众号开发者密码 String sign = WXPayUtil.generateSignature(paraMap, WXPayConstants.MCH_SECRET);//商户密码 paraMap.put("sign", sign); String xml = WXPayUtil.mapToXml(paraMap);//将所有参数(map)转xml格式 //企业付款 String macPayUrl = WXPayConstants.MAC_PAY_URL; // String xmlStr = HttpClientUtil.sendPost(macPayUrl, xml); String xmlStr = HttpClientUtil.posts(macPayUrl, xml); Map<String, String> map = WXPayUtil.xmlToMap(xmlStr); if (CollectionUtil.isNotEmpty(map) && "SUCCESS".equals(map.get("result_code"))) { //成功需要进行的逻辑操作 iUserAccountService.cashSuccess(userInfo,amount); resMap.put("code",1); }else { if (CollectionUtil.isNotEmpty(map)) { resMap.put("msg","提现失败:"+map.get("err_code") + ":" + map.get("err_code_des")); } resMap.put("code",0); } } catch (Exception e) { e.printStackTrace(); resMap.put("code",0); resMap.put("msg","提现失败"); } return resMap; }

    以下是所涉及到的工具类,一并列举,选自己需要的即可 

    import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.URL; import java.net.URLConnection; import java.security.KeyStore; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Map.Entry; import javax.net.ssl.SSLContext; import org.apache.http.NameValuePair; import org.apache.http.client.config.RequestConfig; import org.apache.http.client.entity.UrlEncodedFormEntity; 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.message.BasicNameValuePair; import org.apache.http.ssl.SSLContexts; import org.apache.http.util.EntityUtils; import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.Resource; import cc.mrbird.common.constant.WXPayConstants; /** Http请求工具类 * @author Administrator * @date crete by on 2019/3/8 18:08 * @description */ public class HttpClientUtil { private static final int CONNECT_TIME_OUT = 5000; //链接超时时间3秒 private static final RequestConfig REQUEST_CONFIG = RequestConfig.custom().setConnectTimeout(CONNECT_TIME_OUT).build(); private static SSLContext wx_ssl_context = null; //微信支付ssl证书 private static final String MCH_ID = WXPayConstants.MCH_ID;//证书密码默认是商户号 static{ Resource resource = new ClassPathResource("wan_apiclient_cert.p12");//该证书名字最好改为别人猜不到的 try { KeyStore keystore = KeyStore.getInstance("PKCS12"); char[] keyPassword = MCH_ID.toCharArray(); //证书密码 keystore.load(resource.getInputStream(), keyPassword); wx_ssl_context = SSLContexts.custom().loadKeyMaterial(keystore, keyPassword).build(); } catch (Exception e) { e.printStackTrace(); } } /** * 向指定URL发送GET方法的请求 * * @param url * 发送请求的URL * @param param * 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。 * @return URL 所代表远程资源的响应结果 */ public static String sendGet(String url, String param) { String result = ""; BufferedReader in = null; try { String urlNameString = url + "?" + param; System.out.println(urlNameString); URL realUrl = new URL(urlNameString); // 打开和URL之间的连接 URLConnection connection = realUrl.openConnection(); // 设置通用的请求属性 connection.setRequestProperty("accept", "*/*"); connection.setRequestProperty("connection", "Keep-Alive"); connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"); // 建立实际的连接 connection.connect(); // 获取所有响应头字段 Map<String, List<String>> map = connection.getHeaderFields(); // 遍历所有的响应头字段 for (String key : map.keySet()) { //System.out.println(key + "--->" + map.get(key)); } // 定义 BufferedReader输入流来读取URL的响应 in = new BufferedReader(new InputStreamReader(connection.getInputStream())); String line; while ((line = in.readLine()) != null) { result += line; } } catch (Exception e) { System.out.println("发送GET请求出现异常!" + e); e.printStackTrace(); } // 使用finally块来关闭输入流 finally { try { if (in != null) { in.close(); } } catch (Exception e2) { e2.printStackTrace(); } } return result; } /** * 向指定 URL 发送POST方法的请求 * * @param url * 发送请求的 URL * @param param * 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。 * @return 所代表远程资源的响应结果 */ public static String sendPost(String url, String param) { PrintWriter out = null; BufferedReader in = null; String result = ""; try { URL realUrl = new URL(url); // 打开和URL之间的连接 URLConnection conn = realUrl.openConnection(); // 设置通用的请求属性 conn.setRequestProperty("accept", "*/*"); conn.setRequestProperty("connection", "Keep-Alive"); conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"); // 发送POST请求必须设置如下两行 conn.setDoOutput(true); conn.setDoInput(true); // 获取URLConnection对象对应的输出流 out = new PrintWriter(conn.getOutputStream()); // 发送请求参数 out.print(param); // flush输出流的缓冲 out.flush(); // 定义BufferedReader输入流来读取URL的响应 in = new BufferedReader(new InputStreamReader(conn.getInputStream())); String line; while ((line = in.readLine()) != null) { result += line; } } catch (Exception e) { System.out.println("发送 POST 请求出现异常!"+e); e.printStackTrace(); } //使用finally块来关闭输出流、输入流 finally{ try{ if(out!=null){ out.close(); } if(in!=null){ in.close(); } } catch(IOException ex){ ex.printStackTrace(); } } return result; } /** * @description 功能描述: post https请求,服务器双向证书验证 * @param url 请求地址 * @param params 参数 * @return 请求失败返回null */ public static String posts(String url, Map<String, String> params) { CloseableHttpClient httpClient = null; HttpPost httpPost = new HttpPost(url); List<NameValuePair> nameValuePairs = new ArrayList<>(); if (params != null && !params.isEmpty()) { for (Entry<String, String> entry : params.entrySet()) { nameValuePairs.add(new BasicNameValuePair(entry.getKey(), entry.getValue())); } } String body = null; CloseableHttpResponse response = null; try { httpClient = HttpClients.custom().setDefaultRequestConfig(REQUEST_CONFIG).setSSLSocketFactory(getSSLConnectionSocket()).build(); httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs, "UTF-8")); response = httpClient.execute(httpPost); body = EntityUtils.toString(response.getEntity(), "UTF-8"); } catch (Exception e) { e.printStackTrace(); } finally { if (response != null) { try { response.close(); } catch (IOException e) { e.printStackTrace(); } } if (httpClient != null) { try { httpClient.close(); } catch (IOException e) { e.printStackTrace(); } } } return body; } /** * @description 功能描述: post https请求,服务器双向证书验证 * @param url 请求地址 * @param s 参数xml * @return 请求失败返回null */ public static String posts(String url, String s) { CloseableHttpClient httpClient = null; HttpPost httpPost = new HttpPost(url); String body = null; CloseableHttpResponse response = null; try { httpClient = HttpClients.custom().setDefaultRequestConfig(REQUEST_CONFIG).setSSLSocketFactory(getSSLConnectionSocket()).build(); httpPost.setEntity(new StringEntity(s, "UTF-8")); response = httpClient.execute(httpPost); body = EntityUtils.toString(response.getEntity(), "UTF-8"); } catch (Exception e) { e.printStackTrace(); } finally { if (response != null) { try { response.close(); } catch (IOException e) { e.printStackTrace(); } } if (httpClient != null) { try { httpClient.close(); } catch (IOException e) { e.printStackTrace(); } } } return body; } //获取ssl connection链接 private static SSLConnectionSocketFactory getSSLConnectionSocket() { return new SSLConnectionSocketFactory(wx_ssl_context, new String[] {"TLSv1", "TLSv1.1", "TLSv1.2"}, null, SSLConnectionSocketFactory.getDefaultHostnameVerifier()); } } import java.io.BufferedReader; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.StringWriter; import java.io.UnsupportedEncodingException; import java.security.MessageDigest; import java.security.SecureRandom; import java.util.Arrays; import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; import java.util.Random; import java.util.Set; import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; import javax.xml.parsers.DocumentBuilder; 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 org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import com.github.pagehelper.util.StringUtil; import cc.mrbird.common.constant.WXPayConstants; import cc.mrbird.common.constant.WXPayConstants.SignType; public class WXPayUtil { private static final String SYMBOLS = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; private static final Random RANDOM = new SecureRandom(); private static final String PREFIX_XML = "<xml>"; private static final String SUFFIX_XML = "</xml>"; private static final String PREFIX_CDATA = "<![CDATA["; private static final String SUFFIX_CDATA = "]]>"; /** * 转化成xml, 单层无嵌套 * * @param parm * @param isAddCDATA * @return */ public static String xmlFormat(Map<String, String> parm, boolean isAddCDATA) { StringBuffer strbuff = new StringBuffer(PREFIX_XML); if (CollectionUtil.isNotEmpty(parm)) { for (Entry<String, String> entry : parm.entrySet()) { strbuff.append("<").append(entry.getKey()).append(">"); if (isAddCDATA) { strbuff.append(PREFIX_CDATA); if (StringUtil.isNotEmpty(entry.getValue())) { strbuff.append(entry.getValue()); } strbuff.append(SUFFIX_CDATA); } else { if (StringUtil.isNotEmpty(entry.getValue())) { strbuff.append(entry.getValue()); } } strbuff.append("</").append(entry.getKey()).append(">"); } } return strbuff.append(SUFFIX_XML).toString(); } /** * 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) { WXPayUtil.getLogger().warn("Invalid XML, can not convert to map. Error message: {}. XML content: {}", ex.getMessage(), strXML); throw ex; } } /** * 将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; } /** * 生成带有 sign 的 XML 格式字符串 * * @param data Map类型数据 * @param key API密钥 * @return 含有sign字段的XML */ public static String generateSignedXml(final Map<String, String> data, String key) throws Exception { return generateSignedXml(data, key, SignType.MD5); } /** * 生成带有 sign 的 XML 格式字符串 * * @param data Map类型数据 * @param key API密钥 * @param signType 签名类型 * @return 含有sign字段的XML */ public static String generateSignedXml(final Map<String, String> data, String key, SignType signType) throws Exception { String sign = generateSignature(data, key, signType); data.put(WXPayConstants.FIELD_SIGN, sign); return mapToXml(data); } /** * 判断签名是否正确 * * @param xmlStr XML格式数据 * @param key API密钥 * @return 签名是否正确 * @throws Exception */ public static boolean isSignatureValid(String xmlStr, String key) throws Exception { Map<String, String> data = xmlToMap(xmlStr); if (!data.containsKey(WXPayConstants.FIELD_SIGN) ) { return false; } String sign = data.get(WXPayConstants.FIELD_SIGN); return generateSignature(data, key).equals(sign); } /** * 判断签名是否正确,必须包含sign字段,否则返回false。使用MD5签名。 * * @param data Map类型数据 * @param key API密钥 * @return 签名是否正确 * @throws Exception */ public static boolean isSignatureValid(Map<String, String> data, String key) throws Exception { return isSignatureValid(data, key, SignType.MD5); } /** * 判断签名是否正确,必须包含sign字段,否则返回false。 * * @param data Map类型数据 * @param key API密钥 * @param signType 签名方式 * @return 签名是否正确 * @throws Exception */ public static boolean isSignatureValid(Map<String, String> data, String key, SignType signType) throws Exception { if (!data.containsKey(WXPayConstants.FIELD_SIGN) ) { return false; } String sign = data.get(WXPayConstants.FIELD_SIGN); return generateSignature(data, key, signType).equals(sign); } /** * 生成签名 * * @param data 待签名数据 * @param key API密钥 * @return 签名 */ public static String generateSignature(final Map<String, String> data, String key) throws Exception { return generateSignature(data, key, SignType.MD5); } /** * 生成签名. 注意,若含有sign_type字段,必须和signType参数保持一致。 * * @param data 待签名数据 * @param key API密钥 * @param signType 签名方式 * @return 签名 */ public static String generateSignature(final Map<String, String> data, String key, SignType 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(WXPayConstants.FIELD_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 (SignType.MD5.equals(signType)) { return MD5(sb.toString()).toUpperCase(); } else if (SignType.HMACSHA256.equals(signType)) { return HMACSHA256(sb.toString(), key); } else { throw new Exception(String.format("Invalid sign_type: %s", signType)); } } /** * 获取随机字符串 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); } /** * 生成 MD5 * * @param data 待处理数据 * @return MD5结果 */ public static String MD5(String data) throws Exception { 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(); } /** * 生成 HMACSHA256 * @param data 待处理数据 * @param key 密钥 * @return 加密结果 * @throws Exception */ public static String HMACSHA256(String data, String key) throws Exception { Mac sha256_HMAC = Mac.getInstance("HmacSHA256"); SecretKeySpec secret_key = new SecretKeySpec(key.getBytes("UTF-8"), "HmacSHA256"); sha256_HMAC.init(secret_key); byte[] array = sha256_HMAC.doFinal(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(); } /** * 日志 * @return */ public static Logger getLogger() { Logger logger = LoggerFactory.getLogger("wxpay java sdk"); return logger; } /** * 获取当前时间戳,单位秒 * @return */ public static long getCurrentTimestamp() { return System.currentTimeMillis()/1000; } /** * 获取当前时间戳,单位毫秒 * @return */ public static long getCurrentTimestampMs() { return System.currentTimeMillis(); } public static String inputStream2String(InputStream in) { InputStreamReader reader = null; try { reader = new InputStreamReader(in, "UTF-8"); } catch (UnsupportedEncodingException e1) { e1.printStackTrace(); } BufferedReader br = new BufferedReader(reader); StringBuilder sb = new StringBuilder(); String line = ""; try { while ((line = br.readLine()) != null) { sb.append(line); } } catch (IOException e) { e.printStackTrace(); } return sb.toString(); } } 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(); } } import org.apache.commons.httpclient.HttpClient; /** * 常量 */ public class WXPayConstants { public enum SignType { MD5, HMACSHA256 } public static final String APP_ID = ";//appid public static final String MCH_ID = "";//商家ID public static final String SECRET = "";//APP KEY 微信公众号里的开发者密码 public static final String MCH_SECRET = "";//商户 KEY public static final String OPENID_URL = "https://api.weixin.qq.com/sns/oauth2/access_token";//code 换取网页授权access_token public static final String USERINFO_URL = "https://api.weixin.qq.com/sns/userinfo";//access_token 拉取用户信息 public static final String UNIFIEDORDER_URL = "https://api.mch.weixin.qq.com/pay/unifiedorder";//统一下单接口 public static final String RESOUT_CALLBACK_URL = "";//支付成功回调接口 public static final String MAC_PAY_URL = "https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers";//商户支付地址 public static final String DOMAIN_API = "api.mch.weixin.qq.com"; public static final String DOMAIN_API2 = "api2.mch.weixin.qq.com"; public static final String DOMAIN_APIHK = "apihk.mch.weixin.qq.com"; public static final String DOMAIN_APIUS = "apius.mch.weixin.qq.com"; public static final String FAIL = "FAIL"; public static final String SUCCESS = "SUCCESS"; public static final String HMACSHA256 = "HMAC-SHA256"; public static final String MD5 = "MD5"; public static final String FIELD_SIGN = "sign"; public static final String FIELD_SIGN_TYPE = "sign_type"; 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 static final String MICROPAY_URL_SUFFIX = "/pay/micropay"; public static final String UNIFIEDORDER_URL_SUFFIX = "/pay/unifiedorder"; public static final String ORDERQUERY_URL_SUFFIX = "/pay/orderquery"; public static final String REVERSE_URL_SUFFIX = "/secapi/pay/reverse"; public static final String CLOSEORDER_URL_SUFFIX = "/pay/closeorder"; public static final String REFUND_URL_SUFFIX = "/secapi/pay/refund"; public static final String REFUNDQUERY_URL_SUFFIX = "/pay/refundquery"; public static final String DOWNLOADBILL_URL_SUFFIX = "/pay/downloadbill"; public static final String REPORT_URL_SUFFIX = "/payitil/report"; public static final String SHORTURL_URL_SUFFIX = "/tools/shorturl"; public static final String AUTHCODETOOPENID_URL_SUFFIX = "/tools/authcodetoopenid"; // sandbox public static final String SANDBOX_MICROPAY_URL_SUFFIX = "/sandboxnew/pay/micropay"; public static final String SANDBOX_UNIFIEDORDER_URL_SUFFIX = "/sandboxnew/pay/unifiedorder"; public static final String SANDBOX_ORDERQUERY_URL_SUFFIX = "/sandboxnew/pay/orderquery"; public static final String SANDBOX_REVERSE_URL_SUFFIX = "/sandboxnew/secapi/pay/reverse"; public static final String SANDBOX_CLOSEORDER_URL_SUFFIX = "/sandboxnew/pay/closeorder"; public static final String SANDBOX_REFUND_URL_SUFFIX = "/sandboxnew/secapi/pay/refund"; public static final String SANDBOX_REFUNDQUERY_URL_SUFFIX = "/sandboxnew/pay/refundquery"; public static final String SANDBOX_DOWNLOADBILL_URL_SUFFIX = "/sandboxnew/pay/downloadbill"; public static final String SANDBOX_REPORT_URL_SUFFIX = "/sandboxnew/payitil/report"; public static final String SANDBOX_SHORTURL_URL_SUFFIX = "/sandboxnew/tools/shorturl"; public static final String SANDBOX_AUTHCODETOOPENID_URL_SUFFIX = "/sandboxnew/tools/authcodetoopenid"; } package cc.mrbird.common.util; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Map; public class CollectionUtil { private CollectionUtil() { super(); } // 判断一个集合是否为空 public static <T> boolean isEmpty(Collection<T> col) { if (col == null || col.isEmpty()) { return true; } return false; } // 判断一个集合是否不为空 public static <T> boolean isNotEmpty(Collection<T> col) { return !isEmpty(col); } // 判断Map是否为空 public static <K, V> boolean isEmpty(Map<K, V> map) { if (map == null || map.isEmpty()) { return true; } return false; } // 判断Map是否不为空为空 public static <K, V> boolean isNotEmpty(Map<K, V> map) { return !isEmpty(map); } // 去除list中的重复数据 public static <T> List<T> removeRepeat(List<T> list) { if (isEmpty(list)) { return list; } List<T> result = new ArrayList<T>(); for (T e : list) { if (!result.contains(e)) { result.add(e); } } return result; } // 将集合转换为String数组 public static <T> String[] toArray(List<T> list) { if (isEmpty(list)) { return null; } String[] result = new String[list.size()]; for (int i = 0; i < list.size(); i++) { result[i] = String.valueOf(list.get(i)); } return result; } }

    4、代码测试(报错)

    原因:因为我这是新入住的商户,所以会报这个错

     5、其它参考示例:https://blog.csdn.net/Goldmeng/article/details/86302004

    最新回复(0)