CSDN手机充值后能退款吗如何退款

java技术分享
java-微信支付-微信退款
这篇文章已经给很多人解决了问题,所以很多人发邮件给我要项目,我想说:最近很多人发邮件给我要MobilePay。我想说 自己加群下载,群链接会点吧?有问题随时群里问我!群主。这项目中包含了支付宝支付、退款、微信支付、退款。加群加群...作者:HONGLINCHEN.上海·黄埔作者邮箱:请关注作者的今日头条号:《专注JavaWeb开发》 博客地址:请关注作者的CSDN博客:《专注JavaWeb开发》 博客地址:作者的QQ群:专注JavaWeb开发.群号:1、前面的申请微信支付流程我在这里就不介绍了,今天主要讲的是微信退款这一块。主要是我会把退款的所有代码贡献出来给大家,方便大家可以直接copy到自己工程中就可以使用,不用再去自己写!2、微信退款 首选需要一个商户证书,可以百度“微信商户平台”,点击api安全去下载这个证书,证书名字是“apiclient_cert.p12”3、随后就是代码片段这些代码copy下来的确是可以跑起来,小编不像有些人,贴代码的时候不贴import的jar和pom文件,导致别人copy下来一堆jar找不到(请叫我良心小编)...大家在手机端看的时候可能代码过于长,大家可以主要看核心代码部分,生成签名,生成订单,这类代码!有什么疑问随时私我。下面有好东西哦!ClientCustomSSL类代码如下package com.mobilepay.wxpay.
import com.alibaba.fastjson.JSONO
import com.mobilepay.wxpay.constants.WXPayC
import org.apache.http.HttpE
import org.apache.http.client.methods.CloseableHttpR
import org.apache.http.client.methods.HttpP
import org.apache.http.conn.ssl.SSLConnectionSocketF
import org.apache.http.entity.StringE
import org.apache.http.impl.client.CloseableHttpC
import org.apache.http.impl.client.HttpC
import org.apache.http.ssl.SSLC
import org.apache.http.util.EntityU
import org.dom4j.D
import org.dom4j.DocumentH
import org.dom4j.E
import org.dom4j.io.SAXR
import javax.net.ssl.SSLC
import java.io.F
import java.io.FileInputS
import java.security.KeyS
* @Author: HONGLINCHEN
* @Description: 微信退款
public class ClientCustomSSL {
* @Author: HONGLINCHEN
* @Description:微信退款方法封装
注意::微信金额的单位是分 所以这里要X100 转成int是因为 退款的时候不能有小数点
* @param merchantNumber 商户这边的订单号
* @param wxTransactionNumber 微信那边的交易单号
* @param totalFee 订单的金额
public static Object setUrl(String merchantNumber,String wxTransactionNumber,double totalFee) {
KeyStore keyStore = KeyStore.getInstance("PKCS12");
FileInputStream instream = new FileInputStream(new File("D:\\微信商户平台支付证书\\apiclient_cert.p12"));
keyStore.load(instream, WXPayConstants.MCH_ID.toCharArray());
}finally {
instream.close();
// Trust own CA and all self-signed certs
SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore, WXPayConstants.MCH_ID.toCharArray()).build();
// Allow TLSv1 protocol only
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
sslcontext, new String[] { "TLSv1" }, null,
SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
CloseableHttpClient httpclient = HttpClients.custom()
.setSSLSocketFactory(sslsf).build();
HttpPost httppost = new HttpPost("https://api.mch.weixin.qq.com/secapi/pay/refund");
String xml = com.mobilepay.wxpay.wxpayutils.WXPayUtil.wxPayRefund(merchantNumber,wxTransactionNumber,String.valueOf((int)(totalFee*100)));
StringEntity se = new StringEntity(xml);
httppost.setEntity(se);
System.out.println("executing request" + httppost.getRequestLine());
CloseableHttpResponse responseEntry = httpclient.execute(httppost);
HttpEntity entity = responseEntry.getEntity();
System.out.println(responseEntry.getStatusLine());
if (entity != null) {
System.out.println("Response content length: "
+ entity.getContentLength());
SAXReader saxReader = new SAXReader();
Document document = saxReader.read(entity.getContent());
Element rootElt = document.getRootElement();
System.out.println("根节点:" + rootElt.getName());
System.out.println("==="+rootElt.elementText("result_code"));
System.out.println("==="+rootElt.elementText("return_msg"));
String resultCode = rootElt.elementText("result_code");
JSONObject result = new JSONObject();
Document documentXml = DocumentHelper.parseText(xml);
Element rootEltXml = documentXml.getRootElement();
if(resultCode.equals("SUCCESS")){
System.out.println("=================prepay_id===================="+ rootElt.elementText("prepay_id"));
System.out.println("=================sign===================="+ rootEltXml.elementText("sign"));
result.put("weixinPayUrl", rootElt.elementText("code_url"));
result.put("prepayId", rootElt.elementText("prepay_id"));
result.put("status","success");
result.put("msg","success");
result.put("status","false");
result.put("msg",rootElt.elementText("err_code_des"));
EntityUtils.consume(entity);
responseEntry.close();
httpclient.close();
}catch(Exception e){
e.printStackTrace();
JSONObject result = new JSONObject();
result.put("status","error");
result.put("msg",e.getMessage());
}WXPayUtil类代码如下package com.mobilepay.wxpay.
import com.mobilepay.wxpay.constants.WXPayC
import com.mobilepay.wxpay.utils.MD5U
import org.apache.commons.httpclient.HttpC
import org.apache.commons.httpclient.methods.PostM
import org.apache.http.HttpE
import org.apache.http.client.methods.CloseableHttpR
import org.apache.http.client.methods.HttpP
import org.apache.http.conn.ssl.SSLConnectionSocketF
import org.apache.http.conn.ssl.SSLC
import org.apache.http.entity.StringE
import org.apache.http.impl.client.CloseableHttpC
import org.apache.http.impl.client.HttpC
import org.apache.http.util.EntityU
import org.slf4j.L
import org.slf4j.LoggerF
import org.w3c.dom.N
import org.w3c.dom.NodeL
import javax.crypto.M
import javax.crypto.spec.SecretKeyS
import javax.net.ssl.SSLC
import javax.xml.parsers.DocumentB
import javax.xml.parsers.DocumentBuilderF
import java.io.*;
import java.security.KeyS
import java.security.MessageD
import java.util.*;
* @Author: HONGLINCHEN
* @Description:微信支付
public class WXPayUtil {
public static String PostRequest(String url, String data) throws IOException {
HttpClient client = new HttpClient();
PostMethod post=new PostMethod(url);
String result = "";
post.addRequestHeader("Content-Type", "text/ charset=utf-8");
post.addRequestHeader("content", "text/ charset=utf-8");
post.setRequestBody(data);
int status=client.executeMethod(post);
result = post.getResponseBodyAsString();
result = new String(result.getBytes(post.getResponseCharSet()), "utf-8");
} catch (IOException e){
// TODO Auto-generated catch block
e.printStackTrace();
* 创建md5摘要,规则是:按参数名称a-z排序,遇到空值的参数不参加签名。
public static String createSign(SortedMap&String, String& packageParams, String AppKey) {
StringBuffer 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();
* @Author: HONGLINCHEN
* @Description:微信支付 统一下单
* @param out_trade_no
* @param body
* @param detail
* @param total_fee
* @param ip_address
* @return:
public static String unifiedOrder(String out_trade_no, String body, String detail, int total_fee,String ip_address) {
StringBuffer xml = new StringBuffer();
String data = null;
xml.append("&/xml&");
if (body.length() & 32) {
body = body.substring(0, 32);
SortedMap&String, String& parameters = new TreeMap();
parameters.put("appid", WXPayConstants.APP_ID);
parameters.put("body", body);
parameters.put("detail", detail);
parameters.put("mch_id", WXPayConstants.MCH_ID);
parameters.put("nonce_str", genNonceStr());
parameters.put("notify_url", "http://www.aidongsports.com/wx");
parameters.put("out_trade_no", out_trade_no);
parameters.put("fee_type", "CNY");
parameters.put("spbill_create_ip", ip_address);
parameters.put("total_fee", String.valueOf(total_fee));
parameters.put("trade_type", "APP");
parameters.put("sign", createSign(parameters, WXPayConstants.API_KEY));
data = PostRequest("https://api.mch.weixin.qq.com/pay/unifiedorder",SortedMaptoXml(parameters));
}catch (Exception e){
e.printStackTrace();
* @Author: HONGLINCHEN
* @Description:微信退款
* @param out_trade_no
* @param total_fee
* @return:
public static String wxPayRefund(String out_trade_no, String transaction_id,String total_fee) {
StringBuffer xml = new StringBuffer();
String data = null;
String nonceStr = genNonceStr();
xml.append("&/xml&");
SortedMap&String,String& parameters = new TreeMap&String,String&();
parameters.put("appid", WXPayConstants.APP_ID);
parameters.put("mch_id", WXPayConstants.MCH_ID);
parameters.put("nonce_str", nonceStr);
parameters.put("out_trade_no", out_trade_no);
parameters.put("transaction_id", transaction_id);
parameters.put("out_refund_no", nonceStr);
parameters.put("fee_type", "CNY");
parameters.put("total_fee", total_fee);
parameters.put("refund_fee", total_fee);
parameters.put("op_user_id", WXPayConstants.MCH_ID);
parameters.put("sign", createSign(parameters, WXPayConstants.API_KEY));
data =SortedMaptoXml(parameters);
} catch (Exception e) {
System.err.println(e.getMessage());
return null;
* 证书使用
* 微信退款
public static String wxPayBack(String url, String data) throws Exception {
KeyStore keyStore
= KeyStore.getInstance("PKCS12");
FileInputStream instream = new FileInputStream(new File("D:\\微信商户平台支付证书\\apiclient_cert.p12"));
String result="";
keyStore.load(instream, WXPayConstants.MCH_ID.toCharArray());
} finally {
instream.close();
// Trust own CA and all self-signed certs
SSLContext sslcontext = SSLContexts.custom()
.loadKeyMaterial(keyStore, WXPayConstants.MCH_ID.toCharArray())
// Allow TLSv1 protocol only
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
sslcontext,
new String[] { "TLSv1" },
SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
CloseableHttpClient httpclient = HttpClients.custom()
.setSSLSocketFactory(sslsf)
HttpPost httppost = new HttpPost("https://api.mch.weixin.qq.com/secapi/pay/refund");
StringEntity entitys = new StringEntity(data);
httppost.setEntity((HttpEntity) entitys);
CloseableHttpResponse response = httpclient.execute(httppost);
HttpEntity entity = response.getEntity();
if (entity != null) {
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(entity.getContent()));
String text="";
String t="";
while ((text=bufferedReader.readLine()) != null) {
byte[] temp=t.getBytes("gbk");//这里写原编码方式
String newStr=new String(temp,"utf-8");//这里写转换后的编码方式
result=newS
EntityUtils.consume(entity);
} finally {
response.close();
} finally {
httpclient.close();
* XML格式字符串转换为Map
* 微信支付 解析xml xml转map
获取prepay_id
* @param strXML XML字符串
* @return XML数据转换后的Map
* @throws Exception
public static Map&String, String& xmlToMap(String strXML) throws Exception {
Map&String, String& data = new HashMap&String, String&();
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
InputStream stream = new ByteArrayInputStream(strXML.getBytes("UTF-8"));
org.w3c.dom.Document doc = documentBuilder.parse(stream);
doc.getDocumentElement().normalize();
NodeList nodeList = doc.getDocumentElement().getChildNodes();
for (int idx = 0; idx & nodeList.getLength(); ++idx) {
Node node = nodeList.item(idx);
if (node.getNodeType() == Node.ELEMENT_NODE) {
org.w3c.dom.Element element = (org.w3c.dom.Element)
data.put(element.getNodeName(), element.getTextContent());
stream.close();
} catch (Exception ex) {
// do nothing
} catch (Exception ex) {
WXPayUtil.getLogger().warn("Invalid XML, can not convert to map. Error message: {}. XML content: {}", ex.getMessage(), strXML);
* 获取随机字符串 Nonce Str
* @return String 随机字符串
public static String generateNonceStr() {
return UUID.randomUUID().toString().replaceAll("-", "").substring(0, 32);
* 生成 MD5
* @param data 待处理数据
* @return MD5结果
public static String MD5(String data) throws Exception {
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] array = md.digest(data.getBytes("UTF-8"));
StringBuilder sb = new StringBuilder();
for (byte item : array) {
sb.append(Integer.toHexString((item & 0xFF) | <span style="color:#).substring(1, 3));
return sb.toString().toUpperCase();
* 生成 HMACSHA256
* @param data 待处理数据
* @param key 密钥
* @return 加密结果
* @throws Exception
public static String HMACSHA256(String data, String key) throws Exception {
Mac sha256_HMAC = Mac.getInstance("HmacSHA256");
SecretKeySpec secret_key = new SecretKeySpec(key.getBytes("UTF-8"), "HmacSHA256");
sha256_HMAC.init(secret_key);
byte[] array = sha256_HMAC.doFinal(data.getBytes("UTF-8"));
StringBuilder sb = new StringBuilder();
for (byte item : array) {
sb.append(Integer.toHexString((item & 0xFF) | <span style="color:#).substring(1, 3));
return sb.toString().toUpperCase();
* @Author: HONGLINCHEN
* @Description:通过prepay_id 生成微信支付参数
* @param prepay_id
public static
SortedMap&Object,Object& genPayRequest(String prepay_id) {
SortedMap&Object,Object& parameters = new TreeMap&Object,Object&();
parameters.put("appid", WXPayConstants.APP_ID);
parameters.put("noncestr", genNonceStr());
parameters.put("package", "Sign=WXPay");
parameters.put("partnerid", WXPayConstants.MCH_ID);
parameters.put("prepayid", prepay_id);
parameters.put("timestamp",getCurrentTimestamp());
parameters.put("sign", MD5.createSign("utf-8", parameters).toUpperCase());
* @Author: HONGLINCHEN
* @Description:请求值转换为xml格式 SortedMap转xml
* @param params
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();
public static Logger getLogger() {
Logger logger = LoggerFactory.getLogger("wxpay java sdk");
* 生成32位随机数字
public static String genNonceStr() {
Random random = new Random();
return MD5.getMessageDigest(String.valueOf(random.nextInt(<span style="color:#)).getBytes());
* 获取当前时间戳,单位秒
public static long getCurrentTimestamp() {
return System.currentTimeMillis()/<span style="color:#;
* 生成 uuid, 即用来标识一笔单,也用做 nonce_str
public static String generateUUID() {
return UUID.randomUUID().toString().replaceAll("-", "").substring(0, 32);
MD5Util类代码如下package com.mobilepay.wxpay.
import java.security.MessageD
public class MD5Util {
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();
private static String byteToHexString(byte b) {
if (n & 0)
n += <span style="color:#;
int d1 = n / 16;
int d2 = n % 16;
return hexDigits[d1] + hexDigits[d2];
public static String MD5Encode(String origin, String charsetname) {
String resultString = null;
resultString = new String(origin);
MessageDigest md = MessageDigest.getInstance("MD5");
if (charsetname == null || "".equals(charsetname))
resultString = byteArrayToHexString(md.digest(resultString
.getBytes()));
resultString = byteArrayToHexString(md.digest(resultString
.getBytes(charsetname)));
} catch (Exception exception) {
return resultS
private static final String hexDigits[] = { "0", "1", "2", "3", "4", "5",
"6", "7", "8", "9", "a", "b", "c", "d", "e", "f" };
WeiXinPayController类代码如下package com.mobilepay.wxpay.
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONO
import com.mobilepay.wxpay.constants.WXPayC
import com.mobilepay.wxpay.utils.ClientCustomSSL;
import com.mobilepay.wxpay.utils.RequestU
import com.mobilepay.wxpay.wxpayutils.WXPayU
import org.apache.http.HttpE
import org.apache.http.client.methods.CloseableHttpR
import org.apache.http.client.methods.HttpP
import org.apache.http.conn.ssl.SSLConnectionSocketF
import org.apache.http.entity.StringE
import org.apache.http.impl.client.CloseableHttpC
import org.apache.http.impl.client.HttpC
import org.apache.http.ssl.SSLC
import org.apache.http.util.EntityU
import org.apache.log4j.L
import org.dom4j.D
import org.dom4j.DocumentH
import org.dom4j.E
import org.dom4j.io.SAXR
import org.springframework.stereotype.Controller;
import org.springframework.ui.M
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestM
import javax.net.ssl.SSLC
import javax.servlet.http.HttpServletR
import javax.servlet.http.HttpServletR
import java.io.F
import java.io.FileInputS
import java.io.IOE
import java.security.KeyS
import java.util.SortedM
import java.util.regex.M
import java.util.regex.P
import static com.mobilepay.wxpay.wxpayutils.WXPayUtil.genPayRequest;
* @Author: HONGLINCHEN
* @Description:微信支付
@Controller
public class WeiXinPayController {
private static final Logger logger = Logger.getLogger(WeiXinPayController.class);
@RequestMapping(value = "/weixinpay",method = {RequestMethod.GET})
public String weixinpay(HttpServletRequest request, HttpServletResponse response, Model model){
return "wxpay";
@RequestMapping(value = "/wechatRefund",method = {RequestMethod.GET})
public String wecharrefund(HttpServletRequest request, HttpServletResponse response, Model model){
return "wechatrefund";
* @Author: HONGLINCHEN
* @Description: 微信支付
* @param number
* @param money
* @param request
* @param response
* @param model
@RequestMapping(value = "/wxPay",method = {RequestMethod.GET,RequestMethod.POST})
public String weixinpay(String number, double money, HttpServletRequest request, HttpServletResponse response, Model model) throws IOException {
String ipAddress = RequestUtils.getClientIpAddress(request);
String bodyStr = "参与活动", detailStr = "微信支付测试 1.0*1";
String paySignXml = WXPayUtil.unifiedOrder(number, bodyStr, detailStr, (int)(money*<span style="color:#), ipAddress);
System.err.println("加密以后的支付参数\n"+paySignXml);
String prepay_id = WXPayUtil.xmlToMap(paySignXml).get("prepay_id").toString();
if(prepay_id!=null&&!"".equals(prepay_id)){
SortedMap&Object,Object& pay = genPayRequest(prepay_id);
System.err.println("实际支付参数\n"+pay);
response.getWriter().print(JSON.toJSON(pay));
model.addAttribute("result","请求支付参数错误!");
} catch (Exception e) {
e.printStackTrace();
return null;
* @Author: HONGLINCHEN
* @Description: 微信取消订单
* @param number
* @param money
* @param request
* @param response
* @param model
@RequestMapping(value = "/wxPayCancelOrder",method = {RequestMethod.GET,RequestMethod.POST})
public String wxPayCancelOrder(String number, double money, HttpServletRequest request, HttpServletResponse response, Model model) throws IOException {
String ipAddress = RequestUtils.getClientIpAddress(request);
String bodyStr = "参与活动", detailStr = "微信支付测试 1.0*1";
String paySignXml = WXPayUtil.unifiedOrder(number, bodyStr, detailStr, (int)(money*<span style="color:#), ipAddress);
System.err.println("加密以后的支付参数\n"+paySignXml);
String prepay_id = WXPayUtil.xmlToMap(paySignXml).get("prepay_id").toString();
if(prepay_id!=null&&!"".equals(prepay_id)){
SortedMap&Object,Object& pay = genPayRequest(prepay_id);
System.err.println("实际支付参数\n"+pay);
response.getWriter().print(JSON.toJSON(pay));
model.addAttribute("result","请求支付参数错误!");
} catch (Exception e) {
e.printStackTrace();
return null;
* @Author: HONGLINCHEN
微信退款三种方式,随便哪一个都可以
* @Description:微信退款
注意::微信金额的单位是分 所以这里要X100 转成int是因为 退款的时候不能有小数点
* @param merchantNumber 商户这边的订单号
* @param wxTransactionNumber 微信那边的交易单号
* @param totalFee 订单的金额
@RequestMapping(value = "/wxPayRefundTwo", method = { RequestMethod.GET, RequestMethod.POST })
public String qxwxsign(String merchantNumber,String wxTransactionNumber,double totalFee,HttpServletResponse response, HttpServletRequest request) throws IOException {
String param = WXPayUtil.wxPayRefund(merchantNumber,wxTransactionNumber,String.valueOf((int)(totalFee*<span style="color:#)));
System.err.println("param"+param);
String result = "";
String url = "https://api.mch.weixin.qq.com/secapi/pay/refund";
result = WXPayUtil.wxPayBack(url, param);
} catch (Exception e) {
e.printStackTrace();
String tt = "3503";
Pattern p = Pattern.compile("\\.*(\\w{" + tt.length() + "})\\.*");
int st = result.indexOf("&refund_id&");
String res = "";
if (st &= 0) {
int en = result.indexOf("&/refund_id&");
res = result.substring(st, en);
Matcher m = p.matcher(res);
if (m.find()) {
res = m.group(1);
if (res.length() & 0) {
result = "code:1,msg:退款成功";
result = "code:-1,msg:退款失败";
response.getWriter().print(JSON.toJSON(result));
return null;
* @Author: HONGLINCHEN
* @Description:微信退款
注意::微信金额的单位是分 所以这里要X100 转成int是因为 退款的时候不能有小数点
* @param merchantNumber 商户这边的订单号
* @param wxTransactionNumber 微信那边的交易单号
* @param totalFee 订单的金额
@RequestMapping(value = "/wxPayRefund", method = { RequestMethod.GET, RequestMethod.POST })
public Object wxPayRefund(String merchantNumber,String wxTransactionNumber,double totalFee) {
KeyStore keyStore = KeyStore.getInstance("PKCS12");
FileInputStream instream = new FileInputStream(new File("D:\\微信商户平台支付证书\\apiclient_cert.p12"));
keyStore.load(instream, WXPayConstants.MCH_ID.toCharArray());
}finally {
instream.close();
// Trust own CA and all self-signed certs
SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore, WXPayConstants.MCH_ID.toCharArray()).build();
// Allow TLSv1 protocol only
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
sslcontext, new String[] { "TLSv1" }, null,
SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
CloseableHttpClient httpclient = HttpClients.custom()
.setSSLSocketFactory(sslsf).build();
// HttpGet httpget = new
// HttpGet("https://api.mch.weixin.qq.com/secapi/pay/refund");
HttpPost httppost = new HttpPost("https://api.mch.weixin.qq.com/secapi/pay/refund");
//微信金额的单位是分 所以这里要X100 转成int是因为 退款的时候不能有小数点
String xml = WXPayUtil.wxPayRefund(merchantNumber,wxTransactionNumber,String.valueOf((int)(totalFee*<span style="color:#)));
StringEntity se = new StringEntity(xml);
httppost.setEntity(se);
System.out.println("executing request" + httppost.getRequestLine());
CloseableHttpResponse responseEntry = httpclient.execute(httppost);
HttpEntity entity = responseEntry.getEntity();
System.out.println(responseEntry.getStatusLine());
if (entity != null) {
System.out.println("Response content length: "+ entity.getContentLength());
SAXReader saxReader = new SAXReader();
Document document = saxReader.read(entity.getContent());
Element rootElt = document.getRootElement();
System.out.println("根节点:" + rootElt.getName());
System.out.println("==="+rootElt.elementText("result_code"));
System.out.println("==="+rootElt.elementText("return_msg"));
String resultCode = rootElt.elementText("result_code");
JSONObject result = new JSONObject();
Document documentXml = DocumentHelper.parseText(xml);
Element rootEltXml = documentXml.getRootElement();
if(resultCode.equals("SUCCESS")){
System.out.println("=================prepay_id===================="+ rootElt.elementText("prepay_id"));
System.out.println("=================sign===================="+ rootEltXml.elementText("sign"));
result.put("weixinPayUrl", rootElt.elementText("code_url"));
result.put("prepayId", rootElt.elementText("prepay_id"));
result.put("status","success");
result.put("msg","success");
result.put("status","false");
result.put("msg",rootElt.elementText("err_code_des"));
EntityUtils.consume(entity);
responseEntry.close();
httpclient.close();
return null;
}catch(Exception e){
e.printStackTrace();
JSONObject result = new JSONObject();
result.put("status","error");
result.put("msg",e.getMessage());
* @Author: HONGLINCHEN
* @Description:微信退款
注意::微信金额的单位是分 所以这里要X100 转成int是因为 退款的时候不能有小数点
* @param merchantNumber 商户这边的订单号
* @param wxTransactionNumber 微信那边的交易单号
* @param totalFee 订单的金额
@RequestMapping(value = "/wxPayRefundone", method = { RequestMethod.GET, RequestMethod.POST })
public Object wxPayRefundone(String merchantNumber,String wxTransactionNumber,double totalFee) {
Object object = ClientCustomSSL.setUrl(merchantNumber,wxTransactionNumber,totalFee);
WXPayConstants类代码如下package com.mobilepay.wxpay.
* @Author: HONGLINCHEN
* @Description:微信支付参数
public class WXPayConstants {
//请同时修改
androidmanifest.xml里面 .PayActivityd里的属性&data android:scheme="wxb4ba3c02aa476ea1"/&为新设置的appid
public static final String APP_ID = "替换成自己的";
public static final String MCH_ID = "替换成自己的";
//API密钥,在商户平台设置
public static final
String API_KEY="替换成自己的";
//商户号 微信小程序使用
public static final String APPLET_MCHID = "替换成自己的";
//appid 微信小程序使用
public static final String APPLET_APPID = "替换成自己的";
XMLUtil类代码如下package com.mobilepay.wxpay.
import org.dom4j.DocumentE
import org.dom4j.DocumentH
import org.jdom.D
import org.jdom.E
import org.jdom.JDOME
import org.jdom.input.SAXB
import java.io.ByteArrayInputS
import java.io.IOE
import java.io.InputS
import java.util.HashM
import java.util.I
import java.util.L
import java.util.M
* @Author: HONGLINCHEN
* @Description: xml 工具类
public class XMLUtil {
* 解析xml,返回第一级元素键值对。如果第一级元素有子节点,则此节点的值是子节点的xml数据。 微信支付 解析xml xml转map
获取prepay_id
* @param strxml
* @throws JDOMException
* @throws IOException
public static Map doXMLParse(String strxml) throws JDOMException, IOException {
strxml = strxml.replaceFirst("encoding=\".*\"", "encoding=\"UTF-8\"");
if(null == strxml || "".equals(strxml)) {
return null;
Map m = new HashMap();
InputStream in = new ByteArrayInputStream(strxml.getBytes("UTF-8"));
SAXBuilder builder = new SAXBuilder();
Document doc = builder.build(in);
Element root = doc.getRootElement();
List list = root.getChildren();
Iterator it = list.iterator();
while(it.hasNext()) {
Element e = (Element) it.next();
String k = e.getName();
String v = "";
List children = e.getChildren();
if(children.isEmpty()) {
v = e.getTextNormalize();
v = XMLUtil.getChildrenText(children);
m.put(k, v);
in.close();
* @Author: HONGLINCHEN
* @Description: 微信支付 解析xml xml转map
获取prepay_id
* @param xml
public static Map&String,Object& getResult(String xml){
Map&String,Object& map = new HashMap&String, Object&();
org.dom4j.Document document = DocumentHelper.parseText(xml);
org.dom4j.Element root = document.getRootElement();
Iterator&org.dom4j.Element& it = root.elementIterator();
while (it.hasNext()) {
org.dom4j.Element element = it.next();
map.put(element.getName(), element.getTextTrim());
} catch (DocumentException e) {
e.printStackTrace();
* 获取子结点的xml
* @param children
* @return String
public static String getChildrenText(List children) {
StringBuffer sb = new StringBuffer();
if(!children.isEmpty()) {
Iterator it = children.iterator();
while(it.hasNext()) {
Element e = (Element) it.next();
String name = e.getName();
String value = e.getTextNormalize();
List list = e.getChildren();
sb.append("&" + name + "&");
if(!list.isEmpty()) {
sb.append(XMLUtil.getChildrenText(list));
sb.append(value);
sb.append("&/" + name + "&");
return sb.toString();
* 获取xml编码字符集
* @param strxml
* @throws IOException
* @throws JDOMException
public static String getXMLEncoding(String strxml) throws JDOMException, IOException {
InputStream in = String2Inputstream(strxml);
SAXBuilder builder = new SAXBuilder();
Document doc = builder.build(in);
in.close();
return (String)doc.getProperty("encoding");
public static InputStream String2Inputstream(String str) {
return new ByteArrayInputStream(str.getBytes());
MD5类代码如下package com.mobilepay.wxpay.
import com.mobilepay.wxpay.constants.WXPayC
import java.security.MessageD
import java.util.I
import java.util.M
import java.util.S
import java.util.SortedM
* @Author: HONGLINCHEN
* @Description: MD5 工具类
public class MD5 {
public final static String getMessageDigest(byte[] buffer) {
char hexDigits[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
MessageDigest mdTemp = MessageDigest.getInstance("MD5");
mdTemp.update(buffer);
byte[] md = mdTemp.digest();
int j = md.length;
char str[] = new char[j * 2];
int k = 0;
for (int i = 0; i & i++) {
byte byte0 = md[i];
str[k++] = hexDigits[byte0 &&& 4 & 0xf];
str[k++] = hexDigits[byte0 & 0xf];
return new String(str);
} catch (Exception e) {
return null;
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();
private static String byteToHexString(byte b) {
if (n & 0)
n += <span style="color:#;
int d1 = n / 16;
int d2 = n % 16;
return hexDigits[d1] + hexDigits[d2];
public static String MD5Encode(String origin, String charsetname) {
String resultString = null;
resultString = new String(origin);
MessageDigest md = MessageDigest.getInstance("MD5");
if (charsetname == null || "".equals(charsetname))
resultString = byteArrayToHexString(md.digest(resultString
.getBytes()));
resultString = byteArrayToHexString(md.digest(resultString
.getBytes(charsetname)));
} catch (Exception exception) {
return resultS
private static final String hexDigits[] = { "0", "1", "2", "3", "4", "5",
"6", "7", "8", "9", "a", "b", "c", "d", "e", "f" };
* @Author: HONGLINCHEN
* @Description:支付参数生成签名
* @param characterEncoding
* @param parameters
public static String createSign(String characterEncoding,SortedMap&Object,Object& parameters){
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=" + WXPayConstants.API_KEY);
String sign = MD5Encode(sb.toString(), characterEncoding).toUpperCase();
HttpUtil工具类代码如下package com.mobilepay.wxpay.
import org.apache.http.C
import org.apache.http.HttpE
import org.apache.http.NameValueP
import org.apache.http.client.ClientProtocolE
import org.apache.http.client.entity.UrlEncodedFormE
import org.apache.http.client.methods.CloseableHttpR
import org.apache.http.client.methods.HttpG
import org.apache.http.client.methods.HttpP
import org.apache.http.entity.StringE
import org.apache.http.entity.mime.HttpMultipartM
import org.apache.http.entity.mime.MultipartEntityB
import org.apache.http.entity.mime.content.FileB
import org.apache.http.impl.client.CloseableHttpC
import org.apache.http.impl.client.HttpC
import org.apache.http.message.BasicNameValueP
import org.apache.http.util.EntityU
import org.slf4j.L
import org.slf4j.LoggerF
import java.io.F
import java.io.IOE
import java.util.ArrayL
import java.util.L
import java.util.M
* @Author: HONGLINCHEN
* @Description: Http工具类,发送Http请求, Get请求请将参数放在url中 Post请求请将参数放在Map中
public class HttpUtil {
private static final Logger log = LoggerFactory.getLogger(HttpUtil.class);
private static final CloseableHttpClient httpclient = HttpClients.createDefault();
private static final String userAgent = "Mozilla/5.0 (Windows NT 6.2; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.87 Safari/537.36";
* 发送HttpGet请求
* @param url
* @return 返回字符串
public static String sendGet(String url) {
String result = null;
CloseableHttpResponse response = null;
HttpGet httpGet = new HttpGet(url);
httpGet.setHeader("User-Agent", userAgent);
response = httpclient.execute(httpGet);
HttpEntity entity = response.getEntity();
if (entity != null) {
result = EntityUtils.toString(entity);
} catch (Exception e) {
log.error("处理失败 {}" + e);
e.printStackTrace();
} finally {
if (response != null) {
response.close();
} catch (IOException e) {
log.error(e.getMessage());
* 发送HttpPost请求,参数为map
* @param url
* @param map
* @return 返回字符串
public static String sendPost(String url, Map&String, String& map) {
// 设置参数
List&NameValuePair& formparams = new ArrayList&NameValuePair&();
for (Map.Entry&String, String& entry : map.entrySet()) {
formparams.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(formparams, Consts.UTF_8);
// 取得HttpPost对象
HttpPost httpPost = new HttpPost(url);
// 防止被当成攻击添加的
httpPost.setHeader("User-Agent", userAgent);
// 参数放入Entity
httpPost.setEntity(formEntity);
CloseableHttpResponse response = null;
String result = null;
// 执行post请求
response = httpclient.execute(httpPost);
// 得到entity
HttpEntity entity = response.getEntity();
// 得到字符串
result = EntityUtils.toString(entity);
} catch (IOException e) {
log.error(e.getMessage());
} finally {
if (response != null) {
response.close();
} catch (IOException e) {
log.error(e.getMessage());
* 发送HttpPost请求,参数为文件,适用于微信上传素材
* @param url
* @param file
上传的文件
* @return 返回字符串
* @throws IOException
* @throws ClientProtocolException
public static String sendPost(String url, File file) {
String result = null;
HttpPost httpPost = new HttpPost(url);
// 防止被当成攻击添加的
httpPost.setHeader("User-Agent", userAgent);
MultipartEntityBuilder multipartEntity = MultipartEntityBuilder.create();
multipartEntity.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
multipartEntity.addPart("media", new FileBody(file));
httpPost.setEntity(multipartEntity.build());
CloseableHttpResponse response = null;
response = httpclient.execute(httpPost);
HttpEntity entity = response.getEntity();
result = EntityUtils.toString(entity);
} catch (IOException e) {
log.error(e.getMessage());
} finally {
// 关闭CloseableHttpResponse
if (response != null) {
response.close();
} catch (IOException e) {
log.error(e.getMessage());
* 发送HttpPost请求,参数为json字符串
* @param url
* @param jsonStr
public static String sendPost(String url, String jsonStr) {
String result = null;
// 字符串编码
StringEntity entity = new StringEntity(jsonStr, Consts.UTF_8);
// 设置content-type
entity.setContentType("application/json");
HttpPost httpPost = new HttpPost(url);
// 防止被当成攻击添加的
httpPost.setHeader("User-Agent", userAgent);
httpPost.setEntity(entity);
CloseableHttpResponse response = null;
response = httpclient.execute(httpPost);
HttpEntity httpEntity = response.getEntity();
result = EntityUtils.toString(httpEntity);
} catch (IOException e) {
log.error(e.getMessage());
} finally {
// 关闭CloseableHttpResponse
if (response != null) {
response.close();
} catch (IOException e) {
log.error(e.getMessage());
* 发送不带参数的HttpPost请求
* @param url
public static String sendPost(String url) {
String result = null;
// 得到一个HttpPost对象
HttpPost httpPost = new HttpPost(url);
// 防止被当成攻击添加的
httpPost.setHeader("User-Agent", userAgent);
CloseableHttpResponse response = null;
// 执行HttpPost请求,并得到一个CloseableHttpResponse
response = httpclient.execute(httpPost);
// 从CloseableHttpResponse中拿到HttpEntity
HttpEntity entity = response.getEntity();
// 将HttpEntity转换为字符串
result = EntityUtils.toString(entity);
} catch (IOException e) {
log.error(e.getMessage());
} finally {
// 关闭CloseableHttpResponse
if (response != null) {
response.close();
} catch (IOException e) {
log.error(e.getMessage());
}pom文件代码如下:&project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"&
&modelVersion&4.0.0&/modelVersion&
&groupId&com.mobilepay.example&/groupId&
&artifactId&MobilePay&/artifactId&
&packaging&war&/packaging&
&version&1.0-SNAPSHOT&/version&
&name&MobilePay Maven Webapp&/name&
&url&http://maven.apache.org&/url&
&properties&
&!-- spring版本号 --&
&spring.version&4.0.2.RELEASE&/spring.version&
&!-- mybatis版本号 --&
&mybatis.version&3.2.8&/mybatis.version&
&!-- log4j日志文件管理包版本 --&
&log4j.version&1.2.17&/log4j.version&
&slf4j.version&1.7.21&/slf4j.version&
&project.build.sourceEncoding&UTF-8&/project.build.sourceEncoding&
&/properties&
&dependencies&
&!--Spring--&
&dependency&
&groupId&org.springframework&/groupId&
&artifactId&spring-core&/artifactId&
&version&${spring.version}&/version&
&exclusions&
&exclusion&
&artifactId&commons-logging&/artifactId&
&groupId&commons-logging&/groupId&
&/exclusion&
&/exclusions&
&/dependency&
&dependency&
&groupId&org.springframework&/groupId&
&artifactId&spring-web&/artifactId&
&version&${spring.version}&/version&
&/dependency&
&dependency&
&groupId&org.springframework&/groupId&
&artifactId&spring-oxm&/artifactId&
&version&${spring.version}&/version&
&/dependency&
&dependency&
&groupId&org.springframework&/groupId&
&artifactId&spring-tx&/artifactId&
&version&${spring.version}&/version&
&/dependency&
&dependency&
&groupId&org.springframework&/groupId&
&artifactId&spring-jdbc&/artifactId&
&version&${spring.version}&/version&
&/dependency&
&dependency&
&groupId&org.springframework&/groupId&
&artifactId&spring-webmvc&/artifactId&
&version&${spring.version}&/version&
&/dependency&
&dependency&
&groupId&org.springframework&/groupId&
&artifactId&spring-aop&/artifactId&
&version&${spring.version}&/version&
&/dependency&
&dependency&
&groupId&org.springframework&/groupId&
&artifactId&spring-context-support&/artifactId&
&version&${spring.version}&/version&
&/dependency&
&dependency&
&groupId&org.springframework&/groupId&
&artifactId&spring-test&/artifactId&
&version&${spring.version}&/version&
&/dependency&
&!--Spring end--&
&!-- log start --&
&dependency&
&groupId&log4j&/groupId&
&artifactId&log4j&/artifactId&
&version&${log4j.version}&/version&
&/dependency&
&dependency&
&groupId&commons-logging&/groupId&
&artifactId&commons-logging&/artifactId&
&version&1.2&/version&
&/dependency&
&dependency&
&groupId&org.slf4j&/groupId&
&artifactId&slf4j-api&/artifactId&
&version&${slf4j.version}&/version&
&/dependency&
&dependency&
&groupId&org.slf4j&/groupId&
&artifactId&slf4j-simple&/artifactId&
&version&${slf4j.version}&/version&
&exclusions&
&exclusion&
&groupId&org.slf4j&/groupId&
&artifactId&slf4j-api&/artifactId&
&/exclusion&
&/exclusions&
&/dependency&
&!-- log end --&
&dependency&
&groupId&junit&/groupId&
&artifactId&junit&/artifactId&
&version&3.8.1&/version&
&scope&test&/scope&
&/dependency&
&dependency&
&groupId&com.alibaba&/groupId&
&artifactId&fastjson&/artifactId&
&version&1.2.32&/version&
&/dependency&
&dependency&
&groupId&org.apache.httpcomponents&/groupId&
&artifactId&httpcore&/artifactId&
&version&4.4.6&/version&
&/dependency&
&!-- 微信支付工具类需要的jar start--&
&dependency&
&groupId&com.github.wxpay&/groupId&
&artifactId&wxpay-sdk&/artifactId&
&version&0.0.3&/version&
&/dependency&
&!-- 微信支付工具类需要的jar end--&
&dependency&
&groupId&jdom&/groupId&
&artifactId&jdom&/artifactId&
&version&1.1&/version&
&/dependency&
&!-- 支付宝支付需要的jar start 这个没用到,因为不知道为啥下载不下来,下次有时间在解决吧--&
&!--&dependency&
&groupId&com.pentahohub.nexus&/groupId&
&artifactId&alipay-sdk-java&/artifactId&
&version&50&/version&
&/dependency&--&
&!-- 支付宝支付需要的jar end--&
&!-- 支付宝支付需要的jar start 项目中用的是这个,是我用maven命令安装到本地仓库然后引用的--&
&!-- maven安装jar包到本地仓库命令 mvn install:install-file -DgroupId=com.alipay -DartifactId=alipay-sdk-java -Dversion=1.0.0 -Dpackaging=jar -Dfile=F:\alipay-sdk-java30.jar--&
&dependency&
&groupId&com.alipay&/groupId&
&artifactId&alipay-sdk-java&/artifactId&
&version&1.0.0&/version&
&/dependency&
&!-- 支付宝支付需要的jar end--&
&dependency&
&groupId&commons-httpclient&/groupId&
&artifactId&commons-httpclient&/artifactId&
&version&3.1&/version&
&exclusions&
&exclusion&
&artifactId&commons-codec&/artifactId&
&groupId&commons-codec&/groupId&
&/exclusion&
&exclusion&
&artifactId&commons-logging&/artifactId&
&groupId&commons-logging&/groupId&
&/exclusion&
&exclusion&
&artifactId&commons-codec&/artifactId&
&groupId&commons-codec&/groupId&
&/exclusion&
&exclusion&
&artifactId&commons-logging&/artifactId&
&groupId&commons-logging&/groupId&
&/exclusion&
&/exclusions&
&/dependency&
&dependency&
&groupId&commons-cli&/groupId&
&artifactId&commons-cli&/artifactId&
&version&1.4&/version&
&/dependency&
&dependency&
&groupId&commons-beanutils&/groupId&
&artifactId&commons-beanutils&/artifactId&
&version&1.9.3&/version&
&exclusions&
&exclusion&
&artifactId&commons-logging&/artifactId&
&groupId&commons-logging&/groupId&
&/exclusion&
&exclusion&
&groupId&commons-collections&/groupId&
&artifactId&commons-collections&/artifactId&
&/exclusion&
&/exclusions&
&/dependency&
&dependency&
&groupId&commons-codec&/groupId&
&artifactId&commons-codec&/artifactId&
&version&1.10&/version&
&/dependency&
&dependency&
&groupId&org.apache.httpcomponents&/groupId&
&artifactId&httpclient&/artifactId&
&version&4.5.3&/version&
&exclusions&
&exclusion&
&artifactId&commons-codec&/artifactId&
&groupId&commons-codec&/groupId&
&/exclusion&
&exclusion&
&artifactId&commons-logging&/artifactId&
&groupId&commons-logging&/groupId&
&/exclusion&
&exclusion&
&groupId&org.apache.httpcomponents&/groupId&
&artifactId&httpcore&/artifactId&
&/exclusion&
&/exclusions&
&/dependency&
&dependency&
&groupId&commons-collections&/groupId&
&artifactId&commons-collections&/artifactId&
&version&3.2.2&/version&
&/dependency&
&dependency&
&groupId&commons-dbcp&/groupId&
&artifactId&commons-dbcp&/artifactId&
&version&1.4&/version&
&exclusions&
&exclusion&
&artifactId&commons-pool&/artifactId&
&groupId&commons-pool&/groupId&
&/exclusion&
&/exclusions&
&/dependency&
&dependency&
&groupId&commons-pool&/groupId&
&artifactId&commons-pool&/artifactId&
&version&1.6&/version&
&/dependency&
&dependency&
&groupId&org.apache.httpcomponents&/groupId&
&artifactId&httpmime&/artifactId&
&version&4.5.3&/version&
&exclusions&
&exclusion&
&groupId&org.apache.httpcomponents&/groupId&
&artifactId&httpclient&/artifactId&
&/exclusion&
&/exclusions&
&/dependency&
&dependency&
&groupId&net.sf.ezmorph&/groupId&
&artifactId&ezmorph&/artifactId&
&version&1.0.6&/version&
&/dependency&
&dependency&
&groupId&dom4j&/groupId&
&artifactId&dom4j&/artifactId&
&version&1.6.1&/version&
&/dependency&
&dependency&
&groupId&net.sf.json-lib&/groupId&
&artifactId&json-lib&/artifactId&
&version&2.4&/version&
&classifier&jdk15&/classifier&&!--指定jdk版本2.4对应jdk1.5不指定导入到idea就会报错--&
&scope&compile&/scope&
&/dependency&
&/dependencies&
&finalName&MobilePay&/finalName&
&groupId&org.apache.maven.plugins&/groupId&
&artifactId&maven-compiler-plugin&/artifactId&
&version&2.5.1&/version&
&configuration&
&source&1.8&/source&
&target&1.8&/target&
&compilerArgument&-Xlint:all&/compilerArgument&
&showWarnings&true&/showWarnings&
&showDeprecation&true&/showDeprecation&
&/configuration&
&/plugins&
&/project&
好了,把这些 代码复制到自己工程中并替换自己的东西,就可以跑起来了。如果需要源代码,或者整个工程(MobilePay)可以私聊我,我会解压发给大家!MobilePay这个项目中集成了所有的移动支付,包括2大平台支付宝、微信 的支付模块的 登录模块下面这个gif和你们写完代码,测试成功后的表情是不是很像呢?哈哈哈哈哈.....作者:HONGLINCHEN.上海·黄埔作者邮箱:请关注作者的今日头条号:《专注JavaWeb开发》 博客地址:请关注作者的CSDN博客:《专注JavaWeb开发》 博客地址:作者的QQ群:专注JavaWeb开发.群号:
没有更多推荐了,

我要回帖

更多关于 苹果id充值后怎么退款 的文章

 

随机推荐