1.添加依赖
<dependency> <groupId>com.github.wxpay</groupId> <artifactId>WXPay-SDK-Java</artifactId> <version>0.0.4</version> </dependency> |
2.配置参数
3.实现方法
@ApiOperation(value = "企业转账到零钱", httpMethod = "POST", produces = "application/json;charset=UTF-8") @ApiImplicitParams(value = {@ApiImplicitParam(value = "*用户token", name = "token",defaultValue ="", dataType = "String",paramType="header"), @ApiImplicitParam(value = "金额", name = "money",defaultValue ="", dataType = "String",paramType="query") }) @PostMapping("/wxpay/transfer") public Result transfer(HttpServletRequest request,BigDecimal money,String openID) { // 1.0 拼凑企业支付需要的参数 String appid = APPID; // APP对应的微信的appid String mch_id = MCHID; // 商户号 String nonce_str = WXPayUtil.generateNonceStr(); // 生成随机数 String partner_trade_no = WXPayUtil.generateNonceStr(); // 生成商户订单号 String openid = openID; // 收款用户openid String check_name = "NO_CHECK"; // 是否验证真实姓名呢 String re_user_name = "KOLO"; // 收款用户姓名(非必须) String amount = String.valueOf(money); // 企业付款金额,最少为100,单位为分 String desc = "恭喜你,完成了一个订单!"; // 企业付款操作说明信息。必填。 String spbill_create_ip = IpKit.getIpAddr(request); // 用户的ip地址 // 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地址 try { // 3.0 利用上面的参数,先去生成自己的签名 String sign = WXPayUtil.generateSignature(packageParams, PATERNERKEY); // 4.0 将签名再放回map中,它也是一个参数 packageParams.put("sign", sign); // 5.0将当前的map结合转化成xml格式 String xml = WXPayUtil.mapToXml(packageParams); // 6.0获取需要发送的url地址 String wxUrl = "https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers"; // 获取退款的api接口 System.out.println("发送前的xml为:" + xml); // 7,向微信发送请求转账请求 String returnXml = certHttpUtil.postData(wxUrl, xml, MCHID, CERTPATH); System.out.println("返回的returnXml为:" + returnXml); // 8,将微信返回的xml结果转成map格式 Map<String, String> returnMap = WXPayUtil.xmlToMap(returnXml); if (returnMap.get("result_code").equals("SUCCESS")) { // 付款成功 System.out.println("returnMap为:" + returnMap); }else { return Result.error(902,returnMap.get("err_code_des")); } return Result.ok(returnMap.toString()); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); return Result.error(901,"微信转账失败!"); } } |
4.用到的工具类
import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.security.KeyStore; import javax.net.ssl.SSLContext; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.client.config.RequestConfig; 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.springframework.stereotype.Component; /** * 获取微信apiclient_cert.p12证书 */ @Component public class CertHttpUtil { private static int socketTimeout = 10000;// 连接超时时间,默认10秒 private static int connectTimeout = 30000;// 传输超时时间,默认30秒 private static RequestConfig requestConfig;// 请求器的配置 private static CloseableHttpClient httpClient;// HTTP请求器 /** * 通过Https往API post xml数据 * * @param url API地址 * @param xmlObj 要提交的XML数据对象 * @param mchId 商户ID * @param certPath 证书位置 * @return */ public String postData(String url, String xmlObj, String mchId, String certPath) { // 加载证书 try { initCert(mchId, certPath); } catch (Exception e) { e.printStackTrace(); } String result = null; HttpPost httpPost = new HttpPost(url); // 得指明使用UTF-8编码,否则到API服务器XML的中文不能被成功识别 StringEntity postEntity = new StringEntity(xmlObj, "UTF-8"); httpPost.addHeader("Content-Type", "text/xml"); httpPost.setEntity(postEntity); // 根据默认超时限制初始化requestConfig requestConfig = RequestConfig.custom().setSocketTimeout(socketTimeout).setConnectTimeout(connectTimeout).build(); // 设置请求器的配置 httpPost.setConfig(requestConfig); try { HttpResponse response = null; try { response = httpClient.execute(httpPost); } catch (IOException e) { e.printStackTrace(); } HttpEntity entity = response.getEntity(); try { result = EntityUtils.toString(entity, "UTF-8"); } catch (IOException e) { e.printStackTrace(); } } finally { httpPost.abort(); } return result; } /** * 加载证书 * * @param mchId 商户ID * @param certPath 证书位置 * @throws Exception */ private void initCert(String mchId, String certPath) throws Exception { // 证书密码,默认为商户ID String key = mchId; // 证书的路径 String path = certPath; // 指定读取证书格式为PKCS12 KeyStore keyStore = KeyStore.getInstance("PKCS12"); // 读取本机存放的PKCS12证书文件 File file = new File(path); InputStream in = new FileInputStream(file); try { // 指定PKCS12的密码(商户ID) keyStore.load(in, key.toCharArray()); } finally { in.close(); } SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore, key.toCharArray()).build(); SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext, new String[] {"TLSv1"}, null, SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER); httpClient = HttpClients.custom().setSSLSocketFactory(sslsf).build(); } } |
注意,这个功能的实现需要先获取微信授权,授权后获取微信用户的openid才能完成提现,同时该方法适合微信公众号提现和微信小程序提现。