`
Shuhui
  • 浏览: 5732 次
  • 性别: Icon_minigender_1
  • 来自: 成都
社区版块
存档分类
最新评论

微信企业付款到零钱 带证书请求 Java后台

阅读更多

 本文默认已经准备好微信企业付款证书. 调用createTransfers方法

package com.crown;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.security.KeyStore;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.UUID;

import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;

import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
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.DefaultHostnameVerifier;
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.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;

import com.alibaba.fastjson.JSONObject;

public class TestWX {

	Logger log = LogManager.getLogger(TestWX.class);
	
	private String payUrl = "https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers"; 
	
	private String KEY = "";//商户key
	
	/**
	 * 
	 * @param transfersCode  提现订单编号 全局唯一
	 * @param openid   提现用户openid
	 * @param userName  提现用户真实姓名
	 * @param amount  提现金额 单位 (元)  保留两位小数
	 * @return
	 * @throws Exception
	 */
	public JSONObject createTransfers(String transfersCode, String openid,String userName, String amount) throws Exception {
		JSONObject object = new JSONObject();
		log.info("微信 企业付款 接口调用:" + transfersCode);

		BigDecimal amountFen = new BigDecimal(amount);
		BigDecimal amountFen100 = amountFen.multiply(new BigDecimal("100"));

		BigDecimal setScale = amountFen100.setScale(0, BigDecimal.ROUND_HALF_DOWN);

		System.out.println("付款金额;" + setScale.toString());
		//创建hashmap(用户获得签名)
		SortedMap<String, String> paraMap = new TreeMap<String, String>();
		//设置body变量 (支付成功显示在微信支付 商品详情中)
		String desc = "提现编号[" + transfersCode + "],提现金额[" + amount + "]";
		//设置随机字符串
		String nonceStr = UUID.randomUUID().toString().replaceAll("-", "");

		String appid = "";
		//设置请求参数(小程序ID)
		paraMap.put("mch_appid", appid);
		//设置请求参数(商户号)
		paraMap.put("mchid", "");
		//设置请求参数(随机字符串)
		paraMap.put("nonce_str", nonceStr);
		//设置请求参数(商户订单号)
		paraMap.put("partner_trade_no", transfersCode);
		//设置请求参数(openid)(在接口文档中 该参数 是否必填项 但是一定要注意 如果交易类型设置成'JSAPI'则必须传入openid)
		paraMap.put("openid", openid);
		//设置提现用户真实名称 (收款用户真实姓名。 如果check_name设置为FORCE_CHECK,则必填用户真实姓名)
		paraMap.put("check_name", "FORCE_CHECK");
		//设置用户真实姓名
		paraMap.put("re_user_name", userName);
		//设置请求参数(总金额)
		paraMap.put("amount", setScale.toString());
		//设置请求参数(商品描述)
		paraMap.put("desc", desc);
		//设置请求参数(终端IP)
		paraMap.put("spbill_create_ip", "127.0.0.1");//服务器公网IP

		//调用逻辑传入参数按照字段名的 ASCII 码从小到大排序(字典序)
		String stringA = formatUrlMap(paraMap, false, false);
		//第二步,在stringA最后拼接上key得到stringSignTemp字符串,并对stringSignTemp进行MD5运算,再将得到的字符串所有字符转换为大写,得到sign值signValue。(签名)
		String sign = getMD5String(stringA + "&key=" + KEY).toUpperCase();
		//将参数 编写XML格式
		StringBuffer paramBuffer = new StringBuffer();
		paramBuffer.append("<xml>");
		paramBuffer.append("<mch_appid>" + appid + "</mch_appid>");
		paramBuffer.append("<mchid>" + paraMap.get("mchid") + "</mchid>");
		paramBuffer.append("<nonce_str>" + paraMap.get("nonce_str") + "</nonce_str>");
		paramBuffer.append("<sign>" + sign + "</sign>");
		paramBuffer.append("<partner_trade_no>" + paraMap.get("partner_trade_no") + "</partner_trade_no>");
		paramBuffer.append("<openid>" + openid + "</openid>");
		paramBuffer.append("<check_name>" + paraMap.get("check_name") + "</check_name>");
		paramBuffer.append("<re_user_name>" + userName + "</re_user_name>");
		paramBuffer.append("<amount>" + paraMap.get("amount") + "</amount>");
		paramBuffer.append("<desc>" + desc + "</desc>");
		paramBuffer.append("<spbill_create_ip>" + paraMap.get("spbill_create_ip") + "</spbill_create_ip>");
		paramBuffer.append("</xml>");

		String map = getRestInstance(payUrl,paramBuffer.toString());
		
		Map<String, String> parseObject = doXMLParse(map);

		//应该创建 支付表数据
		if (parseObject != null && parseObject.get("return_code").equals("SUCCESS")) {
			log.info("微信订单返回数据:", parseObject);
			log.info("微信 统一下单 接口调用成功 新增支付信息 :" + paraMap.get("partner_trade_no"));
			
			if (parseObject.get("result_code").equals("SUCCESS")) {//提现成功,修改数据
				
				object.put("status", 0);
				object.put("data", "success");
				
				return object;
			}else { //失败以及提示失败原因
				String err_code = parseObject.get("err_code");//错误代码
				String err_code_des = parseObject.get("err_code_des");//错误代码描述
				
				object.put("status", -1);
				object.put("errCode", err_code);
				object.put("errCodeDes", err_code_des);
				return object;
			}
		}

		throw new RuntimeException("错误信息:" + "微信提现失败>返回数据为:" + map);
	
	}
	
	
	public String getRestInstance(String url,String data) throws Exception{
		
		 char[] password = "证书密码".toCharArray();
        InputStream certStream = caConfig();//证书的流
        KeyStore ks = KeyStore.getInstance("PKCS12");
        ks.load(certStream, password);

        // 实例化密钥库 & 初始化密钥工厂
        KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
        kmf.init(ks, password);

        // 创建 SSLContext
        SSLContext sslContext = SSLContext.getInstance("TLS");
        sslContext.init(kmf.getKeyManagers(), null, new SecureRandom());

        SSLConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory(
                sslContext,
                new String[]{"TLSv1"},
                null,
                new DefaultHostnameVerifier());

        BasicHttpClientConnectionManager connManager = new BasicHttpClientConnectionManager(
                RegistryBuilder.<ConnectionSocketFactory>create()
                        .register("http", PlainConnectionSocketFactory.getSocketFactory())
                        .register("https", sslConnectionSocketFactory)
                        .build(),
                null,
                null,
                null
        );
		
        HttpClient httpClient = HttpClientBuilder.create().setConnectionManager(connManager).build();
        
        HttpPost httpPost = new HttpPost(url);

        RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(10000).setConnectTimeout(8000).build();
        httpPost.setConfig(requestConfig);

        StringEntity postEntity = new StringEntity(data, "UTF-8");
        httpPost.addHeader("Content-Type", "text/xml");
        httpPost.addHeader("User-Agent",  "This is transfers ");
        httpPost.setEntity(postEntity);

        HttpResponse httpResponse = httpClient.execute(httpPost);
        HttpEntity httpEntity = httpResponse.getEntity();
        return EntityUtils.toString(httpEntity, "UTF-8");
	}
	
	private InputStream caConfig() throws Exception {
		File fDir=new File(File.separator);
		
		String certPath = "usr/apiclient_cert.p12";
	    
	    return  new FileInputStream(new File(fDir,certPath));
	}
	
	
	/**
	 * 
	 * 方法用途: 对所有传入参数按照字段名的 ASCII 码从小到大排序(字典序),并且生成url参数串<br>
	 * 实现步骤: <br>
	 * 
	 * @param paraMap    要排序的Map对象
	 * @param urlEncode  是否需要URLENCODE
	 * @param keyToLower 是否需要将Key转换为全小写 true:key转化成小写,false:不转化
	 * @return
	 */
	private 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>>() {
				@Override
				public 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;
	}
	
	private String getMD5String(String str) {
		return DigestUtils.md5Hex(str);
	}
	
	/**
	 * 解析xml,返回第一级元素键值对。如果第一级元素有子节点,则此节点的值是子节点的xml数据。
	 * 
	 * @param strxml
	 * @return
	 * @throws JDOMException
	 * @throws IOException
	 */
	@SuppressWarnings("rawtypes")
	private Map<String, String> doXMLParse(String strxml) throws Exception {
		if (null == strxml || "".equals(strxml)) {
			return null;
		}

		Map<String, String> m = new HashMap<String, String>();
		InputStream in = String2Inputstream(strxml);
		SAXBuilder builder = new SAXBuilder();
		Document doc = builder.build(in);
		Element root = doc.getRootElement();
		List list = root.getChildren();
		Iterator it = list.iterator();
		while (it.hasNext()) {
			Element e = (Element) it.next();
			String k = e.getName();
			String v = "";
			List children = e.getChildren();
			if (children.isEmpty()) {
				v = e.getTextNormalize();
			} else {
				v = getChildrenText(children);
			}

			m.put(k, v);
		}

		//关闭流
		in.close();

		return m;
	}

	private InputStream String2Inputstream(String str) {
		return new ByteArrayInputStream(str.getBytes());
	}

	/**
	 * 获取子结点的xml
	 * 
	 * @param children
	 * @return String
	 */
	@SuppressWarnings("rawtypes")
	private String getChildrenText(List children) {
		StringBuffer sb = new StringBuffer();
		if (!children.isEmpty()) {
			Iterator it = children.iterator();
			while (it.hasNext()) {
				Element e = (Element) it.next();
				String name = e.getName();
				String value = e.getTextNormalize();
				List list = e.getChildren();
				sb.append("<" + name + ">");
				if (!list.isEmpty()) {
					sb.append(getChildrenText(list));
				}
				sb.append(value);
				sb.append("</" + name + ">");
			}
		}

		return sb.toString();
	}
}

 

0
0
分享到:
评论

相关推荐

    Java实现微信企业付款到个人零钱简易demo.rar

    总之,Java实现微信企业付款到个人零钱功能涉及到微信支付平台的配置、请求参数的构造、签名算法的应用以及服务器间的通信。通过遵循微信支付的接口规范和安全策略,开发者可以安全有效地完成这一功能的集成。在实际...

    Java后台微信企业转账到零钱

    通过以上分析,我们可以看出,实现“Java后台微信企业转账到零钱”涉及到了微信支付API的集成、签名算法的应用、请求参数的构造、错误处理策略以及后台系统的设计等多个技术环节。每个环节都需要精确无误地实现,以...

    微信企业付款到个人零钱 C#Demo

    微信企业付款到个人零钱是微信支付为企业提供的一项服务,允许企业向个人用户进行资金转账,常见于工资发放、退款、奖励等场景。C# Demo则是一个实现这一功能的示例代码,帮助开发者理解并快速集成到自己的系统中。...

    java微信支付企业付款到零钱demo

    Java微信支付企业付款到零钱的DEMO是一个实用的开发示例,主要用于帮助开发者快速集成微信支付功能,以便将款项直接转账到用户的微信零钱账户。这个DEMO提供了完整的流程和必要的API调用,简化了支付接口的对接过程...

    c#微信支付、微信企业付款到个人,微信企业付款到零钱 asp.net源代码demo

    微信支付、微信企业支付到个人,微信企业付款到零钱,微信支付apiJSAPI支付 刷卡支付 扫码支付 订单退款 订单查询 退款查询 下载账单

    c#微信支付、微信企业支付到个人,微信企业付款到零钱, 代码DEMO.rar.rar

    c#微信支付、微信企业支付到个人,微信企业付款到零钱, 代码DEMO.rar.rar c#微信支付、微信企业支付到个人,微信企业付款到零钱, 代码DEMO.rar.rar c#微信支付、微信企业支付到个人,微信企业付款到零钱, 代码...

    微信企业付款到零钱API

    微信企业付款到零钱API是微信支付平台提供的一项服务,允许企业向个人用户(通常是员工、供应商或客户)直接转账,将款项存入他们的微信钱包。这个API在人力资源管理、在线销售、奖励机制等场景中非常实用。在这个...

    c#微信支付、微信企业支付到个人,微信企业付款到零钱, 代码DEMO

    本文将详述基于C#实现微信支付、微信企业支付到个人以及微信企业付款到零钱的相关技术点,并提供代码DEMO供参考。 1. **微信支付API**:微信支付API是微信官方提供的接口,用于商家集成微信支付功能。它包括多种...

    微信付款到零钱demo

    微信付款到零钱demo,可以看看。

    微信支付源码之企业付款到零钱生产环境实例php demo

    在本实例中,我们关注的是“企业付款到零钱”的功能,这通常用于企业向个人用户发放红包、退款或者工资等。这个PHP demo提供了一个在生产环境中实现此功能的具体示例。 首先,我们来看`send.php`,这是核心的处理...

    微信企业付款到零钱实战操作指南(java)

    总的来说,微信企业付款到零钱的Java实现涉及到微信支付SDK的集成、配置信息的设定、证书的处理以及API的调用。通过以上步骤,开发者可以构建一个完整的微信企业付款功能,将款项安全、便捷地转入用户的微信零钱账户...

    微信商户付款到微信用户零钱(v2密钥版)和微信商户转账到微信用户零钱(v3密钥版)源码包

    这几天做项目有一个需求,小程序用户提交记录后,商家后台审核通过自动转账到用户的微信零钱中. 今天分享下如何实现自动打款,已提取出做成demo,SDK的下载地址也在demo中 一种是用v2密钥的接口:企业付款到零钱, 一种...

    微信提现到零钱V3接口的对接java实现demo.rar

    微信提现到零钱V3接口的对接Java实现主要涉及到微信支付平台的相关开发,这是一个关键的金融功能,允许用户将资金从微信支付账户转移到他们的微信零钱。以下是对这个实现过程的详细说明: 1. **微信支付接口对接**...

    微信企业付款到个人银行卡demo java

    微信企业付款到个人银行卡的Java实现是一个常见的支付接口调用任务,主要涉及到微信支付API的使用,以及公钥和私钥的加密解密操作。在这个过程中,开发者需要对微信支付平台的接口规范有深入理解,并熟悉Java的加密...

    微信企业付款到零钱DEMO PHP 单文件本地下载即可执行版本 完美无错

    微信企业付款到零钱功能是微信支付为企业用户提供的资金转账服务,允许企业向个人微信用户进行款项支付,常用于退款、奖励、佣金结算等场景。本DEMO是基于PHP语言实现的一个单文件版本,便于开发者快速理解和应用。...

    微信付款到零钱

    在进行微信付款到零钱的操作时,用户首先需要确保自己的微信账号已经完成了实名认证,并且绑定了至少一张银行卡。这样,当外部资金需要转入微信零钱时,可以通过银行卡转账来实现。 执行此操作的具体步骤通常包括...

    Thinkphp 5.0实现微信企业付款到零钱

    在当前互联网和移动支付盛行的时代,微信支付已经成为了一种重要的支付方式,企业也常需要利用微信支付接口为企业内部人员或者合作伙伴进行款项的转付,此过程称为企业付款到零钱。ThinkPHP 5.0作为一个基于PHP的...

    PHP微信商户支付企业付款到零钱功能

    PHP微信商户支付企业付款到零钱功能,这个是一个php的类文件,就一个文件。 调用方式: $paymentchange = new wechat_paymentchange(); $res = $paymentchange-&gt;sendMoney($amount,$re_openid,$desc='测试',$check_...

Global site tag (gtag.js) - Google Analytics