由于项目中要用到微信提现,参考网上代码和官方文档写了提现的工具类
用到的相关类库
dom4j
commons-lang3
httpclient-4.4.1

具体相关流程可以看微信企业付款到零钱的开发文档

MD5工具类

package com.kk.wechatextract;import java.security.MessageDigest;public class MD5Utils {private static final char hexDigits[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};/** 先转为utf-8* */public static String MD5Encoding(String s) {byte[] btInput = null;try {btInput = s.getBytes("UTF-8");}catch (Exception e){}return MD5(btInput, 32);}public static String MD5(String s) {byte[] btInput = s.getBytes();return MD5(btInput, 32);}public static String MD5_16(String str) {byte[] btInput = str.getBytes();return MD5(btInput, 16);}private static String MD5(byte[] btInput, int length) {try {// 获得MD5摘要算法的 MessageDigest 对象MessageDigest mdInst = MessageDigest.getInstance("MD5");// MessageDigest mdInst = MessageDigest.getInstance("SHA-1");// 使用指定的字节更新摘要mdInst.update(btInput);// 获得密文byte[] md = mdInst.digest();// 把密文转换成十六进制的字符串形式int j = md.length;char str[] = new char[j * 2];int k = 0;for (byte byte0 : md) {str[k++] = hexDigits[byte0 >>> 4 & 0xf];str[k++] = hexDigits[byte0 & 0xf];}String result = new String(str);return length == 16 ? result.substring(8, 24) : result;} catch (Exception e) {e.printStackTrace();return null;}}
}

url排序,随机字符串的操作

package com.kk.wechatextract;import org.apache.commons.lang3.StringUtils;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;public class OtherUtils {/** 生成32位随机字符串* */public static String getNonceStr() {UUID uuid = UUID.randomUUID();return uuid.toString().replace("-", "");}/*** 方法用途: 对所有传入参数按照字段名的Unicode码从小到大排序(字典序),并且生成url参数串<br>* 实现步骤: <br>** @param paraMap    要排序的Map对象* @param urlEncode  是否需要URLENCODE* @param keyToLower 是否需要将Key转换为全小写*                   true:key转化成小写,false:不转化* @return*/public static String formatUrlMap(Map<String, String> paraMap, boolean urlEncode, boolean keyToLower) {String buff = "";Map<String, String> tmpMap = paraMap;try {List<Map.Entry<String, String>> infoIds = new ArrayList<Map.Entry<String, String>>(tmpMap.entrySet());// 对所有传入参数按照字段名的 ASCII 码从小到大排序(字典序)Collections.sort(infoIds, new Comparator<Map.Entry<String, String>>() {@Overridepublic int compare(Map.Entry<String, String> o1, Map.Entry<String, String> o2) {return (o1.getKey()).toString().compareTo(o2.getKey());}});// 构造URL 键值对的格式StringBuilder buf = new StringBuilder();for (Map.Entry<String, String> item : infoIds) {if (StringUtils.isNotBlank(item.getKey())) {String key = item.getKey();String val = item.getValue();if (urlEncode) {val = URLEncoder.encode(val, "utf-8");}if (keyToLower) {buf.append(key.toLowerCase() + "=" + val);} else {buf.append(key + "=" + val);}buf.append("&");}}buff = buf.toString();if (buff.isEmpty() == false) {buff = buff.substring(0, buff.length() - 1);}} catch (Exception e) {return null;}return buff;}/*** 功能描述: 判断值是否为double*/public static boolean isToDouble(Object o){try {Double.valueOf(o.toString());return true;}catch (Exception e){return false;}}/*** @param xml* @return Map* @description 将xml字符串转换成map*/public static Map<String, String> readStringXmlOut(String xml) {Map<String, String> map = new HashMap<String, String>();Document doc = null;try {doc = DocumentHelper.parseText(xml); // 将字符串转为XMLElement rootElt = doc.getRootElement(); // 获取根节点@SuppressWarnings("unchecked")List<Element> list = rootElt.elements();// 获取根节点下所有节点for (Element element : list) { // 遍历节点map.put(element.getName(), element.getText()); // 节点的name为map的key,text为map的value}} catch (DocumentException e) {e.printStackTrace();} catch (Exception e) {e.printStackTrace();}return map;}}

微信提现主方法

package com.kk.wechatextract;import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.security.KeyStore;
import java.security.SecureRandom;
import java.util.HashMap;
import java.util.Map;import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.BasicHttpClientConnectionManager;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;/*** @author Zhou Zhong Qing* @Title: ${file_name}* @Package ${package_name}* @Description: 微信提现*/
@Component
public class WeChatWithdrawUtils {private static final Logger log = LoggerFactory.getLogger(WeChatWithdrawUtils.class.getName());private byte[] certData;/*** 加载证书*/public  InputStream getCertStream() {ByteArrayInputStream certBis;certBis = new ByteArrayInputStream(this.certData);return certBis;}/***读取证书*/public WeChatWithdrawUtils() throws Exception{String certPath = Constant.SSLCERT_PATH;File file = new File(certPath);InputStream certStream = new FileInputStream(file);this.certData = new byte[(int) file.length()];certStream.read(this.certData);certStream.close();}/**** 提现* 请求,只请求一次,不做重试* @param connectTimeoutMs* @param readTimeoutMs* @return* @throws Exception*/public static String withdrawRequestOnce(Map<String,String> params, int connectTimeoutMs, int readTimeoutMs,boolean useCert) throws Exception {/**1.拼凑企业支付需要的参数**/Map<String, String> paraMap = new HashMap<>();paraMap.putAll(params);//微信公众号的appidparaMap.put("mch_appid", Constant.APPID);//商户号paraMap.put("mchid",Constant.MERCHANTID);//随机字符串//paraMap.put("nonce_str", OtherUtils.getNonceStr());paraMap.get("nonce_str");//订单号//paraMap.put("partner_trade_no","qianchen"+System.currentTimeMillis());paraMap.get("partner_trade_no");//openid//paraMap.put("openid",params.getOrDefault("openId","oelSW0uBU233H5YM3dweIZ08kauk"));//"o5mZ40yBjIqco2NzKc19k9oIBI9o");paraMap.get("openid");// 校验用户姓名选项 NO_CHECK:不校验真实姓名  FORCE_CHECK:强校验真实姓名paraMap.put("check_name","NO_CHECK");//paraMap.put("amount",params.getOrDefault("money","0"));//"100");paraMap.get("amount");//企业付款操作说明信息。必填。//paraMap.put("desc",params.getOrDefault("clientId","")+"用户提现");paraMap.get("desc");//ip地址,地址可以不是真实地址paraMap.put("spbill_create_ip",params.getOrDefault("spbillCreateIp","127.0.01"));/**2.Unicode码从小到大排序**/String url = OtherUtils.formatUrlMap(paraMap, false, false);url = url + "&key=" + Constant.MERCHANTKEY;/**3.用MD5加密生成签名**/String sign = MD5Utils.MD5Encoding(url).toUpperCase();/**4.将map拼接成xml格式**/StringBuffer xml = new StringBuffer();xml.append("<xml>");for (Map.Entry<String, String> entry : paraMap.entrySet()) {xml.append("<" + entry.getKey() + ">");xml.append(entry.getValue());xml.append("</" + entry.getKey() + ">" + "\n");}xml.append("<sign>");xml.append(sign);xml.append("</sign>");xml.append("</xml>");log.info("xml {} ", xml.toString());BasicHttpClientConnectionManager connManager;/**5.操作证书**/if (useCert) {// 证书char[] password = Constant.MERCHANTID.toCharArray();InputStream certStream =  new WeChatWithdrawUtils().getCertStream();KeyStore ks = KeyStore.getInstance("PKCS12");ks.load(certStream, password);// 实例化密钥库 & 初始化密钥工厂KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());kmf.init(ks, password);// 创建 SSLContextSSLContext sslContext = SSLContext.getInstance("TLS");sslContext.init(kmf.getKeyManagers(), null, new SecureRandom());SSLConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory(sslContext,new String[]{"TLSv1"},null,new org.apache.http.conn.ssl.DefaultHostnameVerifier());connManager = new BasicHttpClientConnectionManager(RegistryBuilder.<ConnectionSocketFactory>create().register("http", PlainConnectionSocketFactory.getSocketFactory()).register("https", sslConnectionSocketFactory).build(),null,null,null);}else {connManager = new BasicHttpClientConnectionManager(RegistryBuilder.<ConnectionSocketFactory>create().register("http", PlainConnectionSocketFactory.getSocketFactory()).register("https", SSLConnectionSocketFactory.getSocketFactory()).build(),null,null,null);}org.apache.http.client.HttpClient httpClient = HttpClientBuilder.create().setConnectionManager(connManager).build();/**发送信息到微信服务器**/HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers");/**设置超时时间**/RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(readTimeoutMs).setConnectTimeout(connectTimeoutMs).build();httpPost.setConfig(requestConfig);StringEntity postEntity = new StringEntity(xml.toString(), "UTF-8");httpPost.addHeader("Content-Type", "text/xml");httpPost.addHeader("User-Agent", "wxpay sdk java v1.0 " + Constant.MERCHANTID);  // TODO: 很重要,用来检测 sdk 的使用情况,要不要加上商户信息?httpPost.setEntity(postEntity);/**发送后返回支付结果,xml格式**/HttpResponse httpResponse = httpClient.execute(httpPost);HttpEntity httpEntity = httpResponse.getEntity();return EntityUtils.toString(httpEntity, "UTF-8");}}

微信提现测试

package com.kk.wechatextract;import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalTime;
import java.util.Map;import com.google.common.collect.Maps;/*** @author kk* 微信提现*/
public class WechatExtract {public static void main(String[] args) throws Exception {//提现金额(单位:元)String result = "2";Map<String, String> map = Maps.newHashMap();//元转换为分,微信支付已分为单位BigDecimal sumAmount = new BigDecimal(result);//乘以100,转换为分BigDecimal transAmt = sumAmount.multiply(new BigDecimal(100)); //订单号String Order = "F"+LocalDate.now().toString().replace("-", "")+LocalTime.now().toString().replace("-", "").replace(":","").replace(".", "");//随机字符串map.put("nonce_str",OtherUtils.getNonceStr().toString());//openid("c从数据库中查询")//map.put("openid",openid.get(0).getUserlevel());map.put("openid","ocYeu0V9WccmTP9axyCp_tDscUN0");//金额map.put("amount",transAmt.toString());企业付款操作说明信息map.put("desc","提现测试");//调用支付String returnInfo =  WeChatWithdrawUtils.withdrawRequestOnce(map,3000,3000,true);Map<String,String> resultMap = OtherUtils.readStringXmlOut(returnInfo);if(resultMap.containsKey("result_code") && "SUCCESS".equals(resultMap.getOrDefault("result_code",""))){System.out.println("提现成功");System.out.println("返回结果:"+returnInfo);}else{System.out.println("提现成功");System.out.println("返回结果:"+returnInfo);}}
}

常量类

package com.kk.wechatextract;import java.util.LinkedHashMap;
import java.util.Map;import javax.servlet.http.HttpServletRequest;import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;public class Constant {//微信appidpublic static final String APPID= "**********";//微信商户idpublic static final String MERCHANTID = "**********";//微信商户秘钥public static final String MERCHANTKEY = "*****************";public static final String APPSECRET = "*********************";//证书路径public static final String SSLCERT_PATH = "***********";
}

微信企业付款到零钱(微信提现)相关推荐

  1. 微信零钱数据在服务器,关于微信企业付款到零钱X509Certificate2读取证书信息,发布到服务器访问不到的解决方案...

    前言: 最近做了一个通过调用微信企业付款到用户零钱的功能,真的挺奇怪的,在我本地调试的时候都没有问题,但是当我发布到服务上的时候却一直无法读取到我的证书信息.读取的代码如下,使用的是微信官方文档提供的 ...

  2. JAVA微信企业付款到零钱(十分钟搞定),附完整DEMO下载

    最近帮朋友做了一个简单的微分销系统,实现从企业付款到零钱分润的功能,简单记录一下微信提现功能开发的流程, 主要就是按规则封装好请求参数调用微信接口,涉及一些签名校验: A.接口流程 获取用户OPENI ...

  3. 微信支付、微信企业付款到零钱工具类

    微信支付.微信企业付款到零钱工具类 主要依赖:apache httpclient 4.5 jdk1.8 工具类主要功能: xml参数拼接 签名算法实现 post加密请求 import lombok.e ...

  4. 微信企业付款到零钱出现请提交付款接口调用IP

    最近开通了微信企业付款到零钱产品,相关的支付域名都配置,可以在提交IP时候一直提示 请提交付款接口调用IP 错误,查阅了官网很多资料,有的说要填写出口IP,明明填写的是服务器的IP地址,缺一直提示这个 ...

  5. java零钱换整程序_JAVA微信企业付款到零钱(十分钟搞定),

    JAVA微信企业付款到零钱(十分钟搞定), 最近帮朋友做了一个简单的微分销系统,实现从企业付款到零钱分润的功能,简单记录一下微信企业付款到零钱的开发过程, 主要就是按规则封装好请求参数调用微信接口,涉 ...

  6. 微信企业付款到零钱功能介绍

    微信企业付款到零钱功能介绍 一.企业付款至零钱业务介绍 企业付款业务是为了协助商户方便地实现企业向个人付款,针对部分有开发能力的商户,通过API或网页操作,付款至目标用户(企业可根据APPID+Ope ...

  7. 微信 企业付款到零钱 提现

    官方文档:https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=14_1 关键参数如图: 证书如图: 证书路径要与代码里的路 ...

  8. 企业付款到零钱微信API请求报错:error:0909006C:PEM routines:get_name:no start line

    背景 对接企业付款到零钱,微信api请求时需要用到证书(node环境使用pem格式) 微信API:[微信支付]付款开发者文档 已经用微信的\WXCertUtil工具在本地生成了证书文件 问题所在: 证 ...

  9. 微信企业付款到零钱,查询接口报错<err_code_des><![CDATA[参数错误:必须输入商户号]]></err_code_des>

    <xml> <return_code><![CDATA[SUCCESS]]></return_code> <return_msg><! ...

最新文章

  1. [Elasticsearch] 部分匹配 (三) - 查询期间的即时搜索
  2. Oracle Compile 编译 无效对象(ORA-04063: package body SYS.DBMS_XPLAN 有错误)
  3. java解析xml文件四种方式介绍、性能比较和基本使用方法
  4. HDU6184【Counting Stars】(三元环计数)
  5. 使用shell实现zookeeper集群的自动搭建
  6. Convert your single instance to 10g RAC by manual
  7. R语言柯西概率分布(cauchy distribution)函数(dcauchy, pcauchy, qcauchy rcauchy)实战
  8. global全局对象
  9. vm装linux不能上网 系统,VM 安装Linux后,以前的系统无法上网
  10. 2022团队天梯赛答案解析
  11. 第三方能查到我们的微信聊天记录?
  12. 计算机专业英语教程6版答案,计算机专业英语教程(第4版)译文6.2
  13. canny算法(1)——高斯平滑滤波
  14. L2TP与PPTP区别
  15. Unity 简单动画
  16. 图书馆区域集群管理系统软件V4.0
  17. ich7支持服务器内存,英特尔 4 Series芯片组-ICH7是什么主板,支持的CPU有哪些?
  18. 魂武者怎么在电脑上玩 魂武者电脑版使用教程
  19. 几何学小课堂:非欧几何(广义相对论采用黎曼几何作为数学工具)【学数学关键是要学会在什么情况下,知道使用什么工具。】
  20. 多功能悬浮球下载_悬浮球app下载

热门文章

  1. WIFI跟WLAN是一样的吗
  2. nginx实战(二) WebDAV 模块 http_dav_module
  3. FLOPS、FLOPs、FPS
  4. Nike的虚拟运动鞋,致敬Air Force 1
  5. QQ如何设置关闭“可能认识的人”推荐
  6. JavaScript获取变量数据类型
  7. 【硬件】电源选购解读手册
  8. Eclipse常用插件在线安装和离线安装方式
  9. c语言验证卡不列克常数,卡布列克数
  10. toString与valueOf区别