公共配置类
import lombok.Data;
import springboot.util.TestProperties;
@Data
public class PayConfig {
//appId(与你商户号绑定的小程序或公众号的appid)
private String appID= "wxzf.appID";
//小程序秘钥
private String aPPSECRET="wxzf.aPPSECRET";
//商户号
private String mchID="wxzf.mchID";
//支付秘钥
private String Key="wxzf.Key";
}
支付签名工具
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.security.MessageDigest;
import java.util.Arrays;
import java.util.Map;
import java.util.Set;
/**
* 生成签名
*/
public class SignUtil {
//指定为MD5加密方式
public static String generateSignature(Map<String, String> data, String key) throws Exception {
return generateSignature(data, key, "MD5");
}
//自选加密方式加密方式
public static String generateSignature(Map<String, String> data, String key, String signType) throws Exception {
Set<String> keySet = data.keySet();
String[] keyArray = (String[])keySet.toArray(new String[keySet.size()]);
Arrays.sort(keyArray);
StringBuilder sb = new StringBuilder();
String[] var6 = keyArray;
int var7 = keyArray.length;
for(int var8 = 0; var8 < var7; ++var8) {
String k = var6[var8];
if (!k.equals("sign") && ((String)data.get(k)).trim().length() > 0) {
sb.append(k).append("=").append(((String)data.get(k)).trim()).append("&");
}
}
sb.append("key=").append(key);
if ("MD5".equals(signType)) {
return MD5(sb.toString()).toUpperCase();
} else if ("HMACSHA256".equals(signType)) {
return HMACSHA256(sb.toString(), key);
} else {
throw new Exception(String.format("Invalid sign_type: %s", signType));
}
}
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();
byte[] var4 = array;
int var5 = array.length;
for(int var6 = 0; var6 < var5; ++var6) {
byte item = var4[var6];
sb.append(Integer.toHexString(item & 255 | 256).substring(1, 3));
}
return sb.toString().toUpperCase();
}
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();
byte[] var6 = array;
int var7 = array.length;
for(int var8 = 0; var8 < var7; ++var8) {
byte item = var6[var8];
sb.append(Integer.toHexString(item & 255 | 256).substring(1, 3));
}
return sb.toString().toUpperCase();
}
}
支付签名验证工具
import springboot.wexPayApi.dto.PayConfig;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.security.MessageDigest;
import java.util.Arrays;
import java.util.Map;
import java.util.Set;
/**
* 验证签名
*/
public class Verification {
public static boolean isPayResultNotifySignatureValid(Map<String, String> reqData) throws Exception {
String signTypeInData = (String)reqData.get("sign_type");
String signType;
if (signTypeInData == null) {
signType = "MD5";
} else {
signTypeInData = signTypeInData.trim();
if (signTypeInData.length() == 0) {
signType = "MD5";
} else if ("MD5".equals(signTypeInData)) {
signType = "MD5";
} else {
if (!"HMAC-SHA256".equals(signTypeInData)) {
throw new Exception(String.format("Unsupported sign_type: %s", signTypeInData));
}
signType = "HMACSHA256";
}
}
PayConfig config=new PayConfig();
return isSignatureValid(reqData, config.getKey(), signType);
}
public static boolean isSignatureValid(Map<String, String> data, String key, String signType) throws Exception {
if (!data.containsKey("sign")) {
return false;
} else {
String sign = (String)data.get("sign");
return generateSignature(data, key, signType).equals(sign);
}
}
public static String generateSignature(Map<String, String> data, String key, String signType) throws Exception {
Set<String> keySet = data.keySet();
String[] keyArray = (String[])keySet.toArray(new String[keySet.size()]);
Arrays.sort(keyArray);
StringBuilder sb = new StringBuilder();
String[] var6 = keyArray;
int var7 = keyArray.length;
for(int var8 = 0; var8 < var7; ++var8) {
String k = var6[var8];
if (!k.equals("sign") && ((String)data.get(k)).trim().length() > 0) {
sb.append(k).append("=").append(((String)data.get(k)).trim()).append("&");
}
}
sb.append("key=").append(key);
if ("MD5".equals(signType)) {
return MD5(sb.toString()).toUpperCase();
} else if ("HMACSHA256".equals(signType)) {
return HMACSHA256(sb.toString(), key);
} else {
throw new Exception(String.format("Invalid sign_type: %s", signType));
}
}
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();
byte[] var6 = array;
int var7 = array.length;
for(int var8 = 0; var8 < var7; ++var8) {
byte item = var6[var8];
sb.append(Integer.toHexString(item & 255 | 256).substring(1, 3));
}
return sb.toString().toUpperCase();
}
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();
byte[] var4 = array;
int var5 = array.length;
for(int var6 = 0; var6 < var5; ++var6) {
byte item = var4[var6];
sb.append(Integer.toHexString(item & 255 | 256).substring(1, 3));
}
return sb.toString().toUpperCase();
}
}
普通请求发送工具post,get请求
import javax.net.ssl.*;
import javax.servlet.http.HttpServletRequest;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Iterator;
import java.util.Map;
/**
* 发送请求(post,get请求)
*/
public class HttpKit {
private static String CHARSET = "UTF-8";
private static final SSLSocketFactory sslSocketFactory = initSSLSocketFactory();
private static final TrustAnyHostnameVerifier trustAnyHostnameVerifier = new HttpKit().new TrustAnyHostnameVerifier();
// public static final OkHttp3Delegate delegate = new OkHttp3Delegate();
private HttpKit() {
}
private static SSLSocketFactory initSSLSocketFactory() {
try {
TrustManager[] e = new TrustManager[]{new HttpKit().new TrustAnyTrustManager()};
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init((KeyManager[])null, e, new SecureRandom());
return sslContext.getSocketFactory();
} catch (Exception var2) {
throw new RuntimeException(var2);
}
}
private static HttpURLConnection getHttpConnection(String url, String method, Map<String, String> headers) throws IOException, NoSuchAlgorithmException, NoSuchProviderException, KeyManagementException{
URL _url = new URL(url);
HttpURLConnection conn = (HttpURLConnection)_url.openConnection();
if(conn instanceof HttpsURLConnection) {
((HttpsURLConnection)conn).setSSLSocketFactory(sslSocketFactory);
((HttpsURLConnection)conn).setHostnameVerifier(trustAnyHostnameVerifier);
}
conn.setRequestMethod(method);
conn.setDoOutput(true);
conn.setDoInput(true);
conn.setConnectTimeout(19000);
conn.setReadTimeout(19000);
conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
conn.setRequestProperty("AuthUser-Agent", "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.146 Safari/537.36");
if(headers != null && !headers.isEmpty()) {
Iterator i$ = headers.entrySet().iterator();
while(i$.hasNext()) {
Map.Entry entry = (Map.Entry)i$.next();
conn.setRequestProperty((String)entry.getKey(), (String)entry.getValue());
}
}
return conn;
}
public static String get(String url, Map<String, String> queryParas, Map<String, String> headers) {
HttpURLConnection conn = null;
String e;
try {
conn = getHttpConnection(buildUrlWithQueryString(url, queryParas), "GET", headers);
conn.connect();
e = readResponseString(conn);
} catch (Exception var8) {
throw new RuntimeException(var8);
} finally {
if(conn != null) {
conn.disconnect();
}
}
return e;
}
public static String get(String url, Map<String, String> queryParas) {
return get(url, queryParas, (Map)null);
}
public static String get(String url) {
return get(url, (Map)null, (Map)null);
}
public static String post(String url, Map<String, String> queryParas, String data, Map<String, String> headers) {
HttpURLConnection conn = null;
String var6;
try {
conn = getHttpConnection(buildUrlWithQueryString(url, queryParas), "POST", headers);
conn.connect();
OutputStream e = conn.getOutputStream();
e.write(data.getBytes(CHARSET));
e.flush();
e.close();
var6 = readResponseString(conn);
} catch (Exception var10) {
throw new RuntimeException(var10);
} finally {
if(conn != null) {
conn.disconnect();
}
}
return var6;
}
public static String post(String url, Map<String, String> queryParas, String data) {
return post(url, queryParas, data, (Map)null);
}
public static String post(String url, String data, Map<String, String> headers) {
return post(url, (Map)null, data, headers);
}
public static String post(String url, String data) {
return post(url, (Map)null, data, (Map)null);
}
private static String readResponseString(HttpURLConnection conn) {
StringBuilder sb = new StringBuilder();
InputStream inputStream = null;
try {
inputStream = conn.getInputStream();
BufferedReader e = new BufferedReader(new InputStreamReader(inputStream, CHARSET));
String line = null;
while((line = e.readLine()) != null) {
sb.append(line).append("\n");
}
String var5 = sb.toString();
return var5;
} catch (Exception var14) {
throw new RuntimeException(var14);
} finally {
if(inputStream != null) {
try {
inputStream.close();
} catch (IOException var13) {
}
}
}
}
private static String buildUrlWithQueryString(String url, Map<String, String> queryParas) {
if(queryParas != null && !queryParas.isEmpty()) {
StringBuilder sb = new StringBuilder(url);
boolean isFirst;
if(url.indexOf("?") == -1) {
isFirst = true;
sb.append("?");
} else {
isFirst = false;
}
String key;
String value;
for(Iterator i$ = queryParas.entrySet().iterator() ; i$.hasNext(); sb.append(key).append("=").append(value)) {
Map.Entry entry = (Map.Entry)i$.next();
if(isFirst) {
isFirst = false;
} else {
sb.append("&");
}
key = (String)entry.getKey();
value = (String)entry.getValue();
if(value!=null && !"".equals(value)) {
try {
value = URLEncoder.encode(value, CHARSET);
} catch (UnsupportedEncodingException var9) {
throw new RuntimeException(var9);
}
}
}
return sb.toString();
} else {
return url;
}
}
public static String readData(HttpServletRequest request) {
BufferedReader br = null;
try {
StringBuilder e = new StringBuilder();
br = request.getReader();
String line = null;
while((line = br.readLine()) != null) {
e.append(line).append("\n");
}
line = e.toString();
return line;
} catch (IOException var12) {
throw new RuntimeException(var12);
} finally {
if(br != null) {
try {
br.close();
} catch (IOException var11) {
}
}
}
}
/** @deprecated */
@Deprecated
public static String readIncommingRequestData(HttpServletRequest request) {
return readData(request);
}
private class TrustAnyTrustManager implements X509TrustManager {
private TrustAnyTrustManager() {
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return null;
}
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException{
}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
}
private class TrustAnyHostnameVerifier implements HostnameVerifier {
private TrustAnyHostnameVerifier() {
}
@Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
}
}
携带证书请求与处理Xml格式
import com.google.common.reflect.TypeToken;
import com.google.gson.Gson;
import com.google.gson.JsonSyntaxException;
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.InputStreamEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContexts;
import org.springframework.core.io.ClassPathResource;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import springboot.util.TestProperties;
import javax.net.ssl.SSLContext;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.security.KeyStore;
import java.util.HashMap;
import java.util.Map;
/**
* 发送HTTPS的post的请求携带证书请求
* xml转map,map转xml
*
*/
public class HttpsPost {
/**
* 微信下单,map to xml
* @param params 参数
* @return String
*/
public static String toXml(Map<String, String> params) {
StringBuilder xml = new StringBuilder();
xml.append("<xml>");
//遍历map获取key与value
for (Map.Entry<String, String> entry : params.entrySet()) {
String key = entry.getKey();
String value = entry.getValue();
// 略过空值
if (isEmpty(value)){ continue;}
xml.append("<").append(key).append(">");
xml.append(entry.getValue());
xml.append("</").append(key).append(">");
}
xml.append("</xml>");
return xml.toString();
}
/**
* 检测字符串是否为空(null,"","null")
*
* @param s
* @return 为空则返回true,不否则返回false
*/
public static boolean isEmpty(String s) {
return s == null || "".equals(s) || "null".equals(s);
}
/**
* String转map
* @param str_json
* @return
*/
public static Map<String, String> json2map(String str_json) {
Map<String, String> res = null;
try {
Gson gson = new Gson();
res = gson.fromJson(str_json, new TypeToken<Map<String, String>>() {
}.getType());
} catch (JsonSyntaxException e) {
}
return res;
}
/**
* 带证书httpPost请求
* @param url 接口地址
* @param param 参数
* @return
* @throws Exception
*/
public static String sendRedEnvelope(String url, String param) throws Exception {
//PKCS12的密码
String PKCS12 = TestProperties.getvalue("wxzf.mchID");
//证书地址 apiclient_cert.p12
String fileRoute = TestProperties.getvalue("wxzf.certPath");
//指定读取证书格式为PKCS12
KeyStore keyStore = KeyStore.getInstance("PKCS12");
//读取本机存放的PKCS12证书文件
// FileInputStream instream = new FileInputStream(new File(fileRoute));
InputStream instream = new ClassPathResource(fileRoute).getInputStream();
try {
//指定PKCS12的密码
keyStore.load(instream, PKCS12.toCharArray());
} finally {
instream.close();
}
//指定TLS版本
SSLContext sslcontext = SSLContexts.custom()
.loadKeyMaterial(keyStore, PKCS12.toCharArray())
.build();
//设置httpclient的SSLSocketFactory
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
sslcontext,
new String[]{"TLSv1"},
null,
SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
CloseableHttpClient httpclient = HttpClients.custom()
.setSSLSocketFactory(sslsf)
.build();
StringBuffer stringBuffer = new StringBuffer();
try {
HttpPost httpPost = new HttpPost(url);
InputStream is = new ByteArrayInputStream(param.getBytes("UTF-8"));
//InputStreamEntity严格是对内容和长度相匹配的。用法和BasicHttpEntity类似
InputStreamEntity inputStreamEntity = new InputStreamEntity(is, is.available());
httpPost.setEntity(inputStreamEntity);
CloseableHttpResponse response = httpclient.execute(httpPost);
try {
HttpEntity entity = response.getEntity();
BufferedReader reader = new BufferedReader(new InputStreamReader(
entity.getContent(), "UTF-8"));
String inputLine;
while ((inputLine = reader.readLine()) != null) {
stringBuffer.append(inputLine);
}
} finally {
response.close();
}
} finally {
httpclient.close();
}
String str=stringBuffer.toString();
return str;
}
/**
* XML格式字符串转换为Map
*
* @param xml XML字符串
* @return XML数据转换后的Map
* @throws Exception
*/
public static Map<String, String> xmlToMap(String xml) {
try {
Map<String, String> data = new HashMap<>();
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
InputStream stream = new ByteArrayInputStream(xml.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) node;
data.put(element.getNodeName(), element.getTextContent());
}
}
stream.close();
return data;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
Jsapi支付
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import springboot.util.startuputil.IpUtil;
import springboot.wexPayApi.controller.HDController;
import springboot.wexPayApi.dto.PayConfig;
import springboot.wexPayApi.util.HttpKit;
import springboot.wexPayApi.util.HttpsPost;
import springboot.wexPayApi.util.SignUtil;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
/**
* Jsapi支付接口
* 文档地址:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1
* 作者:王文斌
*/
@Component
public class JsapiPayUtil {
private static Logger logger = LoggerFactory.getLogger(HDController.class);//可注释
/**
* 微信支付接口
*
* @param money 金额
* @param openid 用户openid
* @return
* @throws Exception
*/
public Object genWxProgramPayChannel(String money, String orderNumber, String openid, String body) throws Exception {
//orderNumber号 订单
PayConfig config = new PayConfig();
Map<String, String> reqParams = new HashMap<>();
//微信分配的小程序ID
reqParams.put("appid", config.getAppID());
//微信支付分配的商户号
reqParams.put("mch_id", config.getMchID());
//随机字符串
reqParams.put("nonce_str", System.currentTimeMillis() / 1000 + "");
//签名类型
reqParams.put("sign_type", "MD5");
//充值订单 商品描述
reqParams.put("body", body);
//商户订单号
reqParams.put("out_trade_no", orderNumber);
//订单总金额,单位为分
reqParams.put("total_fee", money);
//终端IP
reqParams.put("spbill_create_ip", IpUtil.getRequestIp());
//通知地址http://www.bskuqi.cn/
reqParams.put("notify_url", "https://bskuqi.cn/yldh/web/api/yys/JSAPI/notify/");
//交易类型
reqParams.put("trade_type", "JSAPI");
//用户标识
reqParams.put("openid", openid);
//签名
String sign = SignUtil.generateSignature(reqParams, config.getKey());
// request.getSession().setAttribute(orderNumber,sign);
reqParams.put("sign", sign);
/*
调用支付定义下单API,返回预付单信息 prepay_id
*/
String xmlResult = HttpKit.post("https://api.mch.weixin.qq.com/pay/unifiedorder", HttpsPost.toXml(reqParams));
logger.info("---" + xmlResult);
Map<String, String> result = HttpsPost.xmlToMap(xmlResult);
System.out.println("money========================================"+money);
String prepay_id = result.get("prepay_id");
/*
小程序调起支付数据签名
*/
Map<String, String> packageParams = new HashMap<String, String>();
packageParams.put("appId", config.getAppID());
packageParams.put("timeStamp", System.currentTimeMillis() / 1000 + "");
packageParams.put("nonceStr", System.currentTimeMillis() + "");
packageParams.put("package", "prepay_id=" + prepay_id);
packageParams.put("signType", "MD5");
String packageSign = SignUtil.generateSignature(packageParams, config.getKey());
packageParams.put("paySign", packageSign);
return packageParams;
}
/**
* jsapi退款方法
* @param outTradeNo 退款订单号(支付时产生的订单号)
* @param total_fee 总金额(及退款金额)
* @return
* @throws Exception MD5Util签名异常
*/
public boolean refund(String outTradeNo, String total_fee) throws Exception {
PayConfig config = new PayConfig();
Date now = new Date();
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
String hehe = dateFormat.format(now);
String out_refund_no = hehe + "wxrefund";
int allFee = (int) (Double.parseDouble(total_fee))*100;
Map<String, String> reqParams = new HashMap<>();
reqParams.put("appid",config.getAppID());
reqParams.put("mch_id", config.getMchID());
reqParams.put("nonce_str", System.currentTimeMillis() / 1000 + "");
reqParams.put("out_trade_no", outTradeNo);
reqParams.put("total_fee",String.valueOf(allFee));
reqParams.put("refund_fee",String.valueOf(allFee));
reqParams.put("out_refund_no",out_refund_no);
//签名
String sign = SignUtil.generateSignature(reqParams, config.getKey());
reqParams.put("sign", sign);
System.out.println(HttpsPost.toXml(reqParams));
String xmlResult = HttpsPost.sendRedEnvelope("https://api.mch.weixin.qq.com/secapi/pay/refund", HttpsPost.toXml(reqParams));
logger.info("---" + xmlResult);
Map<String, String> result = HttpsPost.xmlToMap(xmlResult);
if(xmlResult.contains("大于可退金额")){
return false;
}else {
return true;
}
}
/**
* 退回剩余金额
* @param outTradeNo (支付时产生的订单号)
* @param all_fee 总金额
* @param over_fee 退回金额
* @return
* @throws Exception
*/
public boolean overrefund(String outTradeNo, String all_fee,String over_fee) throws Exception {
PayConfig config = new PayConfig();
System.err.println("进入微信退款申请");
Date now = new Date();
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmss");//可以方便地修改日期格式
String hehe = dateFormat.format(now);
int allFee = (int) (Double.parseDouble(all_fee))*100; //需要*100
int overFee = (int) (Double.parseDouble(over_fee))*100; //需要*100
String out_refund_no = hehe + "wxrefund";
Map<String, String> reqParams = new HashMap<>();
reqParams.put("appid",config.getAppID());
reqParams.put("mch_id", config.getMchID());
reqParams.put("nonce_str", System.currentTimeMillis() / 1000 + "");
reqParams.put("out_trade_no", outTradeNo);
reqParams.put("total_fee",String.valueOf(allFee));
reqParams.put("refund_fee",String.valueOf(overFee));
reqParams.put("out_refund_no",out_refund_no);
//签名
String sign = SignUtil.generateSignature(reqParams, config.getKey());
reqParams.put("sign", sign);
System.out.println(HttpsPost.toXml(reqParams));
String xmlResult = HttpsPost.sendRedEnvelope("https://api.mch.weixin.qq.com/secapi/pay/refund", HttpsPost.toXml(reqParams));
logger.info("---" + xmlResult);
Map<String, String> result = HttpsPost.xmlToMap(xmlResult);
if(xmlResult.contains("大于可退金额")){
return false;
}else {
return true;
}
}
}
回调
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import springboot.common.api.ApiResult;
import springboot.common.constant.CommonConstant;
import springboot.wexPayApi.SelectAndCloseUtil;
import springboot.wexPayApi.dto.PayConfig;
import springboot.wexPayApi.util.HttpsPost;
import springboot.wexPayApi.util.Verification;
import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Map;
/**
* 回调
* @Author ttaurus
* @Date Create in 2020/1/21 11:24
*/
@RestController
@Api(value = CommonConstant.WEB_API_PREFIX + "pay", description = "微信支付")
@RequestMapping(CommonConstant.WEB_API_PREFIX + "/pay")
@Slf4j
public class HDController {
//可注释
private static Logger logger = LoggerFactory.getLogger(HDController.class);
@Autowired
private SelectAndCloseUtil selectAndCloseUtil;
@PostMapping(value = "/JSAPI/notify/") //回调函数
@ApiOperation(value = "添加微信支付回调", notes = "添加微信支付回调", response = ApiResult.class)
public String payJSAPI(HttpServletRequest request) {
InputStream is = null;
String xmlBack = "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[报文为空]]></return_msg></xml> ";
try {
is = request.getInputStream();
// 将InputStream转换成String
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
StringBuilder sb = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null) {
sb.append(line + "\n");
}
xmlBack = notify(request, sb.toString()); //调用通知方法
System.out.println("返回的信息如下:\n" + sb.toString());
System.out.println("已成功支付且回复到微信服务器!");
} catch (Exception e) {
logger.error("微信手机支付回调通知失败:", e);
} finally {
if (is != null) {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
System.out.println("已成功支付且回复到微信服务器!");
return xmlBack;
}
public String notify(HttpServletRequest request, String notifyStr) {
String xmlBack = "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[报文为空]]></return_msg></xml> ";
try {
// 转换成map,判断是否是你本商户的支付订单
Map<String, String> resultMap = HttpsPost.xmlToMap(notifyStr);
if (Verification.isPayResultNotifySignatureValid(resultMap)) {
//状态
String returnCode = resultMap.get("return_code");
String transactionId = resultMap.get("transaction_id");
System.out.println(transactionId);
if ("SUCCESS".equals(returnCode)) {
String outTradeNo = resultMap.get("out_trade_no");
//这个if判断是判断该订单是否支付成功,如果支付成功的话就关闭,
//都返回Ok就行了不用多此一举做判断了
if (selectAndCloseUtil.genSupply(outTradeNo)) {
selectAndCloseUtil.CloseSupply(outTradeNo);
}
//这里写支付完成后的逻辑,你需要更改订单状态之类的东西
xmlBack = "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";
}
}
} catch (Exception e) {
e.printStackTrace();
}
return xmlBack;
}
}