100字范文,内容丰富有趣,生活中的好帮手!
100字范文 > 微信支付 微信企业付款到零钱工具类

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

时间:2023-11-15 20:32:47

相关推荐

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

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

主要依赖:apache httpclient 4.5 jdk1.8

工具类主要功能:

xml参数拼接签名算法实现post加密请求

import lombok.extern.slf4j.Slf4j;import org.apache.http.HttpEntity;import org.apache.http.HttpResponse;import org.apache.http.HttpStatus;import org.apache.http.client.config.RequestConfig;import org.apache.http.client.methods.HttpPost;import org.apache.http.conn.ConnectTimeoutException;import org.apache.http.conn.ConnectionPoolTimeoutException;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.ssl.SSLContexts;import org.apache.http.util.EntityUtils;import .ssl.HostnameVerifier;import .ssl.SSLContext;import .ssl.SSLSession;import java.io.File;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.IOException;import java.lang.reflect.Field;import .SocketTimeoutException;import java.security.*;import java.security.cert.CertificateException;import java.util.Set;import java.util.SortedMap;import java.util.TreeMap;@Slf4jpublic class WxPayHelper {/*** 企业付款到零钱接口URL.*/private static final String TRANS_URL = "https://api.mch./mmpaymkttransfers/promotion/transfers";private static final String hexDigits[] = {"0", "1", "2", "3", "4", "5","6", "7", "8", "9", "a", "b", "c", "d", "e", "f" };/*** 微信支付签名算法sign* @param parameters 参数集合* @return 返回md5签名*/public static String createSign(String signKey,SortedMap<Object,Object> parameters) {StringBuilder sb = new StringBuilder(); // 多线程访问的情况下需要用StringBufferSet es = parameters.keySet(); // 所有参与传参的key按照accsii排序(升序)for (Object set : es) {String k = set.toString();Object v = parameters.get(k);sb.append(k).append("=").append(v.toString()).append("&");}sb.append("key=").append(signKey);return str2MD5(sb.toString(), "utf-8").toUpperCase();}/*** MD5加密* @param data 要加密的数据* @param encode 加密的编码* @return md5字符串*/public static String str2MD5(String data, String encode) {String resultString = null;try {MessageDigest md = MessageDigest.getInstance("MD5");if (encode == null || "".equals(encode))resultString = byteArrayToHexString(md.digest(data.getBytes()));else {resultString = byteArrayToHexString(md.digest(data.getBytes(encode)));}} catch (Exception exception) {}return resultString;}/*** byte数组转换16进制字符串* @param b 要转换的byte数组* @return 16进制字符串*/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();}/*** byte转换成16进制字符串* @param b 要转换的byte* @return byte对应的16进制字符串*/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];}/*** map集合参数转换为xml格式* @param dataMap 要转换的map对象* @return XML格式的字符串*/public static String map2XML(SortedMap<Object, Object> dataMap) {StringBuilder strBuilder = new StringBuilder();Set<Object> objSet = dataMap.keySet();strBuilder.append("<xml>\n");for (Object key : objSet){if (key == null){continue;}Object value = dataMap.get(key);strBuilder.append("<").append(key.toString()).append(">").append(value).append("</").append(key.toString()).append(">\n");}strBuilder.append("</xml>");return strBuilder.toString();}/** 生成随机数.* @param count 要生成的随机数位数* @return 随机数字符串*/private String createNonceStr(int count){String[] nums = {"0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F"};int maxIndex = nums.length - 1;int numIndex;StringBuilder builder = new StringBuilder(count);for (int i = 0; i < count; i++){numIndex = (int)(Math.random() * maxIndex);builder.append(nums[numIndex]);}return builder.toString();}/*** 生成签名和xml参数的main方法测试.* see https://pay./wiki/doc/api/tools/mch_pay.php?chapter=4_3* @param args*/public static void main(String[] args) {String key = "19250b4c09247ec02edce69f6a2d";SortedMap<Object, Object> map = new TreeMap<>();map.put("appid","wxd930ea5d5a258f4f");map.put("mch_id","10000100");map.put("device_info","1000");map.put("body","test");map.put("nonce_str","ibuaiVcKdpRxkhJA"); // 这里为了跟文档的结果对应,直接使用文档的随机数String sign = WxPayHelper.createSign(key, map);map.put("sign",sign);String xmlParam = WxPayHelper.map2XML(map);System.out.println(xmlParam);}//*** 以下是http请求相关接口方法.*///*** 加载证书.* @param certPath 证书文件绝对路径* @param mchid 商户id*/private static KeyStore initCert(String certPath, String mchid) {KeyStore keyStore = null;// 加载本地的证书进行https加密传输FileInputStream instream = null;try {keyStore = KeyStore.getInstance("PKCS12");instream = new FileInputStream(new File(certPath));keyStore.load(instream, mchid.toCharArray()); // 加载证书密码,默认为商户ID} catch (KeyStoreException e) {log.error(e.getMessage(), e);} catch (FileNotFoundException e) {log.error(e.getMessage(), e);} catch (NoSuchAlgorithmException e) {log.error(e.getMessage(), e);} catch (CertificateException e) {log.error(e.getMessage(), e);} catch (IOException e) {log.error(e.getMessage(), e);} finally {if (instream!=null) {try {instream.close();} catch (IOException e) {log.error(e.getMessage(), e);}}}return keyStore;}/**** 创建CloseableHttpClient.* @param keyStore* @param keyPassword* @return*/private static CloseableHttpClient createHttpClient(KeyStore keyStore, char[] keyPassword) {// Trust own CA and all self-signed certsSSLContext sslcontext = null;try {sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore, keyPassword).build();} catch (NoSuchAlgorithmException e) {log.error(e.getMessage(), e);} catch (KeyManagementException e) {log.error(e.getMessage(), e);} catch (KeyStoreException e) {log.error(e.getMessage(), e);} catch (UnrecoverableKeyException e) {log.error(e.getMessage(), e);}// Allow TLSv1 protocol onlySSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext,new String[] {"TLSv1"},null,new HostnameVerifier() {@Overridepublic boolean verify(String hostname, SSLSession sslSession) {// 微信商户平台的支付接口验证直接通过if ("api.mch.".equals(hostname)) {return true;} else {HostnameVerifier hv = SSLConnectionSocketFactory.getDefaultHostnameVerifier();return hv.verify(hostname, sslSession);}}});CloseableHttpClient httpClient = HttpClients.custom().setSSLSocketFactory(sslsf).build();// 根据默认超时限制初始化requestConfigreturn httpClient;}/*** post传输xml数据.* @param url 传输url* @param xmlObj xml参数* @param mchid 商户id* @param certPath 证书文件的绝对路径* @return*/public static String post(String url, String xmlObj, String mchid, String certPath) {RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(5000).setConnectTimeout(10000).build();// 加载证书KeyStore keyStore = initCert(certPath, mchid);CloseableHttpClient httpClient = createHttpClient(keyStore, mchid.toCharArray());String result = null;HttpPost httpPost = new HttpPost(url);// 得指明使用UTF-8编码,否则到API服务器XML的中文不能被成功识别String defaultCharset = "UTF-8";StringEntity postEntity = new StringEntity(xmlObj, defaultCharset);httpPost.addHeader("Content-Type", "text/xml");httpPost.setEntity(postEntity);// 设置请求器的配置httpPost.setConfig(requestConfig);try {HttpResponse res = httpClient.execute(httpPost);if (res.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {HttpEntity entity = res.getEntity();result = EntityUtils.toString(entity, defaultCharset);}} catch (ConnectionPoolTimeoutException e) {log.error(e.getMessage(), e);} catch (ConnectTimeoutException e) {log.error(e.getMessage(), e);} catch (SocketTimeoutException e) {log.error(e.getMessage(), e);} catch (Exception e) {log.error(e.getMessage(), e);} finally {httpPost.abort();}return result;}/*** 发送请求.* @param key 密钥* @param certPath API证书证书apiclient_cert.p12* @param model 企业付款到零钱接口所需参数* @return String*/public static String doTransfers(String key, String certPath, WxMchPayB2c model)throws IllegalAccessException {SortedMap<Object, Object> map = new TreeMap<>();Field[] declaredFields = model.getClass().getDeclaredFields();for (Field field : declaredFields) {field.setAccessible(true);String k = field.getName();Object v = field.get(model);if (v != null) {map.put(k, v);}}String sign = WxPayHelper.createSign(key, map);map.put("sign",sign);String xmlParam = WxPayHelper.map2XML(map);String result = post(TRANS_URL, xmlParam, model.getMchid(), certPath);return result;}}

import io.swagger.annotations.ApiModel;import io.swagger.annotations.ApiModelProperty;import lombok.Data;/*** @Desc https://pay./wiki/doc/api/tools/mch_pay.php?chapter=14_2*/@Data@ApiModel(value="net.mondelez.scan.microservice.entity.vo.WxMchPayB2c", description = "微信商户平台-微信支付-企业付款到零钱")public class WxMchPayB2c {@ApiModelProperty(value="申请商户号的appid或商户号绑定的appid", required=true)private String mch_appid;@ApiModelProperty(value="微信支付分配的商户号", required=true)private String mchid;@ApiModelProperty(value="微信支付分配的终端设备号", required=false)private String device_info;@ApiModelProperty(value="随机字符串,不长于32位", required=true)private String nonce_str;@ApiModelProperty(value="签名,签名算法:https://pay./wiki/doc/api/tools/mch_pay.php?chapter=4_3", required=true)private String sign;@ApiModelProperty(value="商户订单号,需保持唯一性(只能是字母或者数字,不能包含有其它字符)", required=true)private String partner_trade_no;@ApiModelProperty(value="商户appid下,某用户的openid", required=true)private String openid;@ApiModelProperty(value="校验用户姓名选项,NO_CHECK:不校验真实姓名,FORCE_CHECK:强校验真实姓名", required=true)private String check_name="NO_CHECK";@ApiModelProperty(value="收款用户真实姓名,如果check_name设置为FORCE_CHECK,则必填用户真实姓名,如需电子回单,需要传入收款用户姓名", required=false)private String re_user_name;@ApiModelProperty(value="企业付款金额,单位为分", required=true)private Integer amount;@ApiModelProperty(value="企业付款备注,必填。注意:备注中的敏感词会被转成字符*", required=true)private String desc;@ApiModelProperty(value="Ip地址,该IP同在商户平台设置的IP白名单中的IP没有关联,该IP可传用户端或者服务端的IP", required=false)private String spbill_create_ip;}

参考:

/u013564742/article/details/88648885

https://pay./wiki/doc/api/tools/mch_pay.php?chapter=4_3

/faq/140225MveaUz150107ERniAN.html

/p/a361ed7c6691

/p/ad4c7ce94518

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。