• 微信官方提供了微信企业账户付款到微信个人零钱接口,提供企业向用户付款的功能,支持企业通过API接口付款,或通过微信支付商户平台网页功能操作付款。该接口并不是直接所有的商户都拥有,企业要开启必须满足以下两个条件:
    1、商户号已入驻90日
    2、商户号有30天连续正常交易
    满足以上条件就可登录微信支付商户平台-产品中心,开通企业付款。
    调用的链接地址:接口链接:https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers
    微信官方接口文档提供的调用微信企业付款的参数:

    参数中最重要是获取用户openid和调用接口ip,获取openid可以通过公众号获取,app端可以直接获取。具体的代码实现如下:
    封装请求微信企业付款的实体类Transfers:

    public class Transfers implements Serializable{private static final long serialVersionUID = 1L;/** 商户账号appid*/public String mch_appid;/** 微信支付商户号*/public String mchid;/** 随机串*/public String nonce_str;/** 签名*/public String sign;/** 商户订单号*/public String partner_trade_no;/** 用户id*/public String openid;/** 是否校验用户姓名 NO_CHECK:不校验真实姓名  FORCE_CHECK:强校验真实姓名*/public String check_name;/** 金额 单位:分*/public Integer amount;/** 企业付款描述信息*/public String desc;/** ip地址*/public String spbill_create_ip;public String getMch_appid() {return mch_appid;}public void setMch_appid(String mch_appid) {this.mch_appid = mch_appid;}public String getMchid() {return mchid;}public void setMchid(String mchid) {this.mchid = mchid;}public String getNonce_str() {return nonce_str;}public void setNonce_str(String nonce_str) {this.nonce_str = nonce_str;}public String getSign() {return sign;}public void setSign(String sign) {this.sign = sign;}public String getPartner_trade_no() {return partner_trade_no;}public void setPartner_trade_no(String partner_trade_no) {this.partner_trade_no = partner_trade_no;}public String getOpenid() {return openid;}public void setOpenid(String openid) {this.openid = openid;}public String getCheck_name() {return check_name;}public void setCheck_name(String check_name) {this.check_name = check_name;}public Integer getAmount() {return amount;}public void setAmount(Integer amount) {this.amount = amount;}public String getDesc() {return desc;}public void setDesc(String desc) {this.desc = desc;}public String getSpbill_create_ip() {return spbill_create_ip;}public void setSpbill_create_ip(String spbill_create_ip) {this.spbill_create_ip = spbill_create_ip;}}

接口部分代码:

private Transfers transfers = new Transfers();
// 构造签名的mapprivate SortedMap<Object, Object> parameters = new TreeMap<Object, Object>();
// 微信的参数private WeixinConfigUtils config = new WeixinConfigUtils();/*** 微信提现(企业付款)*/@Action("weixinWithdraw")public String weixinWithdraw(){String openId = request.getParameter("openid");String ip = request.getParameter("ip");String money = request.getParameter("money");String doctorId = request.getParameter("doctorId");if (StringUtils.isNotBlank(money) && StringUtils.isNotBlank(ip) && StringUtils.isNotBlank(openId) && StringUtils.isNotBlank(doctorId)) {// 参数组String appid = config.appid;String mch_id = config.mch_id;String nonce_str = RandCharsUtils.getRandomString(16);//是否校验用户姓名 NO_CHECK:不校验真实姓名  FORCE_CHECK:强校验真实姓名String checkName ="NO_CHECK";//等待确认转账金额,ip,openid的来源Integer amount = Integer.valueOf(money);String spbill_create_ip = ip;String partner_trade_no = UuIdUtils.getUUID();//描述String desc = "健康由我医师助手提现"+amount/100+"元";// 参数:开始生成第一次签名parameters.put("appid", appid);parameters.put("mch_id", mch_id);parameters.put("partner_trade_no", partner_trade_no);parameters.put("nonce_str", nonce_str);parameters.put("openId", openId);parameters.put("checkName", checkName);parameters.put("amount", amount);parameters.put("spbill_create_ip", spbill_create_ip);parameters.put("desc", desc);String sign = WXSignUtils.createSign("UTF-8", parameters);transfers.setAmount(amount);transfers.setCheck_name(checkName);transfers.setDesc(desc);transfers.setMch_appid(appid);transfers.setMchid(mch_id);transfers.setNonce_str(nonce_str);transfers.setOpenid(openId);transfers.setPartner_trade_no(partner_trade_no);transfers.setSign(sign);transfers.setSpbill_create_ip(spbill_create_ip);String xmlInfo = HttpXmlUtils.transferXml(transfers);try {CloseableHttpResponse response =  HttpUtil.Post(weixinConstant.WITHDRAW_URL, xmlInfo, true);String transfersXml = EntityUtils.toString(response.getEntity(), "utf-8");Map<String, String> transferMap = HttpXmlUtils.parseRefundXml(transfersXml);if (transferMap.size()>0) {if (transferMap.get("result_code").equals("SUCCESS") && transferMap.get("return_code").equals("SUCCESS")) {//成功需要进行的逻辑操作,}}System.out.println("成功");} catch (Exception e) {log.error(e.getMessage());throw new BasicRuntimeException(this, "企业付款异常" + e.getMessage());}}else {System.out.println("失败");}return NONE;}

产生随机串部分代码:

public class RandCharsUtils {private static SimpleDateFormat df = new SimpleDateFormat("yyyyMMddHHmmss");public static String getRandomString(int length) { //length表示生成字符串的长度String base = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz";   Random random = new Random();   StringBuffer sb = new StringBuffer();int number = 0;for (int i = 0; i < length; i++) {   number = random.nextInt(base.length());   sb.append(base.charAt(number));   }   return sb.toString();   }   }

生成签名:

public class WXSignUtils {/*** 微信支付签名算法sign* @param characterEncoding* @param parameters* @return*/@SuppressWarnings("rawtypes")public static String createSign(String characterEncoding,SortedMap<Object,Object> parameters){StringBuffer sb = new StringBuffer();Set es = parameters.entrySet();//所有参与传参的参数按照accsii排序(升序)Iterator it = es.iterator();while(it.hasNext()) {Map.Entry entry = (Map.Entry)it.next();String k = (String)entry.getKey();Object v = entry.getValue();if(null != v && !"".equals(v) && !"sign".equals(k) && !"key".equals(k)) {sb.append(k + "=" + v + "&");}}sb.append("key=" + weixinConstant.KEY);String sign = MD5Util.MD5Encode(sb.toString(), characterEncoding).toUpperCase();return sign;}
}

md5部分代码:

import java.security.MessageDigest;public class MD5Util {private static String byteArrayToHexString(byte b[]) {StringBuffer resultSb = new StringBuffer();for (int i = 0; i < b.length; i++)resultSb.append(byteToHexString(b[i]));return resultSb.toString();}private static String byteToHexString(byte b) {int n = b;if (n < 0)n += 256;int d1 = n / 16;int d2 = n % 16;return hexDigits[d1] + hexDigits[d2];}public static String MD5Encode(String origin, String charsetname) {String resultString = null;try {resultString = new String(origin);MessageDigest md = MessageDigest.getInstance("MD5");if (charsetname == null || "".equals(charsetname))resultString = byteArrayToHexString(md.digest(resultString.getBytes()));elseresultString = byteArrayToHexString(md.digest(resultString.getBytes(charsetname)));} catch (Exception exception) {}return resultString;}private static final String hexDigits[] = { "0", "1", "2", "3", "4", "5","6", "7", "8", "9", "a", "b", "c", "d", "e", "f" };}

构造xml:

/*** 构造企业付款xml参数* @param xml* @return*/public static String transferXml(Transfers transfers){xStream.autodetectAnnotations(true);xStream.alias("xml", Transfers.class);return xStream.toXML(transfers);}

向微信发送xml请求(验证证书)部分代码:

public class HttpUtil {/*** 发送post请求* * @param url*            请求地址* @param outputEntity*            发送内容* @param isLoadCert*            是否加载证书*/public static CloseableHttpResponse Post(String url, String outputEntity, boolean isLoadCert) throws Exception {HttpPost httpPost = new HttpPost(url);// 得指明使用UTF-8编码,否则到API服务器XML的中文不能被成功识别httpPost.addHeader("Content-Type", "text/xml");httpPost.setEntity(new StringEntity(outputEntity, "UTF-8"));if (isLoadCert) {// 加载含有证书的http请求return HttpClients.custom().setSSLSocketFactory(CertUtil.initCert()).build().execute(httpPost);} else {return HttpClients.custom().build().execute(httpPost);}}
}

加载证书部分代码:(加载证书需要注意证书放置位置在项目下的webapp中建文件夹,linux单独防止只要地址配置正确即可。)

import java.io.File;
import java.io.FileInputStream;
import java.security.KeyStore;import javax.net.ssl.SSLContext;import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.ssl.SSLContexts;/*** 加载证书的类* @author * @since 2017/08/16*/@SuppressWarnings("deprecation")
public class CertUtil {private static  WeixinConfigUtils config = new WeixinConfigUtils();/*** 加载证书*/public static SSLConnectionSocketFactory initCert() throws Exception {FileInputStream instream = null;KeyStore keyStore = KeyStore.getInstance("PKCS12");instream = new FileInputStream(new File(weixinConstant.PATH));keyStore.load(instream, config.mch_id.toCharArray());if (null != instream) {instream.close();}SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore,config.mch_id.toCharArray()).build();SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext, new String[]{"TLSv1"}, null, SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);return sslsf;}
}

加载配置文件部分代码:

@SuppressWarnings("unused")
public class WeixinConfigUtils {private static final Log log = LogFactory.getLog(WeixinConfigUtils.class);public static String appid;public static String mch_id;public static String notify_url;public static String order_notify_url;public static String doctor_notify_url;static {try{InputStream is = WeixinConfigUtils.class.getResourceAsStream("/weixin.properties");Properties properties = new Properties();properties.load(is);appid = properties.getProperty("weixin.appid");mch_id = properties.getProperty("weixin.mch_id");notify_url = properties.getProperty("weixin.notify_url");order_notify_url = properties.getProperty("weixin.order_notify_url");doctor_notify_url = properties.getProperty("weixin.doctor_notify_url");}catch(Exception ex){log.debug("加载配置文件:"+ex.getMessage());}}
}

获取返回的xml参数并解析为map:

/*** 解析申请退款之后微信返回的值并进行存库操作* @throws IOException * @throws JDOMException */public static Map<String, String> parseRefundXml(String refundXml) throws JDOMException, IOException{ParseXMLUtils.jdomParseXml(refundXml);StringReader read = new StringReader(refundXml);// 创建新的输入源SAX 解析器将使用 InputSource 对象来确定如何读取 XML 输入InputSource source = new InputSource(read);// 创建一个新的SAXBuilderSAXBuilder sb = new SAXBuilder();// 通过输入源构造一个Documentorg.jdom.Document doc;doc = (org.jdom.Document) sb.build(source);org.jdom.Element root = doc.getRootElement();// 指向根节点List<org.jdom.Element> list = root.getChildren();Map<String, String> refundOrderMap = new HashMap<String, String>();if(list!=null&&list.size()>0){for (org.jdom.Element element : list) {refundOrderMap.put(element.getName(), element.getText());}return refundOrderMap;}return null;}

调用时候主要是获取openid和调起接口的ip(ip十分重要,微信在收到xml后会校验传过去的ip和微信获取的调起接口ip是否一致)
在调用时候当返回错误码为“SYSTEMERROR”时,一定要使用原单号重试,否则可能造成重复支付等资金风险。
微信官方文档提供有相关的参数错误码https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=14_2。

java实现微信企业付款到个人账户相关推荐

  1. java实现微信企业付款到个人零钱(微信红包)

    今天公司打算做一个活动,就是可以让用户领取平台发送的红包,根据微信官方文档实现微信企业付款到零钱(因为商户号不满足一些条件无法使用红包,红包跟零钱实现方法基本一样),然后又加入了一些简单的红包算法.微 ...

  2. java实现微信企业付款到银行卡_微信企业付款到银行卡实现方式 - 黎明互联-官方博客 - 黎明互联 - 区块链培训,PHP培训,IT培训,职业技能培训,追求极致!改变您的职业生涯!...

    首先说一下微信支付已上线企业付款至银行卡功能.商户可以将商户号余额付款至指定的收款银行账户.通过指定收款银行账户户名.卡号,以及收款银行信息即可实现付款.但是功能目前为灰度开放,已灰度新资金流直连普通 ...

  3. 【Java】微信企业付款报错:java.io.IOException: toDerInputStream rejects tag type 45

    原因是证书格式问题,之前用PHP做一直用.pem格式的证书,看了官方文档才知道,其他语言大多用.p12格式的证书: 更换为.p12格式证书,不报错了.

  4. java 企业付款_java实现微信企业付款到个人功能

    微信官方提供了微信企业账户付款到微信个人零钱接口,提供企业向用户付款的功能,支持企业通过API接口付款,或通过微信支付商户平台网页功能操作付款.该接口并不是直接所有的商户都拥有,企业要开启必须满足以下 ...

  5. Java 微信企业付款到个人钱包

    Java 微信企业付款到个人钱包 希望可以帮助到你 文章目录 **Java 微信企业付款到个人钱包** 前言 一.需要准备的配置 二.开发 总结 前言 微信企业付款到个人钱包,此功能模块需要提前在微信 ...

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

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

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

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

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

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

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

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

最新文章

  1. 全面屏适配方案,终极版,华为隐藏导航栏解决方案
  2. 客户信贷应收总额相关
  3. python中的print()、str()和repr()的区别
  4. 关于centos6升级python3.6无法使用pip的问题
  5. 【转】Linux 静态库与共享库的使用
  6. HTTP Live Streaming直播(iOS直播)技术分析与实现(转)
  7. 猜物品游戏java编程_小猿圈Java初学者练习小案例:猜数字游戏
  8. android 实现自定义卫星菜单
  9. 华北水利水电大学计算机实验报告怎么写,考试类:华北水利水电大学C语言实验报告.doc...
  10. WPS Office 2019 For Linux 8722 发布,引入pdf组件
  11. 备忘录怎么用红笔标注_备忘录丢失怎么找回来?教你轻松玩转备忘录
  12. mac终端编写c语言,【新手提问】有知道用mac终端编c语言的网络编程的人吗?
  13. Python爬虫之(二)工具的使用
  14. Ruby First
  15. windows程序设计之简单界面入门
  16. 贵州大学旧物交易系统
  17. 远距离485无线传输方案
  18. 通常环境光照度参照表
  19. 少室山论道——天下武功
  20. 节点表征学习与节点预测和边预测

热门文章

  1. Domain name server 域名服务
  2. Android手电筒开发
  3. 结果集没有当前行的解决方法
  4. LATEXT导入.sty
  5. 什么叫loopback地址?是怎样用的?
  6. android 开发论坛资源URL
  7. php 根据父级id查出,php,_三级分类 like查询 查询到很多id 需要找到对应的父级id 并根据父级id组合 应该怎么根据父级id将数据组合在一起呢?,php - phpStudy...
  8. 如何将scr文件设置为屏保
  9. pageHelper与PageInfo联合进行分页查询原理
  10. 用伪造的TCP协议头花式欺骗核心转发设备?