- 微信提现到零钱代码,可直接运行,代码如下:
import java.io.File;
import java.io.FileInputStream;
import java.security.KeyStore;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;
import javax.net.ssl.SSLContext;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContexts;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.junit.Test;
import com.github.wxpay.sdk.MD5Util;
/**
* @ClassName: [WeiXinCashTest]
* @Description: [微信提现到零钱]
* @Author: [songdx]
* @CreateDate: [2018年11月11日 下午4:32:24]
* @Version: [v1.0]
*/
public class WeiXinCashTest {
@Test
public void OldBook(){
//1.0 封装参数
String appid = "wx**************"; //微信公众号的appid
String mch_id = "***********"; //商户号
String nonce_str = "******************"; //生成随机数
String partner_trade_no = "******************"; //生成商户订单号
String openid = "**********************"; // 支付给用户openid
String check_name = "NO_CHECK"; //是否验证真实姓名呢
String re_user_name = "小宋"; //收款用户姓名
String amount = "100"; //企业付款金额,单位为分
String desc = "测试开发,稍后会还给公司的"; //企业付款操作说明信息。必填。
String spbill_create_ip = "127.0.0.1"; //
//2.0 生成map集合
SortedMap<String, String> packageParams = new TreeMap<String, String>();
packageParams.put("mch_appid", appid); //微信公众号的appid
packageParams.put("mchid", mch_id); //商务号
packageParams.put("nonce_str",nonce_str); //随机生成后数字,保证安全性
packageParams.put("partner_trade_no",partner_trade_no); //生成商户订单号
packageParams.put("openid",openid); // 支付给用户openid
packageParams.put("check_name",check_name); //是否验证真实姓名呢
packageParams.put("re_user_name",re_user_name);//收款用户姓名
packageParams.put("amount",amount); //企业付款金额,单位为分
packageParams.put("desc",desc); //企业付款操作说明信息。必填。
packageParams.put("spbill_create_ip",spbill_create_ip); //调用接口的机器Ip地址
//3.0 生成签名
String sign = createSign("UTF-8",packageParams,"************************************");
//4.0 封装退款对象
packageParams.put("sign", sign);
//5.0将当前的map结合转化成xml格式
String reuqestXml = getRequestXml(packageParams);
//6.0获取需要发送的url地址
String wxUrl = "https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers"; //获取退款的api接口
try {
String weixinPost = doRefund(wxUrl, reuqestXml).toString();
//7.0 解析返回的xml数据
//得到解析数据后根据返回内容自行解析下即可
System.out.println("解析返回的数据:"+weixinPost);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* @Description: 封装为xml
* @param @param parameters
* @param @return
* @return String
* @throws
* @author songdx
* @date 2018年11月11日
*/
public static String getRequestXml(SortedMap<String,String> 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();
}
/**
* @Description: 发起退款请求
* @param @param url
* @param @param data
* @param @return
* @param @throws Exception
* @return String
* @throws
* @author songdx
* @date 2018年11月11日
*/
public String doRefund(String url,String data) throws Exception {
char[] password = "**********".toCharArray();
KeyStore keyStore = KeyStore.getInstance("PKCS12");
FileInputStream instream = new FileInputStream(new File("D://apiclient_cert.p12"));//P12文件目录
try {
keyStore.load(instream, password);//这里写密码
} finally {
instream.close();
}
SSLContext sslcontext = SSLContexts.custom()
.loadKeyMaterial(keyStore, password)//这里也是写密码的
.build();
// Allow TLSv1 protocol only
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
sslcontext,
new String[] { "TLSv1" },
null,
SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
CloseableHttpClient httpclient = HttpClients.custom()
.setSSLSocketFactory(sslsf)
.build();
try {
HttpPost httpost = new HttpPost(url); // 设置响应头信息
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(data, "UTF-8"));
System.out.println("请求的内容:"+data);
CloseableHttpResponse response = httpclient.execute(httpost);
try {
HttpEntity entity = response.getEntity();
String jsonStr = EntityUtils.toString(response.getEntity(), "UTF-8");
System.out.println("微信返回的内容:"+jsonStr);
EntityUtils.consume(entity);
return jsonStr;
} finally {
response.close();
}
} finally {
httpclient.close();
}
}
/**
* 微信支付签名算法sign
* @param characterEncoding
* @param parameters
* @return
*/
@SuppressWarnings("unchecked")
public static String createSign(String characterEncoding,SortedMap<String,String> parameters,String key){
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=" + key);
System.out.println("parameters=" + parameters);
System.out.println("key=" + key);
System.out.println("===========================================");
String sign = MD5Util.MD5Encode(sb.toString(), characterEncoding).toUpperCase();
System.out.println("================sign:"+sign+"=======================");
return sign;
}
}
注意事项:
1. 在开发微信提现时也遇到很多坑和注意的地方,比如签名问题,NO_AUTH | 产品权限验证问题
2. 开通条件:入驻满90天,截止今日往回推30天连续不间断保持有交易(每天可交易一分钱)
3. 登录微信支付平台,地址:https://pay.weixin.qq.com/index.php
4. 开通地址需前往【商户平台】->【产品中心】申请开通
5. 签名错误格式和顺序问题,参照上面签名代码即可(加密形式需要注意下或采用默认)
6. 提现会从“运营账户”扣款,操作时需要保证账户余额有钱,否则提示余额不足情况