java-微信--企业向个人付款

17 篇文章 2 订阅
3 篇文章 0 订阅

功能描述:在微信公众号H5 用户赚取的金额 提现到微信用户个人钱包里;

实现原理:调用微信企业向个人付款接口 接口地址:https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers

 通过openId 和appId绑定用户.

开通企业向个人付款功能 必须要满足:1,商户号已入驻90日, 2,商户号有30天连续正常交易

需要的参数

商户账号appid mch_appid

 微信公众号配置里可以看到

商户号 mchid
微信支付分配的商户号   微信商户平台里查看

随机字符串 nonce_str
随机字符串,不长于32位

String nonce_str = UUID.randomUUID().toString().toUpperCase().replaceAll("-", "");// 随机获取UUID

商户订单号 partner_trade_no
商户订单号,需保持唯一性
(只能是字母或者数字,不能包含有符号)

String fsNO = GenerateKeyNO.generate("FS");
String partner_trade_no = fsNO;

    /**
* 生成订单号,格式:XX(前缀) + yyyyMMddHHmmss + 10位数
* @param prefix
* @return
*/
public static String generate(String prefix) {

synchronized(locker) {
if (sn == 999999999) {
sn = 0;
} else {
sn ++;
}
String str = String.format("%010d", sn);
return prefix + sdf.format(new Date()) + str;
}
}

用户openid openid
商户appid下,某用户的openid

如何获取openid请参考我的另一篇文章

校验用户姓名选项 check_name
NO_CHECK:不校验真实姓名 
FORCE_CHECK:强校验真实姓名

金额 amount
企业付款金额,单位为分  

String.valueOf((int)(amount*100)

企业付款描述信息 desc
企业付款操作说明信息。必填。

Ip地址 spbill_create_ip
String spbill_create_ip = PayCommonUtil.getIpAddr(request).replace("_", "."); // 获取发起电脑ip

   /**
     * 
     * 功能描述:获取真实的IP地址
     * @param request
     * @return
     * @author guoyx
     */
    public static String getIpAddr(HttpServletRequest request)
    {
        String ip = request.getHeader("x-forwarded-for");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip))
        {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip))
        {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip))
        {
            ip = request.getRemoteAddr();
        }
        if (!isnull(ip) && ip.contains(","))
        {
            String[] ips = ip.split(",");
            ip = ips[ips.length - 1];
        }
        //转换IP 格式
        if(!isnull(ip)){
            ip=ip.replace(".", "_");
        }
        return ip;
    }

签名 sign

 SortedMap<Object, Object> signParams = new TreeMap<Object, Object>();
   signParams.put("mch_appid", mch_appid); // 微信分配的公众账号ID(企业号corpid即为此appId)
   signParams.put("mchid", mchid);// 微信支付分配的商户号
   signParams.put("nonce_str", nonce_str); // 随机字符串,不长于32位
   signParams.put("partner_trade_no", partner_trade_no);// 商户订单号,需保持唯一性
   signParams.put("openid", openid); // 商户appid下,某用户的openid
   signParams.put("check_name", "NO_CHECK");// 校验用户姓名选项  NO_CHECK:不校验真实姓名  FORCE_CHECK:强校验真实姓名
   signParams.put("amount", String.valueOf((int)(amount*100))); // 企业付款金额,单位为分
   signParams.put("desc", desc);  // 企业付款操作说明信息。必填。
   signParams.put("spbill_create_ip", spbill_create_ip); // 调用接口的机器Ip地址

String sign = PayCommonUtil.createSign("UTF-8", signParams,key); //生成支付签名,要采用URLENCODER的原始值进行MD5算法!

signParams.put("sign", sign);

/**
* @author
* @date 2016-4-22
* @Description:sign签名
* @param characterEncoding
*            编码格式
* @param parameters
*            请求参数
* @return
*/
public static String createSign(String characterEncoding, SortedMap<Object, Object> packageParams, String API_KEY) {
StringBuffer sb = new StringBuffer();
@SuppressWarnings("rawtypes")
Set es = packageParams.entrySet();
@SuppressWarnings("rawtypes")
Iterator it = es.iterator();
while (it.hasNext()) {
@SuppressWarnings("rawtypes")
Map.Entry entry = (Map.Entry) it.next();
String k = (String) entry.getKey();
String v = (String) entry.getValue();
if (null != v && !"".equals(v) && !"sign".equals(k) && !"key".equals(k)) {
sb.append(k + "=" + v + "&");
}
}
sb.append("key=" + API_KEY);
String sign = MD5Util.MD5Encode(sb.toString(), characterEncoding).toUpperCase();
return sign;
}

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()));
else
resultString = byteArrayToHexString(md.digest(resultString.getBytes(charsetname)));
} catch (Exception exception) {
}
return resultString;
}

把参数封闭成XML格式

String requestXML = PayCommonUtil.getRequestXml(signParams);//封闭成XML格式

/**
* @author
* @date 2016-4-22
* @Description:将请求参数转换为xml格式的string
* @param parameters
*            请求参数
* @return
*/
@SuppressWarnings("rawtypes")
public static String getRequestXml(SortedMap<Object, Object> parameters) {
StringBuffer sb = new StringBuffer();
sb.append("<xml>");
Set es = parameters.entrySet();
Iterator it = es.iterator();
while (it.hasNext()) {
Map.Entry entry = (Map.Entry) it.next();
String k = (String) entry.getKey();
String v = (String) entry.getValue();
if ("attach".equalsIgnoreCase(k) || "body".equalsIgnoreCase(k) || "sign".equalsIgnoreCase(k)) {
sb.append("<" + k + ">" + "<![CDATA[" + v + "]]></" + k + ">");
} else {
sb.append("<" + k + ">" + v + "</" + k + ">");
}
}
sb.append("</xml>");
return sb.toString();
}

调用微信企业向个人付款接口

String jsonStr = HttpUtil.jsonStr(requestXML); //调用微信企业向个人付款接口


下面操作 调用微信需要的证书  证书在微信商户平台下载  java只用到apiclient_cert.p12这个证书  支付必须要有证书 

/**
* 调用微信企业向个人付款接口
*/
public static String jsonStr (String requestXML) throws Exception{
KeyStore keyStore = KeyStore.getInstance("PKCS12");
FileInputStream instream = new FileInputStream(new File(PropertiesHandler.getConfigValue("phoen.addr.url").toString())); // 从配置文件里读取证书的路径信息
String mchid = PropertiesHandler.getConfigValue("phoen.mch.id").toString(); // 商业号
keyStore.load(instream, mchid.toCharArray());// 证书密码是商户ID
instream.close();
SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore, mchid.toCharArray()).build();
@SuppressWarnings("deprecation")
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext, new String[] { "TLSv1" }, null, SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build();
HttpPost httpost = new HttpPost(PropertiesHandler.getConfigValue("ufdoder.url").toString()); //请求微信地址
httpost.addHeader("Connection", "keep-alive");
httpost.addHeader("Accept", "*/*");
httpost.addHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
httpost.addHeader("Host", "api.mch.weixin.qq.com");
httpost.addHeader("X-Requested-With", "XMLHttpRequest");
httpost.addHeader("Cache-Control", "max-age=0");
httpost.addHeader("User-Agent", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0) ");
httpost.setEntity(new StringEntity(requestXML, "UTF-8"));
CloseableHttpResponse response = httpclient.execute(httpost);
String jsonStr = EntityUtils.toString(response.getEntity(), "UTF-8");
return jsonStr;
}

     如果参数都对的上的话  就可以见到如下见面


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zengsange

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值