微信企业付款到零钱(微信提现)
由于项目中要用到微信提现,参考网上代码和官方文档写了提现的工具类
用到的相关类库
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 = "***********";
}
微信企业付款到零钱(微信提现)相关推荐
- 微信零钱数据在服务器,关于微信企业付款到零钱X509Certificate2读取证书信息,发布到服务器访问不到的解决方案...
前言: 最近做了一个通过调用微信企业付款到用户零钱的功能,真的挺奇怪的,在我本地调试的时候都没有问题,但是当我发布到服务上的时候却一直无法读取到我的证书信息.读取的代码如下,使用的是微信官方文档提供的 ...
- JAVA微信企业付款到零钱(十分钟搞定),附完整DEMO下载
最近帮朋友做了一个简单的微分销系统,实现从企业付款到零钱分润的功能,简单记录一下微信提现功能开发的流程, 主要就是按规则封装好请求参数调用微信接口,涉及一些签名校验: A.接口流程 获取用户OPENI ...
- 微信支付、微信企业付款到零钱工具类
微信支付.微信企业付款到零钱工具类 主要依赖:apache httpclient 4.5 jdk1.8 工具类主要功能: xml参数拼接 签名算法实现 post加密请求 import lombok.e ...
- 微信企业付款到零钱出现请提交付款接口调用IP
最近开通了微信企业付款到零钱产品,相关的支付域名都配置,可以在提交IP时候一直提示 请提交付款接口调用IP 错误,查阅了官网很多资料,有的说要填写出口IP,明明填写的是服务器的IP地址,缺一直提示这个 ...
- java零钱换整程序_JAVA微信企业付款到零钱(十分钟搞定),
JAVA微信企业付款到零钱(十分钟搞定), 最近帮朋友做了一个简单的微分销系统,实现从企业付款到零钱分润的功能,简单记录一下微信企业付款到零钱的开发过程, 主要就是按规则封装好请求参数调用微信接口,涉 ...
- 微信企业付款到零钱功能介绍
微信企业付款到零钱功能介绍 一.企业付款至零钱业务介绍 企业付款业务是为了协助商户方便地实现企业向个人付款,针对部分有开发能力的商户,通过API或网页操作,付款至目标用户(企业可根据APPID+Ope ...
- 微信 企业付款到零钱 提现
官方文档:https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=14_1 关键参数如图: 证书如图: 证书路径要与代码里的路 ...
- 企业付款到零钱微信API请求报错:error:0909006C:PEM routines:get_name:no start line
背景 对接企业付款到零钱,微信api请求时需要用到证书(node环境使用pem格式) 微信API:[微信支付]付款开发者文档 已经用微信的\WXCertUtil工具在本地生成了证书文件 问题所在: 证 ...
- 微信企业付款到零钱,查询接口报错<err_code_des><![CDATA[参数错误:必须输入商户号]]></err_code_des>
<xml> <return_code><![CDATA[SUCCESS]]></return_code> <return_msg><! ...
最新文章
- [Elasticsearch] 部分匹配 (三) - 查询期间的即时搜索
- Oracle Compile 编译 无效对象(ORA-04063: package body SYS.DBMS_XPLAN 有错误)
- java解析xml文件四种方式介绍、性能比较和基本使用方法
- HDU6184【Counting Stars】(三元环计数)
- 使用shell实现zookeeper集群的自动搭建
- Convert your single instance to 10g RAC by manual
- R语言柯西概率分布(cauchy distribution)函数(dcauchy, pcauchy, qcauchy rcauchy)实战
- global全局对象
- vm装linux不能上网 系统,VM 安装Linux后,以前的系统无法上网
- 2022团队天梯赛答案解析
- 第三方能查到我们的微信聊天记录?
- 计算机专业英语教程6版答案,计算机专业英语教程(第4版)译文6.2
- canny算法(1)——高斯平滑滤波
- L2TP与PPTP区别
- Unity 简单动画
- 图书馆区域集群管理系统软件V4.0
- ich7支持服务器内存,英特尔 4 Series芯片组-ICH7是什么主板,支持的CPU有哪些?
- 魂武者怎么在电脑上玩 魂武者电脑版使用教程
- 几何学小课堂:非欧几何(广义相对论采用黎曼几何作为数学工具)【学数学关键是要学会在什么情况下,知道使用什么工具。】
- 多功能悬浮球下载_悬浮球app下载