准备:①下载证书:微信商户平台(pay.weixin.qq.com)-->账户中心-->账户设置-->API安全-->证书下载 必须是管理员账户才能下载
如果加入了微信退款回调函数:②一定要需要替换本地的两个jar包,local_policy.jar、US_export_policy.jar,具体路径为jdk1.7\jre\lib\security。
替换的包下载地址:
jdk1.7: 下载地址为:http://www.oracle.com/technetwork/java/javase/downloads/jce-7-download-432124.html
jdk1.8:下载地址为:http://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html
jdk1.6:下载地址为:http://www.oracle.com/technetwork/java/javase/downloads/jce-6-download-429243.html
接着附上mvc层代码:
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.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.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
/**
* @Description:微信退款 注意::微信金额的单位是分 所以这里要X100 转成int是因为 退款的时候不能有小数点
* @param merchantNumber 商户这边的订单号
* @param wxTransactionNumber 微信那边的交易单号
* @param totalFee 订单的金额 单位分
*/
@RequestMapping(value = "wxPayRefund", produces = {"application/json;charset=UTF-8"}, method = RequestMethod.POST)
@ResponseBody
public Object wxPayRefund(String merchantNumber,String wxTransactionNumber,double totalFee) {
try{
KeyStore keyStore = KeyStore.getInstance("PKCS12");
String weixin_docx = ConfigureUtil.getProperty("weixin_docx");//微信文档apiclient_cert.p12路径
FileInputStream instream = new FileInputStream(new File(weixin_docx));
try {
keyStore.load(instream, ConfigureUtil.getProperty("weixin_mch_id").toCharArray());
}finally {
instream.close();
}
// Trust own CA and all self-signed certs
SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore, ConfigureUtil.getProperty("weixin_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)));
try {
StringEntity se = new StringEntity(xml);
httppost.setEntity(se);
System.out.println("executing request" + httppost.getRequestLine());
CloseableHttpResponse responseEntry = httpclient.execute(httppost);
try {
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("result_code==="+rootElt.elementText("result_code")+",return_msg=="+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");
}else{
result.put("status","false");
result.put("msg",rootElt.elementText("err_code_des"));
}
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;
}
}
工具类WXPayUtil.java
package com.hb.common.util.pay;
import com.hb.common.util.ConfigureUtil;
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 javax.net.ssl.SSLContext;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.security.KeyStore;
import java.util.*;
public class WXPayUtil {
/**
* 证书使用
* 微信退款
*/
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="";
try {
keyStore.load(instream, ConfigureUtil.getProperty("weixin_mch_id").toCharArray());//添加商户号
} finally {
instream.close();
}
// Trust own CA and all self-signed certs
SSLContext sslcontext = SSLContexts.custom()
.loadKeyMaterial(keyStore, ConfigureUtil.getProperty("weixin_mch_id").toCharArray())
.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 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);
try {
HttpEntity entity = response.getEntity();
if (entity != null) {
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(entity.getContent()));
String text="";
String t="";
while ((text=bufferedReader.readLine()) != null) {
t+=text;
}
byte[] temp=t.getBytes("gbk");//这里写原编码方式
String newStr=new String(temp,"utf-8");//这里写转换后的编码方式
result=newStr;
}
EntityUtils.consume(entity);
} finally {
response.close();
}
} finally {
httpclient.close();
}
return result;
}
/**
* @Description:微信退款
* @param out_trade_no
* @param total_fee
* @Date: 2017-9-11 14:35
* @return:
*/
public static String wxPayRefund(String out_trade_no, String transaction_id,String total_fee) {
StringBuffer xml = new StringBuffer();
String data = null;
String callbackUrl = ConfigureUtil.getProperty("aiwen.ip") + "/service/weixinBack/wxRegisterNotify";//回调函数
try {
String nonceStr = PayCommonUtil.CreateNoncestr();
System.out.println("nonceStr====="+nonceStr);
xml.append("</xml>");
SortedMap<String,String> parameters = new TreeMap<String,String>();
parameters.put("appid", ConfigureUtil.getProperty("weixin_appid"));
parameters.put("mch_id",ConfigureUtil.getProperty("weixin_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("refund_fee_type", "CNY");
parameters.put("total_fee", total_fee);
parameters.put("refund_fee", total_fee);
parameters.put("notify_url",callbackUrl);
parameters.put("op_user_id", ConfigureUtil.getProperty("weixin_mch_id"));
parameters.put("sign", createSign(parameters,ConfigureUtil.getProperty("weixin_key")));
data = SortedMaptoXml(parameters);
} catch (Exception e) {
System.err.println(e.getMessage());
return null;
}
return data;
}
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();
return sign;
}
/**
* @Description:请求值转换为xml格式 SortedMap转xml
* @param params
* @Date:
*/
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();
}
}
工具类PayCommonUtil.java
package com.hb.common.util.pay;
import java.util.Iterator;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.SortedMap;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.ConnectException;
import java.net.URL;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import com.alibaba.fastjson.JSONObject;
import com.hb.common.util.ConfigureUtil;
public class PayCommonUtil {
public static String CreateNoncestr(int length) {
String chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
String res = "";
for (int i = 0; i < length; i++) {
Random rd = new Random();
res += chars.indexOf(rd.nextInt(chars.length() - 1));
}
return res;
}
public static String CreateNoncestr() {
String chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
String res = "";
for (int i = 0; i < 16; i++) {
Random rd = new Random();
res += chars.charAt(rd.nextInt(chars.length() - 1));
}
return res;
}
/**
* 是否签名正确,规则是:按参数名称a-z排序,遇到空值的参数不参加签名。
* @return boolean
*/
public static boolean isTenpaySign(String characterEncoding, SortedMap<Object, Object> packageParams) {
String key = ConfigureUtil.getProperty("weixin_key");
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(!"sign".equals(k) && null != v && !"".equals(v)) {
sb.append(k + "=" + v + "&");
}
}
sb.append("key="+key);
//算出摘要
String mysign = MD5Util.MD5Encode(sb.toString(), characterEncoding).toLowerCase();
String tenpaySign = ((String)packageParams.get("sign")).toLowerCase();
//System.out.println(tenpaySign + "/n" + mysign);
return tenpaySign.equals(mysign);
}
/**
* @Description:sign签名
* @param characterEncoding 编码格式
* @param parameters 请求参数
* @return
*/
public static String createSign(String characterEncoding,SortedMap<Object,Object> parameters){
String key = ConfigureUtil.getProperty("weixin_key");
StringBuffer sb = new StringBuffer();
Set es = parameters.entrySet();
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);
String sign = MD5Util.MD5Encode(sb.toString(), characterEncoding).toUpperCase();
return sign;
}
/**
* @Description:将请求参数转换为xml格式的string
* @param parameters 请求参数
* @return
*/
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();
//sb.append("<"+k+">"+"<![CDATA["+v+"]]></"+k+">");
/*if ("attach".equalsIgnoreCase(k)||"body".equalsIgnoreCase(k)) {
sb.append("<"+k+">"+"<![CDATA["+v+"]]></"+k+">");
}else if("mch_id".equalsIgnoreCase(k)){
sb.append("<"+k+">1492021772</"+k+">");
}else {
sb.append("<"+k+">"+v+"</"+k+">");
}*/
if("trade_type".equalsIgnoreCase(k)){
sb.append("<"+k+">"+v+"</"+k+">");
}else {
sb.append("<"+k+">"+"<![CDATA["+v+"]]></"+k+">");
}
}
sb.append("</xml>");
return sb.toString();
}
/**
* @Description:返回给微信的参数
* @param return_code 返回编码
* @param return_msg 返回信息
* @return
*/
public static String setXML(String return_code, String return_msg) {
return "<xml><return_code><![CDATA[" + return_code
+ "]]></return_code><return_msg><![CDATA[" + return_msg
+ "]]></return_msg></xml>";
}
/**
* 发送https请求
* @param requestUrl 请求地址
* @param requestMethod 请求方式(GET、POST)
* @param outputStr 提交的数据
* @return 返回微信服务器响应的信息
*/
public static String httpsRequest(String requestUrl, String requestMethod, String outputStr) {
try {
// 创建SSLContext对象,并使用我们指定的信任管理器初始化
TrustManager[] tm = { new MyX509TrustManager() };
SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
sslContext.init(null, tm, new java.security.SecureRandom());
// 从上述SSLContext对象中得到SSLSocketFactory对象
SSLSocketFactory ssf = sslContext.getSocketFactory();
URL url = new URL(requestUrl);
HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
//conn.setSSLSocketFactory(ssf);
conn.setDoOutput(true);
conn.setDoInput(true);
conn.setUseCaches(false);
// 设置请求方式(GET/POST)
conn.setRequestMethod(requestMethod);
conn.setRequestProperty("content-type", "application/x-www-form-urlencoded");
// 当outputStr不为null时向输出流写数据
if (null != outputStr) {
OutputStream outputStream = conn.getOutputStream();
// 注意编码格式
outputStream.write(outputStr.getBytes("UTF-8"));
outputStream.close();
}
// 从输入流读取返回内容
InputStream inputStream = conn.getInputStream();
InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "UTF-8");
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String str = null;
StringBuffer buffer = new StringBuffer();
while ((str = bufferedReader.readLine()) != null) {
buffer.append(str);
}
// 释放资源
bufferedReader.close();
inputStreamReader.close();
inputStream.close();
inputStream = null;
conn.disconnect();
return buffer.toString();
} catch (ConnectException ce) {
// log.error("连接超时:{}", ce);
} catch (Exception e) {
// log.error("https请求异常:{}", e);
}
return null;
}
/**
* 发送https请求
*
* @param requestUrl 请求地址
* @param requestMethod 请求方式(GET、POST)
* @param ‘outputStr’ 提交的数据
* @return JSONObject(通过JSONObject.get(key)的方式获取json对象的属性值)
*/
public static JSONObject httpsRequest(String requestUrl, String requestMethod) {
JSONObject jsonObject = null;
try {
// 创建SSLContext对象,并使用我们指定的信任管理器初始化
TrustManager[] tm = { new MyX509TrustManager() };
SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
sslContext.init(null, tm, new java.security.SecureRandom());
// 从上述SSLContext对象中得到SSLSocketFactory对象
SSLSocketFactory ssf = sslContext.getSocketFactory();
URL url = new URL(requestUrl);
HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
//conn.setSSLSocketFactory(ssf);
conn.setDoOutput(true);
conn.setDoInput(true);
conn.setUseCaches(false);
conn.setConnectTimeout(3000);
// 设置请求方式(GET/POST)
conn.setRequestMethod(requestMethod);
//conn.setRequestProperty("content-type", "application/x-www-form-urlencoded");
// 当outputStr不为null时向输出流写数据
// 从输入流读取返回内容
InputStream inputStream = conn.getInputStream();
InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "UTF-8");
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String str = null;
StringBuffer buffer = new StringBuffer();
while ((str = bufferedReader.readLine()) != null) {
buffer.append(str);
}
// 释放资源
bufferedReader.close();
inputStreamReader.close();
inputStream.close();
inputStream = null;
conn.disconnect();
jsonObject = JSONObject.parseObject(buffer.toString());
} catch (ConnectException ce) {
// log.error("连接超时:{}", ce);
} catch (Exception e) {
System.out.println(e);
// log.error("https请求异常:{}", e);
}
return jsonObject;
}
public static String urlEncodeUTF8(String source){
String result = source;
try {
result = java.net.URLEncoder.encode(source,"utf-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return result;
}
}
微信回调地址下一页
AESDecodeUtil.java 工具类 (解密 对回调函数的req_info进行解密)
package com.hb.common.util.pay;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.MessageDigest;
import java.security.Security;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import com.hb.common.util.ConfigureUtil;
import org.apache.commons.codec.binary.Base64;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;
import java.security.NoSuchAlgorithmException;
import java.util.*;
public class AESDecodeUtil {
public static final String ALGORITHM = "AES/ECB/PKCS7Padding";
public static String decode(String reqInfo) throws Exception{
try {
String key = ConfigureUtil.getProperty("weixin_key");//key的内容
//String key = "02a86cb980b1237eaa77fb86adf64657";
byte[] decodeBase64 = Base64.decodeBase64(reqInfo);
String md5Key =encryption(key);
Security.addProvider(new BouncyCastleProvider());
Cipher cipher = Cipher.getInstance(ALGORITHM);
SecretKey keySpec = new SecretKeySpec(md5Key.getBytes(), "AES"); //生成加密解密需要的Key
cipher.init(Cipher.DECRYPT_MODE, keySpec);
byte[] decoded = cipher.doFinal(decodeBase64);
String result = new String(decoded, "UTF-8");
return result;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static String encryption(String plainText) {
String re_md5 = new String();
try {
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(plainText.getBytes());
byte b[] = md.digest();
int i;
StringBuffer buf = new StringBuffer("");
for (int offset = 0; offset < b.length; offset++) {
i = b[offset];
if (i < 0)
i += 256;
if (i < 16)
buf.append("0");
buf.append(Integer.toHexString(i));
}
re_md5 = buf.toString();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return re_md5;
}
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();
} else {
v = XMLUtil.getChildrenText(children);
}
m.put(k, v);
}
//关闭流
in.close();
return m;
}
public static SortedMap<Object,Object> sortedMap( Map<String, String> m){
SortedMap<Object,Object> packageParams = new TreeMap<Object,Object>();
Iterator<String> it = m.keySet().iterator();
while (it.hasNext()) {
String parameter = (String) it.next();
String parameterValue = m.get(parameter);
String v = "";
if(null != parameterValue) {
v = parameterValue.trim();
}
packageParams.put(parameter, v);
}
return packageParams;
}
public static void main(String[] args) {
AESDecodeUtil test = new AESDecodeUtil();
String A = "cbRfjwOKrLQCOjAU0v1Ac6cDJQhK6349ngVplZHLe010obV59BJ75z05eUzG+Um3Zk9WxNO6jtk60bBDkMLmf4dZk41wSbyx/GiNNcRp3g0GdUMjGjhlyJgMAKiLbmVwcPEQnOoikcCbwGd0VmOdWcTk67kDlE4ssYW6pgBXp5bSBVotuar2Wxi0z20HGgsz7dcIVELP9+JfGwuiVV9xkhO8sPbEO4SIO2qhkRQ0QzbDYgn9gU1Iprzv6wGxFh+Bm/lJWuiBGwhFCT2fq1xEF1nDPEyW3LOWq4daCegXpvTXoXLZp9Xp6zcdxiDCsLgj8yj+q7ZNmVNt1vTUR94ZQAI1UAtCqK+1dI89DZdbifU7o0fVm/9WQqjcOIo4WemUJU7WfCsyHXBVvx8lZezoQc5ZGZOqTEZJCVKV6OF5iqvlNnZJ1byPg7BfHZnmbIjdETFMIOkq3oPicshnNlVZ9g08DvesDZzG/KJzI8NBMFfXNMjSJyuemsZ/0jFJRtKDOWoCQetWox+mORa5BPrMwvibTLkPZL0okvnyrJgFwGtE4BFTdnN/+cfuUISXMTbeZv6UjRJwD9y8B+wi4wTSUC1QXjlZEkV+RgBNnJD/n13NWUK1nlrwev/RHLsgjoMSYnF0mYec8g1BCyW0POcp4iEDaRVMrjQnACyyeMncSxA+KawdoFEOqMuAITv3B0Q9iZOTpI7yqnpquWiphXMuKovJgLp4vnPqerMMthTeaQ/rfVVO/U6Z4K/heTZKT2Y0y7kQP2GS+r/N5Qvu+J0sihJ8opoZ0AJ7ktwGrzcmkIq/DCCtAfgdAT8x3rtSXA4f8pb7WqFssdGRqgzMZR1jlcz3LD5+Du+BWK5QmyCeynywd9b6s7oYdyU0aI75LrT5EBOtEHAMGi2rmwb1X2wlEd3g4gCr2l1EEA4dUTdhsqynG0w64VHWJkvJgTOdmzMPWYksLu463qcy6dN44WuNBG0aw7uEQQIUXeRhDEwCBQVmzXNLzwQ6wHv6O9j7yvkvZll3SuGw7bbsfdSdAfQkJkLCj/MHuEKUauiV0mQS/2M=";
try {
String B = test.decode(A);
System.out.println(B);
System.out.println("======================================");
Map<String, String> m = doXMLParse(B);
System.out.println(m);
System.out.println(m.get("refund_recv_accout"));
System.out.println("======================================");
SortedMap<Object,Object> packageParams = sortedMap(m);
System.out.println(packageParams);
}catch (Exception e){
e.printStackTrace();
}
}
}
回调函数返回接口方法
/**
* 微信app支付回调通知
*/
@RequestMapping(value = "/wxRegisterNotify")
@ResponseBody
public String wxRegisterNotify(HttpServletRequest request, HttpServletResponse response) throws Exception{
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
response.setHeader("Access-Control-Allow-Origin", "*");
String result="";//返回给微信的处理结果
String inputLine;
String notityXml = "";
//微信给返回的东西
try {
while ((inputLine = request.getReader().readLine()) != null) {
notityXml += inputLine;
}
request.getReader().close();
} catch (Exception e) {
e.printStackTrace();
result = setXml("FAIL","xml获取失败");
System.out.println("退款失败,错误信息:" + "xml获取失败");
return result;
}
if (isEmpty(notityXml)) {
result = setXml("FAIL","xml为空");
System.out.println("退款失败,错误信息:" + "xml为空");
return result;
}
Map<String, String> m = XMLUtil.doXMLParse(notityXml);
//过滤空 设置 TreeMap
SortedMap<Object,Object> packageParams = new TreeMap<Object,Object>();
Iterator<String> it = m.keySet().iterator();
while (it.hasNext()) {
String parameter = (String) it.next();
String parameterValue = m.get(parameter);
String v = "";
if(null != parameterValue) {
v = parameterValue.trim();
}
packageParams.put(parameter, v);
}
//判断签名是否正确
if(PayCommonUtil.isTenpaySign("UTF-8", packageParams)) {//验证签名得注意
if("SUCCESS".equals((String)packageParams.get("return_code"))) {
String req_info = (String)packageParams.get("req_info"); //加密信息
String rel = AESDecodeUtil.decode(req_info);//处理加密信息
Map<String, String> relSutSuccess = XMLUtil.doXMLParse(rel);//解析xml
if("SUCCESS".equals(relSutSuccess.get("refund_status"))){//退款成功
System.out.println("微信退款订单开始处理");
// 这里是支付成功
//执行自己的业务逻辑
String mch_id = (String)relSutSuccess.get("settlement_refund_fee"); //退款金额=申请退款金额-非充值代金券退款金额
String openid = (String)relSutSuccess.get("refund_fee"); //申请退款金额
String out_trade_no = (String)relSutSuccess.get("out_trade_no"); //商户订单号
String total_fee = (String)relSutSuccess.get("total_fee");//金额
String transaction_id = (String)relSutSuccess.get("transaction_id"); //微信支付订单号
String time_end = (String)relSutSuccess.get("success_time");//退款成功时间
String refund_id = (String)relSutSuccess.get("refund_id");//微信退款单号
String out_refund_no = (String)relSutSuccess.get("out_refund_no");//商户退款单号
}else if("CHANGE".equals(relSutSuccess.get("refund_status"))){
String out_trade_no = (String)relSutSuccess.get("out_trade_no"); //商户订单号
System.out.println("退款异常:===返回订单号:"+out_trade_no);
result = setXml("FAIL","报文为空");
}else {
String out_trade_no = (String)relSutSuccess.get("out_trade_no"); //商户订单号
System.out.println("退款关闭:===返回订单号:"+out_trade_no);
result = setXml("FAIL","报文为空");
}
}else {
System.out.println("支付失败,错误信息:" + packageParams.get("return_msg"));
result = setXml("FAIL","报文为空");
}
}else {
result = setXml("FAIL","通知签名验证失败");
System.out.println("通知签名验证失败");
}
return result;
}
//通过xml 发给微信消息
public static String setXml(String return_code, String return_msg) {
SortedMap<String, String> parameters = new TreeMap<String, String>();
parameters.put("return_code", return_code);
parameters.put("return_msg", return_msg);
return "<xml><return_code><![CDATA[" + return_code + "]]>" +
"</return_code><return_msg><![CDATA[" + return_msg + "]]></return_msg></xml>";
}
public String orderIDget(){
SimpleDateFormat sd = new SimpleDateFormat("yyMMddHHmmss");
String date = sd.format(new Date());
StringBuffer sb = new StringBuffer();
sb.append(date);
String num = getRandomString(4);
sb.append(num);
return sb.toString();
}
//随机数
public static String getRandomString(int length) { // length表示生成字符串的长度
String base = "0123456789";
Random random = new Random();
StringBuffer sb = new StringBuffer();
for (int i = 0; i < length; i++) {
int number = random.nextInt(base.length());
sb.append(base.charAt(number));
}
return sb.toString();
}

1万+

被折叠的 条评论
为什么被折叠?



