New file |
| | |
| | | package com.hx.corp.util; |
| | | |
| | | import com.alibaba.fastjson.JSON; |
| | | import com.hx.corp.entity.CorpPayRequest; |
| | | import com.hx.corp.entity.CorpPayResponse; |
| | | import com.hx.exception.ServiceException; |
| | | import com.hx.mp.util.*; |
| | | import com.hx.util.SimpleTool; |
| | | import com.hx.util.StringUtils; |
| | | import net.sf.json.JSONObject; |
| | | 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.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 org.dom4j.Document; |
| | | import org.dom4j.Element; |
| | | import org.dom4j.io.SAXReader; |
| | | import org.slf4j.Logger; |
| | | import org.slf4j.LoggerFactory; |
| | | |
| | | import javax.net.ssl.SSLContext; |
| | | import javax.servlet.http.HttpServletRequest; |
| | | import java.io.File; |
| | | import java.io.FileInputStream; |
| | | import java.security.KeyStore; |
| | | import java.util.*; |
| | | |
| | | |
| | | /** 企业微信支付/退款 |
| | | * @author ChenJiaHe |
| | | */ |
| | | public class WxCorpPayUtil { |
| | | |
| | | //log4j日志 |
| | | private static Logger logger = LoggerFactory.getLogger(WxCorpPayUtil.class.getName()); |
| | | |
| | | // 退款接口连接 |
| | | private static final String REFUND_URL = "https://api.mch.weixin.qq.com/secapi/pay/refund"; |
| | | /**查询订单链接*/ |
| | | @SuppressWarnings("unused") |
| | | private static final String QUERY_URL = "https://api.mch.weixin.qq.com/pay/orderquery"; |
| | | /**同意下单链接*/ |
| | | private static final String FIRST_ORDER_URL = "https://api.mch.weixin.qq.com/pay/unifiedorder"; |
| | | |
| | | // 企业付款 |
| | | private static final String CORP_PAY_URL = "https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers"; |
| | | |
| | | |
| | | /** 企业付款 |
| | | * @param corpPayRequest 请求对象 |
| | | * @param mchKey 商户号秘钥 |
| | | * @param certPath 支付证书 |
| | | * @return CorpPayResponse |
| | | * @throws Exception |
| | | */ |
| | | public static CorpPayResponse qdCorpPay(CorpPayRequest corpPayRequest, String mchKey, String certPath) |
| | | throws Exception { |
| | | |
| | | CorpPayResponse corpPayResponse = new CorpPayResponse(); |
| | | |
| | | SortedMap<Object, Object> parameters = new TreeMap<Object, Object>(); |
| | | parameters.put("mch_appid", corpPayRequest.getMch_appid()); |
| | | parameters.put("mchid", corpPayRequest.getMchid()); |
| | | parameters.put("partner_trade_no", corpPayRequest.getPartner_trade_no()); |
| | | //parameters.put("nonce_str", UUID.randomUUID().toString().substring(0, 30)); |
| | | parameters.put("nonce_str", corpPayRequest.getNonce_str()); |
| | | parameters.put("openid", corpPayRequest.getOpenid()); |
| | | parameters.put("check_name", corpPayRequest.getCheck_name()); |
| | | parameters.put("amount", corpPayRequest.getAmount()); |
| | | parameters.put("spbill_create_ip", corpPayRequest.getSpbill_create_ip()); |
| | | parameters.put("desc", corpPayRequest.getDesc()); |
| | | |
| | | String sign = WXSignUtils.createSign("UTF-8", parameters, mchKey); |
| | | |
| | | parameters.put("sign", sign); |
| | | String xmlInfo = HttpXmlUtils.transferXml(parameters); |
| | | |
| | | try { |
| | | CloseableHttpResponse response = HttpUtil.Post(CORP_PAY_URL, xmlInfo, true, certPath, corpPayRequest.getMchid()); |
| | | String transfersXml = EntityUtils.toString(response.getEntity(), "utf-8"); |
| | | // System.out.println("渠道端企业付款:" + transfersXml); |
| | | Map<String, String> transferMap = HttpXmlUtils.parseRefundXml(transfersXml); |
| | | // 将 Map 转换为 实体类 |
| | | corpPayResponse = JSON.parseObject(JSON.toJSONString(transferMap),CorpPayResponse.class); |
| | | } catch (Exception e) { |
| | | logger.error("企业付款接口报错",e); |
| | | } |
| | | return corpPayResponse; |
| | | } |
| | | |
| | | |
| | | /**统一支付 |
| | | * @param request 方法获取 |
| | | * @param appId 小程序号 |
| | | * @param partner 商户号 |
| | | * @param key 秘钥 |
| | | * @param notifyUrl 回调链接 |
| | | * @param out_trade_no 订单号 |
| | | * @param body 商品描述 |
| | | * @param total_fee 支付金额 |
| | | * @param openid 用户openId |
| | | * @param attach 附带数据包 |
| | | * @param notifyUrl 回调通知地址 |
| | | * @param trade_type 交易类型 |
| | | * @return JSON status = "SUC"为成功 |
| | | */ |
| | | public static JSONObject unifiedPay(HttpServletRequest request,String appId,String partner,String key,String notifyUrl,String out_trade_no, String body, String total_fee, String openid, |
| | | String attach,String trade_type) throws Exception { |
| | | |
| | | if (!SimpleTool.checkNotNull(notifyUrl)) { |
| | | throw new ServiceException("支付功能故障!"); |
| | | } |
| | | |
| | | // 创建查询请求对象 |
| | | RequestHandler reqHandler = new RequestHandler(null, null); |
| | | // 通信对象 |
| | | TenpayHttpClient httpClient = new TenpayHttpClient(); |
| | | // 应答对象 |
| | | ClientResponseHandler resHandler = new ClientResponseHandler(); |
| | | |
| | | // ----------------------------- |
| | | // 设置请求参数 |
| | | // ----------------------------- |
| | | // reqHandler.init(); |
| | | reqHandler.setKey(key); |
| | | reqHandler.setGateUrl(FIRST_ORDER_URL);// 请求URL |
| | | |
| | | // ----------------------------- |
| | | // 设置接口参数(sign后台自动生成) |
| | | // ----------------------------- |
| | | reqHandler.setParameter("appid", appId); // 公众号/小程序 |
| | | reqHandler.setParameter("mch_id", partner); // 商户号 |
| | | reqHandler.setParameter("nonce_str", SimpleTool.getUUIDName().substring(0, 30));// 随机乱码 |
| | | reqHandler.setParameter("body", body);// 商品描述 |
| | | reqHandler.setParameter("out_trade_no", out_trade_no);// 商户订单号 |
| | | reqHandler.setParameter("total_fee", total_fee);// 总金额 |
| | | reqHandler.setParameter("spbill_create_ip", "8.8.8.8");// 终端IP |
| | | reqHandler.setParameter("notify_url",notifyUrl);// 通知地址 |
| | | reqHandler.setParameter("trade_type", trade_type);// 交易类型 |
| | | // JSAPI,NATIVE,APP |
| | | reqHandler.setParameter("openid", openid);// openId |
| | | reqHandler.setParameter("attach", attach);// 附带数据包 |
| | | |
| | | // ----------------------------- |
| | | // 设置通信参数 |
| | | // ----------------------------- |
| | | // 设置请求返回的等待时间 |
| | | httpClient.setTimeOut(5); |
| | | |
| | | // 设置ca证书 |
| | | // httpClient.setCaInfo(new File(CA_PATH)); |
| | | |
| | | // 设置个人(商户)证书 |
| | | // httpClient.setCertInfo(new File(CERT_PATH), CERT_PWD); |
| | | |
| | | // 设置发送类型POST |
| | | httpClient.setMethod("POST"); |
| | | |
| | | // 设置请求内容(生成sign) |
| | | String requestUrl = reqHandler.getRequestURL();// 组拼https://www.baidu.com?a=x&b=xx |
| | | |
| | | httpClient.setReqContent(requestUrl);// https://www.baidu.com?a=x&b=xx |
| | | String rescontent = "null"; |
| | | |
| | | httpClient.setRequestHandler(reqHandler);// 把处理对象,像是参数各种东西都设置进去方便获取(quan) |
| | | |
| | | // 返回出去的对象(状态,错误原因,该操作相关信息(参数,返回值)) |
| | | JSONObject returnObj = new JSONObject(); |
| | | |
| | | // 后台调用 |
| | | if (httpClient.call()) { |
| | | System.out.println("统一下单,成功cll了::"); |
| | | |
| | | // 设置结果参数 |
| | | rescontent = httpClient.getResContent(); |
| | | System.out.println("统一下单返回结果:" + rescontent); |
| | | resHandler.setContent(rescontent);// 解析xml |
| | | resHandler.setKey(key); |
| | | |
| | | // 获取返回参数 |
| | | String return_code = resHandler.getParameter("return_code"); |
| | | String return_msg = resHandler.getParameter("return_msg"); |
| | | |
| | | // 判断签名及结果 |
| | | if (resHandler.isTenpaySign() && "SUCCESS".equals(return_code)) { |
| | | String prepay_id = resHandler.getParameter("prepay_id");// 预支付交易会话标识 |
| | | String code_url = resHandler.getParameter("code_url");// 二维码链接 |
| | | |
| | | String result_code = resHandler.getParameter("result_code");// 业务结果 |
| | | String appid = resHandler.getParameter("appid");// 公众账号ID |
| | | String mch_id = resHandler.getParameter("mch_id");// 商户号 |
| | | String nonce_str = resHandler.getParameter("nonce_str");// 随机码 |
| | | String sign = resHandler.getParameter("sign");// 签名 |
| | | |
| | | if (result_code.equals("SUCCESS")) { |
| | | returnObj.put("status", "suc"); |
| | | returnObj.put("sign", sign); |
| | | returnObj.put("nonce_str", nonce_str); |
| | | returnObj.put("mch_id", mch_id); |
| | | returnObj.put("appid", appid); |
| | | returnObj.put("prepay_id", prepay_id); |
| | | returnObj.put("code_url", code_url); |
| | | returnObj.put("out_trade_no", out_trade_no); |
| | | } else { |
| | | String errMsg = "[ERROR]result_code:" + resHandler.getParameter("result_code") + " err_code:" |
| | | + resHandler.getParameter("err_code") + "err_code_des:" |
| | | + resHandler.getParameter("err_code_des"); |
| | | |
| | | // 错误时,返回结果未签名,记录retcode、retmsg看失败详情。 |
| | | returnObj.put("status", "ERROR-C"); |
| | | returnObj.put("errMsg", errMsg); |
| | | } |
| | | } else { |
| | | String errMsg = "return_code:" + return_code + "err_code:" + resHandler.getParameter("err_code") |
| | | + " return_msg:" + return_msg; |
| | | // 错误时,返回结果未签名,记录retcode、retmsg看失败详情。 |
| | | returnObj.put("status", "ERROR-B"); |
| | | returnObj.put("errMsg", errMsg); |
| | | } |
| | | } else { |
| | | // 有可能因为网络原因,请求已经处理,但未收到应答。 |
| | | returnObj.put("status", "ERROR-A"); |
| | | returnObj.put("errMsg", httpClient.getResponseCode() + ":" + httpClient.getErrInfo()); |
| | | } |
| | | |
| | | // 获取debug信息,建议把请求、应答内容、debug信息,通信返回码写入日志,方便定位问题 |
| | | String detail = "http res:" + httpClient.getResponseCode() + "," + httpClient.getErrInfo() + ";" + "req url:" |
| | | + requestUrl + ";" + ";" + "req debug:" + reqHandler.getDebugInfo() + ";" + "res content:" + rescontent |
| | | + ";" + "res debug:" + resHandler.getDebugInfo() + ";"; |
| | | |
| | | returnObj.put("detail", detail); |
| | | |
| | | |
| | | return returnObj; |
| | | } |
| | | |
| | | /**统一支付(分账) |
| | | * @param request 方法获取 |
| | | * @param appId 小程序号 |
| | | * @param partner 商户号 |
| | | * @param key 秘钥 |
| | | * @param notifyUrl 回调链接 |
| | | * @param out_trade_no 订单号 |
| | | * @param body 商品描述 |
| | | * @param total_fee 支付金额 |
| | | * @param openid 用户openId |
| | | * @param attach 附带数据包 |
| | | * @param notifyUrl 回调通知地址 |
| | | * @param trade_type 交易类型 |
| | | * @param profit_sharing 是否分账:N不,Y是 |
| | | * @return JSON status = "SUC"为成功 |
| | | */ |
| | | public static JSONObject unifiedPay(HttpServletRequest request,String appId,String partner,String key,String notifyUrl,String out_trade_no, String body, String total_fee, String openid, |
| | | String attach,String trade_type,String profit_sharing) throws Exception { |
| | | |
| | | if (!SimpleTool.checkNotNull(notifyUrl)) { |
| | | throw new ServiceException("支付功能故障!"); |
| | | } |
| | | |
| | | // 创建查询请求对象 |
| | | RequestHandler reqHandler = new RequestHandler(null, null); |
| | | // 通信对象 |
| | | TenpayHttpClient httpClient = new TenpayHttpClient(); |
| | | // 应答对象 |
| | | ClientResponseHandler resHandler = new ClientResponseHandler(); |
| | | |
| | | // ----------------------------- |
| | | // 设置请求参数 |
| | | // ----------------------------- |
| | | // reqHandler.init(); |
| | | reqHandler.setKey(key); |
| | | reqHandler.setGateUrl(FIRST_ORDER_URL);// 请求URL |
| | | |
| | | // ----------------------------- |
| | | // 设置接口参数(sign后台自动生成) |
| | | // ----------------------------- |
| | | |
| | | reqHandler.setParameter("appid", appId); // 公众号/小程序 |
| | | reqHandler.setParameter("mch_id", partner); // 商户号 |
| | | reqHandler.setParameter("nonce_str", SimpleTool.getUUIDName().substring(0, 30));// 随机乱码 |
| | | reqHandler.setParameter("body", body);// 商品描述 |
| | | reqHandler.setParameter("out_trade_no", out_trade_no);// 商户订单号 |
| | | reqHandler.setParameter("total_fee", total_fee);// 总金额 |
| | | reqHandler.setParameter("spbill_create_ip", "8.8.8.8");// 终端IP |
| | | reqHandler.setParameter("notify_url",notifyUrl);// 通知地址 |
| | | reqHandler.setParameter("trade_type", trade_type);// 交易类型 |
| | | //JSAPI,NATIVE,APP |
| | | reqHandler.setParameter("openid", openid);// openId |
| | | reqHandler.setParameter("attach", attach);// 附带数据包 |
| | | reqHandler.setParameter("profit_sharing", profit_sharing);// 附带数据包 |
| | | |
| | | // ----------------------------- |
| | | // 设置通信参数 |
| | | // ----------------------------- |
| | | // 设置请求返回的等待时间 |
| | | httpClient.setTimeOut(5); |
| | | |
| | | // 设置ca证书 |
| | | // httpClient.setCaInfo(new File(CA_PATH)); |
| | | |
| | | // 设置个人(商户)证书 |
| | | // httpClient.setCertInfo(new File(CERT_PATH), CERT_PWD); |
| | | |
| | | // 设置发送类型POST |
| | | httpClient.setMethod("POST"); |
| | | |
| | | // 设置请求内容(生成sign) |
| | | String requestUrl = reqHandler.getRequestURL();// 组拼https://www.baidu.com?a=x&b=xx |
| | | |
| | | httpClient.setReqContent(requestUrl);// https://www.baidu.com?a=x&b=xx |
| | | String rescontent = "null"; |
| | | |
| | | httpClient.setRequestHandler(reqHandler);// 把处理对象,像是参数各种东西都设置进去方便获取(quan) |
| | | |
| | | // 返回出去的对象(状态,错误原因,该操作相关信息(参数,返回值)) |
| | | JSONObject returnObj = new JSONObject(); |
| | | |
| | | // 后台调用 |
| | | if (httpClient.call()) { |
| | | System.out.println("统一下单,成功cll了::"); |
| | | |
| | | // 设置结果参数 |
| | | rescontent = httpClient.getResContent(); |
| | | System.out.println("统一下单返回结果:" + rescontent); |
| | | resHandler.setContent(rescontent);// 解析xml |
| | | resHandler.setKey(key); |
| | | |
| | | // 获取返回参数 |
| | | String return_code = resHandler.getParameter("return_code"); |
| | | String return_msg = resHandler.getParameter("return_msg"); |
| | | |
| | | // 判断签名及结果 |
| | | if (resHandler.isTenpaySign() && "SUCCESS".equals(return_code)) { |
| | | String prepay_id = resHandler.getParameter("prepay_id");// 预支付交易会话标识 |
| | | String code_url = resHandler.getParameter("code_url");// 二维码链接 |
| | | |
| | | String result_code = resHandler.getParameter("result_code");// 业务结果 |
| | | String appid = resHandler.getParameter("appid");// 公众账号ID |
| | | String mch_id = resHandler.getParameter("mch_id");// 商户号 |
| | | String nonce_str = resHandler.getParameter("nonce_str");// 随机码 |
| | | String sign = resHandler.getParameter("sign");// 签名 |
| | | |
| | | if (result_code.equals("SUCCESS")) { |
| | | returnObj.put("status", "suc"); |
| | | returnObj.put("sign", sign); |
| | | returnObj.put("nonce_str", nonce_str); |
| | | returnObj.put("mch_id", mch_id); |
| | | returnObj.put("appid", appid); |
| | | returnObj.put("prepay_id", prepay_id); |
| | | returnObj.put("code_url", code_url); |
| | | returnObj.put("out_trade_no", out_trade_no); |
| | | } else { |
| | | String errMsg = "[ERROR]result_code:" + resHandler.getParameter("result_code") + " err_code:" |
| | | + resHandler.getParameter("err_code") + "err_code_des:" |
| | | + resHandler.getParameter("err_code_des"); |
| | | |
| | | // 错误时,返回结果未签名,记录retcode、retmsg看失败详情。 |
| | | returnObj.put("status", "ERROR-C"); |
| | | returnObj.put("errMsg", errMsg); |
| | | } |
| | | } else { |
| | | String errMsg = "return_code:" + return_code + "err_code:" + resHandler.getParameter("err_code") |
| | | + " return_msg:" + return_msg; |
| | | // 错误时,返回结果未签名,记录retcode、retmsg看失败详情。 |
| | | returnObj.put("status", "ERROR-B"); |
| | | returnObj.put("errMsg", errMsg); |
| | | } |
| | | } else { |
| | | // 有可能因为网络原因,请求已经处理,但未收到应答。 |
| | | returnObj.put("status", "ERROR-A"); |
| | | returnObj.put("errMsg", httpClient.getResponseCode() + ":" + httpClient.getErrInfo()); |
| | | } |
| | | |
| | | // 获取debug信息,建议把请求、应答内容、debug信息,通信返回码写入日志,方便定位问题 |
| | | String detail = "http res:" + httpClient.getResponseCode() + "," + httpClient.getErrInfo() + ";" + "req url:" |
| | | + requestUrl + ";" + ";" + "req debug:" + reqHandler.getDebugInfo() + ";" + "res content:" + rescontent |
| | | + ";" + "res debug:" + resHandler.getDebugInfo() + ";"; |
| | | |
| | | returnObj.put("detail", detail); |
| | | |
| | | |
| | | return returnObj; |
| | | } |
| | | |
| | | /**处理信息 |
| | | */ |
| | | public static JSONObject paymentData(JSONObject payObj,String key){ |
| | | JSONObject wxObj = new JSONObject(); |
| | | /**统一下单*/ |
| | | String payStatus = payObj.getString("status"); |
| | | if (payStatus.equals("suc")) { |
| | | // JSONObject payObj = po.getJSONObject("inf"); |
| | | String appId = payObj.getString("appid"); |
| | | String nonceStr = payObj.getString("nonce_str"); |
| | | String prepay_id = payObj.getString("prepay_id"); |
| | | // JSAPI调用支付返回的数据 |
| | | String timeStamp = SimpleTool.getTenTime(new Date()).toString(); |
| | | String signType = "MD5"; |
| | | String packagef = "prepay_id=" + prepay_id; |
| | | RequestHandler reqHandler = new RequestHandler(null, null); |
| | | reqHandler.setParameter("appId", appId); |
| | | reqHandler.setParameter("nonceStr", nonceStr); |
| | | reqHandler.setParameter("timeStamp", timeStamp); |
| | | reqHandler.setParameter("package", packagef); |
| | | reqHandler.setParameter("signType", signType); |
| | | reqHandler.setKey(key); |
| | | String paySign = reqHandler.createSign();// 生成签名 |
| | | wxObj.put("orderNo", payObj.getString("out_trade_no")); |
| | | wxObj.put("paySign", paySign); |
| | | wxObj.put("appId", appId); |
| | | wxObj.put("nonceStr", nonceStr); |
| | | wxObj.put("package", packagef); |
| | | wxObj.put("timeStamp", timeStamp); |
| | | } else { |
| | | throw new RuntimeException(payObj.toString()); |
| | | } |
| | | return wxObj; |
| | | } |
| | | |
| | | /** |
| | | * 退款 |
| | | * @param appId 小程序/公众号 appId |
| | | * @param partner 商户号 |
| | | * @param key 商户号秘钥 |
| | | * @param certPath 个人商户证书 |
| | | * @param out_trade_no 商户订单号 |
| | | * @param transaction_id 财付通订单号(微信订单号) |
| | | * @param out_refund_no 商户退单号 |
| | | * @param total_fee 订单总额(单位:分) |
| | | * @param refund_fee 退款金额(单位:分) |
| | | * @return JSON status="SUCCESS"(成功) (状态,错误原因,该操作相关信息(参数,返回值)) |
| | | */ |
| | | public static JSONObject refund(String appId,String partner,String key,String certPath,String out_trade_no, String transaction_id, String out_refund_no, String total_fee, |
| | | String refund_fee) { |
| | | try{ |
| | | KeyStore keyStore = KeyStore.getInstance("PKCS12"); |
| | | FileInputStream instream = new FileInputStream(new File(certPath)); |
| | | try { |
| | | keyStore.load(instream,partner.toCharArray()); |
| | | }finally { |
| | | instream.close(); |
| | | } |
| | | // Trust own CA and all self-signed certs |
| | | SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore,partner.toCharArray()).build(); |
| | | // Allow TLSv1 protocol only |
| | | SSLConnectionSocketFactory sslsf; |
| | | sslsf = new SSLConnectionSocketFactory( |
| | | sslcontext, new String[] { "TLSv1" }, null, |
| | | SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); |
| | | CloseableHttpClient httpclient = HttpClients.custom() |
| | | .setSSLSocketFactory(sslsf).build(); |
| | | HttpPost httppost = new HttpPost(REFUND_URL); |
| | | String xml = wxPayRefundData(appId, partner, key, out_trade_no, transaction_id, out_refund_no, total_fee, refund_fee); |
| | | try { |
| | | StringEntity se = new StringEntity(xml); |
| | | httppost.setEntity(se); |
| | | |
| | | CloseableHttpResponse responseEntry = httpclient.execute(httppost); |
| | | try { |
| | | HttpEntity entity = responseEntry.getEntity(); |
| | | if (entity != null) { |
| | | |
| | | SAXReader saxReader = new SAXReader(); |
| | | Document document = saxReader.read(entity.getContent()); |
| | | Element rootElt = document.getRootElement(); |
| | | String returnCode = rootElt.elementText("return_code"); |
| | | JSONObject result = new JSONObject(); |
| | | |
| | | if(returnCode.equals("SUCCESS")){ |
| | | String resultCode = rootElt.elementText("result_code"); |
| | | if(resultCode.equals("SUCCESS")) { |
| | | result.put("weixinPayUrl", rootElt.elementText("code_url")); |
| | | result.put("prepayId", rootElt.elementText("prepay_id")); |
| | | result.put("msg", "success"); |
| | | |
| | | String refund_id = rootElt.elementText("refund_id");//微信退款单号 |
| | | String r_out_refund_no = rootElt.elementText("out_refund_no"); |
| | | String errMsg = "商户号" + r_out_refund_no + "的退款流水号是:" + refund_id; |
| | | result.put("status", "SUCCESS"); |
| | | result.put("errMsg", errMsg); |
| | | result.put("refund_id", refund_id); |
| | | }else{ |
| | | String errMsg = "[ERROR]result_code:" + rootElt.elementText("result_code")+ |
| | | " err_code:" + rootElt.elementText("err_code"); |
| | | |
| | | //错误时,返回结果未签名,记录retcode、retmsg看失败详情。 |
| | | result.put("errMsg", errMsg); |
| | | result.put("status","false"); |
| | | result.put("msg",rootElt.elementText("err_code_des")); |
| | | } |
| | | }else{ |
| | | String errMsg = "[ERROR]return_code:" + rootElt.elementText("return_code"); |
| | | |
| | | //错误时,返回结果未签名,记录retcode、retmsg看失败详情。 |
| | | result.put("errMsg", errMsg); |
| | | result.put("status","false"); |
| | | result.put("msg",rootElt.elementText("return_msg")); |
| | | } |
| | | return result; |
| | | } |
| | | EntityUtils.consume(entity); |
| | | } |
| | | finally { |
| | | responseEntry.close(); |
| | | } |
| | | } |
| | | finally { |
| | | httpclient.close(); |
| | | } |
| | | return null; |
| | | }catch(Exception e){ |
| | | e.printStackTrace(); |
| | | JSONObject result = new JSONObject(); |
| | | result.put("status","error"); |
| | | result.put("msg",e.getMessage()); |
| | | return result; |
| | | } |
| | | } |
| | | |
| | | /** 封装参数数据 |
| | | * @param appId 小程序/公众号 appId |
| | | * @param partner 商户号 |
| | | * @param key 商户号秘钥 |
| | | * @param out_trade_no 商户订单号 |
| | | * @param transaction_id 财付通订单号(微信订单号) |
| | | * @param out_refund_no 商户退单号 |
| | | * @param total_fee 订单总额(单位:分) |
| | | * @param refund_fee 退款金额(单位:分) |
| | | * @return |
| | | */ |
| | | public static String wxPayRefundData(String appId,String partner,String key,String out_trade_no, String transaction_id,String out_refund_no,String total_fee,String refund_fee) { |
| | | StringBuffer xml = new StringBuffer(); |
| | | String data = null; |
| | | try { |
| | | String nonceStr = SimpleTool.getUUIDName().substring(0,30); |
| | | xml.append("</xml>"); |
| | | SortedMap<String,String> parameters = new TreeMap<String,String>(); |
| | | parameters.put("appid",appId); |
| | | parameters.put("mch_id",partner); |
| | | parameters.put("nonce_str", nonceStr); |
| | | if(!StringUtils.isEmpty(out_trade_no)) { |
| | | parameters.put("out_trade_no", out_trade_no); |
| | | } |
| | | if(!StringUtils.isEmpty(transaction_id)) { |
| | | parameters.put("transaction_id", transaction_id); |
| | | } |
| | | parameters.put("out_refund_no", out_refund_no); |
| | | parameters.put("fee_type", "CNY"); |
| | | parameters.put("total_fee", total_fee);//总金额 |
| | | parameters.put("refund_fee", refund_fee);//退款金额 |
| | | parameters.put("op_user_id",partner); |
| | | parameters.put("sign", createSign(parameters,key)); |
| | | |
| | | data =SortedMaptoXml(parameters); |
| | | } catch (Exception e) { |
| | | System.err.println(e.getMessage()); |
| | | return null; |
| | | } |
| | | return data; |
| | | } |
| | | |
| | | /** |
| | | * 创建md5摘要,规则是:按参数名称a-z排序,遇到空值的参数不参加签名。 |
| | | */ |
| | | public static String createSign(SortedMap<String, String> packageParams, String AppKey) { |
| | | StringBuffer sb; |
| | | sb = new StringBuffer(); |
| | | Set es = packageParams.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 (null != v && !"".equals(v) && !"sign".equals(k) && !"key".equals(k)) { |
| | | sb.append(k + "=" + v + "&"); |
| | | } |
| | | } |
| | | sb.append("key=" + AppKey); |
| | | String sign = MD5Util.MD5Encode(sb.toString(), "UTF-8").toUpperCase(); |
| | | return sign; |
| | | } |
| | | |
| | | /** |
| | | * @Author: HONGLINCHEN |
| | | * @Description:请求值转换为xml格式 SortedMap转xml |
| | | * @param params |
| | | * @Date: 2017-9-7 17:18 |
| | | */ |
| | | private static String SortedMaptoXml(SortedMap<String,String> params) { |
| | | StringBuilder sb = new StringBuilder(); |
| | | Set es = params.entrySet(); |
| | | Iterator it = es.iterator(); |
| | | sb.append("<xml>\n"); |
| | | while(it.hasNext()) { |
| | | Map.Entry entry = (Map.Entry)it.next(); |
| | | String k = (String)entry.getKey(); |
| | | Object v = entry.getValue(); |
| | | sb.append("<"+k+">"); |
| | | sb.append(v); |
| | | sb.append("</"+k+">\n"); |
| | | } |
| | | sb.append("</xml>"); |
| | | return sb.toString(); |
| | | } |
| | | } |